1 // Copyright (C) 2004, 2006 International Business Machines and others.
2 // All Rights Reserved.
3 // This code is published under the Common Public License.
4 //
5 // $Id: IpIpoptApplication.cpp 759 2006-07-07 03:07:08Z andreasw $
6 //
7 // Authors:  Carl Laird, Andreas Waechter     IBM    2004-09-02
8 
9 #include "IpoptConfig.h"
10 #include "IpIpoptApplication.hpp"
11 #include "IpTNLPAdapter.hpp"
12 #include "IpIpoptAlg.hpp"
13 #include "IpOrigIpoptNLP.hpp"
14 #include "IpIpoptData.hpp"
15 #include "IpIpoptCalculatedQuantities.hpp"
16 #include "IpAlgBuilder.hpp"
17 #include "IpSolveStatistics.hpp"
18 #include "IpLinearSolversRegOp.hpp"
19 #include "IpInterfacesRegOp.hpp"
20 #include "IpAlgorithmRegOp.hpp"
21 
22 #ifdef HAVE_CMATH
23 # include <cmath>
24 #else
25 # ifdef HAVE_MATH_H
26 #  include <math.h>
27 # else
28 #  error "don't have header file for math"
29 # endif
30 #endif
31 
32 #include <fstream>
33 
34 namespace SimTKIpopt
35 {
36 #ifdef IP_DEBUG
37   static const Index dbg_verbosity = 0;
38 #endif
39 
IpoptApplication(bool create_console_out)40   IpoptApplication::IpoptApplication(bool create_console_out)
41       :
42       jnlst_(new Journalist()),
43       options_(new OptionsList()),
44       statistics_(NULL),
45       alg_(NULL),
46       nlp_adapter_(NULL)
47   {
48     try {
49 # ifdef IP_DEBUG
50       DebugJournalistWrapper::SetJournalist(GetRawPtr(jnlst_));
51       SmartPtr<Journal> debug_jrnl = jnlst_->AddFileJournal("Debug", "debug.out", J_ITERSUMMARY);
52       debug_jrnl->SetPrintLevel(J_DBG, J_ALL);
53 # endif
54 
55       DBG_START_METH("IpoptApplication::IpoptApplication()",
56                      dbg_verbosity);
57 
58       if (create_console_out) {
59         SmartPtr<Journal> stdout_jrnl =
60           jnlst_->AddFileJournal("console", "stdout", J_ITERSUMMARY);
61         stdout_jrnl->SetPrintLevel(J_DBG, J_NONE);
62       }
63 
64       // Register the valid options
65       reg_options_ = new RegisteredOptions();
66       RegisterAllOptions(reg_options_);
67 
68       options_->SetJournalist(jnlst_);
69       options_->SetRegisteredOptions(reg_options_);
70     }
71     catch(IpoptException& exc) {
72       exc.ReportException(*jnlst_);
73       THROW_EXCEPTION(IPOPT_APPLICATION_ERROR,
74                       "Caught unknown Ipopt exception");
75     }
76     catch(std::bad_alloc) {
77       jnlst_->Printf(J_ERROR, J_MAIN, "\nEXIT: Not enough memory.\n");
78       THROW_EXCEPTION(IPOPT_APPLICATION_ERROR,
79                       "Not enough memory");
80     }
81     catch(...) {
82       IpoptException exc("Unknown Exception caught in ipopt", "Unknown File", -1);
83       exc.ReportException(*jnlst_);
84       THROW_EXCEPTION(IPOPT_APPLICATION_ERROR,
85                       "Caught unknown exception");
86     }
87   }
88 
Initialize(std::string params_file)89   void IpoptApplication::Initialize(std::string params_file /*= "ipopt.opt"*/)
90   {
91     std::ifstream is;
92     if (params_file != "") {
93       try {
94         is.open(params_file.c_str());
95       }
96       catch(std::bad_alloc) {
97         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Not enough memory.\n");
98         exit(-1);
99       }
100       catch(...) {
101         IpoptException exc("Unknown Exception caught in ipopt", "Unknown File", -1);
102         exc.ReportException(*jnlst_);
103         exit(-1);
104       }
105     }
106     Initialize(is);
107     if (is) {
108       is.close();
109     }
110   }
111 
Initialize(std::istream & is)112   void IpoptApplication::Initialize(std::istream& is)
113   {
114     try {
115       // Get the options
116       if (is.good()) {
117         // stream exists, read the content
118         options_->ReadFromStream(*jnlst_, is);
119       }
120 
121       Index ivalue;
122       options_->GetIntegerValue("print_level", ivalue, "");
123       EJournalLevel print_level = (EJournalLevel)ivalue;
124       SmartPtr<Journal> stdout_jrnl = jnlst_->GetJournal("console");
125       if (IsValid(stdout_jrnl)) {
126         // Set printlevel for stdout
127         stdout_jrnl->SetAllPrintLevels(print_level);
128         stdout_jrnl->SetPrintLevel(J_DBG, J_NONE);
129       }
130 
131       bool option_set;
132 
133 #ifdef IP_DEBUG
134       // Set printlevel for debug
135       option_set = options_->GetIntegerValue("debug_print_level",
136                                              ivalue, "");
137       EJournalLevel debug_print_level;
138       if (option_set) {
139         debug_print_level = (EJournalLevel)ivalue;
140       }
141       else {
142         debug_print_level = print_level;
143       }
144       SmartPtr<Journal> debug_jrnl = jnlst_->GetJournal("Debug");
145       debug_jrnl->SetAllPrintLevels(debug_print_level);
146       debug_jrnl->SetPrintLevel(J_DBG, J_ALL);
147 #endif
148 
149       // Open an output file if required
150       std::string output_filename;
151       options_->GetStringValue("output_file", output_filename, "");
152       if (output_filename != "") {
153         EJournalLevel file_print_level;
154         option_set = options_->GetIntegerValue("file_print_level", ivalue, "");
155         if (option_set) {
156           file_print_level = (EJournalLevel)ivalue;
157         }
158         else {
159           file_print_level = print_level;
160         }
161         OpenOutputFile(output_filename, file_print_level);
162       }
163 
164       // output a description of all the options
165       bool print_options_documentation;
166       options_->GetBoolValue("print_options_documentation",
167                              print_options_documentation, "");
168       if (print_options_documentation) {
169         bool latex;
170         options_->GetBoolValue("print_options_latex_mode", latex, "");
171         if (latex) {
172           std::list<std::string> options_to_print;
173           // Output
174           options_to_print.push_back("print_level");
175           options_to_print.push_back("print_user_options");
176           options_to_print.push_back("print_options_documentation");
177           options_to_print.push_back("output_file");
178           options_to_print.push_back("file_print_level");
179           // Termination
180           options_to_print.push_back("tol");
181           options_to_print.push_back("max_iter");
182           options_to_print.push_back("compl_inf_tol");
183           options_to_print.push_back("dual_inf_tol");
184           options_to_print.push_back("constr_viol_tol");
185           options_to_print.push_back("acceptable_tol");
186           options_to_print.push_back("acceptable_compl_inf_tol");
187           options_to_print.push_back("acceptable_constr_viol_tol");
188           options_to_print.push_back("acceptable_dual_inf_tol");
189           options_to_print.push_back("diverging_iterates_tol");
190           options_to_print.push_back("barrier_tol_factor");
191           // NLP scaling
192           options_to_print.push_back("obj_scaling_factor");
193           options_to_print.push_back("nlp_scaling_method");
194           options_to_print.push_back("nlp_scaling_max_gradient");
195           // NLP corrections
196           options_to_print.push_back("bound_relax_factor");
197           options_to_print.push_back("honor_original_bounds");
198           options_to_print.push_back("check_derivatives_for_naninf");
199           // Barrier parameter
200           options_to_print.push_back("mu_strategy");
201           options_to_print.push_back("mu_oracle");
202           options_to_print.push_back("quality_function_max_section_steps");
203           options_to_print.push_back("fixed_mu_oracle");
204           options_to_print.push_back("mu_init");
205           options_to_print.push_back("mu_max_fact");
206           options_to_print.push_back("mu_max");
207           options_to_print.push_back("mu_min");
208           options_to_print.push_back("mu_linear_decrease_factor");
209           options_to_print.push_back("mu_superlinear_decrease_power");
210           //options_to_print.push_back("corrector_type");
211           // Initialization
212           options_to_print.push_back("bound_frac");
213           options_to_print.push_back("bound_push");
214           options_to_print.push_back("bound_mult_init_val");
215           options_to_print.push_back("constr_mult_init_max");
216           options_to_print.push_back("bound_mult_init_val");
217           // Warm start
218           options_to_print.push_back("warm_start_init_point");
219           options_to_print.push_back("warm_start_bound_push");
220           options_to_print.push_back("warm_start_bound_frac");
221           options_to_print.push_back("warm_start_mult_bound_push");
222           options_to_print.push_back("warm_start_mult_init_max");
223           // Multiplier updates
224           options_to_print.push_back("alpha_for_y");
225           options_to_print.push_back("recalc_y");
226           options_to_print.push_back("recalc_y_feas_tol");
227           // Line search
228           options_to_print.push_back("max_soc");
229           options_to_print.push_back("watchdog_shortened_iter_trigger");
230           options_to_print.push_back("watchdog_trial_iter_max");
231           // Restoration phase
232           options_to_print.push_back("expect_infeasible_problem");
233           options_to_print.push_back("expect_infeasible_problem_ctol");
234           options_to_print.push_back("start_with_resto");
235           options_to_print.push_back("soft_resto_pderror_reduction_factor");
236           options_to_print.push_back("required_infeasibility_reduction");
237           options_to_print.push_back("bound_mult_reset_threshold");
238           options_to_print.push_back("constr_mult_reset_threshold");
239           options_to_print.push_back("evaluate_orig_obj_at_resto_trial");
240           // Linear solver
241           options_to_print.push_back("linear_solver");
242           options_to_print.push_back("linear_system_scaling");
243           options_to_print.push_back("linear_scaling_on_demand");
244           options_to_print.push_back("max_refinement_steps");
245           options_to_print.push_back("min_refinement_steps");
246           // Hessian perturbation
247           options_to_print.push_back("max_hessian_perturbation");
248           options_to_print.push_back("min_hessian_perturbation");
249           options_to_print.push_back("first_hessian_perturbation");
250           options_to_print.push_back("perturb_inc_fact_first");
251           options_to_print.push_back("perturb_inc_fact");
252           options_to_print.push_back("perturb_dec_fact");
253           options_to_print.push_back("jacobian_regularization_value");
254           // Quasi-Newton
255           options_to_print.push_back("hessian_approximation");
256           options_to_print.push_back("limited_memory_max_history");
257           options_to_print.push_back("limited_memory_max_skipping");
258           // Derivative test
259           options_to_print.push_back("derivative_test");
260           options_to_print.push_back("derivative_test_perturbation");
261           options_to_print.push_back("derivative_test_tol");
262           options_to_print.push_back("derivative_test_print_all");
263 
264           // Special linear solver
265 #ifdef HAVE_MA27
266 
267           options_to_print.push_back("ma27_pivtol");
268           options_to_print.push_back("ma27_pivtolmax");
269           options_to_print.push_back("ma27_liw_init_factor");
270           options_to_print.push_back("ma27_la_init_factor");
271           options_to_print.push_back("ma27_meminc_factor");
272 #endif
273 
274 #ifdef HAVE_MA57
275 
276           options_to_print.push_back("ma57_pivtol");
277           options_to_print.push_back("ma57_pivtolmax");
278           options_to_print.push_back("ma57_pre_alloc");
279 #endif
280 
281 #ifdef HAVE_PARDISO
282 
283           options_to_print.push_back("pardiso_matching_strategy");
284           options_to_print.push_back("pardiso_out_of_core_power");
285 #endif
286 
287 #ifdef HAVE_WSMP
288 
289           options_to_print.push_back("wsmp_num_threads");
290           options_to_print.push_back("wsmp_ordering_option");
291           options_to_print.push_back("wsmp_pivtol");
292           options_to_print.push_back("wsmp_pivtolmax");
293           options_to_print.push_back("wsmp_scaling");
294 #endif
295 
296           reg_options_->OutputLatexOptionDocumentation(*jnlst_, options_to_print);
297         }
298         else {
299           std::list<std::string> categories;
300           categories.push_back("Output");
301           /*categories.push_back("Main Algorithm");*/
302           categories.push_back("Convergence");
303           categories.push_back("NLP Scaling");
304           categories.push_back("Barrier Parameter Update");
305           categories.push_back("Line Search");
306           categories.push_back("Initialization");
307           categories.push_back("Warm Start");
308           categories.push_back("Linear Solver");
309           categories.push_back("Step Calculation");
310           categories.push_back("Restoration Phase");
311           categories.push_back("NLP");
312           categories.push_back("Derivative Checker");
313           categories.push_back("Hessian Approximation");
314 #ifdef HAVE_MA27
315 
316           categories.push_back("MA27 Linear Solver");
317 #endif
318 #ifdef HAVE_MA57
319 
320           categories.push_back("MA57 Linear Solver");
321 #endif
322 #ifdef HAVE_PARDISO
323 
324           categories.push_back("Pardiso Linear Solver");
325 #endif
326 #ifdef HAVE_WSMP
327 
328           categories.push_back("WSMP Linear Solver");
329 #endif
330 
331           categories.push_back("Uncategorized");
332           //categories.push_back("Undocumented Options");
333           reg_options_->OutputOptionDocumentation(*jnlst_, categories);
334         }
335       }
336 
337     }
338     catch(OPTION_INVALID& exc) {
339       exc.ReportException(*jnlst_, J_ERROR);
340       exit(-1);
341     }
342     catch(IpoptException& exc) {
343       exc.ReportException(*jnlst_, J_ERROR);
344       exit(-1);
345     }
346     catch(std::bad_alloc) {
347       jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Not enough memory.\n");
348       exit(-1);
349     }
350   }
351 
~IpoptApplication()352   IpoptApplication::~IpoptApplication()
353   {
354     DBG_START_METH("IpoptApplication::~IpoptApplication()",
355                    dbg_verbosity);
356   }
357 
RegisterOptions(SmartPtr<RegisteredOptions> roptions)358   void IpoptApplication::RegisterOptions(SmartPtr<RegisteredOptions> roptions)
359   {
360     roptions->SetRegisteringCategory("Output");
361     roptions->AddBoundedIntegerOption(
362       "print_level",
363       "Output verbosity level.",
364       0, J_LAST_LEVEL-1, J_ITERSUMMARY,
365       "Sets the default verbosity level for console output. The "
366       "larger this value the more detailed is the output.");
367 
368     roptions->AddStringOption1(
369       "output_file",
370       "File name of desired output file (leave unset for no file output).",
371       "",
372       "*", "Any acceptable standard file name",
373       "NOTE: This option only works when read from the ipopt.opt options file! "
374       "An output file with this name will be written (leave unset for no "
375       "file output).  The verbosity level is by default set to \"print_level\", "
376       "but can be overridden with \"file_print_level\".  The file name is "
377       "changed to use only small letters.");
378     roptions->AddBoundedIntegerOption(
379       "file_print_level",
380       "Verbosity level for output file.",
381       0, J_LAST_LEVEL-1, J_ITERSUMMARY,
382       "NOTE: This option only works when read from the ipopt.opt options file! "
383       "Determines the verbosity level for the file specified by "
384       "\"output_file\".  By default it is the same as \"print_level\".");
385     roptions->AddStringOption2(
386       "print_user_options",
387       "Print all options set by the user.",
388       "no",
389       "no", "don't print options",
390       "yes", "print options",
391       "If selected, the algorithm will print the list of all options set by "
392       "the user including their values and whether they have been used.");
393     roptions->AddStringOption2(
394       "print_options_documentation",
395       "Switch to print all algorithmic options.",
396       "no",
397       "no", "don't print list",
398       "yes", "print list",
399       "If selected, the algorithm will print the list of all available "
400       "algorithmic options with some documentation before solving the "
401       "optimization problem.");
402 
403 #ifdef IP_DEBUG
404 
405     roptions->AddBoundedIntegerOption(
406       "debug_print_level",
407       "Verbosity level for debug file.",
408       0, J_LAST_LEVEL-1, J_ITERSUMMARY,
409       "This Ipopt library has been compiled in debug mode, and a file "
410       "\"debug.out\" is produced for every run.  This option determines "
411       "the verbosity level for this file.  By default it is the same as "
412       "\"print_level\".");
413 
414 #endif
415 
416     roptions->AddStringOption2(
417       "print_timing_statistics",
418       "Switch to print timing statistics.",
419       "no",
420       "no", "don't print statistics",
421       "yes", "print all timing statistics",
422       "If selected, the program will print the CPU usage (user time) for "
423       "selected tasks.");
424 
425     roptions->SetRegisteringCategory("Undocumented");
426     roptions->AddStringOption2(
427       "print_options_latex_mode",
428       "Undocumented", "no",
429       "no", "Undocumented",
430       "yes", "Undocumented",
431       "Undocumented"
432     );
433   }
434 
435   ApplicationReturnStatus
OptimizeTNLP(const SmartPtr<TNLP> & tnlp)436   IpoptApplication::OptimizeTNLP(const SmartPtr<TNLP>& tnlp)
437   {
438     nlp_adapter_ = new TNLPAdapter(GetRawPtr(tnlp), ConstPtr(jnlst_));
439 
440     return OptimizeNLP(nlp_adapter_);
441   }
442 
443   ApplicationReturnStatus
ReOptimizeTNLP(const SmartPtr<TNLP> & tnlp)444   IpoptApplication::ReOptimizeTNLP(const SmartPtr<TNLP>& tnlp)
445   {
446     ASSERT_EXCEPTION(IsValid(nlp_adapter_), INVALID_WARMSTART,
447                      "ReOptimizeTNLP called before OptimizeTNLP.");
448     TNLPAdapter* adapter =
449       dynamic_cast<TNLPAdapter*> (GetRawPtr(nlp_adapter_));
450     DBG_ASSERT(adapter);
451     ASSERT_EXCEPTION(adapter->tnlp()==tnlp, INVALID_WARMSTART,
452                      "ReOptimizeTNLP called for different TNLP.")
453 
454     return ReOptimizeNLP(nlp_adapter_);
455   }
456 
457   ApplicationReturnStatus
OptimizeNLP(const SmartPtr<NLP> & nlp,SmartPtr<AlgorithmBuilder> alg_builder)458   IpoptApplication::OptimizeNLP(const SmartPtr<NLP>& nlp, SmartPtr<AlgorithmBuilder> alg_builder)
459   {
460     ApplicationReturnStatus retValue = Internal_Error;
461 
462     // Prepare internal data structures of the algorithm
463     try {
464 
465       if (IsNull(alg_builder)) {
466         alg_builder = new AlgorithmBuilder();
467       }
468 
469       alg_builder->BuildIpoptObjects(*jnlst_, *options_, "", nlp,
470                                      ip_nlp_, ip_data_, ip_cq_);
471 
472       alg_ = GetRawPtr(alg_builder->BuildBasicAlgorithm(*jnlst_, *options_, ""));
473 
474       // finally call the optimization
475       retValue = call_optimize();
476     }
477     catch(OPTION_INVALID& exc) {
478       exc.ReportException(*jnlst_, J_ERROR);
479       jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Invalid option encountered.\n");
480       retValue = Invalid_Option;
481     }
482     catch(IpoptException& exc) {
483       exc.ReportException(*jnlst_, J_ERROR);
484       jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Some uncaught Ipopt exception encountered.\n");
485       retValue = Unrecoverable_Exception;
486     }
487     catch(std::bad_alloc) {
488       retValue = Insufficient_Memory;
489       jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Not enough memory.\n");
490     }
491 
492     jnlst_->FlushBuffer();
493 
494     return retValue;
495   }
496 
497   ApplicationReturnStatus
ReOptimizeNLP(const SmartPtr<NLP> & nlp)498   IpoptApplication::ReOptimizeNLP(const SmartPtr<NLP>& nlp)
499   {
500     ASSERT_EXCEPTION(IsValid(alg_), INVALID_WARMSTART,
501                      "ReOptimizeNLP called before OptimizeNLP.");
502     OrigIpoptNLP* orig_nlp =
503       dynamic_cast<OrigIpoptNLP*> (GetRawPtr(ip_nlp_));
504     DBG_ASSERT(orig_nlp);
505     ASSERT_EXCEPTION(orig_nlp->nlp()==nlp, INVALID_WARMSTART,
506                      "ReOptimizeTNLP called for different NLP.")
507 
508     return call_optimize();
509   }
510 
511 
call_optimize()512   ApplicationReturnStatus IpoptApplication::call_optimize()
513   {
514     // Reset the print-level for the screen output
515     Index ivalue;
516     options_->GetIntegerValue("print_level", ivalue, "");
517     EJournalLevel print_level = (EJournalLevel)ivalue;
518     SmartPtr<Journal> stdout_jrnl = jnlst_->GetJournal("console");
519     if (IsValid(stdout_jrnl)) {
520       // Set printlevel for stdout
521       stdout_jrnl->SetAllPrintLevels(print_level);
522       stdout_jrnl->SetPrintLevel(J_DBG, J_NONE);
523     }
524 
525     statistics_ = NULL; /* delete old statistics */
526     // Reset Timing statistics
527     ip_data_->TimingStats().ResetTimes();
528 
529     ApplicationReturnStatus retValue = Internal_Error;
530     try {
531       // Get the pointers to the real objects (need to do it that
532       // awkwardly since otherwise we would have to include so many
533       // things in IpoptApplication, which a user would have to
534       // include, too (SmartPtr doesn't work otherwise on AIX)
535       IpoptAlgorithm* p2alg = dynamic_cast<IpoptAlgorithm*> (GetRawPtr(alg_));
536       IpoptData* p2ip_data = dynamic_cast<IpoptData*> (GetRawPtr(ip_data_));
537       OrigIpoptNLP* p2ip_nlp = dynamic_cast<OrigIpoptNLP*> (GetRawPtr(ip_nlp_));
538       IpoptCalculatedQuantities* p2ip_cq = dynamic_cast<IpoptCalculatedQuantities*> (GetRawPtr(ip_cq_));
539       // Set up the algorithm
540       p2alg->Initialize(*jnlst_, *p2ip_nlp, *p2ip_data, *p2ip_cq,
541                         *options_, "");
542 
543       // Process the options used below
544       bool print_timing_statistics;
545       options_->GetBoolValue("print_timing_statistics",
546                              print_timing_statistics, "");
547 
548       // If selected, print the user options
549       bool print_user_options;
550       options_->GetBoolValue("print_user_options", print_user_options, "");
551       if (print_user_options) {
552         std::string liststr;
553         options_->PrintUserOptions(liststr);
554         jnlst_->Printf(J_ERROR, J_MAIN, "\nList of user-set options:\n\n%s", liststr.c_str());
555       }
556 
557       if( jnlst_->ProduceOutput(J_DETAILED, J_MAIN) ) {
558         // Print out the options (including the number of times they were used
559         std::string liststr;
560         options_->PrintList(liststr);
561 // TODO UNCOMMENT WHEN DONE TESTING
562 /*
563        vatest( stdout, "\nList of user-set options:\n\n%s", liststr.c_str());
564        void vatest( FILE *, const char *, ...  );
565 
566 printf("strlen user-set options= %d\n",strlen(liststr.c_str()) );
567     printf("\nList of user-set options:\n\n%s", liststr.c_str());
568 */
569         jnlst_->Printf(J_DETAILED, J_MAIN, "\nList of options:\n\n%s", liststr.c_str());
570       }
571 
572 
573       // Run the algorithm
574       SolverReturn status = p2alg->Optimize();
575 
576       // Since all the output below doesn't make any sense in this
577       // case, we rethrow the TOO_FEW_DOF exception here
578       ASSERT_EXCEPTION(status != TOO_FEW_DEGREES_OF_FREEDOM, TOO_FEW_DOF,
579                        "Too few degrees of freedom (rethrown)!");
580 
581       jnlst_->Printf(J_SUMMARY, J_SOLUTION,
582                      "\nNumber of Iterations....: %d\n",
583                      p2ip_data->iter_count());
584 
585       if (status!=INVALID_NUMBER_DETECTED) {
586         jnlst_->Printf(J_SUMMARY, J_SOLUTION,
587                        "\n                                   (scaled)                 (unscaled)\n");
588         jnlst_->Printf(J_SUMMARY, J_SOLUTION,
589                        "Objective...............: %24.16e  %24.16e\n",
590                        p2ip_cq->curr_f(),
591                        p2ip_cq->unscaled_curr_f());
592         jnlst_->Printf(J_SUMMARY, J_SOLUTION,
593                        "Dual infeasibility......: %24.16e  %24.16e\n",
594                        p2ip_cq->curr_dual_infeasibility(NORM_MAX),
595                        p2ip_cq->unscaled_curr_dual_infeasibility(NORM_MAX));
596         jnlst_->Printf(J_SUMMARY, J_SOLUTION,
597                        "Constraint violation....: %24.16e  %24.16e\n",
598                        p2ip_cq->curr_nlp_constraint_violation(NORM_MAX),
599                        p2ip_cq->unscaled_curr_nlp_constraint_violation(NORM_MAX));
600         jnlst_->Printf(J_SUMMARY, J_SOLUTION,
601                        "Complementarity.........: %24.16e  %24.16e\n",
602                        p2ip_cq->curr_complementarity(0., NORM_MAX),
603                        p2ip_cq->unscaled_curr_complementarity(0., NORM_MAX));
604         jnlst_->Printf(J_SUMMARY, J_SOLUTION,
605                        "Overall NLP error.......: %24.16e  %24.16e\n\n",
606                        p2ip_cq->curr_nlp_error(),
607                        p2ip_cq->unscaled_curr_nlp_error());
608       }
609 
610       p2ip_data->curr()->x()->Print(*jnlst_, J_VECTOR, J_SOLUTION, "x");
611       p2ip_data->curr()->y_c()->Print(*jnlst_, J_VECTOR, J_SOLUTION, "y_c");
612       p2ip_data->curr()->y_d()->Print(*jnlst_, J_VECTOR, J_SOLUTION, "y_d");
613       p2ip_data->curr()->z_L()->Print(*jnlst_, J_VECTOR, J_SOLUTION, "z_L");
614       p2ip_data->curr()->z_U()->Print(*jnlst_, J_VECTOR, J_SOLUTION, "z_U");
615       p2ip_data->curr()->v_L()->Print(*jnlst_, J_VECTOR, J_SOLUTION, "v_L");
616       p2ip_data->curr()->v_U()->Print(*jnlst_, J_VECTOR, J_SOLUTION, "v_U");
617 
618       if (status==LOCAL_INFEASIBILITY) {
619         p2ip_cq->curr_c()->Print(*jnlst_, J_VECTOR, J_SOLUTION, "curr_c");
620         p2ip_cq->curr_d_minus_s()->Print(*jnlst_, J_VECTOR, J_SOLUTION,
621                                          "curr_d_minus_s");
622       }
623 
624       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
625                      "\nNumber of objective function evaluations             = %d\n",
626                      p2ip_nlp->f_evals());
627       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
628                      "Number of objective gradient evaluations             = %d\n",
629                      p2ip_nlp->grad_f_evals());
630       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
631                      "Number of equality constraint evaluations            = %d\n",
632                      p2ip_nlp->c_evals());
633       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
634                      "Number of inequality constraint evaluations          = %d\n",
635                      p2ip_nlp->d_evals());
636       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
637                      "Number of equality constraint Jacobian evaluations   = %d\n",
638                      p2ip_nlp->jac_c_evals());
639       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
640                      "Number of inequality constraint Jacobian evaluations = %d\n",
641                      p2ip_nlp->jac_d_evals());
642       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
643                      "Number of Lagrangian Hessian evaluations             = %d\n",
644                      p2ip_nlp->h_evals());
645       Number time_overall_alg = p2ip_data->TimingStats().OverallAlgorithm().TotalTime();
646       Number time_funcs = p2ip_nlp->TotalFunctionEvaluationCPUTime();
647       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
648                      "Total CPU secs in IPOPT (w/o function evaluations)   = %10.3f\n",
649                      time_overall_alg-time_funcs);
650       jnlst_->Printf(J_SUMMARY, J_STATISTICS,
651                      "Total CPU secs in NLP function evaluations           = %10.3f\n",
652                      time_funcs);
653 
654       // Write timing statistics information
655       if (print_timing_statistics) {
656         jnlst_->Printf(J_SUMMARY, J_TIMING_STATISTICS,
657                        "\n\nTiming Statistics:\n\n");
658         p2ip_data->TimingStats().PrintAllTimingStatistics(*jnlst_, J_SUMMARY,
659             J_TIMING_STATISTICS);
660         p2ip_nlp->PrintTimingStatistics(*jnlst_, J_SUMMARY,
661                                         J_TIMING_STATISTICS);
662       }
663 
664       // Write EXIT message
665       if (status == SUCCESS) {
666         retValue = Solve_Succeeded;
667         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Optimal Solution Found.\n");
668       }
669       else if (status == MAXITER_EXCEEDED) {
670         retValue = Maximum_Iterations_Exceeded;
671         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Maximum Number of Iterations Exceeded.\n");
672       }
673       else if (status == STOP_AT_TINY_STEP) {
674         retValue = Search_Direction_Becomes_Too_Small;
675         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Search Direction is becoming Too Small.\n");
676       }
677       else if (status == STOP_AT_ACCEPTABLE_POINT) {
678         retValue = Solved_To_Acceptable_Level;
679         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Solved To Acceptable Level.\n");
680       }
681       else if (status == DIVERGING_ITERATES) {
682         retValue = Diverging_Iterates;
683         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Iterates divering; problem might be unbounded.\n");
684       }
685       else if (status == RESTORATION_FAILURE) {
686         retValue = Restoration_Failed;
687         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Restoration Failed!\n");
688       }
689       else if (status == ERROR_IN_STEP_COMPUTATION) {
690         retValue = Error_In_Step_Computation;
691         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Error in step computation (regularization becomes too large?)!\n");
692       }
693       else if (status == LOCAL_INFEASIBILITY) {
694         retValue = Infeasible_Problem_Detected;
695         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Converged to a point of local infeasibility. Problem may be infeasible.\n");
696       }
697       else if (status == USER_REQUESTED_STOP) {
698         retValue = User_Requested_Stop;
699         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Stopping optimization at current point as requested by user.\n");
700       }
701       else if (status == INVALID_NUMBER_DETECTED) {
702         retValue = Invalid_Number_Detected;
703         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Invalid number in NLP function or derivative detected.\n");
704       }
705       else {
706         retValue = Internal_Error;
707         jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: INTERNAL ERROR: Unknown SolverReturn value - Notify IPOPT Authors.\n");
708         return retValue;
709       }
710       p2ip_nlp->FinalizeSolution(status,
711                                  *p2ip_data->curr()->x(),
712                                  *p2ip_data->curr()->z_L(),
713                                  *p2ip_data->curr()->z_U(),
714                                  *p2ip_cq->curr_c(), *p2ip_cq->curr_d(),
715                                  *p2ip_data->curr()->y_c(),
716                                  *p2ip_data->curr()->y_d(),
717                                  p2ip_cq->curr_f());
718 
719       if (status!=INVALID_NUMBER_DETECTED) {
720         // Create a SolveStatistics object
721         statistics_ = new SolveStatistics(p2ip_nlp, p2ip_data, p2ip_cq);
722       }
723     }
724     catch(TOO_FEW_DOF& exc) {
725       exc.ReportException(*jnlst_, J_MOREDETAILED);
726       jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Problem has too few degrees of freedom.\n");
727       retValue = Not_Enough_Degrees_Of_Freedom;
728     }
729     catch(OPTION_INVALID& exc) {
730       exc.ReportException(*jnlst_, J_MOREDETAILED);
731       jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Invalid option encountered.\n");
732       retValue = Invalid_Option;
733     }
734     catch(IpoptException& exc) {
735       exc.ReportException(*jnlst_, J_ERROR);
736       jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Some uncaught Ipopt exception encountered.\n");
737       retValue = Unrecoverable_Exception;
738     }
739     catch(std::bad_alloc) {
740       retValue = Insufficient_Memory;
741       jnlst_->Printf(J_SUMMARY, J_MAIN, "\nEXIT: Not enough memory.\n");
742     }
743 
744     jnlst_->FlushBuffer();
745 
746     return retValue;
747   }
vatest(FILE * fp,const char * format,...)748 static void vatest( FILE *fp, const char *format, ... ) {
749    va_list ap;
750    va_start( ap, format );
751    vfprintf( fp, format, ap );
752    va_end(ap);
753 }
754 
OpenOutputFile(std::string file_name,EJournalLevel print_level)755   bool IpoptApplication::OpenOutputFile(std::string file_name,
756                                         EJournalLevel print_level)
757   {
758     SmartPtr<Journal> file_jrnl = jnlst_->GetJournal("OutputFile:"+file_name);
759 
760     if (IsNull(file_jrnl)) {
761       file_jrnl = jnlst_->AddFileJournal("OutputFile:"+file_name,
762                                          file_name.c_str(),
763                                          print_level);
764     }
765 
766     file_jrnl->SetPrintLevel(J_DBG, J_NONE);
767 
768     return true;
769   }
770 
RegisterAllOptions(const SmartPtr<RegisteredOptions> & roptions)771   void IpoptApplication::RegisterAllOptions(const SmartPtr<RegisteredOptions>& roptions)
772   {
773     RegisterOptions_Interfaces(roptions);
774     RegisterOptions_Algorithm(roptions);
775     RegisterOptions_LinearSolvers(roptions);
776   }
777 
Statistics()778   SmartPtr<SolveStatistics> IpoptApplication::Statistics()
779   {
780     return statistics_;
781   }
782 
783 } // namespace Ipopt
784