Prev Next

Nonlinear Programming Using Ipopt and CppAD

Syntax
# include "ipopt_cppad_nlp.hpp"
# ipopt_cppad_solution solution;
ipopt_cppad_nlp cppad_nlp(
     
nmx_ix_lx_ug_lg_ufg_info, &solution
)


Purpose
The class ipopt_cppad_nlp is used to solve nonlinear programming problems of the form  \[
\begin{array}{rll}
{\rm minimize}      & f(x) 
\\
{\rm subject \; to} & g^l \leq g(x) \leq g^u
\\
                    & x^l  \leq x   \leq x^u
\end{array}
\] 
This is done using Ipopt optimizer and CppAD Algorithmic Differentiation package.

Warning
This is only an example use of CppAD. It is expected that this class will be improved and that its user interface may change in ways that are not backward compatible.

fg(x)
The function  fg : \R^n \rightarrow \R^{m+1} is defined by  \[
\begin{array}{rcl}
     fg_0 (x)     & = & f(x)         \\
     fg_1 (x)     & = & g_0 (x)      \\
                  & \vdots &         \\
     fg_m (x)     & = & g_{m-1} (x)
     \end{array}
\] 


Index Vector
We define an index vector as a vector of non-negative integers for which none of the values are equal; i.e., it is both a vector and a set. If  I is an index vector  |I| is used to denote the number of elements in  I and  \| I \| is used to denote the value of the maximum element in  I .

Projection
Given an index vector  J and a positive integer  n where  n > \| J \| , we use  J \otimes n for the mapping  J \otimes n : \R^n \rightarrow \R^{|J|} defined by  \[
     J \otimes n (x)_j = x_{J(j)}
\] 
for  j = 0 , \ldots |J| - 1 .

