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