// 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 #include /* 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 GetIntegerSuffixValues(Index n, std::string suffix_string, Suffix_Source source) const; std::vector 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 suffix_ids_; std::vector suffix_types_; std::vector 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 options, SmartPtr jnlst, void** nerror = NULL) : ipopt_name_(ipopt_name), options_(options), jnlst_(jnlst), nerror_(nerror) {} const std::string& IpoptName() const { return ipopt_name_; } const SmartPtr& Options() const { return options_; } const SmartPtr& Jnlst() const { return jnlst_; } void** NError() { return nerror_; } private: const std::string ipopt_name_; const SmartPtr options_; const SmartPtr 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 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& options, SmartPtr 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 jnlst); /** map for storing registered AMPL options */ std::map > 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 > 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& jnlst, const SmartPtr options, char**& argv, SmartPtr suffix_handler = NULL, bool allow_discrete = false, SmartPtr 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 meta_data) { var_string_md_[tag] = meta_data; } void set_integer_metadata_for_var(std::string tag, std::vector meta_data) { var_integer_md_[tag] = meta_data; } void set_numeric_metadata_for_var(std::string tag, std::vector meta_data) { var_numeric_md_[tag] = meta_data; } void set_string_metadata_for_con(std::string tag, std::vector meta_data) { con_string_md_[tag] = meta_data; } void set_integer_metadata_for_con(std::string tag, std::vector meta_data) { con_integer_md_[tag] = meta_data; } void set_numeric_metadata_for_con(std::string tag, std::vector meta_data) { con_numeric_md_[tag] = meta_data; } //@} /** Method for returning the suffix handler */ SmartPtr 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 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 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& options, SmartPtr& 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