Example #1
0
// Function definitions.
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[])
try {

    // Check to see if we have the correct number of input arguments.
    if (nrhs < minNumInputArgs)
        throw MatlabException("Incorrect number of input arguments");

    // Get the starting point for the variables. This is specified in
    // the first input argument. The variables must be either a single
    // matrix or a cell array of matrices.
    int k = 0;  // The index of the current input argument.
    int l = 0;  // The index of the current output argument.
    ArrayOfMatrices x0(prhs[k++]);

    // Check to see if we have the correct number of output arguments.
    if ((nlhs < x0.length() + 1) || nlhs > x0.length() + 3)
        throw MatlabException("Incorrect number of output arguments");

    // Create the first output, which will store the termination
    // status of the optimization algorithm.
    MatlabScalar status(plhs[l++],0);

    // Create the second set of outputs, which will store the solution
    // obtained from running IPOPT. There should be at least as many
    // output arguments as cell entries in X.
    ArrayOfMatrices x(&plhs[l],x0);
    l += x0.length();

    // Load the lower and upper bounds on the variables as
    // ArrayOfMatrices objects. They should have the same structure as
    // the ArrayOfMatrices object "x".
    ArrayOfMatrices lb(prhs[k++]);
    ArrayOfMatrices ub(prhs[k++]);

    // Check to make sure the bounds make sense.
    if (lb != x || ub != x)
        throw MatlabException("Input arguments LB and UB must have the same \
structure as X");

    // Load the lower and upper bounds on the constraints. Each of
    // these is a Matlab array. They should have the same length.
    Matrix constraintlb(prhs[k++]);
    Matrix constraintub(prhs[k++]);
    if (constraintlb.length() != constraintub.length())
        throw MatlabException("Input arguments CONSTRAINTLB and CONSTRAINTUB \
should have the same number of elements");

    // If requested, create the output that will store the values of
    // the multipliers obtained when IPOPT converges to a stationary
    // point. This output is a MATLAB structure with three fields, two
    // for the final values of the upper and lower bound multipliers,
    // and one for the constraint multipliers.
    Multipliers* multipliers = 0;
    if (nlhs > l)
        multipliers = new Multipliers(plhs[l++],x.numelems(),
                                      constraintlb.length());

    // If requested, create the output that will store the number if
    // iterations needed to attain convergence to a stationary point.
    MatlabScalar* numiter = 0;
    if (nlhs > l)
        numiter = new MatlabScalar(plhs[l++],0);

    // Get the Matlab callback functions.
    MatlabFunctionHandle objFunc(prhs[k++]);
    MatlabFunctionHandle gradFunc(prhs[k++]);
    MatlabFunctionHandle constraintFunc(prhs[k++]);
    MatlabFunctionHandle jacobianFunc(prhs[k++]);
    MatlabFunctionHandle hessianFunc(prhs[k++]);

    // Get the auxiliary data.
    const mxArray* auxData = 0;
    const mxArray* ptr     = prhs[k++];
    if (nrhs > 10)
        if (!mxIsEmpty(ptr))
            auxData = ptr;

    // Get the iterative callback function.
    MatlabFunctionHandle* iterFunc = new MatlabFunctionHandle();
    ptr = prhs[k++];
    if (nrhs > 11)
        if (!mxIsEmpty(ptr)) {
            delete iterFunc;
            iterFunc = new MatlabFunctionHandle(ptr);
        }

    // Create a new instance of IpoptApplication.
    EJournalLevel printLevel = defaultPrintLevel;
    if (*iterFunc)
        printLevel = Ipopt::J_NONE;
    SmartPtr<Journal> console = new MatlabJournal(printLevel);
    IpoptApplication  app(false);
    app.Jnlst()->AddJournal(console);

    // If an upper/lower bound is set to infinity, then it means that
    // the variable is not upper/lower bounded.
    double lower_infty;
    double upper_infty;
    app.Options()->GetNumericValue("nlp_lower_bound_inf",lower_infty,"");
    app.Options()->GetNumericValue("nlp_upper_bound_inf",upper_infty,"");

    for (int i = 0; i < lb.length(); i++)
        convertMatlabConstraints(*lb[i],lower_infty);
    for (int i = 0; i < ub.length(); i++)
        convertMatlabConstraints(*ub[i],upper_infty);
    convertMatlabConstraints(constraintlb,lower_infty);
    convertMatlabConstraints(constraintub,upper_infty);

    // Get the initial Lagrange multipliers, if provided.
    Multipliers* initialMultipliers = 0;
    ptr = prhs[k++];
    app.Options()->SetStringValue("warm_start_init_point","no");
    if (nrhs > 12)
        if (!mxIsEmpty(ptr)) {
            initialMultipliers = new Multipliers(ptr);

            // Notify the IPOPT algorithm that we will provide our own
            // values for the initial Lagrange multipliers.
            app.Options()->SetStringValue("warm_start_init_point","yes");
        }


    // Process the remaining input arguments, which set options for
    // the IPOPT algorithm.
    bool useQuasiNewton = false;
    while (k < nrhs) {

        // Get the option label from the Matlab input argument.
        MatlabString optionLabel(prhs[k++]);

        if (k < nrhs) {

            // Get the option value from the Matlab input argument.
            MatlabOption optionValue(prhs[k++]);

            // Next, check to make sure we have a valid option.
            SmartPtr<const RegisteredOption> option
                = app.RegOptions()->GetOption(optionLabel);
            if (!IsValid(option)) {
                delete iterFunc;
                throw MatlabException("Nonexistent IPOPT option");
            }

            if (optionValue.isString()) {

                // Set the string option.
                if (!app.Options()->SetStringValue(optionLabel,optionValue)) {
                    delete iterFunc;
                    throw MatlabException("Invalid IPOPT option value");
                }

                // Special treatment is needed for the limited-memory
                // quasi-Newton approximation to the Hessian.
                if ((strcmp(optionLabel,"hessian_approximation") == 0) &&
                        (strcmp(optionValue,"limited-memory")) == 0)
                    useQuasiNewton = true;
            } else {

                // Set the numeric option.
                if (option->Type() == Ipopt::OT_Integer) {
                    if (!app.Options()->SetIntegerValue(optionLabel,optionValue)) {
                        delete iterFunc;
                        throw MatlabException("Invalid IPOPT option value");
                    }

                    // Special treatment is needed if the print level is set
                    // by the user.
                    if (strcmp(optionLabel,"print_level") == 0) {
                        int printLevel = optionValue;
                        console->SetAllPrintLevels((EJournalLevel) printLevel);
                    }
                }
                else if (!app.Options()->SetNumericValue(optionLabel,optionValue)) {
                    delete iterFunc;
                    throw MatlabException("Invalid IPOPT option value");
                }
            }
        }
    }

    // Intialize the IpoptApplication object and process the options.
    ApplicationReturnStatus exitstatus = app.Initialize();
    if (exitstatus != Ipopt::Solve_Succeeded) {
        throw MatlabException("IPOPT solver initialization failed");
    }

    // Create a new instance of the constrained, nonlinear program.
    MatlabProgram* matlabprogram
        = new MatlabProgram(x0,lb,ub,constraintlb,constraintub,objFunc,
                            gradFunc,constraintFunc,jacobianFunc,hessianFunc,
                            *iterFunc,auxData,x,useQuasiNewton,
                            initialMultipliers,multipliers);
    SmartPtr<TNLP> program = matlabprogram;

    // Ask Ipopt to solve the problem.
    exitstatus = app.OptimizeTNLP(program);
    status     = (double) exitstatus;

    // Return the number of IPOPT iterations, if requested.
    if (numiter)
        *numiter = matlabprogram->getnumiterations();

    // Get rid of the dynamically allocated memory.
    if (multipliers)        delete multipliers;
    if (numiter)            delete numiter;
    if (iterFunc)           delete iterFunc;
    if (initialMultipliers) delete initialMultipliers;

} catch (std::exception& error) {
    mexErrMsgTxt(error.what());
}
Example #2
0
// Function definitions.
// -----------------------------------------------------------------
void mexFunction (int nlhs, mxArray *plhs[], 
		  int nrhs, const mxArray *prhs[]) 
  try {

    // Check to see if we have the correct number of input and output
    // arguments.
    if (nrhs != 3)
      throw MatlabException("Incorrect number of input arguments");
    if (nlhs != 2)
      throw MatlabException("Incorrect number of output arguments");

    // Get the first input which specifies the initial iterate.
    Iterate x0(mxDuplicateArray(prhs[0]));

    // Get the second input which specifies the callback functions.
    CallbackFunctions funcs(prhs[1]);

    // Create a new IPOPT application object and process the options.
    IpoptApplication app(false);
    Options          options(x0,app,prhs[2]);

    app.RethrowNonIpoptException(false);

    // The first output argument is the value of the optimization
    // variables obtained at the solution.
    plhs[0] = mxDuplicateArray(x0);
    Iterate x(plhs[0]);

    // The second output argument stores other information, such as
    // the exit status, the value of the Lagrange multipliers upon
    // termination, the final state of the auxiliary data, and so on.
    MatlabInfo info(plhs[1]);

    // Check to see whether the user provided a callback function for
    // computing the Hessian. This is not needed in the special case
    // when a quasi-Newton approximation to the Hessian is being used.
    if (!options.ipoptOptions().useQuasiNewton() && 
	!funcs.hessianFuncIsAvailable())
      throw MatlabException("You must supply a callback function for \
computing the Hessian unless you decide to use a quasi-Newton \
approximation to the Hessian");

    // If the user tried to use her own scaling, report an error.
    if (options.ipoptOptions().userScaling())
      throw MatlabException("The user-defined scaling option does not \
work in the MATLAB interface for IPOPT");

    // If the user supplied initial values for the Lagrange
    // multipliers, activate the "warm start" option in IPOPT.
    if (options.multlb() && options.multub() &&
	(numconstraints(options)==0 || options.multconstr()) )
      app.Options()->SetStringValue("warm_start_init_point","yes");

    // Set up the IPOPT console.
    EJournalLevel printLevel = (EJournalLevel) 
      options.ipoptOptions().printLevel();
    if(printLevel > 0) { //prevents IPOPT display if we don't want it
        SmartPtr<Journal> console = new MatlabJournal(printLevel);
        app.Jnlst()->AddJournal(console);
    }

    // Intialize the IpoptApplication object and process the options.
    ApplicationReturnStatus exitstatus;
    exitstatus = app.Initialize();
    if (exitstatus != Ipopt::Solve_Succeeded)
      throw MatlabException("IPOPT solver initialization failed");

    // Create a new instance of the constrained, nonlinear program.
    MatlabProgram* matlabProgram 
      = new MatlabProgram(x0,funcs,options,x,info);
    SmartPtr<TNLP> program = matlabProgram;

    // Ask Ipopt to solve the problem.
    exitstatus = app.OptimizeTNLP(program);
    info.setExitStatus(exitstatus);

    // Collect statistics about Ipopt run
    if (IsValid(app.Statistics())) {
      SmartPtr<SolveStatistics> stats = app.Statistics();
      info.setIterationCount(stats->IterationCount());
      //Get Function Calls
      int obj, con, grad, jac, hess;
      stats->NumberOfEvaluations(obj,con,grad,jac,hess);
      info.setFuncEvals(obj, con, grad, jac, hess);      
      //CPU Time
      info.setCpuTime(stats->TotalCpuTime());
    }

    // Free the dynamically allocated memory.
    mxDestroyArray(x0);

  } catch (std::exception& error) {
    mexErrMsgTxt(error.what());
  }