Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.

 View Only
  • 1.  How to use setVectors, writeMIPStart and readMIPStart?

    Posted Thu January 14, 2010 10:42 AM

    Originally posted by: jmirandap


    Hi all:
    I need to set a starting point for a MIP model in cpp. But I don't know how to use cplex::setVectors properly. I'm using CPLEX 10.2, and addMIPStart isn't available.
    I have a IloNumArray called w that I need to put some initials values in. In fact this vector is nearly optimal solution of the problem.
    I try to set those values by hand and solve the problem, then writeMIPStart, and readMIPStart, I set AdvInd=1 as the manual says.
    Can someone post an example of the use of this function???? or maybe about writeMIPStart and readMIStart working together?

    thanks in advance!
    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: How to use setVectors, writeMIPStart and readMIPStart?

    Posted Thu January 14, 2010 05:11 PM

    Originally posted by: SystemAdmin


    Here is how you use setVectors() in CPLEX 10.2:
    Assume that x is the array of your model variables and that
    x[0], x[3], x[5] are your integral variables in the model
    which have values 1, 2, 3 in your starting solution.
    IloNumVarArray vars(env);
    IloNumArray vals(env);
     
    // Fill vars and vals
    // x[0] = 1
    vars.add(x[0]);
    vals.add(1);
    // x[3] = 2
    vars.add(x[3]);
    vals.add(2);
    // x[5] = 3
    vars.add(x[5]);
    vals.add(3);
     
    // Set start solution and solve.
    cplex.setVectors(vals, 0, vars, 0, 0, 0);
    cplex.solve();
    

    The arrays vars and vals must be of the same length and their elements must
    be in 1-to-1-correspondence. This means that vals[i] is the starting
    value for variable vars[i].
    Note that it is sufficient to specify starting values only for integral
    variables (i.e. vars contains only the integral variables and vals contains
    only values for the integral values, as in my example).
    You may even leave out some of the integral values and CPLEX will try to
    construct a solution from the partial information you gave.

    And here is how you use writeMIPStart():
    cplex.solve();
    cplex.writeMIPStart("solution");
    

    Note that writeMIPStart() only works if the IloCplex instance on which
    you invoke it has already found a feasible solution. Otherwise it will
    just throw an exception. To read in the mip start you just do
    cplex.readMIPStart("solution");
    cplex.solve();
    

    The default setting for AdvInd is 1, so there is no need to set it
    explicitly here.
    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: How to use setVectors, writeMIPStart and readMIPStart?

    Posted Fri January 15, 2010 11:27 AM

    Originally posted by: jmirandap


    Thank you for your answer...
    I did what you just say but cplex ignores the values I gave it...
    I did it with two different sets of arrays... but it doesn't work.
    I also solved the problem, then create a second Cplex object,
    and set the values with the solution of the first one... like this:
    /////////////////
    cplex.solve();//solve the first one

    IloNumVarArray varS1(m_env);
    IloNumArray valS1(m_env);
    IloNumVarArray varS2(m_env);
    IloNumArray valS2(m_env);
    //set the values with the solution!
    for(i=0; i<m1; i++){
    varS1.add(S1[i]);
    valS1.add(cplex.getValue(S1[i]));
    }
    for(i=0; i<m2 ; i++){
    varS2.add(S2[i]);
    valS2.add(cplex.getValue(S2[i]));
    }
    IloCplex cplex2(mod);
    cplex2.setVectors(valS1,0,varS1,0,0,0);
    cplex2.setVectors(valS2,0,varS2,0,0,0);
    cplex2.solve();
    /////////

    ... but still doesn't work, CPLEX solves the full problem again.
    The variable cplex is for the first run and cplex2 is the second run.
    S1, S2 both are IloIntVarArray with possible values 0 and 1, but setVectors supports only IloNumVarArrays in Cplex class.
    I have 2 other vars, v and w wich are IloNumVarArray, these values are the ones I need to set up. I did it to with setVectors and happens the same....

    PD: Documentation is really poor in these subjects...
    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: How to use setVectors, writeMIPStart and readMIPStart?

    Posted Sat January 16, 2010 01:44 AM

    Originally posted by: SystemAdmin


    I agree, the documentation for this topic in Cplex 10.2 is not the best.
    This has improved a lot in more recent versions. Anyway, here is a
    working example for the setVectors() method of class IloCplex:
    #include <cstring>
    #include <iostream>
    #include <ilcplex/ilocplex.h>
     
    ILOSTLBEGIN
     
    /** The problem we solve is: * \min 1^T x * a^Tx = C * 0 <= x <= 1000 * x integral * * Vector A is given by the COEF field in the INFO structure, * C is calculated as sum of the product of the COEF and FEASIBLE * fields of that structure. */
    static struct {
       int const coef;
       int const feasible;
    } const info[] = {
       { 13719, 348 },
       { 20289, 1 },
       { 29067, 2 },
       { 60517, 1 },
       { 64354, 1 },
       { 65633, 0 },
       { 76969, 0 },
       { 102024, 6 },
       { 106036, 0 },
       { 119930, 64}
    };
    /** Number of variables in the model. */
    static unsigned int const count = sizeof(info) / sizeof(info[0]);
     
    int
    main(void)
    {
       IloEnv env;
     
       try {
          // Create the model.
          IloModel model(env);
          IloNumVarArray x(env, count);
          for (unsigned int i = 0; i < count; ++i)
             x[i] = IloIntVar(env, 0, 1000);
     
          IloNumExpr obj(env); // Objective function.
          IloNumExpr lhs(env); // Left-hand side of constraint.
          IloInt rhs = 0;      // Right-hand side of constraint.
          for (unsigned int i = 0; i < count; ++i) {
             obj += x[i];
             lhs += info[i].coef * x[i];
             rhs += info[i].coef * info[i].feasible;
          }
          model.add(IloMinimize(env, obj));
          model.add(IloRange(env, rhs, lhs, rhs));
     
          IloCplex cplex(model);
     
          // Setup a feasible solution.
          IloNumArray vals(env);
          IloNumVarArray vars(env);
          for (unsigned int i = 0; i < count; ++i) {
             vars.add(x[i]);
             vals.add(info[i].feasible);
          }
          cplex.setVectors(vals, 0, vars, 0, 0, 0);
     
          // Solve (this uses the feasible solution from above as
          // start solution.
          cplex.solve();
     
          cplex.writeMIPStart("setvectors");
     
       } catch (IloException& e) {
          std::cerr << "Exception: " << e << std::endl;
       }
       return 0;
    }
    

    When you run it you should see a line
    MIP start values provide initial solution with objective 423.0000.
    in the output that does not appear if you remove the setVectors() call.
    Concerning the other problems you mentioned:
    • It is no problem that the arguments of setVectors() are IloNumArray and
    IloNumVarArray. You can put IloIntVar instances into an IloNumVarArray
    and Cplex will still do the correct things (in particular, the type of
    the variable is not changed by this operation). And similarly for
    IloInt and IloNumArray.
    • What is the output of your program? Can you post it here? Maybe your
    start vector does not contain enough of the integral variables for
    Cplex to construct a feasible solution from that?
    • I don't know what goes wrong in your code (can you post the whole thing
    or is it too big?) but here is a version of the above program that
    does the same as your code: Setup the same problem twice, solve it once,
    use solution of first solve as starting point for a second solve.
    #include <cstring>
    #include <iostream>
    #include <ilcplex/ilocplex.h>
     
    ILOSTLBEGIN
     
    /** The problem we solve is: * \min 1^T x * a^Tx = C * 0 <= x <= 1000 * x integral * * Vector A is given by the COEF field in the INFO structure, * C is calculated as sum of the product of the COEF and FEASIBLE * fields of that structure. */
    static struct {
       int const coef;
       int const feasible;
    } const info[] = {
       { 13719, 348 },
       { 20289, 1 },
       { 29067, 2 },
       { 60517, 1 },
       { 64354, 1 },
       { 65633, 0 },
       { 76969, 0 },
       { 102024, 6 },
       { 106036, 0 },
       { 119930, 64}
    };
    /** Number of variables in the model. */
    static unsigned int const count = sizeof(info) / sizeof(info[0]);
     
    int
    main(void)
    {
       IloEnv env;
     
       try {
          // Create the model.
          IloModel model(env), model2(env);;
          IloNumVarArray x(env, count);
          for (unsigned int i = 0; i < count; ++i)
             x[i] = IloIntVar(env, 0, 1000);
     
          IloNumExpr obj(env), obj2(env); // Objective function.
          IloNumExpr lhs(env), lhs2(env); // Left-hand side of constraint.
          IloInt rhs = 0;      // Right-hand side of constraint.
          for (unsigned int i = 0; i < count; ++i) {
             obj += x[i]; obj2 += x[i];
             lhs += info[i].coef * x[i]; lhs2 += info[i].coef * x[i];
             rhs += info[i].coef * info[i].feasible;
          }
          model.add(IloMinimize(env, obj));
          model.add(IloRange(env, rhs, lhs, rhs));
     
          model2.add(IloMinimize(env, obj2));
          model2.add(IloRange(env, rhs, lhs2, rhs));
     
          // Solve the problem once but stop at first feasible solution.
          std::cout << "========== First run ==========" << std::endl;
          IloCplex cplex(model);
          cplex.setParam(IloCplex::IntSolLim, 1);
          cplex.solve();
     
          // Now solve the problem again but start with the solution
          // found in the previous run.
          std::cout << "========== Second run ==========" << std::endl;
          IloCplex cplex2(model);
          // Setup a feasible solution.
          IloNumArray vals(env);
          IloNumVarArray vars(env);
          for (unsigned int i = 0; i < count; ++i) {
             vars.add(x[i]);
             vals.add(cplex.getValue(x[i]));
          }
     
          cplex2.setVectors(vals, 0, vars, 0, 0, 0);
          cplex2.solve();
     
       } catch (IloException& e) {
          std::cerr << "Exception: " << e << std::endl;
       }
       return 0;
    }
    

    I have tested both codes and they work fine, though I am not exactly sure
    whether it is valid to share variables between models (as in the second
    example).
    #CPLEXOptimizers
    #DecisionOptimization