bool IASolverRelaxed::solve() { // solve the nlp to get a non-integral solution, which we hope is close to a good integer solution // adapted from HS071 ipopt example // p_norm set in constructor. 3 seems to work well, comes close to lex-max-min // smaller p has the effect of valuing the fidelity of shorter curves over longer curves more // larger p approaches min max IANlp *myianlp = new IANlp(iaData, iaSolution, silent); Ipopt::SmartPtr<TNLP> mynlp = myianlp; // Ipopt requires the use of smartptrs! Ipopt::SmartPtr<Ipopt::IpoptApplication> app = IpoptApplicationFactory(); app->Options()->SetNumericValue("tol", 1e-7); // 2 seems close enough, could do less, say .1 app->Options()->SetStringValue("mu_strategy", "adaptive"); // print level 0 to 12, most. Ipopt Default is 5 int print_level = (silent) ? 0 : 1; // 1, 5 // int print_level = 5; app->Options()->SetIntegerValue("print_level", print_level); // uncomment next line to write the solution to an output file // app->Options()->SetStringValue("output_file", "IA.out"); // The following overwrites the default name (ipopt.opt) of the options file // app->Options()->SetStringValue("option_file_name", "IA.opt"); // Intialize the IpoptApplication and process the options Ipopt::ApplicationReturnStatus status; status = app->Initialize(); if (status != Ipopt::Solve_Succeeded) { if (!silent) printf("\n\n*** Error during ipopt initialization!\n"); return (int) status; } // Ask Ipopt to solve the problem status = app->OptimizeTNLP(mynlp); // the inherited IANlp // todo: also check for a valid solution even if ! Solve_Succeeded, such as a sub-optimal time-out bool is_solved = (status == Ipopt::Solve_Succeeded); bool is_satisfied = is_solved && equal_constraints( false, debugging ); // don't check even-ness, as those are like the integrality constraints and are not solved here if (!silent) { if (is_solved) { printf("\n\n*** The relaxed problem solved!"); if (!is_satisfied) printf(" But equality-constraints were VIOLATED!"); printf("\n"); } else { printf("\n\n*** The relaxed problem FAILED!\n"); } } return is_satisfied; }
IpoptSolution CppADSolver::solve(OptProblemData &data){ size_t n = opt_prob->num_of_variables(); size_t m = opt_prob->num_of_constraints(); // create the Ipopt interface cppad_ipopt_solution solution; CppADOptProblemData cppad_data(data); Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new cppad_ipopt_nlp( n, m, cppad_data.x_i, cppad_data.x_l, cppad_data.x_u, cppad_data.g_l, cppad_data.g_u, &(*fg_info_ptr), &solution ); // Create an instance of the IpoptApplication Ipopt::SmartPtr<Ipopt::IpoptApplication> app = new IpoptApplication(); // turn off any printing app->Options()->SetIntegerValue("print_level", 4); app->Options()->SetStringValue("sb", "yes"); // maximum number of iterations app->Options()->SetIntegerValue("max_iter", 5000); // 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(); assert(status == Ipopt::Solve_Succeeded); // Run the IpoptApplication status = app->OptimizeTNLP(cppad_nlp); return IpoptSolution(solution); }
bool retape_k1_l1(void) { bool ok = true; size_t j; // number of independent variables (domain dimension for f and g) size_t n = 2; // number of constraints (range dimension for g) size_t m = 1; // initial value of the independent variables NumberVector x_i(n); x_i[0] = 2.0; x_i[1] = 2.0; // lower and upper limits for x NumberVector x_l(n); NumberVector x_u(n); for(j = 0; j < n; j++) { x_l[j] = -10.; x_u[j] = +10.; } // lower and upper limits for g NumberVector g_l(m); NumberVector g_u(m); g_l[0] = -1.; g_u[0] = 1.0e19; // object in derived class FG_retape fg_retape; cppad_ipopt_fg_info *fg_info = &fg_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"); // 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., 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 ); } return ok; }
bool multiple_solution(void) { bool ok = true; // number of independent variables (domain dimension for f and g) size_t n = 2; // number of constraints (range dimension for g) size_t m = 2; // initial value of the independent variables NumberVector x_i(n); NumberVector x_l(n); NumberVector x_u(n); size_t i = 0; for(i = 0; i < n; i++) { x_i[i] = 0.; x_l[i] = -1.0; x_u[i] = +1.0; } // lower and upper limits for g NumberVector g_l(m); NumberVector g_u(m); g_l[0] = -1; g_u[0] = 0.; g_l[1] = 0.; g_u[1] = 1.; // object for evaluating function bool retape = false; FG_J_changes my_fg_info(retape); cppad_ipopt_fg_info *fg_info = &my_fg_info; 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"); // 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); app->Options()-> SetStringValue("derivative_test", "second-order"); // 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 solution status */ ok &= solution.status == cppad_ipopt_solution::success; ok &= CppAD::NearEqual(solution.x[1], 0., 1e-6, 1e-6); return ok; }
bool k_gt_one(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; // known solution to check against double check_x[] = { 1.000000, 4.743000, 3.82115, 1.379408 }; 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 = bool(icase); // check case where upper and lower limits are equal if( icase == 1 ) { x_l[2] = check_x[2]; x_u[2] = check_x[2]; } // object in derived class FG_K_gt_one my_fg_info(retape); cppad_ipopt_fg_info *fg_info = &my_fg_info; // 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); // 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"); // 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_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; }
void solve( const std::string& options , const Dvector& xi , const Dvector& xl , const Dvector& xu , const Dvector& gl , const Dvector& gu , FG_eval& fg_eval , ipopt::solve_result<Dvector>& solution ) { bool ok = true; typedef typename FG_eval::ADvector ADvector; CPPAD_ASSERT_KNOWN( xi.size() == xl.size() && xi.size() == xu.size() , "ipopt::solve: size of xi, xl, and xu are not all equal." ); CPPAD_ASSERT_KNOWN( gl.size() == gu.size() , "ipopt::solve: size of gl and gu are not equal." ); size_t nx = xi.size(); size_t ng = gl.size(); // Create an IpoptApplication using Ipopt::IpoptApplication; Ipopt::SmartPtr<IpoptApplication> app = new IpoptApplication(); // process the options argument size_t begin_1, end_1, begin_2, end_2, begin_3, end_3; begin_1 = 0; bool retape = false; bool sparse_forward = false; bool sparse_reverse = false; while( begin_1 < options.size() ) { // split this line into tokens while( options[begin_1] == ' ') begin_1++; end_1 = options.find_first_of(" \n", begin_1); begin_2 = end_1; while( options[begin_2] == ' ') begin_2++; end_2 = options.find_first_of(" \n", begin_2); begin_3 = end_2; while( options[begin_3] == ' ') begin_3++; end_3 = options.find_first_of(" \n", begin_3); // check for errors CPPAD_ASSERT_KNOWN( (end_1 != std::string::npos) & (end_2 != std::string::npos) & (end_3 != std::string::npos) , "ipopt::solve: missing '\\n' at end of an option line" ); CPPAD_ASSERT_KNOWN( (end_1 > begin_1) & (end_2 > begin_2) , "ipopt::solve: an option line does not have two tokens" ); // get first two tokens std::string tok_1 = options.substr(begin_1, end_1 - begin_1); std::string tok_2 = options.substr(begin_2, end_2 - begin_2); // get third token std::string tok_3; bool three_tok = false; three_tok |= tok_1 == "Sparse"; three_tok |= tok_1 == "String"; three_tok |= tok_1 == "Numeric"; three_tok |= tok_1 == "Integer"; if( three_tok ) { CPPAD_ASSERT_KNOWN( (end_3 > begin_3) , "ipopt::solve: a Sparse, String, Numeric, or Integer\n" "option line does not have three tokens." ); tok_3 = options.substr(begin_3, end_3 - begin_3); } // switch on option type if( tok_1 == "Retape" ) { CPPAD_ASSERT_KNOWN( (tok_2 == "true") | (tok_2 == "false") , "ipopt::solve: Retape value is not true or false" ); retape = (tok_2 == "true"); } else if( tok_1 == "Sparse" ) { CPPAD_ASSERT_KNOWN( (tok_2 == "true") | (tok_2 == "false") , "ipopt::solve: Sparse value is not true or false" ); CPPAD_ASSERT_KNOWN( (tok_3 == "forward") | (tok_3 == "reverse") , "ipopt::solve: Sparse direction is not forward or reverse" ); if( tok_2 == "false" ) { sparse_forward = false; sparse_reverse = false; } else { sparse_forward = tok_3 == "forward"; sparse_reverse = tok_3 == "reverse"; } } else if ( tok_1 == "String" ) app->Options()->SetStringValue(tok_2.c_str(), tok_3.c_str()); else if ( tok_1 == "Numeric" ) { Ipopt::Number value = std::atof( tok_3.c_str() ); app->Options()->SetNumericValue(tok_2.c_str(), value); } else if ( tok_1 == "Integer" ) { Ipopt::Index value = std::atoi( tok_3.c_str() ); app->Options()->SetIntegerValue(tok_2.c_str(), value); } else CPPAD_ASSERT_KNOWN( false, "ipopt::solve: First token is not one of\n" "Retape, Sparse, String, Numeric, Integer" ); begin_1 = end_3; while( options[begin_1] == ' ') begin_1++; if( options[begin_1] != '\n' ) CPPAD_ASSERT_KNOWN( false, "ipopt::solve: either more than three tokens " "or no '\\n' at end of a line" ); begin_1++; } CPPAD_ASSERT_KNOWN( ! ( retape & (sparse_forward | sparse_reverse) ) , "ipopt::solve: retape and sparse both true is not supported." ); // Initialize the IpoptApplication and process the options Ipopt::ApplicationReturnStatus status = app->Initialize(); ok &= status == Ipopt::Solve_Succeeded; if( ! ok ) { solution.status = solve_result<Dvector>::unknown; return; } // Create an interface from Ipopt to this specific problem. // Note the assumption here that ADvector is same as cppd_ipopt::ADvector size_t nf = 1; Ipopt::SmartPtr<Ipopt::TNLP> cppad_nlp = new CppAD::ipopt::solve_callback<Dvector, ADvector, FG_eval>( nf, nx, ng, xi, xl, xu, gl, gu, fg_eval, retape, sparse_forward, sparse_reverse, solution ); // Run the IpoptApplication app->OptimizeTNLP(cppad_nlp); return; }
bool IASolverInt::solve_round() { // set up and call the separate IARoundingNlp, which has a linear objective to get a natural integer solution // the intuition is this will solve integrality for most variables all at once if (debugging) { printf("IASolverInt::solve_bend_workhorse() - "); } // solver setup Ipopt::SmartPtr<Ipopt::IpoptApplication> app = IpoptApplicationFactory(); // convergence parameters // see $IPOPTDIR/Ipopt/src/Interfaces/IpIpoptApplication.cpp // our real criteria are: all integer, constraints satisfied. How to test the "all_integer" part? app->Options()->SetNumericValue("tol", 1e-6); //"converged" if NLP error<this, default is 1e-7. Obj are scaled to be >1, so e-2 is plenty // was 1e-2 app->Options()->SetNumericValue("max_cpu_time", sqrt( iaData->num_variables() ) ); // max time allowed in seconds app->Options()->SetIntegerValue("max_iter", 3 * iaData->num_variables() ); // max number of iterations // app->Options()->SetNumericValue("primal_inf_tol", 1e-2 ); app->Options()->SetNumericValue("dual_inf_tol", 1e-6 ); // how close to infeasibility? // was 1e-2 app->Options()->SetNumericValue("constr_viol_tol", 1e-6 ); // by how much can constraints be violated? app->Options()->SetNumericValue("compl_inf_tol", 1e-6 ); // max norm of complementary condition // was 1e-2 // second criteria convergence parameters: quit if within this tol for many iterations // was app->Options()->SetIntegerValue("acceptable_iter", 4 + sqrt( iaData->num_variables() ) ); //as "tol" app->Options()->SetNumericValue("acceptable_tol", 1e-6 ); //as "tol" was 1e-1 app->Options()->SetStringValue("mu_strategy", "adaptive"); // print level 0 to 12, Ipopt default is 5 const int print_level = (silent) ? 0 : 1; app->Options()->SetIntegerValue("print_level", print_level); // uncomment next line to write the solution to an output file // app->Options()->SetStringValue("output_file", "IA.out"); // The following overwrites the default name (ipopt.opt) of the options file // app->Options()->SetStringValue("option_file_name", "IA.opt"); // Intialize the IpoptApplication and process the options Ipopt::ApplicationReturnStatus status; status = app->Initialize(); if (status != Ipopt::Solve_Succeeded) { if (!silent) printf("\n\n*** Error during initialization!\n"); return (int) status; } Ipopt::TNLP *tnlp = NULL; IARoundingNlp *myianlp = new IARoundingNlp(iaData, ipData, iaSolution, silent); if (debugging) { printf("ROUNDING problem formulation\n"); printf("Attempting to find a naturally-integer solution by linearizing the objective function.\n"); printf("Variables are constrained within [floor,ceil] of relaxed solution.\n"); } // problem setup // a couple of different models, simplest to more complex // IARoundingFarNlp *myianlp = new IARoundingFarNlp(iaData, ipData, this); // IARoundingFar3StepNlp *myianlp = new IARoundingFar3StepNlp(iaData, ipData, this); // haven't tested this. It compiles and runs but perhaps isn't correct // IAIntWaveNlp *myianlp = new IAIntWaveNlp(iaData, ipData, this); // haven't tested this. It compiles and runs but perhaps isn't correct tnlp = myianlp; Ipopt::SmartPtr<Ipopt::TNLP> mynlp = tnlp; // Ipopt requires the use of smartptrs! bool try_again = true; int iter = 0; do { printf("%d rounding iteration\n", iter ); // Ask Ipopt to solve the problem status = app->OptimizeTNLP(mynlp); // the inherited IANlp if (!silent) { if (status == Ipopt::Solve_Succeeded) { printf("\n\n*** The problem solved!\n"); } else { printf("\n\n*** The problem FAILED!\n"); } } // The problem should have been feasible, but it is possible that it had no integer solution. // figure out which variables are still integer // check solution for integrality and constraint satified if (debugging) { printf("\nChecking Natural (non-rounded) solution.\n"); bool integer_sat = solution_is_integer(true); bool even_sat = even_constraints( false, true); bool equal_sat = equal_constraints( false, true ); printf("Natural solution summary, %s, equal-constraints %s, even-constraints %s.\n", integer_sat ? "integer" : "NON-INTEGER", equal_sat ? "satisfied" : "VIOLATED", even_sat ? "satisfied" : "VIOLATED" ); if (!integer_sat) printf("investigate this\n"); } IASolution nlp_solution; nlp_solution.x_solution = ia_solution()->x_solution; // vector copy IASolverToolInt sti( ia_data(), &nlp_solution ); sti.round_solution(); if (debugging) printf("Checking rounded solution, ignoring even constraints.\n"); if (sti.equal_constraints(false, debugging)) { // also even constraints if (debugging) printf("Rounding worked.\n"); // rounding was a valid integer solution ia_solution()->x_solution.swap( nlp_solution.x_solution ); // ia_solution()->obj_value is no longer accurate, as it was for the non-rounded solution return true; } // find out which vars were not integer, // try rounding their weights and resolving // bool int_sat = solution_is_integer(); ++iter; try_again = iter < 4 + sqrt(iaData->num_variables()); if (try_again) { if (debugging) printf("rounding failed, randomizing weights\n"); myianlp->randomize_weights_of_non_int(); // try again? debug } else if (debugging) printf("giving up on rounding to non-integer solution\n"); // try_again = false; // debug } while (try_again); // todo: update partially-integer solution, perhaps using ipData - figure out how we're going to use it, first, for what structure makes sense. // As the SmartPtrs go out of scope, the reference count // will be decremented and the objects will automatically // be deleted. return status == Ipopt::Solve_Succeeded; }