text: // Copyright (C) 2004, 2009 International Business Machines and others.
  // All Rights Reserved.
  // This code is published under the Eclipse Public License.
  //
  // Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
  
  #ifndef __IPTNLP_HPP__
  #define __IPTNLP_HPP__
  
  #include "IpUtils.hpp"
  #include "IpReferenced.hpp"
  #include "IpException.hpp"
  #include "IpAlgTypes.hpp"
  #include "IpReturnCodes.hpp"
  
  #include <map>
  
  namespace Ipopt
  {
  // forward declarations
  class IpoptData;
  class IpoptCalculatedQuantities;
  class IteratesVector;
  
  /** Base class for all NLP's that use standard triplet matrix form and dense vectors.
   *
   *  This is the standard base class for all NLP's that use the standard triplet matrix
   *  form and dense vectors.
   *  The class TNLPAdapter then converts this interface to an interface that can be used
   *  directly by \Ipopt.
   *
   *  This interface presents the problem form:
   *
   *     min f(x)
   *
   *     s.t. gL <= g(x) <= gU
   *
   *          xL <=  x   <= xU
   *
   *  In order to specify an equality constraint, set gL_i = gU_i = rhs.
   *  The value that indicates "infinity" for the bounds
   *  (i.e. the variable or constraint has no lower bound (-infinity) or upper bound (+infinity))
   *  is set through the option nlp_lower_bound_inf and nlp_upper_bound_inf, respectively.
   *  To indicate that a variable has no upper or lower bound, set the bound to
   *  -ipopt_inf or +ipopt_inf, respectively.
   */
  class IPOPTLIB_EXPORT TNLP : public ReferencedObject
  {
  public:
  
     /** Linearity-types of variables and constraints. */
     enum LinearityType
     {
        LINEAR,    /**< Constraint/Variable is linear */
        NON_LINEAR /**< Constraint/Variable is non-linear */
     };
  
     /**@name Constructors/Destructors */
     //@{
     TNLP()
     { }
  
     /** Default destructor */
     virtual ~TNLP()
     { }
     //@}
  
     DECLARE_STD_EXCEPTION(INVALID_TNLP);
  
     /**@name methods to gather information about the NLP */
     //@{
  
     enum IndexStyleEnum
     {
        C_STYLE       = 0,
        FORTRAN_STYLE = 1
     };
  
     /** Method to request the initial information about the problem.
      *
      *  \Ipopt uses this information when allocating the arrays
      *  that it will later ask you to fill with values. Be careful in this
      *  method since incorrect values will cause memory bugs which may be very
      *  difficult to find.
      *
      *  @param n           (out) Storage for the number of variables \f$x\f$
      *  @param m           (out) Storage for the number of constraints \f$g(x)\f$
      *  @param nnz_jac_g   (out) Storage for the number of nonzero entries in the Jacobian
      *  @param nnz_h_lag   (out) Storage for the number of nonzero entries in the Hessian
      *  @param index_style (out) Storage for the index style,
      *                     the numbering style used for row/col entries in the sparse matrix format
      *                     (TNLP::C_STYLE: 0-based, TNLP::FORTRAN_STYLE: 1-based; see also \ref TRIPLET)
      */
     // [TNLP_get_nlp_info]
     virtual bool get_nlp_info(
        Index&          n,
        Index&          m,
        Index&          nnz_jac_g,
        Index&          nnz_h_lag,
        IndexStyleEnum& index_style
     ) = 0;
     // [TNLP_get_nlp_info]
  
     typedef std::map<std::string, std::vector<std::string> > StringMetaDataMapType;
     typedef std::map<std::string, std::vector<Index> > IntegerMetaDataMapType;
     typedef std::map<std::string, std::vector<Number> > NumericMetaDataMapType;
  
     /** Method to request meta data for the variables and the constraints.
      *
      * This method is used to pass meta data about variables or constraints to
      * \Ipopt. The data can be either of integer, numeric, or string type.
      * \Ipopt passes this data on to its internal problem representation.
      * The meta data type is a std::map with std::string as key type and
      * a std::vector as value type. So far, \Ipopt itself makes only use of
      * string meta data under the key idx_names. With this key, variable
      * and constraint names can be passed to \Ipopt, which are shown when
      * printing internal vector or matrix data structures if \Ipopt is run
      * with a high value for the option. This allows a user to identify
      * the original variables and constraints corresponding to \Ipopt's
      * internal problem representation.
      *
      * If this method is not overloaded, the default implementation does
      * not set any meta data and returns false.
      */
     // [TNLP_get_var_con_metadata]
     virtual bool get_var_con_metadata(
        Index                   n,
        StringMetaDataMapType&  var_string_md,
        IntegerMetaDataMapType& var_integer_md,
        NumericMetaDataMapType& var_numeric_md,
        Index                   m,
        StringMetaDataMapType&  con_string_md,
        IntegerMetaDataMapType& con_integer_md,
        NumericMetaDataMapType& con_numeric_md
     )
     // [TNLP_get_var_con_metadata]
     {
        (void) n;
        (void) var_string_md;
        (void) var_integer_md;
        (void) var_numeric_md;
        (void) m;
        (void) con_string_md;
        (void) con_integer_md;
        (void) con_numeric_md;
        return false;
     }
  
     /** Method to request bounds on the variables and constraints.
      *
      *  @param n   (in) the number of variables \f$x\f$ in the problem
      *  @param x_l (out) the lower bounds \f$x^L\f$ for the variables \f$x\f$
      *  @param x_u (out) the upper bounds \f$x^U\f$ for the variables \f$x\f$
      *  @param m   (in) the number of constraints \f$g(x)\f$ in the problem
      *  @param g_l (out) the lower bounds \f$g^L\f$ for the constraints \f$g(x)\f$
      *  @param g_u (out) the upper bounds \f$g^U\f$ for the constraints \f$g(x)\f$
      *
      *  @return true if success, false otherwise.
      *
      * The values of `n` and `m` that were specified in TNLP::get_nlp_info are passed
      * here for debug checking. Setting a lower bound to a value less than or
      * equal to the value of the option \ref OPT_nlp_lower_bound_inf "nlp_lower_bound_inf"
      * will cause \Ipopt to assume no lower bound. Likewise, specifying the upper bound above or
      * equal to the value of the option \ref OPT_nlp_upper_bound_inf "nlp_upper_bound_inf"
      * will cause \Ipopt to assume no upper bound. These options are set to -10<sup>19</sup> and
      * 10<sup>19</sup>, respectively, by default, but may be modified by changing these
      * options.
      */
     // [TNLP_get_bounds_info]
     virtual bool get_bounds_info(
        Index   n,
        Number* x_l,
        Number* x_u,
        Index   m,
        Number* g_l,
        Number* g_u
     ) = 0;
     // [TNLP_get_bounds_info]
  
     /** Method to request scaling parameters.
      *
      * This is only called if the options are set to retrieve user scaling,
      * that is, if nlp_scaling_method is chosen as "user-scaling".
      * The method should provide scaling factors for the objective
      * function as well as for the optimization variables and/or constraints.
      * The return value should be true, unless an error occurred, and the
      * program is to be aborted.
      *
      * The value returned in obj_scaling determines, how \Ipopt
      * should internally scale the objective function. For example, if this
      * number is chosen to be 10, then \Ipopt solves internally an
      * optimization problem that has 10 times the value of the original
      * objective function provided by the TNLP. In particular, if this value
      * is negative, then \Ipopt will maximize the objective function instead
      * of minimizing it.
      *
      * The scaling factors for the variables can be returned in x_scaling,
      * which has the same length as x in the other TNLP methods, and the
      * factors are ordered like x. use_x_scaling needs to be set to true,
      * if \Ipopt should scale the variables. If it is false, no internal
      * scaling of the variables is done. Similarly, the scaling factors
      * for the constraints can be returned in g_scaling, and this
      * scaling is activated by setting use_g_scaling to true.
      *
      * As a guideline, we suggest to scale the optimization problem (either
      * directly in the original formulation, or after using scaling factors)
      * so that all sensitivities, i.e., all non-zero first partial derivatives,
      * are typically of the order 0.1-10.
      */
     // [TNLP_get_scaling_parameters]
     virtual bool get_scaling_parameters(
        Number& obj_scaling,
        bool&   use_x_scaling,
        Index   n,
        Number* x_scaling,
        bool&   use_g_scaling,
        Index   m,
        Number* g_scaling
     )
     // [TNLP_get_scaling_parameters]
     {
        (void) obj_scaling;
        (void) use_x_scaling;
        (void) n;
        (void) x_scaling;
        (void) use_g_scaling;
        (void) m;
        (void) g_scaling;
        return false;
     }
  
     /** Method to request the variables linearity.
      *
      * This method is never called by \Ipopt, but is used by Bonmin
      * to get information about which variables occur only in linear terms.
      * \Ipopt passes the array var_types of length at least n, which should
      * be filled with the appropriate linearity type of the variables
      * (TNLP::LINEAR or TNLP::NON_LINEAR).
      *
      * The default implementation just returns false and does not fill the array.
      */
     // [TNLP_get_variables_linearity]
     virtual bool get_variables_linearity(
        Index          n,
        LinearityType* var_types
     )
     // [TNLP_get_variables_linearity]
     {
        (void) n;
        (void) var_types;
        return false;
     }
  
     /** Method to request the constraints linearity.
      *
      * This method is never called by \Ipopt, but is used by Bonmin
      * to get information about which constraints are linear.
      * \Ipopt passes the array const_types of size m, which should be filled
      * with the appropriate linearity type of the constraints
      * (TNLP::LINEAR or TNLP::NON_LINEAR).
      *
      * The default implementation just returns false and does not fill the array.
      */
     // [TNLP_get_constraints_linearity]
     virtual bool get_constraints_linearity(
        Index          m,
        LinearityType* const_types
     )
     // [TNLP_get_constraints_linearity]
     {
        (void) m;
        (void) const_types;
        return false;
     }
  
     /** Method to request the starting point before iterating.
      *
      *  @param n      (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param init_x (in) if true, this method must provide an initial value for \f$x\f$
      *  @param x      (out) the initial values for the primal variables \f$x\f$
      *  @param init_z (in) if true, this method must provide an initial value for the bound multipliers \f$z^L\f$ and \f$z^U\f$
      *  @param z_L    (out) the initial values for the bound multipliers \f$z^L\f$
      *  @param z_U    (out) the initial values for the bound multipliers \f$z^U\f$
      *  @param m      (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param init_lambda (in) if true, this method must provide an initial value for the constraint multipliers \f$\lambda\f$
      *  @param lambda (out) the initial values for the constraint multipliers, \f$\lambda\f$
      *
      *  @return true if success, false otherwise.
      *
      *  The boolean variables indicate whether the algorithm requires to
      *  have x, z_L/z_u, and lambda initialized, respectively.  If, for some
      *  reason, the algorithm requires initializations that cannot be
      *  provided, false should be returned and \Ipopt will stop.
      *  The default options only require initial values for the primal
      *  variables \f$x\f$.
      *
      *  Note, that the initial values for bound multiplier components for
      *  absent bounds (\f$x^L_i=-\infty\f$ or \f$x^U_i=\infty\f$) are ignored.
      */
     // [TNLP_get_starting_point]
     virtual bool get_starting_point(
        Index   n,
        bool    init_x,
        Number* x,
        bool    init_z,
        Number* z_L,
        Number* z_U,
        Index   m,
        bool    init_lambda,
        Number* lambda
     ) = 0;
     // [TNLP_get_starting_point]
  
     /** Method to provide an \Ipopt warm start iterate which is already in the
      * form \Ipopt requires it internally for warm starts.
      *
      * This method is only for expert users.
      * The default implementation does not provide a warm start iterate
      * and returns false.
      */
     // [TNLP_get_warm_start_iterate]
     virtual bool get_warm_start_iterate(
        IteratesVector& warm_start_iterate /**< storage for warm start iterate in the form \Ipopt requires it internally */
     )
     {
        (void) warm_start_iterate;
        return false;
     }
     // [TNLP_get_warm_start_iterate]
  
     /** Method to request the value of the objective function.
      *
      *  @param n     (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param x     (in) the values for the primal variables \f$x\f$ at which the objective function \f$f(x)\f$ is to be evaluated
      *  @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise.
      *                    This can be helpful when users have efficient implementations that calculate multiple outputs at once.
      *                    \Ipopt internally caches results from the TNLP and generally, this flag can be ignored.
      *  @param obj_value (out) storage for the value of the objective function \f$f(x)\f$
      *
      *  @return true if success, false otherwise.
      */
     // [TNLP_eval_f]
     virtual bool eval_f(
        Index         n,
        const Number* x,
        bool          new_x,
        Number&       obj_value
     ) = 0;
     // [TNLP_eval_f]
  
     /** Method to request the gradient of the objective function.
      *
      *  @param n     (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param x     (in) the values for the primal variables \f$x\f$ at which the gradient \f$\nabla f(x)\f$ is to be evaluated
      *  @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise; see also TNLP::eval_f
      *  @param grad_f (out) array to store values of the gradient of the objective function \f$\nabla f(x)\f$.
      *                      The gradient array is in the same order as the \f$x\f$ variables
      *                      (i.e., the gradient of the objective with respect to `x[2]` should be put in `grad_f[2]`).
      *
      *  @return true if success, false otherwise.
      */
     // [TNLP_eval_grad_f]
     virtual bool eval_grad_f(
        Index         n,
        const Number* x,
        bool          new_x,
        Number*       grad_f
     ) = 0;
     // [TNLP_eval_grad_f]
  
     /** Method to request the constraint values.
      *
      *  @param n     (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param x     (in) the values for the primal variables \f$x\f$ at which the constraint functions \f$g(x)\f$ are to be evaluated
      *  @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise; see also TNLP::eval_f
      *  @param m     (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param g     (out) array to store constraint function values \f$g(x)\f$, do not add or subtract the bound values \f$g^L\f$ or \f$g^U\f$.
      *
      *  @return true if success, false otherwise.
      */
     // [TNLP_eval_g]
     virtual bool eval_g(
        Index         n,
        const Number* x,
        bool          new_x,
        Index         m,
        Number*       g
     ) = 0;
     // [TNLP_eval_g]
  
     /** Method to request either the sparsity structure or the values of the Jacobian of the constraints.
      *
      * The Jacobian is the matrix of derivatives where the derivative of
      * constraint function \f$g_i\f$ with respect to variable \f$x_j\f$ is placed in row
      * \f$i\f$ and column \f$j\f$.
      * See \ref TRIPLET for a discussion of the sparse matrix format used in this method.
      *
      *  @param n     (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param x     (in) first call: NULL; later calls: the values for the primal variables \f$x\f$ at which the constraint Jacobian \f$\nabla g(x)^T\f$ is to be evaluated
      *  @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise; see also TNLP::eval_f
      *  @param m     (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param nele_jac (in) the number of nonzero elements in the Jacobian; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param iRow  (out) first call: array of length nele_jac to store the row indices of entries in the Jacobian of the constraints; later calls: NULL
      *  @param jCol  (out) first call: array of length nele_jac to store the column indices of entries in the Jacobian of the constraints; later calls: NULL
      *  @param values (out) first call: NULL; later calls: array of length nele_jac to store the values of the entries in the Jacobian of the constraints
      *
      *  @return true if success, false otherwise.
      *
      * @note The arrays iRow and jCol only need to be filled once.
      * If the iRow and jCol arguments are not NULL (first call to this function),
      * then \Ipopt expects that the sparsity structure of the Jacobian
      * (the row and column indices only) are written into iRow and jCol.
      * At this call, the arguments `x` and `values` will be NULL.
      * If the arguments `x` and `values` are not NULL, then \Ipopt
      * expects that the value of the Jacobian as calculated from array `x`
      * is stored in array `values` (using the same order as used when
      * specifying the sparsity structure).
      * At this call, the arguments `iRow` and `jCol` will be NULL.
      */
     // [TNLP_eval_jac_g]
     virtual bool eval_jac_g(
        Index         n,
        const Number* x,
        bool          new_x,
        Index         m,
        Index         nele_jac,
        Index*        iRow,
        Index*        jCol,
        Number*       values
     ) = 0;
     // [TNLP_eval_jac_g]
  
     /** Method to request either the sparsity structure or the values of the Hessian of the Lagrangian.
      *
      * The Hessian matrix that \Ipopt uses is
      * \f[ \sigma_f \nabla^2 f(x_k) + \sum_{i=1}^m\lambda_i\nabla^2 g_i(x_k) \f]
      * for the given values for \f$x\f$, \f$\sigma_f\f$, and \f$\lambda\f$.
      * See \ref TRIPLET for a discussion of the sparse matrix format used in this method.
      *
      *  @param n     (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param x     (in) first call: NULL; later calls: the values for the primal variables \f$x\f$ at which the Hessian is to be evaluated
      *  @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise; see also TNLP::eval_f
      *  @param obj_factor (in) factor \f$\sigma_f\f$ in front of the objective term in the Hessian
      *  @param m     (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param lambda (in) the values for the constraint multipliers \f$\lambda\f$ at which the Hessian is to be evaluated
      *  @param new_lambda (in) false if any evaluation method was previously called with the same values in lambda, true otherwise
      *  @param nele_hess (in) the number of nonzero elements in the Hessian; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param iRow  (out) first call: array of length nele_hess to store the row indices of entries in the Hessian; later calls: NULL
      *  @param jCol  (out) first call: array of length nele_hess to store the column indices of entries in the Hessian; later calls: NULL
      *  @param values (out) first call: NULL; later calls: array of length nele_hess to store the values of the entries in the Hessian
      *
      *  @return true if success, false otherwise.
      *
      * @note The arrays iRow and jCol only need to be filled once.
      * If the iRow and jCol arguments are not NULL (first call to this function),
      * then \Ipopt expects that the sparsity structure of the Hessian
      * (the row and column indices only) are written into iRow and jCol.
      * At this call, the arguments `x`, `lambda`, and `values` will be NULL.
      * If the arguments `x`, `lambda`, and `values` are not NULL, then \Ipopt
      * expects that the value of the Hessian as calculated from arrays `x`
      * and `lambda` are stored in array `values` (using the same order as
      * used when specifying the sparsity structure).
      * At this call, the arguments `iRow` and `jCol` will be NULL.
      *
      * @attention As this matrix is symmetric, \Ipopt expects that only the lower diagonal entries are specified.
      *
      * A default implementation is provided, in case the user
      * wants to set quasi-Newton approximations to estimate the second
      * derivatives and doesn't not need to implement this method.
      */
     // [TNLP_eval_h]
     virtual bool eval_h(
        Index         n,
        const Number* x,
        bool          new_x,
        Number        obj_factor,
        Index         m,
        const Number* lambda,
        bool          new_lambda,
        Index         nele_hess,
        Index*        iRow,
        Index*        jCol,
        Number*       values
     )
     // [TNLP_eval_h]
     {
        (void) n;
        (void) x;
        (void) new_x;
        (void) obj_factor;
        (void) m;
        (void) lambda;
        (void) new_lambda;
        (void) nele_hess;
        (void) iRow;
        (void) jCol;
        (void) values;
        return false;
     }
     //@}
  
     /** @name Solution Methods */
     //@{
     /** This method is called when the algorithm has finished (successfully or not) so the TNLP can digest the outcome, e.g., store/write the solution, if any.
      *
      *  @param status @parblock (in) gives the status of the algorithm
      *   - SUCCESS: Algorithm terminated successfully at a locally optimal
      *     point, satisfying the convergence tolerances (can be specified
      *     by options).
      *   - MAXITER_EXCEEDED: Maximum number of iterations exceeded (can be specified by an option).
      *   - CPUTIME_EXCEEDED: Maximum number of CPU seconds exceeded (can be specified by an option).
      *   - STOP_AT_TINY_STEP: Algorithm proceeds with very little progress.
      *   - STOP_AT_ACCEPTABLE_POINT: Algorithm stopped at a point that was converged, not to "desired" tolerances, but to "acceptable" tolerances (see the acceptable-... options).
      *   - LOCAL_INFEASIBILITY: Algorithm converged to a point of local infeasibility. Problem may be infeasible.
      *   - USER_REQUESTED_STOP: The user call-back function TNLP::intermediate_callback returned false, i.e., the user code requested a premature termination of the optimization.
      *   - DIVERGING_ITERATES: It seems that the iterates diverge.
      *   - 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 NLP; see also option check_derivatives_for_nan_inf).
      *   - INTERNAL_ERROR: An unknown internal error occurred.
      *   @endparblock
      *  @param n     (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param x     (in) the final values for the primal variables
      *  @param z_L   (in) the final values for the lower bound multipliers
      *  @param z_U   (in) the final values for the upper bound multipliers
      *  @param m     (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info
      *  @param g     (in) the final values of the constraint functions
      *  @param lambda (in) the final values of the constraint multipliers
      *  @param obj_value (in) the final value of the objective function
      *  @param ip_data (in) provided for expert users
      *  @param ip_cq (in) provided for expert users
      */
     // [TNLP_finalize_solution]
     virtual void finalize_solution(
        SolverReturn               status,
        Index                      n,
        const Number*              x,
        const Number*              z_L,
        const Number*              z_U,
        Index                      m,
        const Number*              g,
        const Number*              lambda,
        Number                     obj_value,
        const IpoptData*           ip_data,
        IpoptCalculatedQuantities* ip_cq
     ) = 0;
     // [TNLP_finalize_solution]
  
     /** This method returns any metadata collected during the run of the algorithm.
      *
      * This method is called just before finalize_solution is called.
      * The returned data includes the metadata provided by TNLP::get_var_con_metadata.
      * Each metadata can be of type string, integer, or numeric.
      * It can be associated to either the variables or the constraints.
      * The metadata that was associated with the primal variable vector
      * is stored in `var_..._md`.  The metadata associated with the constraint
      * multipliers is stored in `con_..._md`.  The metadata associated
      * with the bound multipliers is stored in `var_..._md`, with the
      * suffixes "_z_L", and "_z_U", denoting lower and upper bounds.
      *
      * If the user doesn't overload this method in her implementation of the
      * class derived from TNLP, the default implementation does nothing.
      */
     // [TNLP_finalize_metadata]
     virtual void finalize_metadata(
        Index                         n,
        const StringMetaDataMapType&  var_string_md,
        const IntegerMetaDataMapType& var_integer_md,
        const NumericMetaDataMapType& var_numeric_md,
        Index                         m,
        const StringMetaDataMapType&  con_string_md,
        const IntegerMetaDataMapType& con_integer_md,
        const NumericMetaDataMapType& con_numeric_md
     )
     // [TNLP_finalize_metadata]
     {
        (void) n;
        (void) var_string_md;
        (void) var_integer_md;
        (void) var_numeric_md;
        (void) m;
        (void) con_string_md;
        (void) con_integer_md;
        (void) con_numeric_md;
     }
  
     /** Intermediate Callback method for the user.
      *
      * This method is called once per iteration (during the convergence check),
      * and can be used to obtain information about the optimization status while
      * \Ipopt solves the problem, and also to request a premature termination.
      *
      * The information provided by the entities in the argument list correspond
      * to what \Ipopt prints in the iteration summary (see also \ref OUTPUT).
      * Further information can be obtained from the ip_data and ip_cq objects.
      *
      * @return If this method returns false, \Ipopt will terminate with the
      *   User_Requested_Stop status.
      *
      * It is not required to implement (overload) this method.
      * The default implementation always returns true.
      *
      * A frequently asked question is how to access the values of the primal
      * and dual variables in this callback. The values are stored in the `ip_cq`
      * object for the *internal representation* of the problem. To access the
      * values in a form that corresponds to those used in the evaluation
      * routines, the user has to request \Ipopt's TNLPAdapter
      * object to "resort" the data vectors and to fill in information about
      * possibly filtered out fixed variables. The TNLPAdapter can be accessed
      * as follows. First, add the following includes to your TNLP
      * implementation:
      * \code
      * #include "IpIpoptCalculatedQuantities.hpp"
      * #include "IpIpoptData.hpp"
      * #include "IpTNLPAdapter.hpp"
      * #include "IpOrigIpoptNLP.hpp"
      * \endcode
      * Next, add the following code to your implementation of this function:
      * \code
      * Ipopt::TNLPAdapter* tnlp_adapter = NULL;
      * if( ip_cq != NULL )
      * {
      *   Ipopt::OrigIpoptNLP* orignlp;
      *   orignlp = dynamic_cast<OrigIpoptNLP*>(GetRawPtr(ip_cq->GetIpoptNLP()));
      *   if( orignlp != NULL )
      *     tnlp_adapter = dynamic_cast<TNLPAdapter*>(GetRawPtr(orignlp->nlp()));
      * }
      * \endcode
      * Note, that retrieving the TNLPAdapter will fail (i.e., `orignlp` will be NULL)
      * if \Ipopt is currently in restoration mode. If, however,
      * `tnlp_adapter` is not NULL, then it can be used to obtain primal variable
      * values \f$x\f$ and the dual values for the constraints and the variable
      * bounds as follows:
      * \code
      * double* primals = new double[n];
      * double* dualeqs = new double[m];
      * double* duallbs = new double[n];
      * double* dualubs = new double[n];
      * tnlp_adapter->ResortX(*ip_data->curr()->x(), primals);
      * tnlp_adapter->ResortG(*ip_data->curr()->y_c(), *ip_data->curr()->y_d(), dualeqs);
      * tnlp_adapter->ResortBnds(*ip_data->curr()->z_L(), duallbs,
      *                          *ip_data->curr()->z_U(), dualubs);
      * \endcode
      * \note ResortBnds does not provide dual multipliers for fixed variables, even if the
      *   fixed-variable treatment has been set to handle them as constraints.
      *
      * Additionally, information about scaled violation of constraint
      * and violation of complementarity constraints can be obtained via
      * \code
      * tnlp_adapter->ResortG(*ip_cq->curr_c(), *ip_cq->curr_d_minus_s(), ...)
      * tnlp_adapter->ResortBnds(*ip_cq->curr_compl_x_L(), ...,
      *                          *ip_cq->curr_compl_x_U(), ...)
      * tnlp_adapter->ResortG(*ip_cq->curr_compl_s_L(), ...)
      * tnlp_adapter->ResortG(*ip_cq->curr_compl_s_U(), ...)
      * \endcode
      */
     // [TNLP_intermediate_callback]
     virtual bool intermediate_callback(
        AlgorithmMode              mode,
        Index                      iter,
        Number                     obj_value,
        Number                     inf_pr,
        Number                     inf_du,
        Number                     mu,
        Number                     d_norm,
        Number                     regularization_size,
        Number                     alpha_du,
        Number                     alpha_pr,
        Index                      ls_trials,
        const IpoptData*           ip_data,
        IpoptCalculatedQuantities* ip_cq
     )
     // [TNLP_intermediate_callback]
     {
        (void) mode;
        (void) iter;
        (void) obj_value;
        (void) inf_pr;
        (void) inf_du;
        (void) mu;
        (void) d_norm;
        (void) regularization_size;
        (void) alpha_du;
        (void) alpha_pr;
        (void) ls_trials;
        (void) ip_data;
        (void) ip_cq;
        return true;
     }
     //@}
  
     /** @name Methods for quasi-Newton approximation.
      *
      *  If the second derivatives are approximated by \Ipopt, it is better
      *  to do this only in the space of nonlinear variables. The following
      *  methods are call by \Ipopt if the \ref QUASI_NEWTON "quasi-Newton approximation"
      *  is selected.
      *
      * @{
      */
  
     /** Return the number of variables that appear nonlinearly in the objective function or in at least one constraint function
      *
      *  If -1 is returned as number of nonlinear variables,
      *  \Ipopt assumes that all variables are nonlinear.  Otherwise, it
      *  calls get_list_of_nonlinear_variables with an array into which
      *  the indices of the nonlinear variables should be written - the
      *  array has the length num_nonlin_vars, which is identical with
      *  the return value of get_number_of_nonlinear_variables().  It
      *  is assumed that the indices are counted starting with 1 in the
      *  FORTRAN_STYLE, and 0 for the C_STYLE.
      *
      *  The default implementation returns -1, i.e.,
      *  all variables are assumed to be nonlinear.
      */
     // [TNLP_get_number_of_nonlinear_variables]
     virtual Index get_number_of_nonlinear_variables()
     // [TNLP_get_number_of_nonlinear_variables]
     {
        return -1;
     }
  
     /** Return the indices of all nonlinear variables.
      *
      * This method is called only if limited-memory quasi-Newton option
      * is used and get_number_of_nonlinear_variables() returned a positive
      * number. This number is provided in parameter num_nonlin_var.
      *
      * The method must store the indices of all nonlinear variables in
      * pos_nonlin_vars, where the numbering starts with 0 order 1,
      * depending on the numbering style determined in get_nlp_info.
      */
     // [TNLP_get_list_of_nonlinear_variables]
     virtual bool get_list_of_nonlinear_variables(
        Index  num_nonlin_vars,
        Index* pos_nonlin_vars
     )
     // [TNLP_get_list_of_nonlinear_variables]
     {
        (void) num_nonlin_vars;
        (void) pos_nonlin_vars;
        return false;
     }
     //@}
  
  private:
     /**@name Default Compiler Generated Methods
      * (Hidden to avoid implicit creation/calling).
      * These methods are not implemented and
      * we do not want the compiler to implement
      * them for us, so we declare them private
      * and do not define them. This ensures that
      * they will not be implicitly created/called.
      */
     //@{
     /** Copy Constructor */
     TNLP(
        const TNLP&
     );
  
     /** Default Assignment Operator */
     void operator=(
        const TNLP&
     );
     //@}
  };
  
  } // namespace Ipopt
  
  #endif
  