openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

569 lines
18 KiB

// Copyright (C) 2004, 2009 International Business Machines and others.
// All Rights Reserved.
// This code is published under the Eclipse Public License.
//
// $Id: AmplTNLP.hpp 2242 2013-04-24 19:26:30Z stefan $
//
// Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
#ifndef __IPAMPLTNLP_HPP__
#define __IPAMPLTNLP_HPP__
#include "IpUtils.hpp"
#include "IpTNLP.hpp"
#include "IpJournalist.hpp"
#include "IpOptionsList.hpp"
#include <map>
#include <string>
/* non Ipopt forward declaration */
struct ASL_pfgh;
struct SufDecl;
struct SufDesc;
namespace Ipopt
{
class AmplSuffixHandler : public ReferencedObject
{
public:
AmplSuffixHandler();
~AmplSuffixHandler();
enum Suffix_Type
{
Index_Type,
Number_Type
};
enum Suffix_Source
{
Variable_Source,
Constraint_Source,
Objective_Source,
Problem_Source
};
void AddAvailableSuffix(std::string suffix_string, Suffix_Source source, Suffix_Type type)
{
suffix_ids_.push_back(suffix_string);
suffix_types_.push_back(type);
suffix_sources_.push_back(source);
// suffix_values_.push_back();
}
const Index* GetIntegerSuffixValues(std::string suffix_string, Suffix_Source source) const;
const Number* GetNumberSuffixValues(std::string suffix_string, Suffix_Source source) const;
std::vector<Index> GetIntegerSuffixValues(Index n, std::string suffix_string, Suffix_Source source) const;
std::vector<Number> GetNumberSuffixValues(Index n, std::string suffix_string, Suffix_Source source) const;
private:
/**@name Default Compiler Generated Methods
* (Hidden to avoid implicit creation/calling).
* These methods are not implemented and
* we do not want the compiler to implement
* them for us, so we declare them private
* and do not define them. This ensures that
* they will not be implicitly created/called. */
//@{
/** Default Constructor */
//AmplSuffixHandler();
/** Copy Constructor */
AmplSuffixHandler(const AmplSuffixHandler&);
/** Overloaded Equals Operator */
void operator=(const AmplSuffixHandler&);
//@}
mutable ASL_pfgh* asl_;
SufDecl* suftab_;
std::vector<std::string> suffix_ids_;
std::vector<Suffix_Type> suffix_types_;
std::vector<Suffix_Source> suffix_sources_;
/** Method called by AmplTNLP to prepare the asl for the suffixes */
void PrepareAmplForSuffixes(ASL_pfgh* asl);
/** Method called by AmplTNLP to retrieve the suffixes from asl */
// void RetrieveSuffixesFromAmpl(ASL_pfgh* asl);
friend class AmplTNLP;
};
/** Class for storing a number of AMPL options that should be
* registered to the AMPL Solver library interface */
class AmplOptionsList : public ReferencedObject
{
public:
enum AmplOptionType {
String_Option,
Number_Option,
Integer_Option,
WS_Option, /* this is for AMPL's internal wantsol callback */
HaltOnError_Option /* this is for our setting of the nerror_ member */
};
/** Ampl Option class, contains name, type and description for an
* AMPL option */
class AmplOption : public ReferencedObject
{
public:
AmplOption(const std::string ipopt_option_name,
AmplOptionType type,
const std::string description);
~AmplOption()
{
delete [] description_;
}
const std::string& IpoptOptionName() const
{
return ipopt_option_name_;
}
AmplOptionType Type() const
{
return type_;
}
char* Description() const
{
return description_;
}
private:
/**@name Default Compiler Generated Methods
* (Hidden to avoid implicit creation/calling).
* These methods are not implemented and
* we do not want the compiler to implement
* them for us, so we declare them private
* and do not define them. This ensures that
* they will not be implicitly created/called. */
//@{
/** Default Constructor */
AmplOption();
/** Copy Constructor */
AmplOption(const AmplOption&);
/** Overloaded Equals Operator */
void operator=(const AmplOption&);
//@}
const std::string ipopt_option_name_;
const AmplOptionType type_;
char* description_;
};
class PrivatInfo
{
public:
PrivatInfo(const std::string ipopt_name,
SmartPtr<OptionsList> options,
SmartPtr<const Journalist> jnlst,
void** nerror = NULL)
:
ipopt_name_(ipopt_name),
options_(options),
jnlst_(jnlst),
nerror_(nerror)
{}
const std::string& IpoptName() const
{
return ipopt_name_;
}
const SmartPtr<OptionsList>& Options() const
{
return options_;
}
const SmartPtr<const Journalist>& Jnlst() const
{
return jnlst_;
}
void** NError()
{
return nerror_;
}
private:
const std::string ipopt_name_;
const SmartPtr<OptionsList> options_;
const SmartPtr<const Journalist> jnlst_;
void** nerror_;
};
public:
/** Default Constructor */
AmplOptionsList()
:
keywds_(NULL),
nkeywds_(0)
{}
/** Destructor */
~AmplOptionsList();
/** Adding a new AMPL Option */
void AddAmplOption(const std::string ampl_option_name,
const std::string ipopt_option_name,
AmplOptionsList::AmplOptionType type,
const std::string description)
{
SmartPtr<AmplOption> new_option =
new AmplOption(ipopt_option_name, type, description);
ampl_options_map_[ampl_option_name] = ConstPtr(new_option);
}
/** Number of AMPL Options */
Index NumberOfAmplOptions()
{
return (Index)ampl_options_map_.size();
}
/** ASL keywords list for the stored options. */
void* Keywords(const SmartPtr<OptionsList>& options,
SmartPtr<const Journalist> jnlst,
void** nerror);
private:
/**@name Default Compiler Generated Methods
* (Hidden to avoid implicit creation/calling).
* These methods are not implemented and
* we do not want the compiler to implement
* them for us, so we declare them private
* and do not define them. This ensures that
* they will not be implicitly created/called. */
//@{
/** Default Constructor */
//AmplOptionsList();
/** Copy Constructor */
AmplOptionsList(const AmplOptionsList&);
/** Overloaded Equals Operator */
void operator=(const AmplOptionsList&);
//@}
void MakeValidLatexString(std::string source, std::string& dest) const;
void PrintLatex(SmartPtr<const Journalist> jnlst);
/** map for storing registered AMPL options */
std::map<std::string, SmartPtr<const AmplOption> > ampl_options_map_;
// AW: I think it should be with const like in the following line
// but with const the AIX compiler fails
// std::map<const std::string, SmartPtr<const AmplOption> > ampl_options_map_;
/** pointer to the keywords */
void* keywds_;
/** Number of entries stored in keywds_ */
Index nkeywds_;
};
/** Ampl Interface.
* Ampl Interface, implemented as a TNLP.
*/
class AmplTNLP : public TNLP
{
public:
/**@name Constructors/Destructors */
//@{
/** Constructor. */
AmplTNLP(const SmartPtr<const Journalist>& jnlst,
const SmartPtr<OptionsList> options,
char**& argv, SmartPtr<AmplSuffixHandler>
suffix_handler = NULL, bool allow_discrete = false,
SmartPtr<AmplOptionsList> ampl_options_list = NULL,
const char* ampl_option_string = NULL,
const char* ampl_invokation_string = NULL,
const char* ampl_banner_string = NULL,
std::string* nl_file_content = NULL);
/** Default destructor */
virtual ~AmplTNLP();
//@}
/** Exceptions */
DECLARE_STD_EXCEPTION(NONPOSITIVE_SCALING_FACTOR);
/**@name methods to gather information about the NLP. These
* methods are overloaded from TNLP. See TNLP for their more
* detailed documentation. */
//@{
/** returns dimensions of the nlp. Overloaded from TNLP */
virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
Index& nnz_h_lag, IndexStyleEnum& index_style);
/** returns names and other meta data for the variables and constraints
* Overloaded from TNLP */
virtual bool get_var_con_metadata(Index n,
StringMetaDataMapType& var_string_md,
IntegerMetaDataMapType& var_integer_md,
NumericMetaDataMapType& var_numeric_md,
Index m,
StringMetaDataMapType& con_string_md,
IntegerMetaDataMapType& con_integer_md,
NumericMetaDataMapType& con_numeric_md);
/** returns bounds of the nlp. Overloaded from TNLP */
virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
Index m, Number* g_l, Number* g_u);
/** Returns the constraint linearity.
* array will be alocated with length n. (default implementation
* just return false and does not fill the array). */
virtual bool get_constraints_linearity(Index m,
LinearityType* const_types);
/** provides a starting point for the nlp variables. Overloaded
from TNLP */
virtual bool get_starting_point(Index n, bool init_x, Number* x,
bool init_z, Number* z_L, Number* z_U,
Index m, bool init_lambda, Number* lambda);
/** evaluates the objective value for the nlp. Overloaded from TNLP */
virtual bool eval_f(Index n, const Number* x, bool new_x,
Number& obj_value);
/** evaluates the gradient of the objective for the
nlp. Overloaded from TNLP */
virtual bool eval_grad_f(Index n, const Number* x, bool new_x,
Number* grad_f);
/** evaluates the constraint residuals for the nlp. Overloaded from TNLP */
virtual bool eval_g(Index n, const Number* x, bool new_x,
Index m, Number* g);
/** specifies the jacobian structure (if values is NULL) and
* evaluates the jacobian values (if values is not NULL) for the
* nlp. Overloaded from TNLP */
virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
Index m, Index nele_jac, Index* iRow,
Index *jCol, Number* values);
/** specifies the structure of the hessian of the lagrangian (if
* values is NULL) and evaluates the values (if values is not
* NULL). Overloaded from TNLP */
virtual bool eval_h(Index n, const Number* x, bool new_x,
Number obj_factor, Index m, const Number* lambda,
bool new_lambda, Index nele_hess, Index* iRow,
Index* jCol, Number* values);
/** retrieve the scaling parameters for the variables, objective
* function, and constraints. */
virtual bool get_scaling_parameters(Number& obj_scaling,
bool& use_x_scaling, Index n,
Number* x_scaling,
bool& use_g_scaling, Index m,
Number* g_scaling);
//@}
/** @name Solution Methods */
//@{
virtual void finalize_solution(SolverReturn status,
Index n, const Number* x, const Number* z_L, const Number* z_U,
Index m, const Number* g, const Number* lambda,
Number obj_value,
const IpoptData* ip_data,
IpoptCalculatedQuantities* ip_cq);
//@}
/** @name Method for quasi-Newton approximation information. */
//@{
virtual Index get_number_of_nonlinear_variables();
virtual bool get_list_of_nonlinear_variables(Index num_nonlin_vars,
Index* pos_nonlin_vars);
//@}
/**@name Ampl specific methods */
//@{
/** Return the ampl solver object (ASL*) */
ASL_pfgh* AmplSolverObject()
{
return asl_;
}
/** Write the solution file. This is a wrapper for AMPL's
* write_sol. TODO Maybe this should be at a different place, or
* collect the numbers itself? */
void write_solution_file(const std::string& message) const;
/** ampl orders the variables like (continuous, binary, integer).
* This method gives the number of binary and integer variables.
* For details, see Tables 3 and 4 in "Hooking Your Solver to
* AMPL"
*/
void get_discrete_info(Index& nlvb_,
Index& nlvbi_,
Index& nlvc_,
Index& nlvci_,
Index& nlvo_,
Index& nlvoi_,
Index& nbv_,
Index& niv_) const;
//@}
/** A method for setting the index of the objective function to be
* considered. This method must be called after the constructor,
* and before anything else is called. It can only be called
* once, and if there is more than one objective function in the
* AMPL model, it MUST be called. */
void set_active_objective(Index obj_no);
/**@name Methods to set meta data for the variables
* and constraints. These values will be passed on
* to the TNLP in get_var_con_meta_data
*/
//@{
void set_string_metadata_for_var(std::string tag, std::vector<std::string> meta_data)
{
var_string_md_[tag] = meta_data;
}
void set_integer_metadata_for_var(std::string tag, std::vector<Index> meta_data)
{
var_integer_md_[tag] = meta_data;
}
void set_numeric_metadata_for_var(std::string tag, std::vector<Number> meta_data)
{
var_numeric_md_[tag] = meta_data;
}
void set_string_metadata_for_con(std::string tag, std::vector<std::string> meta_data)
{
con_string_md_[tag] = meta_data;
}
void set_integer_metadata_for_con(std::string tag, std::vector<Index> meta_data)
{
con_integer_md_[tag] = meta_data;
}
void set_numeric_metadata_for_con(std::string tag, std::vector<Number> meta_data)
{
con_numeric_md_[tag] = meta_data;
}
//@}
/** Method for returning the suffix handler */
SmartPtr<AmplSuffixHandler> get_suffix_handler()
{
return suffix_handler_;
}
private:
/**@name Default Compiler Generated Methods
* (Hidden to avoid implicit creation/calling).
* These methods are not implemented and
* we do not want the compiler to implement
* them for us, so we declare them private
* and do not define them. This ensures that
* they will not be implicitly created/called. */
//@{
/** Default Constructor */
AmplTNLP();
/** Copy Constructor */
AmplTNLP(const AmplTNLP&);
/** Overloaded Equals Operator */
void operator=(const AmplTNLP&);
//@}
/** Journlist */
SmartPtr<const Journalist> jnlst_;
/** pointer to the main ASL structure */
ASL_pfgh* asl_;
/** Sign of the objective fn (1 for min, -1 for max) */
double obj_sign_;
/**@name Problem Size Data*/
//@{
Index nz_h_full_; // number of nonzeros in the full_x hessian
/* the rest of the problem size data is available easily through the ampl variables */
//@}
/**@name Internal copies of data */
//@{
/** Solution Vectors */
Number* x_sol_;
Number* z_L_sol_;
Number* z_U_sol_;
Number* g_sol_;
Number* lambda_sol_;
Number obj_sol_;
//@}
/**@name Flags to track internal state */
//@{
/** true when the objective value has been calculated with the
* current x, set to false in apply_new_x, and set to true in
* internal_objval */
bool objval_called_with_current_x_;
/** true when the constraint values have been calculated with the
* current x, set to false in apply_new_x, and set to true in
* internal_conval */
bool conval_called_with_current_x_;
/** true when we have called hesset */
bool hesset_called_;
/** true when set_active_objective has been called */
bool set_active_objective_called_;
//@}
/** Pointer to the Oinfo structure */
void* Oinfo_ptr_;
/** nerror flag passed to ampl calls - set to NULL to halt on error */
void* nerror_;
/** Suffix Handler */
SmartPtr<AmplSuffixHandler> suffix_handler_;
/** Make the objective call to ampl */
bool internal_objval(const Number* x, Number& obj_val);
/** Make the constraint call to ampl*/
bool internal_conval(const Number* x, Index m, Number* g=NULL);
/** Internal function to update the internal and ampl state if the
* x value changes */
bool apply_new_x(bool new_x, Index n, const Number* x);
/** Method for obtaining the name of the NL file and the options
* set from AMPL. Returns a pointer to a char* with the name of
* the stub */
char* get_options(const SmartPtr<OptionsList>& options,
SmartPtr<AmplOptionsList>& ampl_options_list,
const char* ampl_option_string,
const char* ampl_invokation_string,
const char* ampl_banner_string, char**& argv);
/** returns true if the ampl nerror code is ok */
bool nerror_ok(void* nerror);
/** calls hesset ASL function */
void call_hesset();
/** meta data to pass on to TNLP */
StringMetaDataMapType var_string_md_;
IntegerMetaDataMapType var_integer_md_;
NumericMetaDataMapType var_numeric_md_;
StringMetaDataMapType con_string_md_;
IntegerMetaDataMapType con_integer_md_;
NumericMetaDataMapType con_numeric_md_;
};
} // namespace Ipopt
#endif