bool InexactSearchDirCalculator::ComputeSearchDirection() { DBG_START_METH("InexactSearchDirCalculator::ComputeSearchDirection", dbg_verbosity); // First check if the iterates have converged to a locally // infeasible point Number curr_scaled_Ac_norm = InexCq().curr_scaled_Ac_norm(); Jnlst().Printf(J_DETAILED, J_SOLVE_PD_SYSTEM, "curr_scaled_Ac_norm = %e\n", curr_scaled_Ac_norm); Number curr_inf = IpCq().curr_primal_infeasibility(NORM_2); // ToDo work on termination criteria if( curr_scaled_Ac_norm <= local_inf_Ac_tol_ && curr_inf > 1e-4 ) { THROW_EXCEPTION(LOCALLY_INFEASIBLE, "The scaled norm of Ac is satisfying tolerance"); } bool compute_normal = false; switch( decomposition_type_ ) { case ALWAYS: compute_normal = true; break; case ADAPTIVE: compute_normal = InexData().next_compute_normal(); break; case SWITCH_ONCE: compute_normal = InexData().next_compute_normal() || InexData().compute_normal(); break; } SmartPtr<Vector> normal_x; SmartPtr<Vector> normal_s; bool retval; SmartPtr<IteratesVector> delta; SmartPtr<const IteratesVector> curr = IpData().curr(); SmartPtr<IteratesVector> rhs; SmartPtr<Vector> tmp; // Now we set up the primal-dual system for computing the // tangential step and the search direction for the multipliers. // This is taken from IpPDSearchDirCal.cpp (rev 549). // We do not need entries for the variable bound multipliers // Upper part of right-hand-side vector is same for both systems rhs = curr->MakeNewContainer(); tmp = curr->x()->MakeNew(); tmp->AddOneVector(-1., *IpCq().curr_grad_lag_with_damping_x(), 0.); rhs->Set_x(*tmp); tmp = curr->s()->MakeNew(); tmp->AddOneVector(-1., *IpCq().curr_grad_lag_with_damping_s(), 0.); rhs->Set_s(*tmp); tmp = curr->v_L()->MakeNew(); tmp->AddOneVector(-1., *IpCq().curr_relaxed_compl_s_L(), 0.); rhs->Set_v_L(*tmp); tmp = curr->v_U()->MakeNew(); tmp->AddOneVector(-1., *IpCq().curr_relaxed_compl_s_U(), 0.); rhs->Set_v_U(*tmp); // Loop through algorithms bool done = false; while( !done ) { InexData().set_compute_normal(compute_normal); InexData().set_next_compute_normal(compute_normal); if( !compute_normal ) { normal_x = NULL; normal_s = NULL; } else { retval = normal_step_calculator_->ComputeNormalStep(normal_x, normal_s); if( !retval ) { return false; } // output if( Jnlst().ProduceOutput(J_VECTOR, J_SOLVE_PD_SYSTEM) ) { Jnlst().Printf(J_VECTOR, J_SOLVE_PD_SYSTEM, "Normal step (without slack scaling):\n"); normal_x->Print(Jnlst(), J_VECTOR, J_SOLVE_PD_SYSTEM, "normal_x"); normal_s->Print(Jnlst(), J_VECTOR, J_SOLVE_PD_SYSTEM, "normal_s"); } } // Lower part of right-hand-side vector is different for each system if( !compute_normal ) { tmp = curr->y_c()->MakeNew(); tmp->AddOneVector(-1., *IpCq().curr_c(), 0.); rhs->Set_y_c(*tmp); tmp = curr->y_d()->MakeNew(); tmp->AddOneVector(-1., *IpCq().curr_d_minus_s(), 0.); rhs->Set_y_d(*tmp); } else { rhs->Set_y_c(*IpCq().curr_jac_c_times_vec(*normal_x)); tmp = normal_s->MakeNew(); tmp->AddTwoVectors(1., *IpCq().curr_jac_d_times_vec(*normal_x), -1., *normal_s, 0.); rhs->Set_y_d(*tmp); } InexData().set_normal_x(normal_x); InexData().set_normal_s(normal_s); delta = rhs->MakeNewIteratesVector(); retval = inexact_pd_solver_->Solve(*rhs, *delta); // Determine if acceptable step has been computed if( !compute_normal && (!retval || InexData().next_compute_normal()) ) { // If normal step has not been computed and step is not satisfactory, try computing normal step InexData().set_compute_normal(true); compute_normal = true; } else { // If normal step has been computed, stop anyway done = true; } } if( retval ) { // Store the search directions in the IpData object IpData().set_delta(delta); if( InexData().compute_normal() ) { IpData().Append_info_string("NT "); } else { IpData().Append_info_string("PD "); } } return retval; }
bool PDSearchDirCalculator::ComputeSearchDirection() { DBG_START_METH("PDSearchDirCalculator::ComputeSearchDirection", dbg_verbosity); bool improve_solution = false; if (IpData().HaveDeltas()) { improve_solution = true; } bool retval; if (improve_solution && fast_step_computation_) { retval = true; } else { SmartPtr<IteratesVector> rhs = IpData().curr()->MakeNewContainer(); rhs->Set_x(*IpCq().curr_grad_lag_with_damping_x()); rhs->Set_s(*IpCq().curr_grad_lag_with_damping_s()); rhs->Set_y_c(*IpCq().curr_c()); rhs->Set_y_d(*IpCq().curr_d_minus_s()); Index nbounds = IpNLP().x_L()->Dim()+ IpNLP().x_U()->Dim() + IpNLP().d_L()->Dim()+ IpNLP().d_U()->Dim(); if (nbounds>0 && mehrotra_algorithm_) { // set up the right hand side a la Mehrotra DBG_ASSERT(IpData().HaveAffineDeltas()); DBG_ASSERT(!IpData().HaveDeltas()); const SmartPtr<const IteratesVector> delta_aff = IpData().delta_aff(); SmartPtr<Vector> tmpvec = delta_aff->z_L()->MakeNew(); IpNLP().Px_L()->TransMultVector(1., *delta_aff->x(), 0., *tmpvec); tmpvec->ElementWiseMultiply(*delta_aff->z_L()); tmpvec->Axpy(1., *IpCq().curr_relaxed_compl_x_L()); rhs->Set_z_L(*tmpvec); tmpvec = delta_aff->z_U()->MakeNew(); IpNLP().Px_U()->TransMultVector(-1., *delta_aff->x(), 0., *tmpvec); tmpvec->ElementWiseMultiply(*delta_aff->z_U()); tmpvec->Axpy(1., *IpCq().curr_relaxed_compl_x_U()); rhs->Set_z_U(*tmpvec); tmpvec = delta_aff->v_L()->MakeNew(); IpNLP().Pd_L()->TransMultVector(1., *delta_aff->s(), 0., *tmpvec); tmpvec->ElementWiseMultiply(*delta_aff->v_L()); tmpvec->Axpy(1., *IpCq().curr_relaxed_compl_s_L()); rhs->Set_v_L(*tmpvec); tmpvec = delta_aff->v_U()->MakeNew(); IpNLP().Pd_U()->TransMultVector(-1., *delta_aff->s(), 0., *tmpvec); tmpvec->ElementWiseMultiply(*delta_aff->v_U()); tmpvec->Axpy(1., *IpCq().curr_relaxed_compl_s_U()); rhs->Set_v_U(*tmpvec); } else { rhs->Set_z_L(*IpCq().curr_relaxed_compl_x_L()); rhs->Set_z_U(*IpCq().curr_relaxed_compl_x_U()); rhs->Set_v_L(*IpCq().curr_relaxed_compl_s_L()); rhs->Set_v_U(*IpCq().curr_relaxed_compl_s_U()); } DBG_PRINT_VECTOR(2, "rhs", *rhs); // Get space for the search direction SmartPtr<IteratesVector> delta = IpData().curr()->MakeNewIteratesVector(true); if (improve_solution) { // We can probably avoid copying and scaling... delta->AddOneVector(-1., *IpData().delta(), 0.); } bool& allow_inexact = fast_step_computation_; retval = pd_solver_->Solve(-1.0, 0.0, *rhs, *delta, allow_inexact, improve_solution); if (retval) { // Store the search directions in the IpData object IpData().set_delta(delta); } } return retval; }