void Callback::constructRHS( GraphVariables const & vars , NodeSet const & dS , NodeSet const & S , IloExpr & rhs ) const { rhs.clear(); for ( Graph::Node const & j : dS ) { rhs += vars.xVars[vars.nodeToIndex[j]]; } for ( Graph::Node const & j : S ) { rhs += vars.yVars[vars.nodeToIndex[j]]; } }
int CProblem::setModel() { //time_t start, end; numvar = 1+n; // lambda + all c; IloEnv env; try { IloModel model(env); IloCplex cplex(env); /*Variables*/ IloNumVar lambda(env, "lambda"); IloNumVarArray c(env, n);// for (unsigned int u=0; u<n; u++) { std::stringstream ss; ss << u; std::string str = "c" + ss.str(); c[u]=IloNumVar(env, str.c_str()); } IloArray<IloIntVarArray> z(env,n); for (unsigned int u=0; u<n; u++) { z[u]= IloIntVarArray(env, n); for (unsigned int v=0; v<n; v++) { std::stringstream ss; ss << u; ss << v; std::string str = "z" + ss.str(); z[u][v] = IloIntVar(env, 0, 1, str.c_str()); } } /* Constant M*/ int M=n*max_d; UB = M; /* Objective*/ model.add(IloMinimize(env, lambda)); //model.add(IloMinimize(env, IloSum(c))); /*Constrains*/ model.add(lambda - UB <= 0); /* d=function of the distance */ IloArray<IloNumArray> Par_d(env,n); for (unsigned int u=0; u<n; u++) { Par_d[u]=IloNumArray(env,n); for (unsigned int v=0; v<n; v++) { Par_d[u][v]=d[u][v]; } } for (unsigned u=0; u<n; u++) { for (unsigned v=0; v<u; v++) { model.add(c[v]-c[u]+M* z[u][v] >= Par_d[u][v] ); model.add(c[u]-c[v]+M*(1-z[u][v]) >= Par_d[u][v]); numvar++; // + z[u][v] } } /* for (unsigned i=0; i<sqrt(n)-1; i=i+1) { for (unsigned j=0; j<sqrt(n)-1; j=j+1) { //square lattice model.add (c[i*sqrt(n)+j] +c[i*sqrt(n)+j+1] + c[(i+1)*sqrt(n)+j] +c[(i+1)*sqrt(n)+j+1]>= 16-4*sqrt(2)); // Bedingung fuer Quadratischen Gridgraph und d(x) = 3-x // // triangular lattice // model.add (c[i*5+j]+c[i*5+j+1] + // c[(i+1)+j] >= 4); // Bedingung fuer Quadratischen Gridgraph und d(x) = 3-x // model.add (c[i*sqrt(n)+j]+c[i*sqrt(n)+j+1] + // c[(i+1)*sqrt(n)+j]+c[(i+1)*sqrt(n)+j+1] >= 22 - 4*sqrt(2)); // Bedingung fuer Quadratischen Gridgraph und d(x) = 4-x } } */ /* for (unsigned i=0; i<sqrt(n)-2; i+=3) { for (unsigned j=0; j<sqrt(n)-2; j+=3) { // model.add (c[i*sqrt(n)+j] + c[i*sqrt(n)+j+1] + c[i*sqrt(n)+j+2] + // c[(i+1)*sqrt(n)+j]+ c[(i+1)*sqrt(n)+j+1]+ c[(i+1)*sqrt(n)+j+2] + // c[(i+2)*sqrt(n)+j]+ c[(i+2)*sqrt(n)+j+1]+ c[(i+2)*sqrt(n)+j+2] // >= 60-17*sqrt(2)-3*sqrt(5)); // Bedingung fuer Quadratischen Gridgraph und d(x) = 3-x // model.add (c[i*sqrt(n)+j] + c[i*sqrt(n)+j+1] + c[i*sqrt(n)+j+2] + // c[(i+1)*sqrt(n)+j]+ c[(i+1)*sqrt(n)+j+1]+ c[(i+1)*sqrt(n)+j+2] + // c[(i+2)*sqrt(n)+j]+ c[(i+2)*sqrt(n)+j+1]+ c[(i+2)*sqrt(n)+j+2] // >= 82-8*sqrt(2)-2*sqrt(5)); // Bedingung fuer Quadratischen Gridgraph und d(x) = 4-x } } */ for (unsigned int v=0; v<n; v++) { IloExpr expr; model.add (c[v] <= lambda); model.add (c[v] >= 0); expr.end(); } std::cout << "Number of variables " << numvar << "\n"; /* solve the Model*/ cplex.extract(model); cplex.exportModel("L-Labeling.lp"); /* start = clock(); int solveError = cplex.solve(); end = clock (); */ IloTimer timer(env); timer.start(); int solveError = cplex.solve(); timer.stop(); if ( !solveError ) { std::cout << "STATUS : "<< cplex.getStatus() << "\n"; env.error() << "Failed to optimize LP \n"; exit(1); } //Info.time = (double)(end-start)/(double)CLOCKS_PER_SEC; Info.time = timer.getTime(); std::cout << "STATUS : "<< cplex.getStatus() << "\n"; /* get the solution*/ env.out() << "Solution status = " << cplex.getStatus() << "\n"; numconst = cplex.getNrows(); env.out() << " Number of constraints = " << numconst << "\n"; lambda_G_d=cplex.getObjValue(); env.out() << "Solution value = " << lambda_G_d << "\n"; for (unsigned int u=0; u<n; u++) { C.push_back(cplex.getValue(c[u])); std::cout << "c(" << u << ")=" << C[u]<< " "; } std::cout <<"\n"; /* for (unsigned int u=0; u<n; u++) { for (unsigned int v=0; v<u; v++) { std::cout<< "z[" << u <<"][" << v << "]="<< cplex.getValue( z[u][v]) << " "; Z.push_back(cplex.getValue( z[u][v])); } std::cout << "\n"; } std::cout <<"\n"; */ } // end try catch (IloException& e) { std::cerr << "Concert exception caught: " << e << std::endl; } catch (...) { std::cerr << "Unknown exception caught" << std::endl; } env.end(); return 0; }
// This routine separates Benders' cuts violated by the current x solution. // Violated cuts are found by solving the worker LP // IloBool separate(const Arcs x, const IloNumArray2 xSol, IloCplex cplex, const IloNumVarArray v, const IloNumVarArray u, IloObjective obj, IloExpr cutLhs, IloNum& cutRhs) { IloBool violatedCutFound = IloFalse; IloEnv env = cplex.getEnv(); IloModel mod = cplex.getModel(); IloInt numNodes = xSol.getSize(); IloInt numArcs = numNodes * numNodes; IloInt i, j, k, h; // Update the objective function in the worker LP: // minimize sum(k in V0) sum((i,j) in A) x(i,j) * v(k,i,j) // - sum(k in V0) u(k,0) + sum(k in V0) u(k,k) mod.remove(obj); IloExpr objExpr = obj.getExpr(); objExpr.clear(); for (k = 1; k < numNodes; ++k) { for (i = 0; i < numNodes; ++i) { for (j = 0; j < numNodes; ++j) { objExpr += xSol[i][j] * v[(k-1)*numArcs + i*numNodes + j]; } } } for (k = 1; k < numNodes; ++k) { objExpr += u[(k-1)*numNodes + k]; objExpr -= u[(k-1)*numNodes]; } obj.setExpr(objExpr); mod.add(obj); objExpr.end(); // Solve the worker LP cplex.solve(); // A violated cut is available iff the solution status is Unbounded if ( cplex.getStatus() == IloAlgorithm::Unbounded ) { IloInt vNumVars = (numNodes-1) * numArcs; IloNumVarArray var(env); IloNumArray val(env); // Get the violated cut as an unbounded ray of the worker LP cplex.getRay(val, var); // Compute the cut from the unbounded ray. The cut is: // sum((i,j) in A) (sum(k in V0) v(k,i,j)) * x(i,j) >= // sum(k in V0) u(k,0) - u(k,k) cutLhs.clear(); cutRhs = 0.; for (h = 0; h < val.getSize(); ++h) { IloInt *index_p = (IloInt*) var[h].getObject(); IloInt index = *index_p; if ( index >= vNumVars ) { index -= vNumVars; k = index / numNodes + 1; i = index - (k-1)*numNodes; if ( i == 0 ) cutRhs += val[h]; else if ( i == k ) cutRhs -= val[h]; } else { k = index / numArcs + 1; i = (index - (k-1)*numArcs) / numNodes; j = index - (k-1)*numArcs - i*numNodes; cutLhs += val[h] * x[i][j]; } } var.end(); val.end(); violatedCutFound = IloTrue; } return violatedCutFound; } // END separate
/** Separation function. * This function is invoked whenever CPLEX finds an integer feasible * solution. It then separates either feasibility or optimality cuts * on this solution. */ void BendersOpt::LazyConstraintCallback::main() { std::cout << "Callback invoked. Separate Benders cuts." << std::endl; IloNumArray x(getEnv()); IloNumArray rayVals(getEnv()); IloNumVarArray rayVars(getEnv()); IloNumArray cutVal(getEnv()); IloNumVarArray cutVar(getEnv()); getValues(x, master->vars); bool error = false; // Iterate over blocks and trigger a separation on each of them. // The separation is triggered asynchronously so that it can happen // on different remote objects simultaneously. for (BlockVector::size_type b = 0; b < blocks.size(); ++b) { Block *const block = blocks[b]; // Remove current objective from the block's model. IloModel model = block->cplex.getModel(); IloObjective obj = block->obj; model.remove(obj); IloExpr newObj = obj.getExpr(); // Iterate over the fixed master variables in this block to update // the block's objective function. // Each fixed variable goes to the right-hand side and therefore // into the objective function. for (std::vector<Block::FixData>::const_iterator it = block->fixed.begin(); it != block->fixed.end(); ++it) newObj -= block->vars[it->row] * (it->val * x[it->col]); obj.setExpr(newObj); model.add(obj); newObj.end(); // If the problem is unbounded we need to get an infinite ray in // order to be able to generate the respective Benders cut. If // CPLEX proves unboundedness in presolve then it will return // CPX_STAT_INForUNBD and no ray will be available. So we need to // disable presolve. block->cplex.setParam(IloCplex::Param::Preprocessing::Presolve, false); block->cplex.setParam(IloCplex::Param::Preprocessing::Reduce, 0); // Solve the updated problem to optimality. block->cplex.setParam(IloCplex::Param::RootAlgorithm, IloCplex::Primal); try { handles[b] = block->cplex.solve(true); } catch (...) { // If there is an exception then we need to kill and join // all remaining solves. Otherwise we may leak handles. while (--b > 0) { handles[b].kill(); handles[b].join(); } throw; } } // Wait for the various LP solves to complete. for (BlockVector::size_type b = 0; b < blocks.size(); ++b) handles[b].join(); // See if we need to generate cuts. for (BlockVector::size_type b = 0; b < blocks.size(); ++b) { Block *const block = blocks[b]; cutVal.clear(); cutVar.clear(); double cutlb = -IloInfinity; double cutub = IloInfinity; // We ust STL types here since they are exception safe. std::vector<double> tmp(master->vars.getSize(), 0); std::map<IloNumVar,double,ExtractableLess<IloNumVar> > rayMap; // Depending on the status either seperate a feasibility or an // optimality cut. switch (block->cplex.getStatus()) { case IloAlgorithm::Unbounded: { // The subproblem is unbounded. We need to extract a feasibility // cut from an unbounded ray of the problem (see also the comments // at the top of this file). std::cout << "unbounded "; block->cplex.getRay(rayVals, rayVars); cutub = 0.0; for (IloInt j = 0; j < rayVars.getSize(); ++j) { cutub -= rayVals[j] * block->objMap[rayVars[j]]; rayMap[rayVars[j]] = rayVals[j]; } for (std::vector<Block::FixData>::const_iterator it = block->fixed.begin(); it != block->fixed.end(); ++it) tmp[it->col] -= it->val * rayMap[block->vars[it->row]]; for (IloInt j = 0; j < master->vars.getSize(); ++j) { if ( fabs (tmp[j]) > 1e-6 ) { cutVar.add(master->vars[j]); cutVal.add(tmp[j]); } } } break; case IloAlgorithm::Optimal: { // The subproblem has a finite optimal solution. // We need to check if this gives rise to an optimality cut (see // also the comments at the top of this file). std::cout << "optimal "; double const objval = block->cplex.getObjValue(); double const eta = x[etaind + b]; block->cplex.getValues(block->vars, rayVals); if ( objval > eta + 1e-6 ) { cutub = 0.0; for (IloInt j = 0; j < block->vars.getSize(); ++j) cutub -= rayVals[j] * block->objMap[block->vars[j]]; for (std::vector<Block::FixData>::const_iterator it = block->fixed.begin(); it != block->fixed.end(); ++it) tmp[it->col] -= it->val * rayVals[it->row]; for (IloInt j = 0; j < master->vars.getSize(); ++j) { if ( fabs (tmp[j]) > 1e-6 ) { cutVal.add(tmp[j]); cutVar.add(master->vars[j]); } } cutVal.add(-1.0); cutVar.add(master->vars[etaind + b]); } } break; default: std::cerr << "Unexpected status " << block->cplex.getStatus() << std::endl; error = true; break; } // If a cut was found then add that. if ( cutVar.getSize() > 0 ) { IloExpr expr(master->env); for (IloInt i = 0; i < cutVar.getSize(); ++i) expr += cutVar[i] * cutVal[i]; IloRange cut(getEnv(), cutlb, expr, cutub); expr.end(); std::cout << "cut found: " << cut << std::endl; add(cut).end(); } else std::cout << "no cuts." << std::endl; } cutVar.end(); cutVal.end(); rayVars.end(); rayVals.end(); x.end(); if ( error ) throw -1; }
int CProblem::setModel() { //time_t start, end; numvar = 1+n; // lambda + all c; IloEnv env; try { IloModel model(env); IloCplex cplex(env); /*Variables*/ IloNumVar lambda(env, "lambda"); IloNumVarArray c(env, n);// for (unsigned int u=0; u<n; u++) { std::stringstream ss; ss << u; std::string str = "c" + ss.str(); c[u]=IloNumVar(env, str.c_str()); } IloArray<IloIntVarArray> z(env,n); for (unsigned int u=0; u<n; u++) { z[u]= IloIntVarArray(env, n); for (unsigned int v=0; v<n; v++) { std::stringstream ss; ss << u; ss << v; std::string str = "z" + ss.str(); z[u][v] = IloIntVar(env, 0, 1, str.c_str()); } } /* Constant M*/ int M=n*max_d; UB = M; /* Objective*/ model.add(IloMinimize(env, lambda)); /*Constrains*/ model.add(lambda - UB <= 0); /* d=function of the distance */ IloArray<IloNumArray> Par_d(env,n); for (unsigned int u=0; u<n; u++) { Par_d[u]=IloNumArray(env,n); for (unsigned int v=0; v<n; v++) { Par_d[u][v]=d[u][v]; } } for (unsigned u=0; u<n; u++) { for (unsigned v=0; v<u; v++) { model.add(c[v]-c[u]+M* z[u][v] >= Par_d[u][v] ); model.add(c[u]-c[v]+M*(1-z[u][v]) >= Par_d[u][v]); numvar++; // + z[u][v] } } for (unsigned int v=0; v<n; v++) { IloExpr expr; model.add (c[v] <= lambda); model.add (c[v] >= 0); expr.end(); } std::cout << "Number of variables " << numvar << "\n"; /* solve the Model*/ cplex.extract(model); cplex.exportModel("L-Labeling.lp"); /* start = clock(); int solveError = cplex.solve(); end = clock (); */ // cplex.setParam(IloCplex::Threads, 1); cplex.setParam(IloCplex::ClockType , 1 ); // CPU time IloTimer timer(env); const double startt = cplex.getTime(); timer.start(); int solveError = cplex.solve(); timer.stop(); const double stopt = cplex.getTime() - startt; if ( !solveError ) { std::cout << "STATUS : "<< cplex.getStatus() << "\n"; env.error() << "Failed to optimize LP \n"; exit(1); } //Info.time = (double)(end-start)/(double)CLOCKS_PER_SEC; Info.time = timer.getTime(); std::cout << "STATUS : "<< cplex.getStatus() << "\n"; /* get the solution*/ env.out() << "Solution status = " << cplex.getStatus() << "\n"; env.out() << "Time cplex.getTime " << stopt << "\n"; numconst = cplex.getNrows(); env.out() << " Number of constraints = " << numconst << "\n"; lambda_G_d=cplex.getObjValue(); env.out() << "Solution value = " << lambda_G_d << "\n"; for (unsigned int u=0; u<n; u++) { C.push_back(cplex.getValue(c[u])); std::cout << "c(" << u << ")=" << C[u]<< " "; } std::cout <<"\n"; /* for (unsigned int u=0; u<n; u++) { for (unsigned int v=0; v<u; v++) { std::cout<< "z[" << u <<"][" << v << "]="<< cplex.getValue( z[u][v]) << " "; Z.push_back(cplex.getValue( z[u][v])); } std::cout << "\n"; } std::cout <<"\n"; */ } // end try catch (IloException& e) { std::cerr << "Concert exception caught: " << e << std::endl; } catch (...) { std::cerr << "Unknown exception caught" << std::endl; } env.end(); return 0; }
int CProblem::setModel() { //time_t start, end; numvar = 1+n; // lambda + all c; IloEnv env; try { IloModel model(env); IloCplex cplex(env); /*Variables*/ IloNumVar lambda(env, "lambda"); IloNumVarArray c(env, n);// for (unsigned int u=0; u<n; u++) { std::stringstream ss; ss << u; std::string str = "c" + ss.str(); c[u]=IloNumVar(env, str.c_str()); } IloArray<IloIntVarArray> z(env,n); for (unsigned int u=0; u<n; u++) { z[u]= IloIntVarArray(env, n); for (unsigned int v=0; v<n; v++) { std::stringstream ss; ss << u; ss << v; std::string str = "z" + ss.str(); z[u][v] = IloIntVar(env, 0, 1, str.c_str()); } } /* Constant M*/ int UB, LB; switch (lattice){ case 1: // hexagonal_lattice if (max_d==3) {LB = 5; UB = 10;} //d(x) = 3 -x else {LB = 9; UB = 27;} break; case 2:// triangular_lattice if (max_d==3) { LB = 8; UB = 16;} //d(x) = 3 -x else {LB = 18; UB = 54;} break; case 3:// square_lattice if (max_d==3) { LB = 6; UB = 12;} //d(x) = 3 -x else { LB = 11; UB = 33;} break; default: UB=n*max_d;break; } std::cout << "Lattice " << lattice << "\n"; std::cout << "UB for lambda " << UB << "\n"; /* Objective*/ model.add(IloMinimize(env, lambda)); /*Constrains*/ model.add(lambda - UB <= 0); model.add(lambda - LB >= 0); /* d=function of the distance */ IloArray<IloNumArray> Par_d(env,n); for (unsigned int u=0; u<n; u++) { Par_d[u]=IloNumArray(env,n); for (unsigned int v=0; v<n; v++) { Par_d[u][v]=d[u][v]; } } int M = INT_MAX;//Par_d[0][0] + UB; for (unsigned u=0; u<n; u++) { for (unsigned v=0; v<u; v++) { model.add(c[v]-c[u]+M* z[u][v] >= Par_d[u][v] ); model.add(c[u]-c[v]+M*(1-z[u][v]) >= Par_d[u][v]); numvar++; // + z[u][v] } } for (unsigned int v=0; v<n; v++) { IloExpr expr; model.add (c[v] <= lambda); model.add (c[v] >= 0); expr.end(); } std::cout << "Number of variables " << numvar << "\n"; /* solve the Model*/ cplex.extract(model); cplex.exportModel("L-Labeling.lp"); IloTimer timer(env); timer.start(); int solveError = cplex.solve(); timer.stop(); if ( !solveError ) { std::cout << "STATUS : "<< cplex.getStatus() << "\n"; env.error() << "Failed to optimize LP \n"; exit(1); } //Info.time = (double)(end-start)/(double)CLOCKS_PER_SEC; Info.time = timer.getTime(); std::cout << "STATUS : "<< cplex.getStatus() << "\n"; /* get the solution*/ env.out() << "Solution status = " << cplex.getStatus() << "\n"; numconst = cplex.getNrows(); env.out() << " Number of constraints = " << numconst << "\n"; lambda_G_d=cplex.getObjValue(); env.out() << "Solution value = " << lambda_G_d << "\n"; for (unsigned int u=0; u<n; u++) { C.push_back(cplex.getValue(c[u])); std::cout << "c(" << u << ")=" << C[u]<< " "; } std::cout <<"\n"; /* for (unsigned int u=0; u<n; u++) { for (unsigned int v=0; v<u; v++) { std::cout<< "z[" << u <<"][" << v << "]="<< cplex.getValue( z[u][v]) << " "; Z.push_back(cplex.getValue( z[u][v])); } std::cout << "\n"; } std::cout <<"\n"; */ } // end try catch (IloException& e) { std::cerr << "Concert exception caught: " << e << std::endl; } catch (...) { std::cerr << "Unknown exception caught" << std::endl; } env.end(); return 0; }
int main(int argc, char **argv) { IloEnv env; try { IloInt i, j; IloNumArray capacity(env), fixedCost(env); FloatMatrix cost(env); IloInt nbLocations; IloInt nbClients; const char* filename = "../../../examples/data/facility.dat"; if (argc > 1) filename = argv[1]; ifstream file(filename); if (!file) { cerr << "ERROR: could not open file '" << filename << "' for reading" << endl; cerr << "usage: " << argv[0] << " <file>" << endl; 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, ILOINT); 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); 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; }