コード例 #1
0
ファイル: solver.cpp プロジェクト: order/lcp-research
SolverResult KojimaSolver::solve(const LCP & lcp,
                                 vec & x,
                                 vec & y) const{
  superlu_opts opts;
  opts.equilibrate = true;
  opts.permutation = superlu_opts::COLAMD;
  opts.refine = superlu_opts::REF_SINGLE;
  
  vec q = lcp.q;
  sp_mat M = lcp.M + regularizer * speye(size(lcp.M));
  uint N = q.n_elem;

  assert(N == x.n_elem);
  assert(N == y.n_elem);

  // Figure out what is free (-inf,inf)
  // and what is bound to be non-negative [0,inf)
  bvec free_vars = lcp.free_vars;
  uvec bound_idx = find(0 == free_vars);
  uvec free_idx = find(1 == free_vars);
  assert(N == bound_idx.n_elem + free_idx.n_elem);
  uint NB = bound_idx.n_elem; // number of bound vars
  uint NF = free_idx.n_elem; // number of free vars
  
  /*
    In what follows, the primal variables x are partitioned into
    free variables and bound variables x = [f;b]'
    Likewise, the dual variables are partitioned into y = [0,s]'
   */
  
  /* The Newton system:
  [M_ff  M_fb  0][df]   [M_f x + q_f]
  [M_bf  M_bb -I][db] + [M_b x + q_b - s]
  [0     S     B][dv]   [u1 + VBe]
  Where "M_ff" is the free-free block
  Overwrite the S,B diagonals every iteration*/

  // Split M matrix into blocks based on free and bound indicies
  block_sp_mat M_part = sp_partition(M,free_idx,bound_idx);
  sp_mat M_recon = block_mat(M_part);
  assert(PRETTY_SMALL > norm(M_recon - M));
  vec qf = q(free_idx);
  vec qb = q(bound_idx);
  vec b = x(bound_idx);
  vec f = x(free_idx);
  vec s = y(bound_idx);

  // Build the Newton matrix
  vector<vector<sp_mat>> block_G;
  block_G.push_back(block_sp_vec{sp_mat(),sp_mat(),sp_mat(NB,NB)});
  block_G.push_back(block_sp_vec{-M_part[0][0],-M_part[0][1],sp_mat()});
  block_G.push_back(block_sp_vec{-M_part[1][0],-M_part[1][1],speye(NB,NB)});
 
  // Start iteration
  double mean_comp, steplen;
  double sigma = initial_sigma;
  uint iter;  
  for(iter = 0; iter < max_iter; iter++){
    if(verbose or iter_verbose)
      cout << "---Iteration " << iter << "---" << endl;
    assert(all(0 == y(free_idx)));

    // Mean complementarity
    mean_comp = dot(b,s) / (double) NB;
    if(mean_comp < comp_thresh)
      break;

    block_G[0][1] = spdiag(s);
    block_G[0][2] = spdiag(b);
    sp_mat G = block_mat(block_G);
    assert(size(N + NB,N + NB) == size(G));    
                    
    // Form RHS from residual and complementarity
    vec h = vec(N + NB);
    vec res_f = M_part[0][0]*f + M_part[0][1]*b + qf;
    vec res_b = M_part[1][0]*f + M_part[1][1]*b + qb - s;
    h.head(NB) = sigma * mean_comp - b % s;
    h.subvec(NB,size(res_f)) = res_f;
    h.tail(NB) = res_b;
    
    //Archiver arch;
    //arch.add_sp_mat("G",G);
    //arch.add_vec("h",h);
    //arch.write("test.sys");

    // Solve and extract directions
    vec dir = spsolve(G,h,"superlu",opts);
    assert((N+NB) == dir.n_elem);
    vec df = dir.head(NF);
    vec db = dir.subvec(NF,N-1);
    assert(NB == db.n_elem);
    vec ds = dir.tail(NB);    
    vec dir_recon = join_vert(df,join_vert(db,ds));
    assert(PRETTY_SMALL > norm(dir_recon-dir));

    steplen = steplen_heuristic(b,s,db,ds,0.9);
    sigma = sigma_heuristic(sigma,steplen);

    f += steplen * df;
    b += steplen * db;
    s += steplen * ds;

    if(verbose){
      double res = norm(join_vert(res_f,res_b));
      cout <<"\t Mean complementarity: " << mean_comp
           <<"\n\t Residual norm: " << res
           <<"\n\t |df|: " << norm(df)
           <<"\n\t |db|: " << norm(db)
           <<"\n\t |ds|: " << norm(ds)
           <<"\n\t Step length: " << steplen
           <<"\n\t Centering sigma: " << sigma << endl;
    }
  }
  if(verbose){
    cout << "Finished"
         <<"\n\t Final mean complementarity: " << mean_comp << endl;
  }
  x(free_idx) = f;
  x(bound_idx) = b;
  y(free_idx).fill(0);
  y(bound_idx) = s;
  return SolverResult(x,y,iter);
}
コード例 #2
0
SolverResult MultiSolver::solveNaive(MultiSolverInput &input)
{
	Vector location = NLLeastSquareSolver(&input);
	return SolverResult(location, input.data);
}
コード例 #3
0
ファイル: solver.cpp プロジェクト: order/lcp-research
SolverResult ProjectiveSolver::solve(const PLCP & plcp,
                            vec & x,
                            vec & y,
                            vec & w) const{
  sp_mat P = plcp.P;
  sp_mat U = plcp.U;
  vec q = plcp.q;
  uint N = P.n_rows;
  uint K = P.n_cols;
  assert(size(P.t()) == size(U));

  bvec free_vars = plcp.free_vars;
  uvec bound_idx = find(0 == free_vars);
  uvec free_idx = find(1 == free_vars);
  assert(N == bound_idx.n_elem + free_idx.n_elem);
  uint NB = bound_idx.n_elem; // number of bound vars
  uint NF = free_idx.n_elem; // number of free vars
  assert(NF == accu(conv_to<uvec>::from(free_vars)));

  assert(N == x.n_elem);
  assert(N == y.n_elem);
  assert(K == w.n_elem);
  assert(ALMOST_ZERO > norm(y(free_idx)));

  if(verbose)
    cout << "Free variables: \t" << NF << endl
         << "Non-neg variables:\t" << NB << endl;
  sp_mat J = join_vert(sp_mat(NF,NB),speye(NB,NB));
  assert(size(N,NB) == size(J));
  assert(PRETTY_SMALL > norm(y(free_idx)));

  if(verbose)
    cout << "Forming pre-computed products..." << endl;
  mat PtP = mat(P.t() * P);
  assert(size(K,K) == size(PtP));
  mat PtPU = PtP*U;
  assert(size(K,N) == size(PtPU));
  mat Pt_PtPU = P.t() - PtPU;
  assert(size(K,N) == size(Pt_PtPU));
  mat PtPUP = PtPU * P;
  assert(size(K,K) == size(PtPUP));

  vec Ptq = P.t() * q;
  if(verbose)
    cout << "Done..." << endl;

  
  double sigma = initial_sigma;

  uint iter;
  double mean_comp;
  for(iter = 0; iter < max_iter; iter++){    
    if(verbose or iter_verbose)
      cout << "---Iteration " << iter << "---" << endl;
    // Mean complementarity
    vec s = y(bound_idx);
    vec b = x(bound_idx);
    mean_comp = dot(s,b) / (double) NB;
    if(mean_comp < comp_thresh)
      break;

    // Generate reduced Netwon system
    mat C = s+b;
    vec g = sigma * mean_comp - s % b;
    assert(NB == g.n_elem);

    // NB: A,G,and h have opposite sign from python version    
    mat A = Pt_PtPU * J * spdiag(1.0 / C);
    assert(size(K,NB) == size(A));
     
    mat G = PtPUP + (A * spdiag(s)) * J.t() * P;
    assert(size(K,K) == size(G));

    vec Ptr = P.t() * (J *  s) - PtPU*x - Ptq;
    vec h = Ptr + A*g;
    assert(K == h.n_elem);

    // Options don't make much difference
    vec dw = arma::solve(G+1e-15*eye(K,K),h,
                         solve_opts::equilibrate);
    assert(K == dw.n_elem);

    // Recover dy
    vec Pdw = P * dw;
    vec JtPdw = J.t() * Pdw;
    assert(NB == JtPdw.n_elem);
    vec ds = (g - s % JtPdw) / C;
    assert(NB == ds.n_elem);
    
    // Recover dx
    vec dx = (J * ds) + (Pdw);
    assert(N == dx.n_elem);    

    double steplen = steplen_heuristic(x(bound_idx),s,dx(bound_idx),ds,0.9);
    sigma = sigma_heuristic(sigma,steplen);

    x += steplen * dx;
    s += steplen * ds;
    y(bound_idx) = s;
    w += steplen * dw;

    if(verbose){
      cout <<"\tMean complementarity: " << mean_comp
           <<"\n\tStep length: " << steplen
           <<"\n\tCentering sigma: " << sigma << endl;
    }
  }
  if(verbose){
    cout << "Finished"
         <<"\n\t Final mean complementarity: " << mean_comp << endl;
  }
  return SolverResult(x,y,iter);
}
コード例 #4
0
ファイル: solvergurobi.cpp プロジェクト: bgrimstad/censo
// Start the optimization
SolverResult SolverGurobi::runOptimizer()
{
    if (!getInitialized())
        initialize();

    try
    {
        // Create Gurobi environment and set parameters
        GRBEnv env = GRBEnv();
        env.set(GRB_IntParam_OutputFlag, 0);

        GRBModel model = GRBModel(env);

        // Get problem info
        int numVars = constraints->getNumVariables();
        int numConstraints = constraints->getNumConstraints();

        // Get variables
        auto variables = constraints->getVariables();

        // Create array of model variables
        GRBVar vars[numVars];
        for (int i = 0; i < numVars; i++)
        {
            //vars[i] = model.addVar(0.0, 1.0, 0.0, GRB_BINARY);

            // Set variable type
            char type = GRB_CONTINUOUS;
            if (variables.at(i)->getType() == VariableType::BINARY)
            {
                type = GRB_BINARY;
            }
            else if (variables.at(i)->getType() == VariableType::INTEGER)
            {
                type = GRB_INTEGER;
            }
            vars[i] = model.addVar(variables.at(i)->getLowerBound(),
                                   variables.at(i)->getUpperBound(),
                                   variables.at(i)->getCost(),
                                   type);
        }

        // Integrate variables into model
        model.update();

        // Set starting points (does not help much...)
        for (int i = 0; i < numVars; i++)
            vars[i].set(GRB_DoubleAttr_Start, variables.at(i)->getValue());

        /*
         * Add constraints Ax <= b (or Ax = b)
         * by evaluating gradient and build A matrix
         */
        DenseVector x = DenseVector::Zero(numVars);
        DenseVector dx = constraints->evalJacobian(x);

        // Get constraint bounds
        std::vector<double> clb;
        std::vector<double> cub;
        constraints->getConstraintBounds(clb,cub);

        std::vector<int> rowGradient, colGradient;
        constraints->structureJacobian(rowGradient, colGradient);
        int nnzJacobian = constraints->getNumNonZerosJacobian();

        // Add constraints one row at the time
        for (int row = 0; row < numConstraints; row++)
        {
            // Build constraint
            GRBLinExpr expr = 0;

            // Loop through all non-zeros (inefficient)
            for (int i = 0; i < nnzJacobian; i++)
            {
                if (rowGradient.at(i) == row)
                {
                    int j = colGradient.at(i);
                    expr += dx(i)*vars[j];
                }
            }

            // Add constraint to model
            if (clb.at(row) == cub.at(row))
            {
                model.addConstr(expr, GRB_EQUAL, cub.at(row));
            }
            else
            {
                model.addConstr(expr, GRB_LESS_EQUAL, cub.at(row));
            }
        }

        // More efficient method - avoids dense matrix
//        std::vector<int> rows = {1,1,1,2,2,3,4,4,4,4,4,5};
//        std::vector<int>::iterator start,stop;
//        start = rows.begin();
//        stop = start;
//        while (start != rows.end())
//        {
//            while (stop != rows.end())
//            {
//                if (*stop == *start)
//                    ++stop;
//                else
//                    break;
//            }
//            for (std::vector<int>::iterator it = start; it != stop; ++it)
//                cout << *it << endl;

//            start = stop;
//        }

        model.update();

        assert(numVars == model.get(GRB_IntAttr_NumVars));
        assert(numConstraints == model.get(GRB_IntAttr_NumConstrs));

        // Optimize model
        model.optimize();

        // Check status
        int optimstatus = model.get(GRB_IntAttr_Status);

        if (optimstatus == GRB_INF_OR_UNBD)
        {
            model.getEnv().set(GRB_IntParam_Presolve, 0);
            model.optimize();
            optimstatus = model.get(GRB_IntAttr_Status);
        }

        // Create result object
        SolverResult result(SolverStatus::ERROR, INF, std::vector<double>(numVars,0));

        // Check Gurobi status
        if (optimstatus == GRB_OPTIMAL)
        {
            result.status = SolverStatus::OPTIMAL;

            // Get solution info
            result.objectiveValue = model.get(GRB_DoubleAttr_ObjVal);

            std::vector<double> optimalSolution;
            for (int i = 0; i < numVars; i++)
            {
                optimalSolution.push_back(vars[i].get(GRB_DoubleAttr_X));
            }

            result.primalVariables = optimalSolution;

            /*
             * Reduced costs and constraint duals are
             * only available for continuous models
             */
            std::vector<double> reducedCosts;
            std::vector<double> constraintDuals;
            if (!model.get(GRB_IntAttr_IsMIP))
            {
                for (int i = 0; i < numVars; i++)
                {
                    // Get reduced costs (related to range constraint duals)
                    reducedCosts.push_back(vars[i].get(GRB_DoubleAttr_RC));
                }

                for (int i = 0; i < numConstraints; i++)
                {
                    GRBConstr c = model.getConstr(i);
                    double pi = c.get(GRB_DoubleAttr_Pi);
                    constraintDuals.push_back(pi);
                }
            }

            result.lowerBoundDualVariables = reducedCosts;
            result.upperBoundDualVariables = reducedCosts;
            result.constraintDualVariables = constraintDuals;

            return result;
        }
        else if (optimstatus == GRB_INFEASIBLE)
        {
            result.status = SolverStatus::INFEASIBLE;
            result.objectiveValue = INF;
            // compute and write out IIS
            // model.computeIIS();
            // model.write("problem.lp");
            return result;
        }
        else if (optimstatus == GRB_UNBOUNDED)
        {
            result.status = SolverStatus::UNBOUNDED;
            result.objectiveValue = -INF;
            return result;
        }
        else
        {
            result.status = SolverStatus::ERROR;
            result.objectiveValue = INF;
            return result;
        }
    }
    catch(GRBException e)
    {
        cout << "SolverGurobi: Error code = " << e.getErrorCode() << endl;
        cout << e.getMessage() << endl;
        return SolverResult(SolverStatus::ERROR, INF, std::vector<double>(constraints->getNumVariables(),0));
    }
    catch (...)
    {
        cout << "SolverGurobi: Error during optimization!" << endl;
        return SolverResult(SolverStatus::ERROR, INF, std::vector<double>(constraints->getNumVariables(),0));
    }
}