Injection
Given an index vector  I and a positive integer  m where  m > \| I \| , we use  m \otimes I for the mapping  m \otimes I: \R^{|I|} \rightarrow \R^m defined by  \[
m \otimes I (y)_i = \left\{ \begin{array}{ll}
y_k & {\rm if} \; i = I(k) \; {\rm for \; some} \; 
     k \in \{ 0 , \cdots, |I|-1 \} 
\\
0   & {\rm otherwise}
\end{array} \right.
\] 


Representation
In many applications, each of the component functions of  fg(x) only depend on a few of the components of  x . In this case, expressing  fg(x) in terms of simpler functions with fewer arguments can greatly reduce the amount of work required to compute its derivatives.

We use the functions  r_k : \R^{q(k)} \rightarrow \R^{p(k)} for  k = 0 , \ldots , K to express our representation of  fg(x) in terms of simpler functions as follows  \[
fg(x) = \sum_{k=0}^{K-1} \; \sum_{\ell=0}^{L(k) - 1} 
(m+1) \otimes I_{k,\ell} \; 
     \{  \; r_k \; [ \; J_{k,\ell} \otimes n \; (x) \; ] \} 
\] 
where for  k = 0 , \ldots , K - 1 , and  \ell = 0 , \ldots , L(k) ,  I_{k,\ell} , and  J_{k,\ell} are index vectors with  | J_{k,\ell} | = q(k) and  | I_{k,\ell} | = p(k) .

Simple Representation
In the simple representation,  r_0 (x) = fg(x) ,  K = 1 ,  q(0) = n ,  p(0) = m ,  L(0) = 1 ,  I_{0,0} = (0 , \ldots , m) , and  J_{0,0} = (0 , \ldots , n-1) .

SizeVector
The type SizeVector is defined by the ipopt_cppad_nlp.hpp include file to be a SimpleVector class with elements of type size_t.

NumberVector
The type NumberVector is defined by the ipopt_cppad_nlp.hpp include file to be a SimpleVector class with elements of type Ipopt::Number.

ADNumber
The type ADNumber is defined by the ipopt_cppad_nlp.hpp include file to be a an AD type that can be used to compute derivatives.

ADVector
The type ADVector is defined by the ipopt_cppad_nlp.hpp include file to be a SimpleVector class with elements of type ADNumber.

n
The argument n has prototype
     size_t 
n
It specifies the dimension of the argument space; i.e.,  x \in \R^n .

m
The argument m has prototype
     size_t 
m
It specifies the dimension of the range space for  g ; i.e.,  g : \R^n \rightarrow \R^m .

x_i
The argument x_i has prototype
     const NumberVector& 
x_i
and its size is equal to  n . It specifies the initial point where Ipopt starts the optimization process.

x_l
The argument x_l has prototype
     const NumberVector& 
x_l
and its size is equal to  n . It specifies the lower limits for the argument in the optimization problem; i.e.,  x^l .

x_u
The argument x_u has prototype
     const NumberVector& 
x_u
and its size is equal to  n . It specifies the upper limits for the argument in the optimization problem; i.e.,  x^u .

g_l
The argument g_l has prototype
     const NumberVector& 
g_l
and its size is equal to  m . It specifies the lower limits for the constraints in the optimization problem; i.e.,  g^l .

g_u
The argument g_u has prototype
     const NumberVector& 
g_u
and its size is equal to  n . It specifies the upper limits for the constraints in the optimization problem; i.e.,  g^u .

fg_info
The argument fg_info has prototype
     ipopt_cppad_fg_info* 
fg_info
where the object *fg_info is a member of a class (referred to as FG_info ) that is derived from the base class ipopt_cppad_fg_info. Certain virtual member functions of ipopt_cppad_fg_info are used to compute the value of  fg(x) . The specifications for these member functions are given below:

fg_info->number_functions
This member function has prototype
     virtual size_t ipopt_cppad_fg_info::number_functions(void)
If K has type size_t, the syntax
     
K = fg_info->number_functions()
sets K to the number of functions used in the representation of  fg(x) ; i.e.,  K in the representation above.

The ipopt_cppad_fg_info implementation of this function corresponds to the simple representation mentioned above; i.e. K = 1 .

fg_info->eval_r
This member function has the prototype
virtual ADVector ipopt_cppad_fg_info::eval_r(size_t 
k, const ADVector& u) = 0;
This prototype is pure virtual and hence it must be defined in the derived class FG_info .

This function computes the value of  r_k (u) used in the representation for  fg(x) . If k is in  \{0 , \ldots , K-1 \} has type size_t, u is an ADVector of size q(k) and r is an ADVector of size p(k) the syntax
     
r = fg_info->eval_r(ku)
set r to the vector  r_k (u) .

fg_info->retape
This member function has the prototype
     virtual bool ipopt_cppad_fg_info::retape(size_t 
k)
If k is in  \{0 , \ldots , K-1 \} has type size_t, and retape has type bool, the syntax
        
retape = fg_info->retape(k)
sets retape to true or false. If retape is true, ipopt_cppad_nlp will retape the operation sequence corresponding to  r_k (u) for every value of u . An ipopt_cppad_nlp object should use much less memory and run faster if retape is false. You can test both the true and false cases to make sure the operation sequence does not depend on u .

The ipopt_cppad_fg_info implementation of this function sets retape to true.

fg_info->domain_size
This member function has prototype
     virtual size_t ipopt_cppad_fg_info::domain_size(size_t 
k)
If k is in  \{0 , \ldots , K-1 \} has type size_t, and q has type size_t, the syntax
     
q = fg_info->domain_size(k)
sets q to the dimension of the domain space for  r_k (u) ; i.e.,  q(k) in the representation above.

The ipopt_cppad_h_base implementation of this function corresponds to the simple representation mentioned above; i.e.,  q = n .

fg_info->range_size
This member function has prototype
     virtual size_t ipopt_cppad_fg_info::range_size(size_t 
k)
If k is in  \{0 , \ldots , K-1 \} has type size_t, and p has type size_t, the syntax
     
p = fg_info->range_size(k)
sets p to the dimension of the range space for  r_k (u) ; i.e.,  p(k) in the representation above.

The ipopt_cppad_h_base implementation of this function corresponds to the simple representation mentioned above; i.e.,  p = m+1 .

fg_info->number_terms
This member function has prototype
     virtual size_t ipopt_cppad_fg_info::number_terms(size_t 
k)
If k is in  \{0 , \ldots , K-1 \} has type size_t, and L has type size_t, the syntax
     
L = fg_info->range_sum(k)
sets L to the number of terms in representation for this value of k ; i.e.,  L(k) in the representation above.

The ipopt_cppad_h_base implementation of this function corresponds to the simple representation mentioned above; i.e.,  L = 1 .

fg_info->index
This member function has prototype
     virtual void ipopt_cppad_fg_info::index(
          size_t 
k, size_t ell, SizeVector& I, SizeVector& J
     )
The argument  
     k
has type size_t and is a value between zero and  K-1 inclusive. The argument  
     ell
has type size_t and is a value between zero and  L(k)-1 inclusive. The argument
     I
is a SimpleVector with elements of type size_t and size greater than or equal to  p(k) . The input value of the elements of I does not matter. The output value of the first  p(k) elements of I must be the corresponding elements of  I_{k,ell} in the representation above. The argument
     J
is a SimpleVector with elements of type size_t and size greater than or equal to  q(k) . The input value of the elements of J does not matter. The output value of the first  q(k) elements of J must be the corresponding elements of  J_{k,ell} in the representation above.

The ipopt_cppad_h_base implementation of this function corresponds to the simple representation mentioned above; i.e., for  i = 0 , \ldots , m , I[i] = i , and for  j = 0 , \ldots , n-1 , J[j] = j .

solution
After the optimization process is completed, solution contains the following information:

status
The status field of solution has prototype
     ipopt_cppad_solution::solution_status 
solution.status
It is the final Ipopt status for the optimizer. Here is a list of the possible values for the status:
status Meaning
not_defined The optimizer did not return a final status to this ipopt_cppad_nlp object.
unknown The status returned by the optimizer is not defined in the Ipopt documentation for finalize_solution.
success Algorithm terminated successfully at a point satisfying the convergence tolerances (see Ipopt options).
maxiter_exceeded The maximum number of iterations was exceeded (see Ipopt options).
stop_at_tiny_step Algorithm terminated because progress was very slow.
stop_at_acceptable_point Algorithm stopped at a point that was converged, not to the 'desired' tolerances, but to 'acceptable' tolerances (see Ipopt options).
local_infeasibility Algorithm converged to a non-feasible point (problem may have no solution).
user_requested_stop This return value should not happen.
diverging_iterates It the iterates are diverging.
restoration_failure Restoration phase failed, algorithm doesn't know how to proceed.
error_in_step_computation An unrecoverable error occurred while Ipopt tried to compute the search direction.
invalid_number_detected Algorithm received an invalid number (such as nan or inf) from the users function fg_info.eval or from the CppAD evaluations of its derivatives (see the Ipopt option check_derivatives_for_naninf).
internal_error An unknown Ipopt internal error occurred. Contact the Ipopt authors through the mailing list.

x
The x field of solution has prototype
     NumberVector 
solution.x
and its size is equal to  n . It is the final  x value for the optimizer.

z_l
The z_l field of solution has prototype
     NumberVector 
solution.z_l
and its size is equal to  n . It is the final Lagrange multipliers for the lower bounds on  x .

z_u
The z_u field of solution has prototype
     NumberVector 
solution.z_u
and its size is equal to  n . It is the final Lagrange multipliers for the upper bounds on  x .

g
The g field of solution has prototype
     NumberVector 
solution.g
and its size is equal to  m . It is the final value for the constraint function  g(x) .

lambda
The lambda field of solution has prototype
     NumberVector 
solution.lambda
and its size is equal to  m . It is the final value for the Lagrange multipliers corresponding to the constraint function.

obj_value
The obj_value field of solution has prototype
     Number 
solution.obj_value
It is the final value of the objective function  f(x) .

Example
The file ipopt_cppad.cpp is an example and test of ipopt_cppad_nlp. that uses the simple representation . The file ipopt_cppad_ode.cpp is a more complex example that optimizes the solution of an ordinary differential equation. They return true if they succeed and false otherwise.
Input File: example/ipopt_cppad_nlp.hpp