Example #1
0
static PyObject *add_int_option(PyObject * self, PyObject * args)
{

	problem *temp = (problem *) self;
	IpoptProblem nlp = (IpoptProblem) (temp->nlp);

	char *param;
	int value;

	Bool ret;

	if (!PyArg_ParseTuple(args, "si:int_option", &param, &value)) {
		return NULL;
	}
	ret = AddIpoptIntOption(nlp, (char *)param, value);
	if (ret) {
		Py_INCREF(Py_True);
		return Py_True;
	} else {
		return PyErr_Format(PyExc_ValueError,
				    "%s is not a valid int option", param);
	}
}
fint F77_FUNC(ipaddintoption,IPADDINTOPTION)
(fptr* FProblem,
 char* KEYWORD,
 fint* VALUE,
 int klen)
{
  char* keyword;
  FUserData* fuser_data = (FUserData*) *FProblem;
  Int value = *VALUE;
  fint retval;

  keyword = f2cstr(KEYWORD, klen);

  retval = AddIpoptIntOption(fuser_data->Problem, keyword, value);

  free(keyword);

  if (retval) {
    return OKRetVal;
  }
  else {
    return NotOKRetVal;
  }
}
Example #3
0
/*!
 *  run optimization with ipopt
 *  author: Vitalij Ruge
 **/
