【benders strategy】
OFF -1 默认分支定界求解
AUTO 0
USER 1 完全按照用户设定的annotation
WORKERS 2 先按照用户的annotation,再自动优化
FULL 3 自动确定主问题(整数变量部分)和子问题(连续型变量部分)
【key】
IloCplex::LongAnnotation bendersdec = _solver.newLongAnnotation(IloCplex::BendersAnnotation,0);
for (int i = 0; i < MFUtil::scnNum; i++)
{
for (int j = 0; j < _legList.size(); j++)
{
_solver.setAnnotation(bendersdec, _z_si[i][j], i+1);
}
}
_solver.setParam(IloCplex::Param::Benders::Strategy,
IloCplex::BendersUser);
【…\cplex\examples\src\cpp\ilobenders.cpp】
(默认:C:\Program Files\IBM\ILOG\CPLEX_Studio127\cplex\examples\src)
model和ann文件均读入,cplex全自动模式(FULL)
// Example:
// ilobenders UFL_30_120_1.mps.gz UFL_30_120_1.ann
//
#include
ILOSTLBEGIN
static void usage (const char *progname);
int
main (int argc, char **argv)
{
IloEnv env;
try {
IloModel model(env);
IloCplex cpx(env);
bool hasannofile = false;
// Check the arguments.
if ( argc == 3 ) {
hasannofile = true;
}
else if ( argc != 2 ) {
usage (argv[0]);
throw(-1);
}
IloObjective obj;
IloNumVarArray var(env);
IloRangeArray rng(env);
// Read the problem file.
cpx.importModel(model, argv[1], obj, var, rng);
// Extract the model.
cpx.extract(model);
// If provided, read the annotation file.
if ( hasannofile ) {
cpx.readAnnotations(argv[2]);
}
else {
// Set benders strategy to auto-generate a decomposition.
cpx.setParam(IloCplex::Param::Benders::Strategy,
IloCplex::BendersFull);
// Write out the auto-generated annotation.
cpx.writeBendersAnnotation("benders.ann");
}
// Solve the problem using Benders' decomposition.
if ( !cpx.solve() ) {
env.error() << "Failed to optimize." << endl;
throw(-1);
}
IloAlgorithm::Status status = cpx.getStatus();
double bestObjValue = cpx.getBestObjValue();
double objValue = cpx.getObjValue();
env.out() << "Solution status: " << status << endl;
env.out() << "Best bound: " << bestObjValue << endl;
env.out() << "Best integer: " << objValue << endl;
}
catch (IloException& e) {
cerr << "Concert exception caught: " << e << endl;
throw;
}
catch (…) {
cerr << “Unknown exception caught” << endl;
throw;
}
env.end();
return 0;
} // END main
static void usage (const char *progname)
{
cerr << “Usage: " << progname << " filename [annofile]” << endl;
cerr << " where filename is a file with extension " << endl;
cerr << " MPS, SAV, or LP (lower case is allowed)" << endl;
cerr << " and annofile is an optional .ann file with model annotations" << endl;
cerr << " Exiting…" << endl;
} // END usage
【…\cplex\examples\src\cpp\facility.cpp】选址问题举例
#include
ILOSTLBEGIN
typedef IloArray FloatMatrix;
typedef IloArray NumVarMatrix;
static void usage(const char *progname);
int
main(int argc, char **argv)
{
IloEnv env;
try {
IloInt i, j;
IloNumArray capacity(env), fixedCost(env);
FloatMatrix cost(env);
IloInt nbLocations;
IloInt nbClients;
int doBenders = false;
const char* filename = "../../../examples/data/facility.dat";
for (i = 1; i < argc; i++) {
if ( argv[i][0] != '-' )
break;
switch ( argv[i][1] ) {
case 'a':
doBenders = 2;
break;
case 'b':
doBenders = true;
break;
case 'd':
break;
default:
usage (argv[0]);
}
}
if (i < argc)
filename = argv[i];
ifstream file(filename);
if (!file) {
cerr << "ERROR: could not open file '" << filename
<< "' for reading" << endl;
usage (argv[0]);
throw(-1);
}
file >> capacity >> fixedCost >> cost;
nbLocations = capacity.getSize();
nbClients = cost.getSize();
IloBool consistentData = (fixedCost.getSize() == nbLocations);
for(i = 0; consistentData && (i < nbClients); i++)
consistentData = (cost[i].getSize() == nbLocations);
if (!consistentData) {
cerr << "ERROR: data file '"
<< filename << "' contains inconsistent data" << endl;
throw(-1);
}
IloNumVarArray open(env, nbLocations, 0, 1, ILOINT);
NumVarMatrix supply(env, nbClients);
for(i = 0; i < nbClients; i++)
supply[i] = IloNumVarArray(env, nbLocations, 0, 1, ILOFLOAT);
IloModel model(env);
for(i = 0; i < nbClients; i++)
model.add(IloSum(supply[i]) == 1);
for(j = 0; j < nbLocations; j++) {
IloExpr v(env);
for(i = 0; i < nbClients; i++)
v += supply[i][j];
model.add(v <= capacity[j] * open[j]);
v.end();
}
IloExpr obj = IloScalProd(fixedCost, open);
for(i = 0; i < nbClients; i++) {
obj += IloScalProd(cost[i], supply[i]);
}
model.add(IloMinimize(env, obj));
obj.end();
IloCplex cplex(env);
cplex.extract(model);
if ( doBenders == 1 ) {
/* We specify the structure for doing a Benders decomposition by telling
* CPLEX which variables are in the master problem using annotations.
*/
IloCplex::LongAnnotation bendersdec = cplex.newLongAnnotation (IloCplex::BendersAnnotation, 1);
for(j = 0; j < nbLocations; j++) {
cplex.setAnnotation (bendersdec, open[j], 0);
}
}
else if ( doBenders == 2 ) {
/* We let CPLEX find out the decomposition. In the case of an
* uncapacitated facility location the variable of the master problem
* are the integer variables and CPLEX will find the right decomposition.
*/
cplex.setParam(IloCplex::Param::Benders::Strategy,
IloCplex::BendersFull);
}
cplex.solve();
cplex.out() << "Solution status: " << cplex.getStatus() << endl;
IloNum tolerance = cplex.getParam(
IloCplex::Param::MIP::Tolerances::Integrality);
cplex.out() << "Optimal value: " << cplex.getObjValue() << endl;
for(j = 0; j < nbLocations; j++) {
if (cplex.getValue(open[j]) >= 1 - tolerance) {
cplex.out() << "Facility " << j << " is open, it serves clients ";
for(i = 0; i < nbClients; i++) {
if (cplex.getValue(supply[i][j]) >= 1 - tolerance)
cplex.out() << i << " ";
}
cplex.out() << endl;
}
}
}
catch(IloException& e) {
cerr << " ERROR: " << e << endl;
}
catch(…) {
cerr << " ERROR" << endl;
}
env.end();
return 0;
}
static void usage(const char *progname)
{
cerr << “Usage: " << progname << “[options] [inputfile]” << endl;
cerr << " where” << endl;
cerr << " inputfile describe a facility location instance as in" << endl;
cerr << " …/…/…/examples/data/facility.dat. If no input file" << endl;
cerr << " is specified read the file in example/data directory." <
cerr << " -d solve problem without using decomposition (default)" << endl;
cerr << " -b solve problem with Benders specifying a decomposition" << endl;
cerr << " -a solve problem with Benders letting CPLEX do the decomposition" << endl;
cerr << " Exiting…" << endl;
throw (-1);
}
facility.dat 5个待选地址,8个客户
[ 3, 1, 2, 4, 1]
[ 480, 200, 320, 340, 300]
[[ 24, 74, 31, 51, 84],
[ 57, 54, 86, 61, 68],
[ 57, 67, 29, 91, 71],
[ 54, 54, 65, 82, 94],
[ 98, 81, 16, 61, 27],
[ 13, 92, 34, 94, 87],
[ 54, 72, 41, 12, 78],
[ 54, 64, 65, 89, 89]]