Пример #1
0
  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;
  }
Пример #2
0
  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;

  }
Пример #3
0
  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);
  }