static inline void optimizationWithIpopt(OptData*optData) {
    IpoptProblem nlp = NULL;

    const int NV = optData->dim.NV;
    const int NRes = optData->dim.NRes;
    const int nsi = optData->dim.nsi;
    const int np = optData->dim.np;
    const int nx = optData->dim.nx;
    const int NJ = optData->dim.nJderx;
    const int NJf = optData->dim.nJfderx;
    const int nH0 = optData->dim.nH0_;
    const int nH1 = optData->dim.nH1_;
    const int njac = np*(NJ*nsi + nx*(np*nsi - 1)) + NJf;
    const int nhess = (nsi*np-1)*nH0+nH1;

    Number * Vmin = optData->bounds.Vmin;
    Number * Vmax = optData->bounds.Vmax;
    Number * gmin = optData->ipop.gmin;
    Number * gmax = optData->ipop.gmax;
    Number * vopt = optData->ipop.vopt;
    Number * mult_g = optData->ipop.mult_g;
    Number * mult_x_L = optData->ipop.mult_x_L;
    Number * mult_x_U = optData->ipop.mult_x_U;
    Number obj;

    char *cflags;
    int max_iter = 5000;
    int res = 0;

    nlp = CreateIpoptProblem(NV, Vmin, Vmax,
                             NRes, gmin, gmax, njac, nhess, 0, &evalfF,
                             &evalfG, &evalfDiffF, &evalfDiffG, &ipopt_h);

    /********************************************************************/
    /*******************       ipopt flags       ************************/
    /********************************************************************/

    /*tol */
    AddIpoptNumOption(nlp, "tol", optData->data->simulationInfo.tolerance);
    AddIpoptStrOption(nlp, "evaluate_orig_obj_at_resto_trial", "yes");

    /* print level */
    if(ACTIVE_STREAM(LOG_IPOPT_FULL)) {
        AddIpoptIntOption(nlp, "print_level", 7);
    } else if(ACTIVE_STREAM(LOG_IPOPT)) {
        AddIpoptIntOption(nlp, "print_level", 5);
    } else if(ACTIVE_STREAM(LOG_STATS)) {
        AddIpoptIntOption(nlp, "print_level", 3);
    } else {
        AddIpoptIntOption(nlp, "print_level", 2);
    }
    AddIpoptIntOption(nlp, "file_print_level", 0);

    /* derivative_test */
    if(ACTIVE_STREAM(LOG_IPOPT_JAC) && ACTIVE_STREAM(LOG_IPOPT_HESSE)) {
        AddIpoptIntOption(nlp, "print_level", 4);
        AddIpoptStrOption(nlp, "derivative_test", "second-order");
    } else if(ACTIVE_STREAM(LOG_IPOPT_JAC)) {
        AddIpoptIntOption(nlp, "print_level", 4);
        AddIpoptStrOption(nlp, "derivative_test", "first-order");
    } else if(ACTIVE_STREAM(LOG_IPOPT_HESSE)) {
        AddIpoptIntOption(nlp, "print_level", 4);
        AddIpoptStrOption(nlp, "derivative_test", "only-second-order");
    } else {
        AddIpoptStrOption(nlp, "derivative_test", "none");
    }


    cflags = (char*)omc_flagValue[FLAG_IPOPT_HESSE];
    if(cflags) {
        if(!strcmp(cflags,"BFGS"))
            AddIpoptStrOption(nlp, "hessian_approximation", "limited-memory");
        else if(!strcmp(cflags,"const") || !strcmp(cflags,"CONST"))
            AddIpoptStrOption(nlp, "hessian_constant", "yes");
        else if(!(!strcmp(cflags,"num") || !strcmp(cflags,"NUM")))
            warningStreamPrint(LOG_STDOUT, 0, "not support ipopt_hesse=%s",cflags);
    }

    /*linear_solver e.g. mumps, MA27, MA57,...
     * be sure HSL solver are installed if your try HSL solver*/
    cflags = (char*)omc_flagValue[FLAG_LS_IPOPT];
    if(cflags)
        AddIpoptStrOption(nlp, "linear_solver", cflags);
    AddIpoptNumOption(nlp,"mumps_pivtolmax",1e-5);


    /* max iter */
    cflags = (char*)omc_flagValue[FLAG_IPOPT_MAX_ITER];
    if(cflags) {
        char buffer[100];
        char c;
        int index_e = -1, i = 0;
        strcpy(buffer,cflags);

        while(buffer[i] != '\0') {
            if(buffer[i] == 'e') {
                index_e = i;
                break;
            }
            ++i;
        }

        if(index_e < 0) {
            max_iter = atoi(cflags);
            if(max_iter >= 0)
                AddIpoptIntOption(nlp, "max_iter", max_iter);
            printf("\nmax_iter = %i",atoi(cflags));

        } else {
            max_iter =  (atoi(cflags)*pow(10.0, (double)atoi(cflags+index_e+1)));
            if(max_iter >= 0)
                AddIpoptIntOption(nlp, "max_iter", (int)max_iter);
            printf("\nmax_iter = (int) %i | (double) %g",(int)max_iter, atoi(cflags)*pow(10.0, (double)atoi(cflags+index_e+1)));
        }
    } else
        AddIpoptIntOption(nlp, "max_iter", 5000);

    /*heuristic optition */
    {
        int ws = 0;
        cflags = (char*)omc_flagValue[FLAG_IPOPT_WARM_START];
        if(cflags) {
            ws = atoi(cflags);
        }

        if(ws > 0) {
            double shift = pow(10,-1.0*ws);
            AddIpoptNumOption(nlp,"mu_init",shift);
            AddIpoptNumOption(nlp,"bound_mult_init_val",shift);
            AddIpoptStrOption(nlp,"mu_strategy", "monotone");
            AddIpoptNumOption(nlp,"bound_push", 1e-5);
            AddIpoptNumOption(nlp,"bound_frac", 1e-5);
            AddIpoptNumOption(nlp,"slack_bound_push", 1e-5);
            AddIpoptNumOption(nlp,"constr_mult_init_max", 1e-5);
            AddIpoptStrOption(nlp,"bound_mult_init_method","mu-based");
        } else {
            AddIpoptStrOption(nlp,"mu_strategy","adaptive");
            AddIpoptStrOption(nlp,"bound_mult_init_method","constant");
        }
        AddIpoptStrOption(nlp,"fixed_variable_treatment","make_parameter");
        AddIpoptStrOption(nlp,"dependency_detection_with_rhs","yes");
        AddIpoptNumOption(nlp,"nu_init",1e-9);
        AddIpoptNumOption(nlp,"eta_phi",1e-10);
    }

    /********************************************************************/


    if(max_iter >=0) {
        optData->iter_ = 0.0;
        optData->index = 1;
        res = IpoptSolve(nlp, vopt, NULL, &obj, mult_g, mult_x_L, mult_x_U, (void*)optData);
    }
    if(res != 0 && !ACTIVE_STREAM(LOG_IPOPT))
        warningStreamPrint(LOG_STDOUT, 0, "No optimal solution found!\nUse -lv=LOG_IPOPT for more information.");
    FreeIpoptProblem(nlp);
}
  /*! \fn ipopt_initialization
   *
   *  This function is used if ipopt is choosen for initialization.
   *
   *  \param [ref] [data]
   *  \param [ref] [initData]
   *  \param [in]  [useScaling]
   *
   *  \author lochel
   */
  int ipopt_initialization(DATA *data, INIT_DATA *initData, int useScaling)
  {
    int n = initData->nz;                /* number of variables */
    int m = (initData->nInitResiduals > initData->nz) ? 0 : initData->nInitResiduals;    /* number of constraints */
    double* x_L = NULL;                  /* lower bounds on x */
    double* x_U = NULL;                  /* upper bounds on x */
    double* g_L = NULL;                  /* lower bounds on g */
    double* g_U = NULL;                  /* upper bounds on g */

    double* x = NULL;                    /* starting point and solution vector */
    double* mult_g = NULL;               /* constraint multipliers at the solution */
    double* mult_x_L = NULL;             /* lower bound multipliers at the solution */
    double* mult_x_U = NULL;             /* upper bound multipliers at the solution */
    double obj;                          /* objective value */
    int i;                               /* generic counter */

    int nele_jac = n*m;                  /* number of nonzeros in the Jacobian of the constraints */
    int nele_hess = 0;                   /* number of nonzeros in the Hessian of the Lagrangian (lower or upper triangual part only) */

    IpoptProblem nlp = NULL;             /* ipopt-problem */
    enum ApplicationReturnStatus status; /* solve return code */

    IPOPT_DATA ipopt_data;

    ipopt_data.data = data;
    ipopt_data.initData = initData;
    ipopt_data.useScaling = useScaling;
    ipopt_data.useSymbolic = (initialAnalyticJacobianG(data) == 0 ? 1 : 0);

    if(ipopt_data.useSymbolic == 1)
    {
      nele_jac = data->simulationInfo.analyticJacobians[INDEX_JAC_G].sparsePattern.leadindex[n-1]; // sparse
      DEBUG_INFO1(LOG_INIT, "number of zeros in the Jacobian of the constraints (jac_g):    %d", n*m-nele_jac);
      DEBUG_INFO1(LOG_INIT, "number of nonzeros in the Jacobian of the constraints (jac_g): %d", nele_jac);
    }

    /* allocate space for the variable bounds */
    x_L = (double*)malloc(n * sizeof(double));
    x_U = (double*)malloc(n * sizeof(double));

    /* allocate space for the constraint bounds */
    g_L = (double*)malloc(m * sizeof(double));
    g_U = (double*)malloc(m * sizeof(double));

    /* allocate space for the initial point */
    x = (double*)malloc(n * sizeof(double));

    /* set values of optimization variable bounds */
    for(i=0; i<n; ++i)
    {
      x[i] = initData->start[i];
      x_L[i] = initData->min[i];
      x_U[i] = initData->max[i];
    }

    /* set values of constraint bounds */
    for(i=0; i<m; ++i)
    {
      g_L[i] = 0.0;
      g_U[i] = 0.0;
    }

    /* create the IpoptProblem */
    nlp = CreateIpoptProblem(
        n,              /* Number of optimization variables */
        x_L,            /* Lower bounds on variables */
        x_U,            /* Upper bounds on variables */
        m,              /* Number of constraints */
        g_L,            /* Lower bounds on constraints */
        g_U,            /* Upper bounds on constraints */
        nele_jac,       /* Number of non-zero elements in constraint Jacobian */
        nele_hess,      /* Number of non-zero elements in Hessian of Lagrangian */
        0,              /* indexing style for iRow & jCol; 0 for C style, 1 for Fortran style */
        &ipopt_f,       /* Callback function for evaluating objective function */
        &ipopt_g,       /* Callback function for evaluating constraint functions */
        &ipopt_grad_f,  /* Callback function for evaluating gradient of objective function */
        &ipopt_jac_g,   /* Callback function for evaluating Jacobian of constraint functions */
        &ipopt_h);      /* Callback function for evaluating Hessian of Lagrangian function */

    ASSERT(nlp, "creating of ipopt problem has failed");

    /* We can free the memory now - the values for the bounds have been
       copied internally in CreateIpoptProblem */
    free(x_L);
    free(x_U);
    free(g_L);
    free(g_U);

    /* Set some options. Note the following ones are only examples,
       they might not be suitable for your problem. */
    AddIpoptNumOption(nlp, "tol", 1e-7);

    AddIpoptIntOption(nlp, "print_level", DEBUG_FLAG(LOG_INIT) ? 5 : 0);
    AddIpoptIntOption(nlp, "max_iter", 5000);

    AddIpoptStrOption(nlp, "mu_strategy", "adaptive");
    AddIpoptStrOption(nlp, "hessian_approximation", "limited-memory");

    /* allocate space to store the bound multipliers at the solution */
    mult_g = (double*)malloc(m*sizeof(double));
    mult_x_L = (double*)malloc(n*sizeof(double));
    mult_x_U = (double*)malloc(n*sizeof(double));

    /* solve the problem */
    status = IpoptSolve(
        nlp,            /* Problem that is to be optimized */
        x,              /* Input: Starting point; Output: Optimal solution */
        NULL,           /* Values of constraint at final point */
        &obj,           /* Final value of objective function */
        mult_g,         /* Final multipliers for constraints */
        mult_x_L,       /* Final multipliers for lower variable bounds */
        mult_x_U,       /* Final multipliers for upper variable bounds */
        &ipopt_data);   /* Pointer to user data */

    setZ(initData, x);

    /* free allocated memory */
    FreeIpoptProblem(nlp);
    free(x);
    free(mult_g);
    free(mult_x_L);
    free(mult_x_U);

    /* debug output */
    DEBUG_INFO1(LOG_INIT, "ending with funcValue = %g", obj);
    DEBUG_INFO_AL(LOG_INIT, "| unfixed variables");
    for(i=0; i<initData->nz; i++)
      DEBUG_INFO_AL4(LOG_INIT, "| | [%ld] %s = %g [scaled: %g]", i+1, initData->name[i], initData->z[i], initData->zScaled[i]);
    DEBUG_INFO_AL(LOG_INIT, "| residuals (> 0.001)");
    for(i=0; i<data->modelData.nInitResiduals; i++)
      if(fabs(initData->initialResiduals[i]) > 1e-3)
        DEBUG_INFO_AL3(LOG_INIT, "| | [%ld] %g [scaled: %g]", i+1, initData->initialResiduals[i], (initData->residualScalingCoefficients[i] != 0.0) ? initData->initialResiduals[i]/initData->residualScalingCoefficients[i] : 0.0);

    if(status != Solve_Succeeded && status != Solved_To_Acceptable_Level)
      THROW("ipopt failed. see last warning. use [-lv LOG_INIT] for more output.");

    return (int)status;
  }
