1 // Copyright (C) 2008 Peter Carbonetto. All Rights Reserved.
2 // This code is published under the Eclipse Public License.
3 //
4 // Author: Peter Carbonetto
5 // Dept. of Computer Science
6 // University of British Columbia
7 // September 18, 2008
8
9 #include "mex.h"
10 #include "iterate.hpp"
11 #include "options.hpp"
12 #include "matlabexception.hpp"
13 #include "callbackfunctions.hpp"
14 #include "matlabinfo.hpp"
15 #include "matlabjournal.hpp"
16 #include "matlabprogram.hpp"
17 #include "IpRegOptions.hpp"
18 #include "IpJournalist.hpp"
19 #include "IpIpoptApplication.hpp"
20 #include "IpSolveStatistics.hpp"
21
22 using Ipopt::IsValid;
23 using Ipopt::RegisteredOption;
24 using Ipopt::EJournalLevel;
25 using Ipopt::Journal;
26 using Ipopt::MatlabJournal;
27 using Ipopt::IpoptApplication;
28 using Ipopt::SmartPtr;
29 using Ipopt::TNLP;
30 using Ipopt::ApplicationReturnStatus;
31 using Ipopt::SolveStatistics;
32
33 extern void _main();
34
35 // Function definitions.
36 // -----------------------------------------------------------------
mexFunction(int nlhs,mxArray * plhs[],int nrhs,const mxArray * prhs[])37 void mexFunction (int nlhs, mxArray *plhs[],
38 int nrhs, const mxArray *prhs[])
39 try {
40
41 // Check to see if we have the correct number of input and output
42 // arguments.
43 if (nrhs != 3)
44 throw MatlabException("Incorrect number of input arguments");
45 if (nlhs != 2)
46 throw MatlabException("Incorrect number of output arguments");
47
48 // Get the first input which specifies the initial iterate.
49 Iterate x0(mxDuplicateArray(prhs[0]));
50
51 // Get the second input which specifies the callback functions.
52 CallbackFunctions funcs(prhs[1]);
53
54 // Create a new IPOPT application object and process the options.
55 IpoptApplication app(false);
56 Options options(x0,app,prhs[2]);
57
58 app.RethrowNonIpoptException(false);
59
60 // The first output argument is the value of the optimization
61 // variables obtained at the solution.
62 plhs[0] = mxDuplicateArray(x0);
63 Iterate x(plhs[0]);
64
65 // The second output argument stores other information, such as
66 // the exit status, the value of the Lagrange multipliers upon
67 // termination, the final state of the auxiliary data, and so on.
68 MatlabInfo info(plhs[1]);
69
70 // Check to see whether the user provided a callback function for
71 // computing the Hessian. This is not needed in the special case
72 // when a quasi-Newton approximation to the Hessian is being used.
73 if (!options.ipoptOptions().useQuasiNewton() &&
74 !funcs.hessianFuncIsAvailable())
75 throw MatlabException("You must supply a callback function for \
76 computing the Hessian unless you decide to use a quasi-Newton \
77 approximation to the Hessian");
78
79 // If the user tried to use her own scaling, report an error.
80 if (options.ipoptOptions().userScaling())
81 throw MatlabException("The user-defined scaling option does not \
82 work in the MATLAB interface for IPOPT");
83
84 // If the user supplied initial values for the Lagrange
85 // multipliers, activate the "warm start" option in IPOPT.
86 if (options.multlb() && options.multub() &&
87 (numconstraints(options)==0 || options.multconstr()) )
88 app.Options()->SetStringValue("warm_start_init_point","yes");
89
90 // Set up the IPOPT console.
91 EJournalLevel printLevel = (EJournalLevel)
92 options.ipoptOptions().printLevel();
93 if(printLevel > 0) { //prevents IPOPT display if we don't want it
94 SmartPtr<Journal> console = new MatlabJournal(printLevel);
95 app.Jnlst()->AddJournal(console);
96 }
97
98 // Intialize the IpoptApplication object and process the options.
99 ApplicationReturnStatus exitstatus;
100 exitstatus = app.Initialize();
101 if (exitstatus != Ipopt::Solve_Succeeded)
102 throw MatlabException("IPOPT solver initialization failed");
103
104 // Create a new instance of the constrained, nonlinear program.
105 MatlabProgram* matlabProgram
106 = new MatlabProgram(x0,funcs,options,x,info);
107 SmartPtr<TNLP> program = matlabProgram;
108
109 // Ask Ipopt to solve the problem.
110 exitstatus = app.OptimizeTNLP(program);
111 info.setExitStatus(exitstatus);
112
113 // Collect statistics about Ipopt run
114 if (IsValid(app.Statistics())) {
115 SmartPtr<SolveStatistics> stats = app.Statistics();
116 info.setIterationCount(stats->IterationCount());
117 //Get Function Calls
118 int obj, con, grad, jac, hess;
119 stats->NumberOfEvaluations(obj,con,grad,jac,hess);
120 info.setFuncEvals(obj, con, grad, jac, hess);
121 //CPU Time
122 info.setCpuTime(stats->TotalCpuTime());
123 }
124
125 // Free the dynamically allocated memory.
126 mxDestroyArray(x0);
127
128 } catch (std::exception& error) {
129 mexErrMsgTxt(error.what());
130 }
131