// 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
ILOSTLBEGIN int main(int argc, char **argv) { IloEnv env; try { IloArray<IloNumArray> distance(env); //Model Initialization IloModel model(env); //Taking Data from Distance Data File ifstream in; in.open("carpool-data.txt",ios::in); in >> distance; in.close(); cout<<distance<<endl; //2D Array for Results IloArray<IloNumArray> X_val(env, 7); for (int i = 0; i < 7; i++) { X_val[i] = IloNumArray(env,7); } IloArray<IloNumArray> Y_val(env, 7); for (int i = 0; i < 7; i++) { Y_val[i] = IloNumArray(env,7); } //2D Array for Xij IloArray<IloNumVarArray> X(env, 7); for (int i = 0; i < 7; i++) { X[i] = IloNumVarArray(env,7,0,1,ILOINT); } //2D Array for Yij IloArray<IloNumVarArray> Y(env, 7); for (int i = 0; i < 7; i++) { Y[i] = IloNumVarArray(env,7,0,1,ILOINT); } // 1D array for Ui and U-val //IloNumVarArray U(env,7,0,7,ILOINT); //IloNumArray U_val(env,7); // Defining Obj to be equal to sum-product(Dij*Xij + Dij*Yij) IloExpr Obj(env); for (int i = 0; i < 7; ++i) { for (int j = 0; j < 7; j++) { if(i != j) { Obj += distance[i][j]*X[i][j] + distance[i][j]*Y[i][j]; } } } //model.add(IloMaximize(env,Obj)); // IloMinimize is used for minimization problems //Alternatively, model.add(IloMaximize(env,Obj)); can be replaced by the following three lines. //This is useful while iterating in Decomposition Techniques where the objective function is redefined at each iteration IloObjective Objective = IloMinimize(env); model.add(Objective); Objective.setExpr(Obj); Obj.end(); //Constraints for the model //One Input per Node except Office IloExpr Input(env); for (int i = 0; i < 6; i++) { for (int j = 0; j < 7; j++) { if(i != j ) { Input += X[i][j] + Y[i][j]; } } model.add(Input == 1); } Input.end(); //One Output per Node except Office IloExpr Output(env); for (int j = 0; j < 6; j++) { for (int i = 0; i < 7; i++) { if(i != j ) { Output += X[i][j] + Y[i][j]; } } model.add(Output == 1); } Output.end(); //Ensuring 2 entries and exits for the Office node IloExpr Entryx(env); for (int i = 0; i <6; i++) { Entryx = Entryx + X[i][6]; } model.add(Entryx == 1); Entryx.end(); IloExpr Exitx(env); for (int i = 0; i <6; i++) { Exitx = Exitx + X[6][i]; } model.add(Exitx == 1); Exitx.end(); IloExpr Entryy(env); for (int i = 0; i <6; i++) { Entryy = Entryy + Y[i][6]; } model.add(Entryy == 1); Entryy.end(); IloExpr Exity(env); for (int i = 0; i <6; i++) { Exity = Exity + Y[6][i]; } model.add(Exity == 1); Exity.end(); // Optimize IloCplex cplex(model); cplex.setOut(env.getNullStream()); // if we get an empty stream in return //cplex.setWarning(env.getNullStream()); cplex.solve();//solving the MODEL //cout << "hey there I reached the breakpoint" << endl; if (cplex.getStatus() == IloAlgorithm::Infeasible) // if the problem is infeasible { env.out() << "Problem Infeasible" << endl; } for(int i = 0; i < 7 ; i++) { cplex.getValues(X_val[i], X[i]); } cout<<X_val<<endl; for(int i = 0; i < 7 ; i++) { cplex.getValues(Y_val[i], Y[i]); } cout<<Y_val<<endl; // cplex.getValues(U_val,U); // Print results cout<< "Objective Value = " << cplex.getObjValue() << endl; //cout<<"X = "<<X_val<<endl; } catch(IloException &e) { env.out() << "ERROR: " << e << endl; } catch(...) { env.out() << "Unknown exception" << endl; } env.end(); return 0; }
/** 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 SolveLpByRuleGeneral(const RULES InputRule, const std::vector<REQ> &Request, const std::vector<DAY> &Day, const std::vector<AIRLINE> &AirLine, std::vector<CAPCONSTRAIN> &CapCon, std::vector<double> &SolVal) { try{ ofstream CheckSolStatus; CheckSolStatus.open("..//OutPut//CplexSatus.txt", ios::trunc); IloBool SolErr= 0; double CurrentProportionEps; if (isIterativeReduceEps) { CurrentProportionEps = StartingProptionEps; } else { CurrentProportionEps = ProportionFairEps; } std::vector<int> ReqSecq2Var;//map Request sequence to variable location std::vector<int> Var2ReqSecq;// revers map Var to request sequence std::vector<int> ReqSecq2ID; // map request sequence to request ID std::vector<int> ReqSecq2DumVar; // map request to dummy variable locations std::vector<int> ID2ReqSecq(Request.size(), InvalidInt);// map request ID to reqeuset secquence std::vector<int> Rio2AirLine;// int NumActRow = 0; int NumVar = getNumVar(InputRule, Request, ReqSecq2Var, Var2ReqSecq, ReqSecq2ID, ID2ReqSecq, ReqSecq2DumVar); int NumAirLineByRule = getAirNumVar(InputRule, AirLine, Rio2AirLine); assert(NumVar > 0); assert(NumAirLineByRule > 0); int Pos; double obj = 0.0; IloEnv env; /***********create variable***************/ IloNumVarArray Xmt(env, NumVar, 0, 1, ILOINT); //IloNumVar DummyTotalObj(env); //IloNumVarArray Xmt(env, NumVar, 0, 1, ILOFLOAT); IloModel LpModel(env); IloExpr TotalDispExp(env); IloExpr WeightedTotalDispExp(env); IloExpr FairObjExp(env); IloExprArray GainEpr(env, Rio2AirLine.size()), LossEpr(env, Rio2AirLine.size()); for (int i = 0; i < Rio2AirLine.size(); i++) { GainEpr[i] = IloExpr(env); LossEpr[i] = IloExpr(env); } /***********Add objective Function***************/ //setDispObj(InputRule, env, LpModel, DummyDisplaceObj, Xmt, Rio2AirLine, Request, AirLine, ID2ReqSecq, ReqSecq2Var, ReqSecq2DumVar); getDispExps(InputRule, env, LpModel, TotalDispExp, WeightedTotalDispExp, Xmt, Rio2AirLine, Request, AirLine, ID2ReqSecq, ReqSecq2Var, ReqSecq2DumVar); //LpModel.add(DummyTotalObj >= TotalDispExp); IloObjective OBJ = IloMinimize(env); //set displacement objective if (DispObj == Disp) { OBJ.setExpr(TotalDispExp); //OBJ.setExpr(DummyTotalObj); } if (DispObj == WeightDisp) { OBJ.setExpr(WeightedTotalDispExp); } LpModel.add(OBJ); /***********Add definational constraints***************/ setDefCon(InputRule, env, LpModel, Xmt, Request, ReqSecq2Var, ID2ReqSecq, ReqSecq2DumVar); /***********Solve the cplex model***************/ IloCplex cplex(env); cplex.setOut(env.getNullStream()); #ifdef DEBUG cplex.setOut(CplexLog); #endif cplex.setParam(IloCplex::Param::TimeLimit, CplexMaxCpuTime); //cplex.setParam(IloCplex::Param::MIP::Tolerances::MIPGap, CplexRelGap); /*if (FairObj!=NoFair) cplex.setParam(IloCplex::Param::MIP::Tolerances::MIPGap, CplexRelGap);*/ cplex.extract(LpModel); SolErr = cplex.solve(); CheckSolStatus << cplex.getCplexStatus() << "\t" << SolErr << "\t" << cplex.getMIPRelativeGap() << "\t" << cplex.getCplexTime() << endl; //cout << "obj = "<<cplex.getObjValue() << endl; /***********Add violated constraints***************/ IloExprArray NewCons(env); addVioCapConByDay(InputRule, env, LpModel, cplex, NewCons, Xmt, CapCon, Request, Day, ReqSecq2Var, ID2ReqSecq); addTurnRoundCon(InputRule, env, LpModel, cplex, NewCons, Xmt, Request, ReqSecq2Var, ID2ReqSecq); while (NewCons.getSize() > 0) { for (int i = 0; i < NewCons.getSize(); i++) { LpModel.add(NewCons[i]); } NumActRow += (int)NewCons.getSize(); cplex.extract(LpModel); SolErr = cplex.solve(); CheckSolStatus << cplex.getCplexStatus() << "\t" << SolErr <<"\t"<<cplex.getMIPRelativeGap()<<"\t"<<cplex.getCplexTime()<<endl; //printf("disp = %f \n", cplex.getValue(TotalDispExp)); //if (FairObj == EnvyFun) //{ // printf("disp = %f \n", cplex.getValue(DummyDisplaceObj)); // printf("envy obj = %f \n", cplex.getValue(FairObjExp)); //} NewCons.clear(); addVioCapConByDay(InputRule, env, LpModel, cplex, NewCons, Xmt, CapCon, Request, Day, ReqSecq2Var, ID2ReqSecq); addTurnRoundCon(InputRule, env, LpModel, cplex, NewCons, Xmt, Request, ReqSecq2Var, ID2ReqSecq); } #ifdef DEBUG cout << "Dummy displacment obj ="<<cplex.getValue(TotalDispExp) <<" expre value"<<cplex.getValue(TotalDispExp)<< endl; #endif if (FairObj == EnvyFun){ BiObj: LpModel.remove(OBJ); GetEnvyLossAndGainExp(InputRule, env, LpModel, GainEpr, LossEpr, Xmt, Rio2AirLine, Request, AirLine, ID2ReqSecq, ReqSecq2Var, ReqSecq2DumVar); FairObjExp.clear(); for (int i = 0; i < Rio2AirLine.size(); i++) { FairObjExp += EnvyGainWeight*GainEpr[i] + EnvyLossWeight*LossEpr[i]; } OBJ.setExpr(EnvyFairWeight*FairObjExp + TotalDispExp); LpModel.add(OBJ); cplex.extract(LpModel); SolErr = cplex.solve(); //CheckSolStatus << cplex.getCplexStatus() << "\t" << SolErr << endl; //printf("disp = %f \n", cplex.getValue(TotalDispExp)); //printf("envy obj = %f \n", cplex.getValue(FairObjExp)); //GetEnvyLossAndGainValue(InputRule, env, LpModel, cplex, Xmt, Rio2AirLine, Request, AirLine, ID2ReqSecq, ReqSecq2Var, ReqSecq2DumVar); //for (int i = 0; i < Rio2AirLine.size(); i++) //{ // //LogMsg("gain = %f, loss = %f \n", cplex.getValue(Gain[i]), cplex.getValue(Loss[i])); // LogMsg("gain = %f, loss = %f \n", cplex.getValue(GainEpr[i]), cplex.getValue(LossEpr[i])); //} NewCons.clear(); addVioCapConByDay(InputRule, env, LpModel, cplex, NewCons, Xmt, CapCon, Request, Day, ReqSecq2Var, ID2ReqSecq); addTurnRoundCon(InputRule, env, LpModel, cplex, NewCons, Xmt, Request, ReqSecq2Var, ID2ReqSecq); while (NewCons.getSize() > 0) { for (int i = 0; i < NewCons.getSize(); i++) { LpModel.add(NewCons[i]); } NumActRow += (int)NewCons.getSize(); cplex.extract(LpModel); SolErr = cplex.solve(); CheckSolStatus << cplex.getCplexStatus() << "\t" << SolErr << "\t" << cplex.getMIPRelativeGap() << "\t" << cplex.getCplexTime() << endl; printf("disp = %f \n", cplex.getValue(TotalDispExp)); printf("envy obj = %f \n", cplex.getValue(FairObjExp)); NewCons.clear(); addVioCapConByDay(InputRule, env, LpModel, cplex, NewCons, Xmt, CapCon, Request, Day, ReqSecq2Var, ID2ReqSecq); addTurnRoundCon(InputRule, env, LpModel, cplex, NewCons, Xmt, Request, ReqSecq2Var, ID2ReqSecq); } if (SolErr == 0) {// resolve displcement first LpModel.remove(OBJ); OBJ.setExpr(TotalDispExp); LpModel.add(OBJ); cplex.extract(LpModel); SolErr = cplex.solve(); CheckSolStatus << cplex.getCplexStatus() << "\t" << SolErr << "\t" << cplex.getMIPRelativeGap() << "\t" << cplex.getCplexTime() << endl; cout << "reinitialize is called" << endl; if (SolErr == 0) { cout << "Resolve falils" << endl; system("Pause"); } else { goto BiObj; } } } AddFairEpsConstraint: int totalFairConstraint = 0; if (ProportionFairEps>MyZero&&EpsCon != NoEps) { NewCons.clear(); addEpsConstraint(InputRule, env, LpModel, Xmt, cplex, NewCons, Rio2AirLine, Request, AirLine, ID2ReqSecq, ReqSecq2Var, ReqSecq2DumVar, CurrentProportionEps); totalFairConstraint += (int)NewCons.getSize(); while (NewCons.getSize() > 0) { for (int i = 0; i < NewCons.getSize(); i++) { LpModel.add(NewCons[i]); } NumActRow += (int)NewCons.getSize(); cplex.extract(LpModel); SolErr = cplex.solve(); CheckSolStatus << cplex.getCplexStatus() << "\t" << SolErr << "\t" << cplex.getMIPRelativeGap() << "\t" << cplex.getCplexTime() << endl; //#ifdef DEBUG //cout << "Dummy displacment obj ="<<cplex.getValue(DummyDisplaceObj) <<" expre value"<<cplex.getValue(TotalDispExp)<< endl; //cout << "Total fair constraint added is " << totalFairConstraint << "; Obj = " <<cplex.getObjValue() << endl; //#endif // DEBUG NewCons.clear(); //addFairConstraints(InputRule, env, LpModel, DummyDisplaceObj, Xmt, cplex, NewCons, Rio2AirLine, Request, AirLine, ID2ReqSecq, ReqSecq2Var, ReqSecq2DumVar); addEpsConstraint(InputRule, env, LpModel, Xmt, cplex, NewCons, Rio2AirLine, Request, AirLine, ID2ReqSecq, ReqSecq2Var, ReqSecq2DumVar, CurrentProportionEps); totalFairConstraint += (int)NewCons.getSize(); //addAbsFairnessConstraint(InputRule, env, LpModel, DummyDisplaceObj, Xmt, cplex, NewCons, Rio2AirLine, Request, AirLine, ID2ReqSecq, ReqSecq2Var, ReqSecq2DumVar); addVioCapConByDay(InputRule, env, LpModel, cplex, NewCons, Xmt, CapCon, Request, Day, ReqSecq2Var, ID2ReqSecq); addTurnRoundCon(InputRule, env, LpModel, cplex, NewCons, Xmt, Request, ReqSecq2Var, ID2ReqSecq); } } // iterative add eps constraints if (CurrentProportionEps > ProportionFairEps && (ProportionFairEps > MyZero) && EpsCon != NoEps) { if (isIterativeReduceEps) { CurrentProportionEps = std::max(CurrentProportionEps - 0.1, ProportionFairEps); goto AddFairEpsConstraint; } } if (isSolveByRule) UpdateCapConByDay(InputRule, cplex, Xmt, CapCon, Request, Day, ReqSecq2Var, ID2ReqSecq); //compute for the weighted //set SolValue for (auto r = Request.begin(); r != Request.end(); r++) { if (isSolveByRule) { if (r->Rule != InputRule) continue; } for (int t = 0; t < NT; t++) { Pos = ReqSecq2Var[ID2ReqSecq[r->ID]] + t; SolVal[r->ID*NT + t] = cplex.getValue(Xmt[Pos]); } if (isIngoreDummy) continue; SolVal[Request.size()*NT + r->ID] = cplex.getValue(Xmt[ReqSecq2DumVar[ID2ReqSecq[r->ID]]]); } TestCaseSum.back().NumRowGenByRule[InputRule] = NumActRow; CheckSolStatus.close(); TestCaseSum.back().CplexRelativeGapByRule[InputRule] = cplex.getMIPRelativeGap(); env.end(); return 0; } catch (IloException& e) { ofstream FinalOut; if (isDefaultFolder) FinalOut.open("..//OutPut//Summary.txt", ios::app); else FinalOut.open((OutPutFolder + "Summary.txt").c_str(), ios::app); FinalOut << "************Warning on cplex****************" << endl; cerr << " ERROR: " << e << endl; FinalOut << " ERROR: " << e << endl; FinalOut.close(); return 1; } catch (...) { cerr << " ERROR" << endl; return 1; } }