Prev Next ipopt_nlp_get_started.cpp

@(@\newcommand{\W}[1]{ \; #1 \; } \newcommand{\R}[1]{ {\rm #1} } \newcommand{\B}[1]{ {\bf #1} } \newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} } \newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} } \newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} } \newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }@)@
Nonlinear Programming Using CppAD and Ipopt: Example and Test

Purpose
This example program demonstrates how to use the class cppad_ipopt_nlp to solve the example problem in the Ipopt documentation; i.e., the problem @[@ \begin{array}{lc} {\rm minimize \; } & x_1 * x_4 * (x_1 + x_2 + x_3) + x_3 \\ {\rm subject \; to \; } & x_1 * x_2 * x_3 * x_4 \geq 25 \\ & x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40 \\ & 1 \leq x_1, x_2, x_3, x_4 \leq 5 \end{array} @]@

Configuration Requirement
This example will be compiled and tested provided that a value for ipopt_prefix is specified on the cmake command line.

# include <cppad_ipopt_nlp.hpp>

namespace {
     using namespace cppad_ipopt;

     class FG_info : public cppad_ipopt_fg_info
     {
     private:
          bool retape_;
     public:
          // derived class part of constructor
          FG_info(bool retape_in)
          : retape_ (retape_in)
          { }
          // Evaluation of the objective f(x), and constraints g(x)
          // using an Algorithmic Differentiation (AD) class.
          ADVector eval_r(size_t k, const ADVector&  x)
          {     ADVector fg(3);

               // Fortran style indexing
               ADNumber x1 = x[0];
               ADNumber x2 = x[1];
               ADNumber x3 = x[2];
               ADNumber x4 = x[3];
               // f(x)
               fg[0] = x1 * x4 * (x1 + x2 + x3) + x3;
               // g_1 (x)
               fg[1] = x1 * x2 * x3 * x4;
               // g_2 (x)
               fg[2] = x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4;
               return fg;
          }
          bool retape(size_t k)
          {     return retape_; }
     };
}

bool ipopt_get_started(void)
{     bool ok = true;
     size_t j;


     // number of independent variables (domain dimension for f and g)
     size_t n = 4;
     // number of constraints (range dimension for g)
     size_t m = 2;
     // initial value of the independent variables
     NumberVector x_i(n);
     x_i[0] = 1.0;
     x_i[1] = 5.0;
     x_i[2] = 5.0;
     x_i[3] = 1.0;
     // lower and upper limits for x
     NumberVector x_l(n);
     NumberVector x_u(n);
     for(j = 0; j < n; j++)
     {     x_l[j] = 1.0;
          x_u[j] = 5.0;
     }
     // lower and upper limits for g
     NumberVector g_l(m);
     NumberVector g_u(m);
     g_l[0] = 25.0;     g_u[0] = 1.0e19;
     g_l[1] = 40.0;     g_u[1] = 40.0;

     size_t icase;
     for(icase = 0; icase <= 1; icase++)
     {     // Should cppad_ipopt_nlp retape the operation sequence for
          // every new x. Can test both true and false cases because
          // the operation sequence does not depend on x (for this case).
          bool retape = icase != 0;

          // object in derived class
          FG_info fg_info(retape);

          // create the Ipopt interface
          cppad_ipopt_solution solution;
          Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new cppad_ipopt_nlp(
          n, m, x_i, x_l, x_u, g_l, g_u, &fg_info, &solution
          );

          // Create an instance of the IpoptApplication
          using Ipopt::IpoptApplication;
          Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication();

          // turn off any printing
          app->Options()->SetIntegerValue("print_level", 0);
          app->Options()->SetStringValue("sb", "yes");

          // maximum number of iterations
          app->Options()->SetIntegerValue("max_iter", 10);

          // approximate accuracy in first order necessary conditions;
          // see Mathematical Programming, Volume 106, Number 1,
          // Pages 25-57, Equation (6)
          app->Options()->SetNumericValue("tol", 1e-9);

          // derivative testing
          app->Options()->
          SetStringValue("derivative_test", "second-order");
          app->Options()-> SetNumericValue(
               "point_perturbation_radius", 0.
          );

          // Initialize the IpoptApplication and process the options
          Ipopt::ApplicationReturnStatus status = app->Initialize();
          ok    &= status == Ipopt::Solve_Succeeded;

          // Run the IpoptApplication
          status = app->OptimizeTNLP(cppad_nlp);
          ok    &= status == Ipopt::Solve_Succeeded;

          /*
          Check some of the solution values
          */
          ok &= solution.status == cppad_ipopt_solution::success;
          //
          double check_x[]   = { 1.000000, 4.743000, 3.82115, 1.379408 };
          double check_z_l[] = { 1.087871, 0.,       0.,      0.       };
          double check_z_u[] = { 0.,       0.,       0.,      0.       };
          double rel_tol     = 1e-6;  // relative tolerance
          double abs_tol     = 1e-6;  // absolute tolerance
          for(j = 0; j < n; j++)
          {     ok &= CppAD::NearEqual(
               check_x[j],   solution.x[j],   rel_tol, abs_tol
               );
               ok &= CppAD::NearEqual(
               check_z_l[j], solution.z_l[j], rel_tol, abs_tol
               );
               ok &= CppAD::NearEqual(
               check_z_u[j], solution.z_u[j], rel_tol, abs_tol
               );
          }
     }

     return ok;
}

Input File: cppad_ipopt/example/get_started.cpp