AmplTNLP.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. // Copyright (C) 2004, 2009 International Business Machines and others.
  2. // All Rights Reserved.
  3. // This code is published under the Eclipse Public License.
  4. //
  5. // $Id: AmplTNLP.hpp 2242 2013-04-24 19:26:30Z stefan $
  6. //
  7. // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
  8. #ifndef __IPAMPLTNLP_HPP__
  9. #define __IPAMPLTNLP_HPP__
  10. #include "IpUtils.hpp"
  11. #include "IpTNLP.hpp"
  12. #include "IpJournalist.hpp"
  13. #include "IpOptionsList.hpp"
  14. #include <map>
  15. #include <string>
  16. /* non Ipopt forward declaration */
  17. struct ASL_pfgh;
  18. struct SufDecl;
  19. struct SufDesc;
  20. namespace Ipopt
  21. {
  22. class AmplSuffixHandler : public ReferencedObject
  23. {
  24. public:
  25. AmplSuffixHandler();
  26. ~AmplSuffixHandler();
  27. enum Suffix_Type
  28. {
  29. Index_Type,
  30. Number_Type
  31. };
  32. enum Suffix_Source
  33. {
  34. Variable_Source,
  35. Constraint_Source,
  36. Objective_Source,
  37. Problem_Source
  38. };
  39. void AddAvailableSuffix(std::string suffix_string, Suffix_Source source, Suffix_Type type)
  40. {
  41. suffix_ids_.push_back(suffix_string);
  42. suffix_types_.push_back(type);
  43. suffix_sources_.push_back(source);
  44. // suffix_values_.push_back();
  45. }
  46. const Index* GetIntegerSuffixValues(std::string suffix_string, Suffix_Source source) const;
  47. const Number* GetNumberSuffixValues(std::string suffix_string, Suffix_Source source) const;
  48. std::vector<Index> GetIntegerSuffixValues(Index n, std::string suffix_string, Suffix_Source source) const;
  49. std::vector<Number> GetNumberSuffixValues(Index n, std::string suffix_string, Suffix_Source source) const;
  50. private:
  51. /**@name Default Compiler Generated Methods
  52. * (Hidden to avoid implicit creation/calling).
  53. * These methods are not implemented and
  54. * we do not want the compiler to implement
  55. * them for us, so we declare them private
  56. * and do not define them. This ensures that
  57. * they will not be implicitly created/called. */
  58. //@{
  59. /** Default Constructor */
  60. //AmplSuffixHandler();
  61. /** Copy Constructor */
  62. AmplSuffixHandler(const AmplSuffixHandler&);
  63. /** Overloaded Equals Operator */
  64. void operator=(const AmplSuffixHandler&);
  65. //@}
  66. mutable ASL_pfgh* asl_;
  67. SufDecl* suftab_;
  68. std::vector<std::string> suffix_ids_;
  69. std::vector<Suffix_Type> suffix_types_;
  70. std::vector<Suffix_Source> suffix_sources_;
  71. /** Method called by AmplTNLP to prepare the asl for the suffixes */
  72. void PrepareAmplForSuffixes(ASL_pfgh* asl);
  73. /** Method called by AmplTNLP to retrieve the suffixes from asl */
  74. // void RetrieveSuffixesFromAmpl(ASL_pfgh* asl);
  75. friend class AmplTNLP;
  76. };
  77. /** Class for storing a number of AMPL options that should be
  78. * registered to the AMPL Solver library interface */
  79. class AmplOptionsList : public ReferencedObject
  80. {
  81. public:
  82. enum AmplOptionType {
  83. String_Option,
  84. Number_Option,
  85. Integer_Option,
  86. WS_Option, /* this is for AMPL's internal wantsol callback */
  87. HaltOnError_Option /* this is for our setting of the nerror_ member */
  88. };
  89. /** Ampl Option class, contains name, type and description for an
  90. * AMPL option */
  91. class AmplOption : public ReferencedObject
  92. {
  93. public:
  94. AmplOption(const std::string ipopt_option_name,
  95. AmplOptionType type,
  96. const std::string description);
  97. ~AmplOption()
  98. {
  99. delete [] description_;
  100. }
  101. const std::string& IpoptOptionName() const
  102. {
  103. return ipopt_option_name_;
  104. }
  105. AmplOptionType Type() const
  106. {
  107. return type_;
  108. }
  109. char* Description() const
  110. {
  111. return description_;
  112. }
  113. private:
  114. /**@name Default Compiler Generated Methods
  115. * (Hidden to avoid implicit creation/calling).
  116. * These methods are not implemented and
  117. * we do not want the compiler to implement
  118. * them for us, so we declare them private
  119. * and do not define them. This ensures that
  120. * they will not be implicitly created/called. */
  121. //@{
  122. /** Default Constructor */
  123. AmplOption();
  124. /** Copy Constructor */
  125. AmplOption(const AmplOption&);
  126. /** Overloaded Equals Operator */
  127. void operator=(const AmplOption&);
  128. //@}
  129. const std::string ipopt_option_name_;
  130. const AmplOptionType type_;
  131. char* description_;
  132. };
  133. class PrivatInfo
  134. {
  135. public:
  136. PrivatInfo(const std::string ipopt_name,
  137. SmartPtr<OptionsList> options,
  138. SmartPtr<const Journalist> jnlst,
  139. void** nerror = NULL)
  140. :
  141. ipopt_name_(ipopt_name),
  142. options_(options),
  143. jnlst_(jnlst),
  144. nerror_(nerror)
  145. {}
  146. const std::string& IpoptName() const
  147. {
  148. return ipopt_name_;
  149. }
  150. const SmartPtr<OptionsList>& Options() const
  151. {
  152. return options_;
  153. }
  154. const SmartPtr<const Journalist>& Jnlst() const
  155. {
  156. return jnlst_;
  157. }
  158. void** NError()
  159. {
  160. return nerror_;
  161. }
  162. private:
  163. const std::string ipopt_name_;
  164. const SmartPtr<OptionsList> options_;
  165. const SmartPtr<const Journalist> jnlst_;
  166. void** nerror_;
  167. };
  168. public:
  169. /** Default Constructor */
  170. AmplOptionsList()
  171. :
  172. keywds_(NULL),
  173. nkeywds_(0)
  174. {}
  175. /** Destructor */
  176. ~AmplOptionsList();
  177. /** Adding a new AMPL Option */
  178. void AddAmplOption(const std::string ampl_option_name,
  179. const std::string ipopt_option_name,
  180. AmplOptionsList::AmplOptionType type,
  181. const std::string description)
  182. {
  183. SmartPtr<AmplOption> new_option =
  184. new AmplOption(ipopt_option_name, type, description);
  185. ampl_options_map_[ampl_option_name] = ConstPtr(new_option);
  186. }
  187. /** Number of AMPL Options */
  188. Index NumberOfAmplOptions()
  189. {
  190. return (Index)ampl_options_map_.size();
  191. }
  192. /** ASL keywords list for the stored options. */
  193. void* Keywords(const SmartPtr<OptionsList>& options,
  194. SmartPtr<const Journalist> jnlst,
  195. void** nerror);
  196. private:
  197. /**@name Default Compiler Generated Methods
  198. * (Hidden to avoid implicit creation/calling).
  199. * These methods are not implemented and
  200. * we do not want the compiler to implement
  201. * them for us, so we declare them private
  202. * and do not define them. This ensures that
  203. * they will not be implicitly created/called. */
  204. //@{
  205. /** Default Constructor */
  206. //AmplOptionsList();
  207. /** Copy Constructor */
  208. AmplOptionsList(const AmplOptionsList&);
  209. /** Overloaded Equals Operator */
  210. void operator=(const AmplOptionsList&);
  211. //@}
  212. void MakeValidLatexString(std::string source, std::string& dest) const;
  213. void PrintLatex(SmartPtr<const Journalist> jnlst);
  214. /** map for storing registered AMPL options */
  215. std::map<std::string, SmartPtr<const AmplOption> > ampl_options_map_;
  216. // AW: I think it should be with const like in the following line
  217. // but with const the AIX compiler fails
  218. // std::map<const std::string, SmartPtr<const AmplOption> > ampl_options_map_;
  219. /** pointer to the keywords */
  220. void* keywds_;
  221. /** Number of entries stored in keywds_ */
  222. Index nkeywds_;
  223. };
  224. /** Ampl Interface.
  225. * Ampl Interface, implemented as a TNLP.
  226. */
  227. class AmplTNLP : public TNLP
  228. {
  229. public:
  230. /**@name Constructors/Destructors */
  231. //@{
  232. /** Constructor. */
  233. AmplTNLP(const SmartPtr<const Journalist>& jnlst,
  234. const SmartPtr<OptionsList> options,
  235. char**& argv, SmartPtr<AmplSuffixHandler>
  236. suffix_handler = NULL, bool allow_discrete = false,
  237. SmartPtr<AmplOptionsList> ampl_options_list = NULL,
  238. const char* ampl_option_string = NULL,
  239. const char* ampl_invokation_string = NULL,
  240. const char* ampl_banner_string = NULL,
  241. std::string* nl_file_content = NULL);
  242. /** Default destructor */
  243. virtual ~AmplTNLP();
  244. //@}
  245. /** Exceptions */
  246. DECLARE_STD_EXCEPTION(NONPOSITIVE_SCALING_FACTOR);
  247. /**@name methods to gather information about the NLP. These
  248. * methods are overloaded from TNLP. See TNLP for their more
  249. * detailed documentation. */
  250. //@{
  251. /** returns dimensions of the nlp. Overloaded from TNLP */
  252. virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
  253. Index& nnz_h_lag, IndexStyleEnum& index_style);
  254. /** returns names and other meta data for the variables and constraints
  255. * Overloaded from TNLP */
  256. virtual bool get_var_con_metadata(Index n,
  257. StringMetaDataMapType& var_string_md,
  258. IntegerMetaDataMapType& var_integer_md,
  259. NumericMetaDataMapType& var_numeric_md,
  260. Index m,
  261. StringMetaDataMapType& con_string_md,
  262. IntegerMetaDataMapType& con_integer_md,
  263. NumericMetaDataMapType& con_numeric_md);
  264. /** returns bounds of the nlp. Overloaded from TNLP */
  265. virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
  266. Index m, Number* g_l, Number* g_u);
  267. /** Returns the constraint linearity.
  268. * array will be alocated with length n. (default implementation
  269. * just return false and does not fill the array). */
  270. virtual bool get_constraints_linearity(Index m,
  271. LinearityType* const_types);
  272. /** provides a starting point for the nlp variables. Overloaded
  273. from TNLP */
  274. virtual bool get_starting_point(Index n, bool init_x, Number* x,
  275. bool init_z, Number* z_L, Number* z_U,
  276. Index m, bool init_lambda, Number* lambda);
  277. /** evaluates the objective value for the nlp. Overloaded from TNLP */
  278. virtual bool eval_f(Index n, const Number* x, bool new_x,
  279. Number& obj_value);
  280. /** evaluates the gradient of the objective for the
  281. nlp. Overloaded from TNLP */
  282. virtual bool eval_grad_f(Index n, const Number* x, bool new_x,
  283. Number* grad_f);
  284. /** evaluates the constraint residuals for the nlp. Overloaded from TNLP */
  285. virtual bool eval_g(Index n, const Number* x, bool new_x,
  286. Index m, Number* g);
  287. /** specifies the jacobian structure (if values is NULL) and
  288. * evaluates the jacobian values (if values is not NULL) for the
  289. * nlp. Overloaded from TNLP */
  290. virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
  291. Index m, Index nele_jac, Index* iRow,
  292. Index *jCol, Number* values);
  293. /** specifies the structure of the hessian of the lagrangian (if
  294. * values is NULL) and evaluates the values (if values is not
  295. * NULL). Overloaded from TNLP */
  296. virtual bool eval_h(Index n, const Number* x, bool new_x,
  297. Number obj_factor, Index m, const Number* lambda,
  298. bool new_lambda, Index nele_hess, Index* iRow,
  299. Index* jCol, Number* values);
  300. /** retrieve the scaling parameters for the variables, objective
  301. * function, and constraints. */
  302. virtual bool get_scaling_parameters(Number& obj_scaling,
  303. bool& use_x_scaling, Index n,
  304. Number* x_scaling,
  305. bool& use_g_scaling, Index m,
  306. Number* g_scaling);
  307. //@}
  308. /** @name Solution Methods */
  309. //@{
  310. virtual void finalize_solution(SolverReturn status,
  311. Index n, const Number* x, const Number* z_L, const Number* z_U,
  312. Index m, const Number* g, const Number* lambda,
  313. Number obj_value,
  314. const IpoptData* ip_data,
  315. IpoptCalculatedQuantities* ip_cq);
  316. //@}
  317. /** @name Method for quasi-Newton approximation information. */
  318. //@{
  319. virtual Index get_number_of_nonlinear_variables();
  320. virtual bool get_list_of_nonlinear_variables(Index num_nonlin_vars,
  321. Index* pos_nonlin_vars);
  322. //@}
  323. /**@name Ampl specific methods */
  324. //@{
  325. /** Return the ampl solver object (ASL*) */
  326. ASL_pfgh* AmplSolverObject()
  327. {
  328. return asl_;
  329. }
  330. /** Write the solution file. This is a wrapper for AMPL's
  331. * write_sol. TODO Maybe this should be at a different place, or
  332. * collect the numbers itself? */
  333. void write_solution_file(const std::string& message) const;
  334. /** ampl orders the variables like (continuous, binary, integer).
  335. * This method gives the number of binary and integer variables.
  336. * For details, see Tables 3 and 4 in "Hooking Your Solver to
  337. * AMPL"
  338. */
  339. void get_discrete_info(Index& nlvb_,
  340. Index& nlvbi_,
  341. Index& nlvc_,
  342. Index& nlvci_,
  343. Index& nlvo_,
  344. Index& nlvoi_,
  345. Index& nbv_,
  346. Index& niv_) const;
  347. //@}
  348. /** A method for setting the index of the objective function to be
  349. * considered. This method must be called after the constructor,
  350. * and before anything else is called. It can only be called
  351. * once, and if there is more than one objective function in the
  352. * AMPL model, it MUST be called. */
  353. void set_active_objective(Index obj_no);
  354. /**@name Methods to set meta data for the variables
  355. * and constraints. These values will be passed on
  356. * to the TNLP in get_var_con_meta_data
  357. */
  358. //@{
  359. void set_string_metadata_for_var(std::string tag, std::vector<std::string> meta_data)
  360. {
  361. var_string_md_[tag] = meta_data;
  362. }
  363. void set_integer_metadata_for_var(std::string tag, std::vector<Index> meta_data)
  364. {
  365. var_integer_md_[tag] = meta_data;
  366. }
  367. void set_numeric_metadata_for_var(std::string tag, std::vector<Number> meta_data)
  368. {
  369. var_numeric_md_[tag] = meta_data;
  370. }
  371. void set_string_metadata_for_con(std::string tag, std::vector<std::string> meta_data)
  372. {
  373. con_string_md_[tag] = meta_data;
  374. }
  375. void set_integer_metadata_for_con(std::string tag, std::vector<Index> meta_data)
  376. {
  377. con_integer_md_[tag] = meta_data;
  378. }
  379. void set_numeric_metadata_for_con(std::string tag, std::vector<Number> meta_data)
  380. {
  381. con_numeric_md_[tag] = meta_data;
  382. }
  383. //@}
  384. /** Method for returning the suffix handler */
  385. SmartPtr<AmplSuffixHandler> get_suffix_handler()
  386. {
  387. return suffix_handler_;
  388. }
  389. private:
  390. /**@name Default Compiler Generated Methods
  391. * (Hidden to avoid implicit creation/calling).
  392. * These methods are not implemented and
  393. * we do not want the compiler to implement
  394. * them for us, so we declare them private
  395. * and do not define them. This ensures that
  396. * they will not be implicitly created/called. */
  397. //@{
  398. /** Default Constructor */
  399. AmplTNLP();
  400. /** Copy Constructor */
  401. AmplTNLP(const AmplTNLP&);
  402. /** Overloaded Equals Operator */
  403. void operator=(const AmplTNLP&);
  404. //@}
  405. /** Journlist */
  406. SmartPtr<const Journalist> jnlst_;
  407. /** pointer to the main ASL structure */
  408. ASL_pfgh* asl_;
  409. /** Sign of the objective fn (1 for min, -1 for max) */
  410. double obj_sign_;
  411. /**@name Problem Size Data*/
  412. //@{
  413. Index nz_h_full_; // number of nonzeros in the full_x hessian
  414. /* the rest of the problem size data is available easily through the ampl variables */
  415. //@}
  416. /**@name Internal copies of data */
  417. //@{
  418. /** Solution Vectors */
  419. Number* x_sol_;
  420. Number* z_L_sol_;
  421. Number* z_U_sol_;
  422. Number* g_sol_;
  423. Number* lambda_sol_;
  424. Number obj_sol_;
  425. //@}
  426. /**@name Flags to track internal state */
  427. //@{
  428. /** true when the objective value has been calculated with the
  429. * current x, set to false in apply_new_x, and set to true in
  430. * internal_objval */
  431. bool objval_called_with_current_x_;
  432. /** true when the constraint values have been calculated with the
  433. * current x, set to false in apply_new_x, and set to true in
  434. * internal_conval */
  435. bool conval_called_with_current_x_;
  436. /** true when we have called hesset */
  437. bool hesset_called_;
  438. /** true when set_active_objective has been called */
  439. bool set_active_objective_called_;
  440. //@}
  441. /** Pointer to the Oinfo structure */
  442. void* Oinfo_ptr_;
  443. /** nerror flag passed to ampl calls - set to NULL to halt on error */
  444. void* nerror_;
  445. /** Suffix Handler */
  446. SmartPtr<AmplSuffixHandler> suffix_handler_;
  447. /** Make the objective call to ampl */
  448. bool internal_objval(const Number* x, Number& obj_val);
  449. /** Make the constraint call to ampl*/
  450. bool internal_conval(const Number* x, Index m, Number* g=NULL);
  451. /** Internal function to update the internal and ampl state if the
  452. * x value changes */
  453. bool apply_new_x(bool new_x, Index n, const Number* x);
  454. /** Method for obtaining the name of the NL file and the options
  455. * set from AMPL. Returns a pointer to a char* with the name of
  456. * the stub */
  457. char* get_options(const SmartPtr<OptionsList>& options,
  458. SmartPtr<AmplOptionsList>& ampl_options_list,
  459. const char* ampl_option_string,
  460. const char* ampl_invokation_string,
  461. const char* ampl_banner_string, char**& argv);
  462. /** returns true if the ampl nerror code is ok */
  463. bool nerror_ok(void* nerror);
  464. /** calls hesset ASL function */
  465. void call_hesset();
  466. /** meta data to pass on to TNLP */
  467. StringMetaDataMapType var_string_md_;
  468. IntegerMetaDataMapType var_integer_md_;
  469. NumericMetaDataMapType var_numeric_md_;
  470. StringMetaDataMapType con_string_md_;
  471. IntegerMetaDataMapType con_integer_md_;
  472. NumericMetaDataMapType con_numeric_md_;
  473. };
  474. } // namespace Ipopt
  475. #endif