Example #5
0
/*!
 *  start main optimization step
 *  author: Vitalij Ruge
 **/
int startIpopt(DATA* data, SOLVER_INFO* solverInfo, int flag)
{
  int i;
  int j,k,l;
  double obj;
  int res;
  char *cflags;

  IpoptProblem nlp = NULL;
  IPOPT_DATA_ *iData = ((IPOPT_DATA_*)solverInfo->solverData);
  iData->current_var = 0;
  iData->current_time = 0;
  iData->data = data;
  iData->mayer = mayer(data, &obj);
  iData->lagrange = lagrange(data, &obj);
  iData->numObject = 2 - iData->mayer -iData->lagrange;

  iData->matrixA = initialAnalyticJacobianA((void*) iData->data);
  iData->matrixB = initialAnalyticJacobianB((void*) iData->data);
  /*
  iData->matrixC = initialAnalyticJacobianC((void*) iData->data);
  iData->matrixD = initialAnalyticJacobianD((void*) iData->data);
  */

  loadDAEmodel(data, iData);
  iData->index_debug_iter=0;
  iData->degub_step =  10;
  iData->index_debug_next=0;

    cflags = omc_flagValue[FLAG_LS_IPOPT];
    if(!cflags)
      cflags = "mumps";

  /*ToDo*/
  for(i=0; i<(*iData).nx; i++)
  {
    iData->Vmin[i] = (*iData).Vmax[i] = (*iData).x0[i]*iData->scalVar[i];
    iData->v[i] = iData->Vmin[i];

    if(ACTIVE_STREAM(LOG_IPOPT))
    {
      printf("\nx[%i] = %s = %g",i, iData->data->modelData.realVarsData[i].info.name,iData->v[i]);
    }
  }
  initial_guess_ipopt(iData,solverInfo);

  if(ACTIVE_STREAM(LOG_IPOPT))
  {
    for(; i<iData->nv; ++i)
      printf("\nu[%i] = %s = %g",i, iData->data->modelData.realVarsData[iData->index_u + i-iData->nx].info.name,iData->v[i]);
  }

  ipoptDebuge(iData,iData->v);

  if(flag == 5)
  {
     nlp = CreateIpoptProblem((*iData).NV, (*iData).Vmin, (*iData).Vmax,
         (*iData).NRes, (*iData).gmin, (*iData).gmax, (*iData).njac, NULL, 0, &evalfF,
                  &evalfG, &evalfDiffF, &evalfDiffG, &ipopt_h);

    AddIpoptNumOption(nlp, "tol", iData->data->simulationInfo.tolerance);

    if(ACTIVE_STREAM(LOG_IPOPT))
    {
      AddIpoptIntOption(nlp, "print_level", 5);
      AddIpoptIntOption(nlp, "file_print_level", 0);
    }
    else if(ACTIVE_STREAM(LOG_STATS))
    {
      AddIpoptIntOption(nlp, "print_level", 3);
      AddIpoptIntOption(nlp, "file_print_level", 0);
    }
    else
    {
      AddIpoptIntOption(nlp, "print_level", 2);
      AddIpoptIntOption(nlp, "file_print_level", 0);
    }

    AddIpoptStrOption(nlp, "mu_strategy", "adaptive");
    AddIpoptStrOption(nlp, "hessian_approximation", "limited-memory");

    if(cflags)
      AddIpoptStrOption(nlp, "linear_solver", cflags);
    else
      AddIpoptStrOption(nlp, "linear_solver", "mumps");

    /* AddIpoptStrOption(nlp, "derivative_test", "second-order"); */
    /* AddIpoptStrOption(nlp, "derivative_test_print_all", "yes"); */
    /* AddIpoptNumOption(nlp,"derivative_test_perturbation",1e-6); */
    AddIpoptIntOption(nlp, "max_iter", 5000);

    res = IpoptSolve(nlp, (*iData).v, NULL, &obj, (*iData).mult_g, (*iData).mult_x_L, (*iData).mult_x_U, (void*)iData);
    FreeIpoptProblem(nlp);

    if(ACTIVE_STREAM(LOG_IPOPT))
    {
      for(i =0; i<iData->nv;i++)
        if(iData->pFile[i])
          fclose(iData->pFile[i]);
      if(iData->pFile)
        free(iData->pFile);
    }

    iData->current_var = 0;
    res2file(iData,solverInfo);
  }
  return 0;
}
    SimTK::Real InteriorPointOptimizer::optimize(  Vector &results ) {

        int n = getOptimizerSystem().getNumParameters();
        int m = getOptimizerSystem().getNumConstraints();

        Index index_style = 0; /* C-style; start counting of rows and column indices at 0 */
        Index nele_hess = 0;
        Index nele_jac = n*m; /* always assume dense */

        // Parameter limits
        Number *x_L = NULL, *x_U = NULL;
        if( getOptimizerSystem().getHasLimits() ) {
           getOptimizerSystem().getParameterLimits( &x_L, &x_U);
        } else {
           x_U = new Number[n];
           x_L = new Number[n];
           for(int i=0;i<n;i++) {
              x_U[i] = SimTK::Real(POSITIVE_INF);
              x_L[i] = SimTK::Real(NEGATIVE_INF);
           }
        }

        SimTK::Real *x = &results[0];

        IpoptProblem nlp = CreateIpoptProblem(n, x_L, x_U, m, g_L, g_U, nele_jac, 
                           nele_hess, index_style, objectiveFuncWrapper, constraintFuncWrapper, 
                           gradientFuncWrapper, constraintJacobianWrapper, hessianWrapper);

        // If you want to verify which options are getting set in the optimizer, you can create a file ipopt.opt
        // with "print_user_options yes", and set print_level to (at least 1).  It will then print the options to the screen.
        
        // sherm 100302: you have to set all of these tolerances to get IpOpt to change
        // its convergence criteria; see OptimalityErrorConvergenceCheck::CheckConvergence().
        // We'll set acceptable tolerances to the same value to disable them.
        AddIpoptNumOption(nlp, "tol", convergenceTolerance);
        AddIpoptNumOption(nlp, "dual_inf_tol", convergenceTolerance);
        AddIpoptNumOption(nlp, "constr_viol_tol", constraintTolerance);
        AddIpoptNumOption(nlp, "compl_inf_tol", convergenceTolerance);
        AddIpoptNumOption(nlp, "acceptable_tol", convergenceTolerance);
        AddIpoptNumOption(nlp, "acceptable_dual_inf_tol", convergenceTolerance);
        AddIpoptNumOption(nlp, "acceptable_constr_viol_tol", constraintTolerance);
        AddIpoptNumOption(nlp, "acceptable_compl_inf_tol", convergenceTolerance);


        AddIpoptIntOption(nlp, "max_iter", maxIterations);
        AddIpoptStrOption(nlp, "mu_strategy", "adaptive");
        AddIpoptStrOption(nlp, "hessian_approximation", "limited-memory"); // needs to be limited-memory unless you have explicit hessians
        AddIpoptIntOption(nlp, "limited_memory_max_history", limitedMemoryHistory);
        AddIpoptIntOption(nlp, "print_level", diagnosticsLevel); // default is 4

        int i;
        static const char *advancedRealOptions[] = {
                                                    "compl_inf_tol", 
                                                    "dual_inf_tol", 
                                                    "constr_viol_tol", 
                                                    "acceptable_tol", 
                                                    "acceptable_compl_inf_tol", 
                                                    "acceptable_constr_viol_tol", 
                                                    "acceptable_dual_inf_tol", 
                                                    "diverging_iterates_tol", 
                                                    "barrier_tol_factor", 
                                                    "obj_scaling_factor", 
                                                    "nlp_scaling_max_gradient", 
                                                    "bounds_relax_factor", 
                                                    "recalc_y_feas_tol", 
                                                    "mu_init", 
                                                    "mu_max_fact", 
                                                    "mu_max", 
                                                    "mu_min", 
                                                    "mu_linear_decrease_factor", 
                                                    "mu_superlinear_decrease_factor", 
                                                    "bound_frac", 
                                                    "bound_push", 
                                                    "bound_mult_init_val", 
                                                    "constr_mult_init_max", 
                                                    "constr_mult_init_val", 
                                                    "warm_start_bound_push", 
                                                    "warm_start_bound_frac", 
                                                    "warm_start_mult_bound_push", 
                                                    "warm_start_mult_init_max", 
                                                    "recalc_y_feas_tol", 
                                                    "expect_infeasible_problem_ctol", 
                                                    "soft_resto_pderror_reduction_factor", 
                                                    "required_infeasibility_reduction", 
                                                    "bound_mult_reset_threshold", 
                                                    "constr_mult_reset_threshold", 
                                                    "max_hessian_perturbation", 
                                                    "min_hessian_perturbation", 
                                                    "first_hessian_perturbation", 
                                                    "perturb_inc_fact_first", 
                                                    "perturb_inc_fact", 
                                                    "perturb_dec_fact", 
                                                    "jacobian_reqularization_value", 
                                                    "derivative_test_perturbation", 
                                                    "derivative_test_tol", 
                                                    0}; 
        Real value;
        for(i=0;advancedRealOptions[i];i++) {
            if(getAdvancedRealOption(advancedRealOptions[i],value))
                AddIpoptNumOption(nlp, advancedRealOptions[i], value);
        }

        static const std::string advancedStrOptions[] = {"nlp_scaling_method",
                                                         "honor_original_bounds", 
                                                         "check_derivatives_for_naninf", 
                                                         "mu_strategy", 
                                                         "mu_oracle", 
                                                         "fixed_mu_oracle", 
                                                         "alpha_for_y", 
                                                         "recalc_y", 
                                                         "expect_infeasible_problem", 
                                                         "print_options_documentation", 
                                                         "print_user_options", 
                                                         "start_with_resto", 
                                                         "evaluate_orig_obj_at_resto_trial", 
                                                         "hessian_approximation", 
                                                         "derivative_test", 
                                                         ""}; 
        std::string svalue;
        for(i=0;!advancedStrOptions[i].empty();i++) {
            if(getAdvancedStrOption(advancedStrOptions[i], svalue))
                AddIpoptStrOption(nlp, advancedStrOptions[i].c_str(), svalue.c_str());
        }

        static const char*  advancedIntOptions[] = {"quality_function_max_section_steps",
                                                         "max_soc",
                                                         "watchdog_shorted_iter_trigger",
                                                         "watchdog_trial_iter_max",
                                                         "max_refinement_steps",
                                                         "min_refinement_steps",
                                                         "limited_memory_max_history",
                                                         "limited_memory_max_skipping",
                                                         "derivative_test_print_all",
                                                         0}; 
        int ivalue;
        for(i=0;advancedIntOptions[i];i++) {
            if(getAdvancedIntOption(advancedIntOptions[i], ivalue))
                AddIpoptIntOption(nlp, advancedIntOptions[i], ivalue);
        }

        // Only makes sense to do a warm start if this is not the first call to optimize() (since we need 
        // reasonable starting multiplier values)
        bool use_warm_start=false;
        if(getAdvancedBoolOption("warm_start", use_warm_start) && use_warm_start && !firstOptimization) {
            AddIpoptStrOption(nlp, "warm_start_init_point", "yes");
            AddIpoptStrOption(nlp, "warm_start_entire_iterate", "yes");
            //AddIpoptStrOption(nlp, "warm_start_same_structure", "yes"); // couldn't get this one to work
        } 

        SimTK::Real obj;

        int status = IpoptSolve(nlp, x, NULL, &obj, mult_g, mult_x_L, mult_x_U, (void *)this );

        FreeIpoptProblem(nlp); 

        // Only delete these if they aren't pointing to existing parameter limits
        if( !getOptimizerSystem().getHasLimits() ) {
           delete [] x_U;
           delete [] x_L;
        }

        if(status == Solved_To_Acceptable_Level) {
            std::cout << "Ipopt: Solved to acceptable level" << std::endl;
        } else if (status != Solve_Succeeded) {
            if( status != NonIpopt_Exception_Thrown) {
                char buf[1024];
                sprintf(buf, "Ipopt: %s (status %d)",applicationReturnStatusToString(status).c_str(),status);
                SimTK_THROW1(SimTK::Exception::OptimizerFailed, SimTK::String(buf));
            }
        }

        firstOptimization = false;

        return(obj);
    }