bool IndexPCalculator::InitializeImpl(const OptionsList& options, const std::string& prefix) { DBG_START_METH("IndexPCalculator::InitializeImpl", dbg_verbosity); SmartPtr<const IteratesVector> iv = IpData().curr(); nrows_ = 0; for (Index i=0; i<iv->NComps(); ++i) { nrows_+=iv->GetComp(i)->Dim(); } data_A()->Print(Jnlst(),J_VECTOR,J_USER1,"PCalc SchurData"); return true; }
ESymSolverStatus AugRestoSystemSolver::Solve(const SymMatrix* W, double W_factor, const Vector* D_x, double delta_x, const Vector* D_s, double delta_s, const Matrix* J_c, const Vector* D_c, double delta_c, const Matrix* J_d, const Vector* D_d, double delta_d, const Vector& rhs_x, const Vector& rhs_s, const Vector& rhs_c, const Vector& rhs_d, Vector& sol_x, Vector& sol_s, Vector& sol_c, Vector& sol_d, bool check_NegEVals, Index numberOfNegEVals) { DBG_START_METH("AugRestoSystemSolver::Solve",dbg_verbosity); DBG_ASSERT(J_c && J_d); // should pass these by ref // I think the comment below is incorrect // Remember, W and the D's may be NULL! // ToDo: I don't think the W's can ever be NULL (we always need the structure) DBG_ASSERT(W); SmartPtr<const CompoundSymMatrix> CW = static_cast<const CompoundSymMatrix*>(W); SmartPtr<const CompoundVector> CD_x = static_cast<const CompoundVector*>(D_x); SmartPtr<const CompoundMatrix> CJ_c = static_cast<const CompoundMatrix*>(J_c); DBG_ASSERT(IsValid(CJ_c)); SmartPtr<const CompoundMatrix> CJ_d = static_cast<const CompoundMatrix*>(J_d); DBG_ASSERT(IsValid(CJ_d)); SmartPtr<const CompoundVector> Crhs_x = static_cast<const CompoundVector*>(&rhs_x); DBG_ASSERT(IsValid(Crhs_x)); SmartPtr<CompoundVector> Csol_x = static_cast<CompoundVector*>(&sol_x); DBG_ASSERT(IsValid(Csol_x)); // Get the Sigma inverses SmartPtr<const Vector> sigma_n_c; SmartPtr<const Vector> sigma_p_c; SmartPtr<const Vector> sigma_n_d; SmartPtr<const Vector> sigma_p_d; if (IsValid(CD_x)) { sigma_n_c = CD_x->GetComp(1); sigma_p_c = CD_x->GetComp(2); sigma_n_d = CD_x->GetComp(3); sigma_p_d = CD_x->GetComp(4); } SmartPtr<const Vector> sigma_tilde_n_c_inv = Sigma_tilde_n_c_inv(sigma_n_c, delta_x, *Crhs_x->GetComp(1)); SmartPtr<const Vector> sigma_tilde_p_c_inv = Sigma_tilde_p_c_inv(sigma_p_c, delta_x, *Crhs_x->GetComp(2)); SmartPtr<const Vector> sigma_tilde_n_d_inv = Sigma_tilde_n_d_inv(sigma_n_d, delta_x, *Crhs_x->GetComp(3)); SmartPtr<const Vector> sigma_tilde_p_d_inv = Sigma_tilde_p_d_inv(sigma_p_d, delta_x, *Crhs_x->GetComp(4)); // Pull out the expansion matrices for d SmartPtr<const Matrix> pd_l = CJ_d->GetComp(0,3); SmartPtr<const Matrix> neg_pd_u = CJ_d->GetComp(0,4); // Now map the correct entries into the Solve method // pull out the parts of the hessian h_orig + diag DBG_PRINT_MATRIX(2, "CW", *CW); SmartPtr<const SymMatrix> h_orig; SmartPtr<const Vector> D_xR; SmartPtr<const SumSymMatrix> WR_sum = dynamic_cast<const SumSymMatrix*>(GetRawPtr(CW->GetComp(0,0))); Number orig_W_factor = W_factor; if (IsValid(WR_sum)) { // We seem to be in the regular situation with exact second // derivatives double temp_factor; WR_sum->GetTerm(0, temp_factor, h_orig); DBG_ASSERT(temp_factor == 1. || temp_factor == 0.); orig_W_factor = temp_factor * W_factor; SmartPtr<const SymMatrix> eta_DR; double factor; WR_sum->GetTerm(1, factor, eta_DR); SmartPtr<const Vector> wr_d = static_cast<const DiagMatrix*>(GetRawPtr(eta_DR))->GetDiag(); if (IsValid(CD_x)) { D_xR = D_x_plus_wr_d(CD_x->GetComp(0), factor, *wr_d); } else { D_xR = D_x_plus_wr_d(NULL, factor, *wr_d); } } else { // Looks like limited memory quasi-Newton stuff const LowRankUpdateSymMatrix* LR_W = static_cast<const LowRankUpdateSymMatrix*>(GetRawPtr(CW->GetComp(0,0))); DBG_ASSERT(LR_W); h_orig = LR_W; if (IsValid(CD_x)) { D_xR = CD_x->GetComp(0); } else { D_xR = NULL; } } Number delta_xR = delta_x; SmartPtr<const Vector> D_sR = D_s; Number delta_sR = delta_s; SmartPtr<const Matrix> J_cR = CJ_c->GetComp(0,0); SmartPtr<const Vector> D_cR = Neg_Omega_c_plus_D_c(sigma_tilde_n_c_inv, sigma_tilde_p_c_inv, D_c, rhs_c); DBG_PRINT((1,"D_cR tag = %d\n",D_cR->GetTag())); Number delta_cR = delta_c; SmartPtr<const Matrix> J_dR = CJ_d->GetComp(0,0); SmartPtr<const Vector> D_dR = Neg_Omega_d_plus_D_d(*pd_l, sigma_tilde_n_d_inv, *neg_pd_u, sigma_tilde_p_d_inv, D_d, rhs_d); Number delta_dR = delta_d; SmartPtr<const Vector> rhs_xR = Crhs_x->GetComp(0); SmartPtr<const Vector> rhs_sR = &rhs_s; SmartPtr<const Vector> rhs_cR = Rhs_cR(rhs_c, sigma_tilde_n_c_inv, *Crhs_x->GetComp(1), sigma_tilde_p_c_inv, *Crhs_x->GetComp(2)); SmartPtr<const Vector> rhs_dR = Rhs_dR(rhs_d, sigma_tilde_n_d_inv, *Crhs_x->GetComp(3), *pd_l, sigma_tilde_p_d_inv, *Crhs_x->GetComp(4), *neg_pd_u); SmartPtr<Vector> sol_xR = Csol_x->GetCompNonConst(0); Vector& sol_sR = sol_s; Vector& sol_cR = sol_c; Vector& sol_dR = sol_d; ESymSolverStatus status = orig_aug_solver_->Solve(GetRawPtr(h_orig), orig_W_factor, GetRawPtr(D_xR), delta_xR, GetRawPtr(D_sR), delta_sR, GetRawPtr(J_cR), GetRawPtr(D_cR), delta_cR, GetRawPtr(J_dR), GetRawPtr(D_dR), delta_dR, *rhs_xR, *rhs_sR, *rhs_cR, *rhs_dR, *sol_xR, sol_sR, sol_cR, sol_dR, check_NegEVals, numberOfNegEVals); if (status == SYMSOLVER_SUCCESS) { // Now back out the solutions for the n and p variables SmartPtr<Vector> sol_n_c = Csol_x->GetCompNonConst(1); sol_n_c->Set(0.0); if (IsValid(sigma_tilde_n_c_inv)) { sol_n_c->AddTwoVectors(1., *Crhs_x->GetComp(1), -1.0, sol_cR, 0.); sol_n_c->ElementWiseMultiply(*sigma_tilde_n_c_inv); } SmartPtr<Vector> sol_p_c = Csol_x->GetCompNonConst(2); sol_p_c->Set(0.0); if (IsValid(sigma_tilde_p_c_inv)) { DBG_PRINT_VECTOR(2, "rhs_pc", *Crhs_x->GetComp(2)); DBG_PRINT_VECTOR(2, "delta_y_c", sol_cR); DBG_PRINT_VECTOR(2, "Sig~_{p_c}^{-1}", *sigma_tilde_p_c_inv); sol_p_c->AddTwoVectors(1., *Crhs_x->GetComp(2), 1.0, sol_cR, 0.); sol_p_c->ElementWiseMultiply(*sigma_tilde_p_c_inv); } SmartPtr<Vector> sol_n_d = Csol_x->GetCompNonConst(3); sol_n_d->Set(0.0); if (IsValid(sigma_tilde_n_d_inv)) { pd_l->TransMultVector(-1.0, sol_dR, 0.0, *sol_n_d); sol_n_d->Axpy(1.0, *Crhs_x->GetComp(3)); sol_n_d->ElementWiseMultiply(*sigma_tilde_n_d_inv); } SmartPtr<Vector> sol_p_d = Csol_x->GetCompNonConst(4); sol_p_d->Set(0.0); if (IsValid(sigma_tilde_p_d_inv)) { neg_pd_u->TransMultVector(-1.0, sol_dR, 0.0, *sol_p_d); sol_p_d->Axpy(1.0, *Crhs_x->GetComp(4)); sol_p_d->ElementWiseMultiply(*sigma_tilde_p_d_inv); } } return status; }
bool MinC_1NrmRestorationPhase::PerformRestoration() { DBG_START_METH("MinC_1NrmRestorationPhase::PerformRestoration", dbg_verbosity); // Increase counter for restoration phase calls count_restorations_++; Jnlst().Printf(J_DETAILED, J_MAIN, "Starting Restoration Phase for the %d. time\n", count_restorations_); DBG_ASSERT(IpCq().curr_constraint_violation()>0.); // ToDo set those up during initialize? // Create the restoration phase NLP etc objects SmartPtr<IpoptData> resto_ip_data = new IpoptData(); SmartPtr<IpoptNLP> resto_ip_nlp = new RestoIpoptNLP(IpNLP(), IpData(), IpCq()); SmartPtr<IpoptCalculatedQuantities> resto_ip_cq = new IpoptCalculatedQuantities(resto_ip_nlp, resto_ip_data); // Determine if this is a square problem bool square_problem = IpCq().IsSquareProblem(); // Decide if we want to use the original option or want to make // some changes SmartPtr<OptionsList> actual_resto_options = resto_options_; if(square_problem) { actual_resto_options = new OptionsList(*resto_options_); // If this is a square problem, the want the restoration phase // never to be left until the problem is converged actual_resto_options->SetNumericValue("resto.required_infeasibility_reduction", 0.); } else if (expect_infeasible_problem_ && count_restorations_==1) { if (IpCq().curr_constraint_violation()>1e-3) { actual_resto_options = new OptionsList(*resto_options_); // Ask for significant reduction of infeasibility, in the hope // that we do not return from the restoration phase is the // problem is infeasible actual_resto_options->SetNumericValue("resto.required_infeasibility_reduction", 1e-3); } } // Initialize the restoration phase algorithm resto_alg_->Initialize(Jnlst(), *resto_ip_nlp, *resto_ip_data, *resto_ip_cq, *actual_resto_options, "resto."); // Set iteration counter and info field for the restoration phase resto_ip_data->Set_iter_count(IpData().iter_count()+1); resto_ip_data->Set_info_regu_x(IpData().info_regu_x()); resto_ip_data->Set_info_alpha_primal(IpData().info_alpha_primal()); resto_ip_data->Set_info_alpha_primal_char(IpData().info_alpha_primal_char()); resto_ip_data->Set_info_alpha_dual(IpData().info_alpha_dual()); resto_ip_data->Set_info_ls_count(IpData().info_ls_count()); // Call the optimization algorithm to solve the restoration phase // problem SolverReturn resto_status = resto_alg_->Optimize(); int retval=-1; if (resto_status == SUCCESS) { if (Jnlst().ProduceOutput(J_DETAILED, J_LINE_SEARCH)) { Jnlst().Printf(J_DETAILED, J_LINE_SEARCH, "\nRESTORATION PHASE RESULTS\n"); Jnlst().Printf(J_DETAILED, J_LINE_SEARCH, "\n\nOptimal solution found! \n"); Jnlst().Printf(J_DETAILED, J_LINE_SEARCH, "Optimal Objective Value = %.16E\n", resto_ip_cq->curr_f()); Jnlst().Printf(J_DETAILED, J_LINE_SEARCH, "Number of Iterations = %d\n", resto_ip_data->iter_count()); } if (Jnlst().ProduceOutput(J_VECTOR, J_LINE_SEARCH)) { resto_ip_data->curr()->Print(Jnlst(), J_VECTOR, J_LINE_SEARCH, "curr"); } retval = 0; } else if (resto_status == STOP_AT_TINY_STEP || resto_status == STOP_AT_ACCEPTABLE_POINT) { Number orig_primal_inf = IpCq().curr_primal_infeasibility(NORM_MAX); // ToDo make the factor in following line an option if (orig_primal_inf <= 1e2*IpData().tol()) { Jnlst().Printf(J_WARNING, J_LINE_SEARCH, "Restoration phase converged to a point with small primal infeasibility.\n"); THROW_EXCEPTION(RESTORATION_CONVERGED_TO_FEASIBLE_POINT, "Restoration phase converged to a point with small primal infeasibility"); } else { THROW_EXCEPTION(LOCALLY_INFEASIBLE, "Restoration phase converged to a point of local infeasibility"); } } else if (resto_status == MAXITER_EXCEEDED) { THROW_EXCEPTION(RESTORATION_MAXITER_EXCEEDED, "Maximal number of iterations exceeded in restoration phase."); } else if (resto_status == LOCAL_INFEASIBILITY) { // converged to locally infeasible point - pass this on to the outer algorithm... THROW_EXCEPTION(LOCALLY_INFEASIBLE, "Restoration phase converged to a point of local infeasibility"); } else if (resto_status == RESTORATION_FAILURE) { Jnlst().Printf(J_WARNING, J_LINE_SEARCH, "Restoration phase in the restoration phase failed.\n"); THROW_EXCEPTION(RESTORATION_FAILED, "Restoration phase in the restoration phase failed."); } else if (resto_status == USER_REQUESTED_STOP) { // Use requested stop during restoration phase - rethrow exception THROW_EXCEPTION(RESTORATION_USER_STOP, "User requested stop during restoration phase"); } else { Jnlst().Printf(J_ERROR, J_MAIN, "Sorry, things failed ?!?!\n"); retval = 1; } if (retval == 0) { // Copy the results into the trial fields;. They will be // accepted later in the full algorithm SmartPtr<const CompoundVector> cx = dynamic_cast<const CompoundVector*>(GetRawPtr(resto_ip_data->curr()->x())); DBG_ASSERT(IsValid(cx)); SmartPtr<IteratesVector> trial = IpData().trial()->MakeNewContainer(); trial->Set_primal(*cx->GetComp(0), *resto_ip_data->curr()->s()); IpData().set_trial(trial); // If this is a square problem, we are done because a // sufficiently feasible point has been found if (square_problem) { Jnlst().Printf(J_DETAILED, J_LINE_SEARCH, "Recursive restoration phase algorithm termined successfully for square problem.\n"); IpData().AcceptTrialPoint(); THROW_EXCEPTION(FEASIBILITY_PROBLEM_SOLVED, "Restoration phase converged to sufficiently feasible point of original square problem."); } // Update the bound multiplers, pretending that the entire // progress in x and s in the restoration phase has been one // [rimal-dual Newton step (and therefore the result of solving // an augmented system) SmartPtr<IteratesVector> delta = IpData().curr()->MakeNewIteratesVector(true); delta->Set(0.0); ComputeBoundMultiplierStep(*delta->z_L_NonConst(), *IpData().curr()->z_L(), *IpCq().curr_slack_x_L(), *IpCq().trial_slack_x_L()); ComputeBoundMultiplierStep(*delta->z_U_NonConst(), *IpData().curr()->z_U(), *IpCq().curr_slack_x_U(), *IpCq().trial_slack_x_U()); ComputeBoundMultiplierStep(*delta->v_L_NonConst(), *IpData().curr()->v_L(), *IpCq().curr_slack_s_L(), *IpCq().trial_slack_s_L()); ComputeBoundMultiplierStep(*delta->v_U_NonConst(), *IpData().curr()->v_U(), *IpCq().curr_slack_s_U(), *IpCq().trial_slack_s_U()); DBG_PRINT_VECTOR(1, "delta_z_L", *delta->z_L()); DBG_PRINT_VECTOR(1, "delta_z_U", *delta->z_U()); DBG_PRINT_VECTOR(1, "delta_v_L", *delta->v_L()); DBG_PRINT_VECTOR(1, "delta_v_U", *delta->v_U()); Number alpha_dual = IpCq().dual_frac_to_the_bound(IpData().curr_tau(), *delta->z_L_NonConst(), *delta->z_U_NonConst(), *delta->v_L_NonConst(), *delta->v_U_NonConst()); Jnlst().Printf(J_DETAILED, J_LINE_SEARCH, "Step size for bound multipliers: %8.2e\n", alpha_dual); IpData().SetTrialBoundMultipliersFromStep(alpha_dual, *delta->z_L(), *delta->z_U(), *delta->v_L(), *delta->v_U() ); // ToDo: Check what to do here: Number bound_mult_max = Max(IpData().trial()->z_L()->Amax(), IpData().trial()->z_U()->Amax(), IpData().trial()->v_L()->Amax(), IpData().trial()->v_U()->Amax()); if (bound_mult_max > bound_mult_reset_threshold_) { trial = IpData().trial()->MakeNewContainer(); Jnlst().Printf(J_DETAILED, J_LINE_SEARCH, "Bound multipliers after restoration phase too large (max=%8.2e). Set all to 1.\n", bound_mult_max); trial->create_new_z_L(); trial->create_new_z_U(); trial->create_new_v_L(); trial->create_new_v_U(); trial->z_L_NonConst()->Set(1.0); trial->z_U_NonConst()->Set(1.0); trial->v_L_NonConst()->Set(1.0); trial->v_U_NonConst()->Set(1.0); IpData().set_trial(trial); } DefaultIterateInitializer::least_square_mults( Jnlst(), IpNLP(), IpData(), IpCq(), eq_mult_calculator_, constr_mult_reset_threshold_); DBG_PRINT_VECTOR(2, "y_c", *IpData().curr()->y_c()); DBG_PRINT_VECTOR(2, "y_d", *IpData().curr()->y_d()); IpData().Set_iter_count(resto_ip_data->iter_count()-1); // Skip the next line, because it would just replicate the first // on during the restoration phase. IpData().Set_info_skip_output(true); } return (retval == 0); }