void addColumn(IloCplex subSolver, IloNumVarArray2 x, IloNumVarArray z, IloNumVarArray lambda, IloObjective rmpObj, IloRangeArray maintConEng, IloRangeArray removeMod, IloRangeArray convex, IloNumArray2 addXCol, IloNumArray addZCol, const IloNumArray compCosts, const IloNumArray convexityCoef) { // loop counter IloInt t; // counter for objective function coefficient for lambda // variable to be added. IloNum lambdaObjCoef = 0; // extract subproblem-optimal solution values // (into IloNumArrays addXCol (2d) and addZCol (1d)). // z values: subSolver.getValues(addZCol,z); //cout << endl << endl << "z = " << endl << addZCol << endl; //cin.get(); // !!! OBS !!! // here we might want to save these z values some column pool's custom-nitted class // array. Or to be specific, we want to add the indexes for NON-ZERO-ENTRIES in addZCol // to our class that keep place of columns. // E.g., given variable lambda(m)_(q_m), we want to know in our own class object, // given (m)(q_m), the indexes of non-zeros in that Z column. // and for each t... for (t = 0; t < TIME_SPAN; t++) { // x values: subSolver.getValues(addXCol[t],x[t]); //cout << endl << endl << "x[t=" << t << "] =" << endl << addXCol[t] << endl; } //cin.get(); // calculate objective function coefficient lambdaObjCoef for (t = 0; t < TIME_SPAN; t++) { // for each fixed t: scalar product of x[m]* vector and // component costs vector compCosts[m]: lambdaObjCoef += IloScalProd(addXCol[t],compCosts); // also clear the addXCol subarrays as soon as they // have been used addXCol[t].clear(); } // now add this column and it's associated lambda variable to the RMP. lambda.add(IloNumVar(rmpObj(lambdaObjCoef) + maintConEng(addZCol) + removeMod(addZCol) + convex(convexityCoef), 0.0, 1.0)); // clear addZCol num array. addZCol.clear(); } // END of addColumn
/** Apply the setting defined by this instance to <code>cplex</code>. */ void apply(IloCplex cplex) const { switch (type) { case 'b': cplex.setParam(IloCplex::BoolParam(num), value.i != 0); break; case 'i': cplex.setParam(IloCplex::IntParam(num), value.i); break; case 'l': cplex.setParam(IloCplex::LongParam(num), value.l); break; case 'd': cplex.setParam(IloCplex::NumParam(num), value.d); break; } }
int setCplexParam(IloCplex& cplex, IloEnv& env, int time_limit){ //Set cplex parameter cplex.setParam(IloCplex::TiLim, time_limit); cplex.setParam(IloCplex::Threads, 2); cplex.setOut(env.getNullStream()); cplex.setParam(IloCplex::PreLinear, 0); return 0; }
void displayResults(IloCplex& cplex, IloNumVarArray inside, IloNumVarArray outside) { cout << "cost: " << cplex.getObjValue() << endl; for(IloInt p = 0; p < nbProds; p++) { cout << "P" << p << endl; cout << "inside: " << cplex.getValue(inside[p]) << endl; cout << "outside: " << cplex.getValue(outside[p]) << endl; } }
/** Destructor. */ ~Worker() { if ( handle ) { handle.kill(); handle.join(); } if ( cplex.getImpl() ) { cplex.userfunction(USERACTION_REMOVECALLBACK, 0, NULL, 0, 0, NULL); cplex.end(); } rng.end(); x.end(); obj.end(); model.end(); }
void PrintStorageBindingResult(BoolVar3DMatrix R, map<int, string> start_time_rev, IloCplex cplex){ double R_[n_m][E][T_MAX]; for(int p = 0; p < n_m; p++){ for(int e = 0; e < E; e++){ for(int t = 0; t < T_MAX; t++){ R_[p][e][t] = cplex.getValue(R[p][e][t]); } } } cout << "STORAGE BINDING RESULTS" << endl; for(int p = 0; p < n_m; p++){ cout << "Module-" << p << " "; for(int e = 0; e < E; e++){ for(int t = 0; t < T_MAX; t++){ if(R_[p][e][t] == 1){ cout << "(" <<start_time_rev[edges.at(e).first] << "-" << start_time_rev[edges.at(e).second] << ")" <<":" << t << " "; } } } cout << endl; } cout << endl; return; }
static void print_values(IloCplex &cplex, const IloIntVarArray *xs) { for (u_int i = 0; i < xs->getSize(); i++) { const int v = cplex.getValue((*xs)[i]); if (v == 0) { continue; } cout << (*xs)[i] << " = " << v << endl; } }
void PrintSchedulingResult(IloNumVarArray s, map<int, string> start_time_rev, IloCplex cplex){ vector<double> s_; for(int i = 0; i <= n; i++){ s_.push_back(cplex.getValue(s[i])); } cout << "\nSCHEDULING RESULTS" << endl; map<string, int>::iterator it; for(it = start_time.begin(); it != start_time.end(); it++){ cout << it->first << setw(4) << s_.at(it->second) << endl; } cout << endl; return; }
DataNumMatrix DataVarBoolTriMatrix::ExtractSumK(IloEnv env, IloCplex cplex){ DataNumMatrix res(env,this->n, this->m); for(int j = 1; j <= this->m; j++){ for(int i = 1; i <= this->n; i++){ Coordinate coord(i,j); res[coord] = 0; for(int l = 0; l < this->k; l++){ res[coord] += cplex.getValue(this->get(i,j,l)); } } } return res; }
DataNumMatrix DataVarBoolMatrix::ExtractSol(IloEnv env, IloCplex cplex, Solution& sol){ DataNumMatrix x_ij(env,sol.get_inst().get_n(),sol.get_inst().get_m()); double Ca_x = 0; double Cp_x = 0; double CaHa_x = 0; double CpHp_x = 0; //int Cost = 0; for(int i = 1; i <= sol.get_inst().get_n(); i++){ for(int j = 1; j <= sol.get_inst().get_m(); j++){ Coordinate coord(i,j); //if(cplex.getValue(this->Matrix[i-1][j-1]) == 1) // Cost++; Ca_x += sol.get_inst().get_grille(coord).get_Ca()*cplex.getValue(this->Matrix[i-1][j-1]); Cp_x += sol.get_inst().get_grille(coord).get_Cp()*cplex.getValue(this->Matrix[i-1][j-1]); CaHa_x += sol.get_inst().get_grille(coord).get_Ha()*sol.get_inst().get_grille(coord).get_Ca()*cplex.getValue(this->Matrix[i-1][j-1]); CpHp_x += sol.get_inst().get_grille(coord).get_Hp()*sol.get_inst().get_grille(coord).get_Cp()*cplex.getValue(this->Matrix[i-1][j-1]); sol.set_Choix_maille(coord) = cplex.getValue(this->Matrix[i-1][j-1]); x_ij[coord] = cplex.getValue(this->Matrix[i-1][j-1]); } } //sol.set_cost() = Cost; sol.set_Ha() = CaHa_x/Ca_x; sol.set_Hp() = CpHp_x/Cp_x; return x_ij; }
bool DataVarBoolTriMatrix::ExtractSol(IloEnv env, IloCplex cplex){ for(int l = 0; l < this->k; l++){ cout << "S : " << l << endl; cout << "----------------------" << endl; for(int j = 1; j <= this->m; j++){ for(int i = 1; i <= this->n; i++){ cout << int(cplex.getValue(this->Matrix[i-1][j-1][l])) ; } cout << endl; } cout << "----------------------" << endl; } return true; }
// Set components[i] to the representative of the // component that contains the vertex i. void getComponents (IloCplex &cplex, const IloArray <IloBoolVarArray>& solution, vector <int>& components) { // The size of the graph. int n = solution.getSize(); // Each vertex is a component itself. for (int i = 0; i < n; i++) components[i] = i; // For each 1 in the incidence matrix, // join the components of these vertex. for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) if (cplex.getValue (solution[i][j]) == 1) join (components, i, j); }
int modelToSol(const Problem<double> &P, Solution<double,double> &s,IloCplex& cplex, IloNumVarArray& t,IloNumVarMatrix& x, IloNumVarMatrix& y,IloNumVarMatrix& b){ const int E=2*P.nbTask; for (int i=0;i<P.nbTask;++i){ for (int e=0;e<E-1;++e){ if (isEqual(cplex.getValue(x[i][e]),1.0)) s.st[i]=cplex.getValue(t[e]); if (isEqual(cplex.getValue(y[i][e]),1.0)) s.ft[i]=cplex.getValue(t[e]); if (!isEqual(cplex.getValue(t[e+1]-t[e]),0.0)) s.b[i][e]=cplex.getValue(b[i][e])/(cplex.getValue(t[e+1]-t[e])); else s.b[i][e]=0.0; } if (isEqual(cplex.getValue(y[i][E-1]),1.0)) s.ft[i]=cplex.getValue(t[E-1]); } for (int e=0;e<E;++e) s.event.push_back(cplex.getValue(t[e])); return 0; }
void PrintMixingBindingResult(BoolVarMatrix M, map<int, string> start_time_rev, IloCplex cplex){ double M_[n_m][E]; for(int i = 0; i < n_m; i++){ for(int j = 0; j < n; j++) M_[i][j] = cplex.getValue(M[i][j]); } cout << "MIXING BINDING RESULTS" << endl; for(int i = 0; i < n_m; i++){ cout << "Module-" << i << " "; for(int j = 0; j < n; j++){ if(M_[i][j] == 1){ cout << start_time_rev[j] << " "; } } cout << endl; } cout << endl; return; }
void profit_load(graph g, IloCplex cplex, IloModel model, IloNumVarArray x, IloNumVarArray p, IloNumVarArray z, int **columns, vector<int>& allocation, vector<double>& pricing) { IloNumVarArray startVar(model.getEnv()); IloNumArray startVal(model.getEnv()); for(int j = 0; j < g->items; j++) { if(boundp(j) > 0){ startVar.add(p[j]); startVal.add(pricing[j]); } } for(int i = 0; i < g->bidders; i++) { for(int e = 0; e < g->dbidder[i]; e++) { int j = g->b_adj[i][e]; startVar.add(x[columns[i][j]]); startVal.add(allocation[i] == j ? 1 : 0); } } for(int i = 0; i < g->bidders; i++) { if(boundu(i) > 0){ startVar.add(z[i]); startVal.add(allocation[i] != -1 ? pricing[allocation[i]] : 0); } } cplex.addMIPStart(startVar, startVal); }
static void solveanddisplay (IloEnv env, IloCplex cplex, IloNumVarArray var, IloRangeArray con) { // Optimize the problem and obtain solution. if ( !cplex.solve() ) { env.error() << "Failed to optimize LP" << endl; throw(-1); } IloNumArray vals(env); env.out() << "Solution status = " << cplex.getStatus() << endl; env.out() << "Solution value = " << cplex.getObjValue() << endl; cplex.getValues(vals, var); env.out() << "Values = " << vals << endl; cplex.getSlacks(vals, con); env.out() << "Slacks = " << vals << endl; cplex.getDuals(vals, con); env.out() << "Duals = " << vals << endl; cplex.getReducedCosts(vals, var); env.out() << "Reduced Costs = " << vals << endl; } // END solveanddisplay
/** Get the best integer feasible objective value in this worker. * Calling this function before calling join() is an error. */ double getObjective() const { return cplex.getObjValue(); }
// Finds the total path if there's no irregularity or an sub-path that // contains I and not I - n (Infeasible for family (5)) void getPath (const IloCplex& cplex, const IloArray <IloBoolVarArray>& solution, vector <int>& P, vector<int>& VP, int src, const vector< Client > &precedences, bool reverse) { // The depot always belongs to P P.push_back(src); // Mark the vertex alread visited on the path vector< bool > visited ( solution.getSize(), false ); visited [src] = true; // Each iteration finds the next vertex on the path while ( P.size() < (size_t) solution.getSize() ) { // Finds the next vertex on the path (after src on the route) int v; for (v = ((reverse && (P.size() == 1)) ? 1 : 0); v < solution [src].getSize(); v++) { if ((cplex.getValue (solution [src][v])) && (visited [v] == false) ) break; } // There must be such a vertex v (This solution is TSP feasible) //assert (v < solution.getSize()); // Testing infeasibility (Searching in the precedence rules) for (size_t i = 0; i < precedences.size(); i++) { // If v is a location in this pair (rule) if (precedences[i].delivery == v || precedences[i].pickup == v) { // Adding v to the path and starting over with src == v; P.push_back(v); src = v; visited [v] = true; // Checking infeasibility if (!reverse) { // If v is a delivery vertex and its pickup wasn't visited yet if ((precedences[i].delivery == v) && (visited [ precedences[i].pickup ] == false)) { getCutComplement (visited, VP); return; } } else { // If v is a pickup vertex and its delivery wasn't visited yet if ((precedences[i].pickup == v) && (visited [ precedences[i].delivery ] == false)) { getCutComplement (visited, VP); return; } } // v is feasible break; } } // Test other vertex at the while } }
// Test KKT conditions on the solution. // The function returns true if the tested KKT conditions are satisfied // and false otherwise. // The function assumes that the model currently extracted to CPLEX is fully // described by obj, vars and rngs. static bool checkkkt (IloCplex& cplex, IloObjective const& obj, IloNumVarArray const& vars, IloRangeArray const& rngs, IloIntArray const& cone, double tol) { IloEnv env = cplex.getEnv(); IloModel model = cplex.getModel(); IloNumArray x(env), dslack(env); IloNumArray pi(env, rngs.getSize()), slack(env); // Read primal and dual solution information. cplex.getValues(x, vars); cplex.getSlacks(slack, rngs); // pi for second order cone constraints. getsocpconstrmultipliers(cplex, vars, rngs, pi, dslack); // pi for linear constraints. for (IloInt i = 0; i < rngs.getSize(); ++i) { IloRange r = rngs[i]; if ( !r.getQuadIterator().ok() ) pi[idx(r)] = cplex.getDual(r); } // Print out the data we just fetched. streamsize oprec = env.out().precision(3); ios_base::fmtflags oflags = env.out().setf(ios::fixed | ios::showpos); env.out() << "x = ["; for (IloInt i = 0; i < x.getSize(); ++i) env.out() << " " << x[i]; env.out() << " ]" << endl; env.out() << "dslack = ["; for (IloInt i = 0; i < dslack.getSize(); ++i) env.out() << " " << dslack[i]; env.out() << " ]" << endl; env.out() << "pi = ["; for (IloInt i = 0; i < rngs.getSize(); ++i) env.out() << " " << pi[i]; env.out() << " ]" << endl; env.out() << "slack = ["; for (IloInt i = 0; i < rngs.getSize(); ++i) env.out() << " " << slack[i]; env.out() << " ]" << endl; env.out().precision(oprec); env.out().flags(oflags); // Test primal feasibility. // This example illustrates the use of dual vectors returned by CPLEX // to verify dual feasibility, so we do not test primal feasibility // here. // Test dual feasibility. // We must have // - for all <= constraints the respective pi value is non-negative, // - for all >= constraints the respective pi value is non-positive, // - the dslack value for all non-cone variables must be non-negative. // Note that we do not support ranged constraints here. for (IloInt i = 0; i < vars.getSize(); ++i) { IloNumVar v = vars[i]; if ( cone[i] == NOT_IN_CONE && dslack[i] < -tol ) { env.error() << "Dual multiplier for " << v << " is not feasible: " << dslack[i] << endl; return false; } } for (IloInt i = 0; i < rngs.getSize(); ++i) { IloRange r = rngs[i]; if ( fabs (r.getLB() - r.getUB()) <= tol ) { // Nothing to check for equality constraints. } else if ( r.getLB() > -IloInfinity && pi[i] > tol ) { env.error() << "Dual multiplier " << pi[i] << " for >= constraint" << endl << r << endl << "not feasible" << endl; return false; } else if ( r.getUB() < IloInfinity && pi[i] < -tol ) { env.error() << "Dual multiplier " << pi[i] << " for <= constraint" << endl << r << endl << "not feasible" << endl; return false; } } // Test complementary slackness. // For each constraint either the constraint must have zero slack or // the dual multiplier for the constraint must be 0. We must also // consider the special case in which a variable is not explicitly // contained in a second order cone constraint. for (IloInt i = 0; i < vars.getSize(); ++i) { if ( cone[i] == NOT_IN_CONE ) { if ( fabs(x[i]) > tol && dslack[i] > tol ) { env.error() << "Invalid complementary slackness for " << vars[i] << ":" << endl << " " << x[i] << " and " << dslack[i] << endl; return false; } } } for (IloInt i = 0; i < rngs.getSize(); ++i) { if ( fabs(slack[i]) > tol && fabs(pi[i]) > tol ) { env.error() << "Invalid complementary slackness for " << endl << rngs[i] << ":" << endl << " " << slack[i] << " and " << pi[i] << endl; return false; } } // Test stationarity. // We must have // c - g[i]'(X)*pi[i] = 0 // where c is the objective function, g[i] is the i-th constraint of the // problem, g[i]'(x) is the derivate of g[i] with respect to x and X is the // optimal solution. // We need to distinguish the following cases: // - linear constraints g(x) = ax - b. The derivative of such a // constraint is g'(x) = a. // - second order constraints g(x[1],...,x[n]) = -x[1] + |(x[2],...,x[n])| // the derivative of such a constraint is // g'(x) = (-1, x[2]/|(x[2],...,x[n])|, ..., x[n]/|(x[2],...,x[n])| // (here |.| denotes the Euclidean norm). // - bound constraints g(x) = -x for variables that are not explicitly // contained in any second order cone constraint. The derivative for // such a constraint is g'(x) = -1. // Note that it may happen that the derivative of a second order cone // constraint is not defined at the optimal solution X (this happens if // X=0). In this case we just skip the stationarity test. IloNumArray sum(env, vars.getSize()); for (IloExpr::LinearIterator it = obj.getLinearIterator(); it.ok(); ++it) sum[idx(it.getVar())] = it.getCoef(); for (IloInt i = 0; i < vars.getSize(); ++i) { IloNumVar v = vars[i]; if ( cone[i] == NOT_IN_CONE ) sum[i] -= dslack[i]; } for (IloInt i = 0; i < rngs.getSize(); ++i) { IloRange r = rngs[i]; if ( r.getQuadIterator().ok() ) { // Quadratic (second order cone) constraint. IloNum norm = 0.0; for (IloExpr::QuadIterator q = r.getQuadIterator(); q.ok(); ++q) { if ( q.getCoef() > 0 ) norm += x[idx(q.getVar1())] * x[idx(q.getVar1())]; } norm = sqrt(norm); if ( fabs(norm) <= tol ) { // Derivative is not defined. Skip test. env.warning() << "Cannot test stationarity at non-differentiable point." << endl; return true; } else { for (IloExpr::QuadIterator q = r.getQuadIterator(); q.ok(); ++q) { if ( q.getCoef() < 0 ) sum[idx(q.getVar1())] -= pi[i]; else sum[idx(q.getVar1())] += pi[i] * x[idx(q.getVar1())] / norm; } } } else { // Linear constraint. for (IloExpr::LinearIterator l = r.getLinearIterator(); l.ok(); ++l) sum[idx(l.getVar())] -= pi[i] * l.getCoef(); } } // Now test that all elements in sum[] are 0. for (IloInt i = 0; i < vars.getSize(); ++i) { if ( fabs(sum[i]) > tol ) { env.error() << "Invalid stationarity " << sum[i] << " for " << vars[i] << endl; return false; } } return true; }
IloNum columnGeneration (IloCplex2 subSolver, IloCplex rmpSolver, IloNumVarArray3 x, IloNumVarArray2 z, IloNumVarArray2 lambda, IloObjective2 reducedCost, IloObjective rmpObj, IloRangeArray2 maintConEng, IloRangeArray2 removeMod, IloRangeArray2 convex, IloNumArray2 addXCol, IloNumArray addZCol, IloNumArray2 priceRemoveMod, IloNumArray2 priceMaintConEng, IloNumArray priceConvex, const IloNumArray2 compCosts, const IloNumArray convexityCoef, IloBool weightedDW_in, IloBool allowCustomTermination, IloInt relChangeSpan, IloNum relChange) { // extract optimization enviroment IloEnv env = rmpSolver.getEnv(); // ANALYSIS: write to file const char* output = "results/colGen_analysis.dat"; // variable declarations.. // loop counters IloInt i, m, t, testCounter; testCounter = 0; // declare two clock_t objects for start and end time. clock_t start, end; // declare an array of size NR_OF_MODULES to temporarily hold the // reduced costs from the NR_OF_MODULES different subproblems. IloNumArray redCosts(env, NR_OF_MODULES); IloBool weightedDW = weightedDW_in; // declare an array to hold the RMP objective values: e.g. add // one value to array for each iteration. // IloNumArray objValues(env); // declare an array to hold the lower bounds for the full MP, given // z(RMP)* + sum_[m in subproblems] redCost(m)^* <= z(full MP)^* <= z(RMP)^* // IloNumArray lowerBounds(env); // declare two temp IloNum objects for temporarily hold rmp objective value // and full MP lower bound. (full: MP with _all_ columns availible). IloNum tempRmpObj, tempLowerBound, bestLowerBound; bestLowerBound = -IloInfinity; // also use a num-array to hold the REL_CHANGE_SPAN most // recent RMP objective values. Used to the relative change // break criteria (if improvement by col-gen becomes to // "slow"/"flat"). IloNumArray recentObjValues(env, REL_CHANGE_SPAN); // declare and initiate col-gen iteration counter IloInt itNum = 0; // ---- weighted DW decomp - for less trailing in colgen. //IloBool weightedDW = IloTrue; // declare two IloNum-array to hold all 2x (NR_OF_MODULES x TIME_SPAN) // dual vars - or specific, best dual vars (giving highest lower bound) IloNumArray2 dualsModBest(env); IloNumArray2 dualsEngBest(env); // temp.. //IloBoolArray continueSub(env, NR_OF_MODULES); // allocate memory for sub-arrays for (m = 0; m < NR_OF_MODULES; m++) { dualsModBest.add(IloNumArray(env,TIME_SPAN)); dualsEngBest.add(IloNumArray(env,TIME_SPAN)); //continueSub[m] = IloTrue; // and maybe: initially set all dual vars to 0? for (t = 0; t < TIME_SPAN; t++) { dualsModBest[m][t] = 0.0; dualsEngBest[m][t] = 0.0; } } // also, a weight for weighted DW: IloNum weight = 2.0; // counter number of improvements of "best duals" IloInt nrOfImprov = 0; // const used in weigt IloNum weightConst = DW_WEIGHT; // initiate numarray for recent objective values // UPDATE: this is not really needed now as we check the // relative change break criteria only when we know this // vector has been filled by REL_CHANGE_SPAN "proper" values... recentObjValues[0] = 0.0; for (i = 1; i < REL_CHANGE_SPAN; i++) { recentObjValues[i] = 0.0; } // model before generation start: //rmpSolver.exportModel("rmpModel.lp"); //write results to file /* ofstream outFile(output); outFile << "Writing out results from initial column generation, T=" << TIME_SPAN << endl << "Form: [(itNum) (dual solution value) (upper bound = tempRmpObj)]" << endl << endl;*/ //cout << endl << "WE GOT OURSELVES A SEGMENTATION FAULT!" << endl; // start timer start = clock(); // also use an alternative time counter.. time_t start2, end2; start2 = time(NULL); // loop until break... for (;;) { // increase iteration counter itNum++; // solve master if ( !rmpSolver.solve() ) { env.error() << "Failed to optimize RMP." << endl; throw(-1); } // get the rmp objective value tempRmpObj = rmpSolver.getValue(rmpObj); // add to objective value array (size: iterations) // objValues.add(tempRmpObj); // update recentObjValues: recentObjValues.remove(0); // remove oldest: recentObjValues.add(tempRmpObj); // save newest // report something (... report1() ) // UPDATE: colgen is to quick for anything to see anything reported... so skip this // update weight: weight = min{ 2, if (itNum>1) { weight = (IloNum(itNum - 1) + IloNum(nrOfImprov))/2; } if ( weight > weightConst) { weight = weightConst; } // update duals // -> updates obj. functions for subproblems (w.r.t. duals) for (m = 0; m < NR_OF_MODULES; m++) { //cout << "weight = " << weight << endl; //cin.get(); for (t = 0; t < TIME_SPAN; t++) { // if we try weightedWD decomp: // for first iteration: just extract duals which will become best duals if (itNum > 1 && weightedDW) { // price associated with const. removeMod priceRemoveMod[m][t] = (rmpSolver.getDual(removeMod[m][t]))/weight + (weight-1)*(dualsModBest[m][t])/weight; // price associated with const. maintConEng priceMaintConEng[m][t] = (rmpSolver.getDual(maintConEng[m][t]))/weight + (weight-1)*(dualsEngBest[m][t])/weight; } // normally: else { // price associated with const. removeMod priceRemoveMod[m][t] = rmpSolver.getDual(removeMod[m][t]); // price associated with const. maintConEng priceMaintConEng[m][t] = rmpSolver.getDual(maintConEng[m][t]); } //cout << "priceRemoveMod[m][t] = " << priceRemoveMod[m][t] << endl; // update subproblem obj. function coefficients for z[m][t] vars: reducedCost[m].setLinearCoef(z[m][t],-(priceRemoveMod[m][t] + priceMaintConEng[m][t])); } //cin.get(); // rmpSolver.getDuals(priceRemoveMod[m], removeMod[m]); // rmpSolver.getDuals(priceMaintConEng[m], maintConEng[m]); // priceConvex[m] = -rmpSolver.getDual(convex[m][0]); // if we try weightedWD decomp: // for first iteration: just extract duals which will become best duals /* if (itNum > 1 && weightedDW) { // price associated with convexity constraint priceConvex[m] = -abs(rmpSolver.getDual(convex[m][0]))/weight - (weight-1)*(dualsConvBest[m])/weight; } */ // price associated with convexity constraint priceConvex[m] = -abs(rmpSolver.getDual(convex[m][0])); // update subproblem obj. function's constant term reducedCost[m].setConstant(priceConvex[m]); } // END of updating duals // solve subproblems for (m = 0; m < NR_OF_MODULES; m++) { //if (continueSub[m]) { // solve subproblem m cout << endl << "Solving subproblem #" << (m+1) << "." << endl; if ( !subSolver[m].solve() ) { env.error() << "Failed to optimize subproblem #" << (m+1) << "." << endl; throw(-1); } // extract reduced cost: subSolver[m].getValue(reducedCost[m]) // into a IloNumArray(env, NR_OF_MODULES) at position m. redCosts[m] = subSolver[m].getValue(reducedCost[m]); //env.out() << endl << "Reduced cost for problem #" << (m+1) << ":" << redCosts[m] << endl; // if reduced cost is negative, att optimal solution to // column pool Q(m) if (!(redCosts[m] > -RC_EPS)) { // add column addColumn(subSolver[m], x[m], z[m], lambda[m], rmpObj, maintConEng[m], removeMod[m], convex[m], addXCol, addZCol, compCosts[m], convexityCoef); //env.out() << endl << "Added a column to pool Q(" << (m+1) // << "). Lambda[" << (m+1) << "].size = " << lambda[m].getSize() << endl; testCounter++; } //else { // continueSub[m] = IloFalse; //} //} //else { // redCosts[m] = 0; //} } // END of solving subproblems (for this iteration) // calculate lower bound on full MP tempLowerBound = tempRmpObj + sumArray(redCosts); // update best lower bound if (tempLowerBound > bestLowerBound) { bestLowerBound = tempLowerBound; // increase counter for number of improved "best duals". nrOfImprov++; //cout << endl << "WHATEVAAAH" << endl; //cin.get(); // save best duals for (m = 0; m < NR_OF_MODULES; m++) { for (t = 0; t < TIME_SPAN; t++) { dualsModBest[m][t] = priceRemoveMod[m][t]; dualsEngBest[m][t] = priceMaintConEng[m][t]; } } } // update lower bounds vector //lowerBounds.add(bestLowerBound); // ANALYSIS: print out to file: // [(itNum) (dual solution value) (upper bound = tempRmpObj)] //outFile << itNum << " " << tempLowerBound << " " << tempRmpObj << endl; // if the smallest reduced cost in the updated red-cost vector // with NR_OF_MODULES entries is greater than -RC_EPS: break // otherwise, repeat. if (minMemberValue(redCosts) > -RC_EPS) { env.out() << endl << "All reduced costs non-negative: breaking." << endl; bestLowerBound = tempRmpObj; break; } // if relative change in objective value over the last REL_CHANGE_SPAN iterations is // less than REL_CHANGE, break. //if (allowCustomTermination && (itNum >= REL_CHANGE_SPAN) && (relativeImprovement(recentObjValues) < REL_CHANGE)) { if (allowCustomTermination && (itNum >= relChangeSpan) && (relativeImprovement(recentObjValues) < relChange)) { env.out() << endl << "Relative change smaller than pre-set acceptance: breaking." << endl; break; } // if the gap currentUpperBound - currentLowerBound is small enough, break if ((tempRmpObj - bestLowerBound) < RC_EPS) { env.out() << endl << "Lower<>Upper bound gap less than pre-set acceptance: breaking." << endl; cout << endl << "(tempRmpObj - bestLowerBound) = " << (tempRmpObj - bestLowerBound) << endl; bestLowerBound = tempRmpObj; break; } } // END of column generation. // alternative: print the REL_CHANGE_SPAN most recent RMP objective values env.out() << endl; /*for (i = 0; i < recentObjValues.getSize(); i++) { env.out() << "Recent #" << (i+1) << ": " << recentObjValues[i] << endl; }*/ // solve master using final column setup if ( !rmpSolver.solve() ) { env.error() << "Failed to optimize RMP." << endl; throw(-1); } // also add final objective value to objective value array (size: iterations) // objValues.add(rmpSolver.getValue(rmpObj)); // create IloNum object and extract the final RMP objective value. IloNum finalObj; finalObj = rmpSolver.getValue(rmpObj); // end program time counter(s) end = clock(); end2 = time(NULL); // print result to file //outFile << endl << endl << "Final objective value: " << finalObj << endl // << "Time required for execution: " << (double)(end-start)/CLOCKS_PER_SEC << " seconds." << endl; // outfile.close() //outFile.close(); itNum = 0; // re- use iteration counter to count total number of columns generated // nr of columns generated from each subproblem for (m = 0; m < NR_OF_MODULES; m++) { // ### outFile << "Number of columns generated from subproblem (m = " << m << "): " << (lambda[m].getSize() - 1) << endl; cout << "Number of columns generated from subproblem (m = " << m << "): " << (lambda[m].getSize() - 1) << endl; //outFile << "Pool (m = " << m << "): " << (lambda[m].getSize() - 1) << endl; itNum += lambda[m].getSize(); } // ### /* outFile << endl << "Total number of columns generated: " << itNum << endl; outFile << "Time required for column generation: " << (double)(end-start)/CLOCKS_PER_SEC << " seconds." << endl; outFile << "ALTERNATIVE: Time required for colgen: " << end2-start2 << " seconds." << endl; outFile << "RMP objective function cost: " << finalObj << endl << endl; //outFile << "Objective function values for each iteration: " << endl; //outFile << objValues; //outFile << endl << endl << "Lower bounds for each iteration: " << endl; //outFile << lowerBounds; outFile.close(); */ //cout << "Initial column generation complete, press enter to continue..." << endl; //cin.get(); // print some results.. /*env.out() << endl << "RMP objective function cost: " << finalObj << endl; env.out() << endl << "Size of objective value vector: " << objValues.getSize() << endl; env.out() << endl << "Nr of iterations: " << itNum << endl; cout << endl << "Number of new columns generated: " << testCounter << endl;*/ // Note: to explicit output (void function), ass columns are added implicitely via // income argument pointers. // clear memory assigned to temporary IloNumArrays: redCosts.end(); //objValues.end(); //lowerBounds.end(); recentObjValues.end(); // save best duals for (m = 0; m < NR_OF_MODULES; m++) { dualsModBest[m].end(); dualsEngBest[m].end(); } dualsModBest.end(); dualsEngBest.end(); //continueSub.end(); //cout << endl << "NR OF IMPROVEMENTS: " << nrOfImprov << endl; //cin.get(); // return lower bound return bestLowerBound; } // END of columnGeneration()
// 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
// This routine set up the IloCplex algorithm to solve the worker LP, and // creates the worker LP (i.e., the dual of flow constraints and // capacity constraints of the flow MILP) // // Modeling variables: // forall k in V0, i in V: // u(k,i) = dual variable associated with flow constraint (k,i) // // forall k in V0, forall (i,j) in A: // v(k,i,j) = dual variable associated with capacity constraint (k,i,j) // // Objective: // 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) // // Constraints: // forall k in V0, forall (i,j) in A: u(k,i) - u(k,j) <= v(k,i,j) // // Nonnegativity on variables v(k,i,j) // forall k in V0, forall (i,j) in A: v(k,i,j) >= 0 // void createWorkerLP(IloCplex cplex, IloNumVarArray v, IloNumVarArray u, IloObjective obj, IloInt numNodes) { IloInt i, j, k; IloEnv env = cplex.getEnv(); IloModel mod(env, "atsp_worker"); // Set up IloCplex algorithm to solve the worker LP cplex.extract(mod); cplex.setOut(env.getNullStream()); // Turn off the presolve reductions and set the CPLEX optimizer // to solve the worker LP with primal simplex method. cplex.setParam(IloCplex::Reduce, 0); cplex.setParam(IloCplex::RootAlg, IloCplex::Primal); // Create variables v(k,i,j) forall k in V0, (i,j) in A // For simplicity, also dummy variables v(k,i,i) are created. // Those variables are fixed to 0 and do not partecipate to // the constraints. IloInt numArcs = numNodes * numNodes; IloInt vNumVars = (numNodes-1) * numArcs; IloNumVarArray vTemp(env, vNumVars, 0, IloInfinity); for (k = 1; k < numNodes; ++k) { for (i = 0; i < numNodes; ++i) { vTemp[(k-1)*numArcs + i *numNodes + i].setBounds(0, 0); } } v.clear(); v.add(vTemp); vTemp.end(); mod.add(v); // Set names for variables v(k,i,j) for (k = 1; k < numNodes; ++k) { for(i = 0; i < numNodes; ++i) { for(j = 0; j < numNodes; ++j) { char varName[100]; sprintf(varName, "v.%d.%d.%d", (int) k, (int) i, (int) j); v[(k-1)*numArcs + i*numNodes + j].setName(varName); } } } // Associate indices to variables v(k,i,j) IloIntArray vIndex(env, vNumVars); for (j = 0; j < vNumVars; ++j) { vIndex[j] = j; v[j].setObject(&vIndex[j]); } // Create variables u(k,i) forall k in V0, i in V IloInt uNumVars = (numNodes-1) * numNodes; IloNumVarArray uTemp(env, uNumVars, -IloInfinity, IloInfinity); u.clear(); u.add(uTemp); uTemp.end(); mod.add(u); // Set names for variables u(k,i) for (k = 1; k < numNodes; ++k) { for(i = 0; i < numNodes; ++i) { char varName[100]; sprintf(varName, "u.%d.%d", (int) k, (int) i); u[(k-1)*numNodes + i].setName(varName); } } // Associate indices to variables u(k,i) IloIntArray uIndex(env, uNumVars); for (j = 0; j < uNumVars; ++j) { uIndex[j] = vNumVars + j; u[j].setObject(&uIndex[j]); } // Initial objective function is empty obj.setSense(IloObjective::Minimize); mod.add(obj); // Add constraints: // forall k in V0, forall (i,j) in A: u(k,i) - u(k,j) <= v(k,i,j) for (k = 1; k < numNodes; ++k) { for(i = 0; i < numNodes; ++i) { for(j = 0; j < numNodes; ++j) { if ( i != j ) { IloExpr expr(env); expr -= v[(k-1)*numArcs + i*(numNodes) + j]; expr += u[(k-1)*numNodes + i]; expr -= u[(k-1)*numNodes + j]; mod.add(expr <= 0); expr.end(); } } } } }// END createWorkerLP
bool FrontalSolverWithoutConnexity::solve(int borne_max, bool warmstart) { LOG(INFO) << name_ << " :: " << description_; //Extracting data VLOG(2) << "Extracting data"; int n = data_.n; int m = data_.m; double Ba = data_.Ba; double Bp = data_.Bp; const vector<vector<double> >& Ha = data_.Ha; const vector<vector<double> >& Ca = data_.Ca; const vector<vector<double> >& Hp = data_.Hp; const vector<vector<double> >& Cp = data_.Cp; //Environement VLOG(2) << "Creating environment"; IloEnv env; IloModel model = IloModel (env); IloCplex cplex = IloCplex(model); //Variables VLOG(2) << "Creating variables"; BoolVarMatrix x(env); NumVarMatrix y(env); NumVarMatrix z(env); VLOG(2) << "Creating variables"; for (int i = 0; i < m ; ++i) { x.add(IloBoolVarArray(env,n)); y.add(IloNumVarArray(env,n,0,Bp)); z.add(IloNumVarArray(env,n,0,Ba)); } IloNumVar ha_var(env); model.add(ha_var); IloNumVar hp_var(env); model.add(hp_var); //Objective function VLOG(2) << "Processing objective function"; IloExpr objective(env,0); for (int i = 0; i < m ; ++i) { for (int j = 0; j < n ; ++j) { objective += x[i][j]; } } model.add(IloMaximize(env, objective )); VLOG(2) << "Creating constraint expressions"; IloExpr sum_Cy(env,0); IloExpr sum_HCPx(env,0); IloExpr sum_Cz(env,0); IloExpr sum_HCAx(env,0); VLOG(2) << "Computing constraint expressions"; for (int i = 0; i < m ; ++i) { for (int j = 0; j < n ; ++j) { VLOG(5) << i << " " << j << " " << Cp[i][j] << endl; sum_Cy += y[i][j]*Cp[i][j]; sum_Cz += z[i][j]*Ca[i][j]; sum_HCPx += x[i][j]*Hp[i][j]*Cp[i][j]; sum_HCAx += x[i][j]*Ha[i][j]*Ca[i][j]; } } VLOG(2) << "Adding constraints"; //Selection of an admissible area model.add(sum_Cy == sum_HCPx); model.add(sum_Cz == sum_HCAx); model.add(ha_var + hp_var >= 2); for (int i = 0; i < m ; ++i) { for (int j = 0; j < n ; ++j) { //Defining y model.add(y[i][j] <= Bp*x[i][j]); model.add(y[i][j] <= hp_var); model.add(y[i][j] >= hp_var - Bp*(1-x[i][j])); model.add(y[i][j] >= 0); //Defining z model.add(z[i][j] <= Ba*x[i][j]); model.add(z[i][j] <= ha_var); model.add(z[i][j] >= ha_var - Ba*(1-x[i][j])); model.add(z[i][j] >= 0); //Constraint on x if (Cp[i][j] == 0) model.add(x[i][j]==0); } } // Warmstart if (warmstart) { // Setting Warmstart from solution VLOG(2) << "Setting informations for warmstart"; IloNumVarArray startVar(env); IloNumArray startVal(env); for (int i = 0; i < m; ++i) for (int j = 0; j < n; ++j) { startVar.add(x[i][j]); startVal.add(sol_.x_[i][j]); if (sol_.x_[i][j] == 0){ startVar.add(y[i][j]); startVal.add(sol_.x_[i][j]); startVar.add(z[i][j]); startVal.add(sol_.x_[i][j]); } } cplex.addMIPStart(startVar, startVal); startVal.end(); startVar.end(); } //Solve VLOG(2) << "Resolution..."; cplex.solve(); //Output VLOG(2) << "Solution status = " << cplex.getStatus() << endl; VLOG(2) << "Solution value = " << cplex.getObjValue() << endl; for (int i = 0; i < data_.m; ++i) { for (int j = 0; j < data_.n; ++j) { sol_.x_[i][j] = cplex.getValue(x[i][j]); } } env.end(); return false; }
std::string CPLEX_LP_MSTSolverIF::getCPLEXStatus(IloCplex& cplex) { std::ostringstream oss { }; oss << cplex.getStatus() << std::flush; return oss.str(); }
/** Get the solution status for this worker. * Calling this function before calling join() is an error. */ IloAlgorithm::Status getStatus() const { return cplex.getStatus(); }
/** Create a new worker. * The constructor mainly does the following: * - create an IloCplex instance that refers to a remote worker, * - load the model in <code>modelfile</code>, * - setup parameters depending on this worker's index, * - start an asynchronous solve. * If anything fails then an exception will be thrown. * @param env The environment used for instantiating Ilo* objects. * @param i The index of the worker to be created. This also * determines the parameter settings to use in this worker. * @param s A pointer to the global solve state. * @param transport The transport name for the IloCplex constructor. * @param argc The argument count for the IloCplex constructor. * @param argv The array of transport arguments for the IloCplex * constructor. * @param modelfile Name of the model to be loaded into the worker. * @param output The output mode. * @param objdiff The minimal difference between so that two * consecutive objective function values are considered * different. */ Worker(IloEnv env, int i, SolveState *s, char const *transport, int argc, char const **argv, char const *modelfile, OUTPUT output, double objdiff) : idx(i), state(s), model(env), cplex(0), handle(0), primal(IloInfinity), dual(-IloInfinity), obj(env), x(env), rng(env), infoHandler(this), outb(idx), outs(&outb) { try { // Create remote object, setup output and load the model. cplex = IloCplex(model, transport, argc, argv); switch (output) { case OUTPUT_SILENT: // Disable output on the output and warning stream. cplex.setOut(env.getNullStream()); cplex.setWarning(env.getNullStream()); break; case OUTPUT_PREFIXED: // Redirect output to our custom stream. cplex.setOut(outs); cplex.setWarning(outs); break; case OUTPUT_LOG: // Nothing to do here. By default output is enabled. break; } cplex.importModel(model, modelfile, obj, x, rng); if ( obj.getSense() == IloObjective::Minimize ) { primal = -IloInfinity; dual = IloInfinity; } // We set the thread count for each solver to 1 so that we do not // run into problems if multiple solves are performed on the same // machine. cplex.setParam(IloCplex::Param::Threads, 1); // Each worker runs with a different random seed. This way we // get different paths through the tree even if the other // parameter settings are the same. cplex.setParam(IloCplex::Param::RandomSeed, idx); // Apply parameter settings. for (class ParamValue const *vals = settings[idx % NUMSETTINGS].values; vals->isValid(); ++vals) vals->apply(cplex); // Install callback and set objective change. int status = cplex.userfunction (USERACTION_ADDCALLBACK, 0, NULL, 0, 0, NULL); if ( status ) throw status; IloCplex::Serializer s; s.add(objdiff); status = cplex.userfunction (USERACTION_CHANGEOBJDIFF, s.getRawLength(), s.getRawData(), 0, 0, NULL); if ( status ) throw status; // Register the handler that will process info messages sent // from the worker. cplex.setRemoteInfoHandler(&infoHandler); // Everything is setup. Launch the asynchronous solve. handle = cplex.solve(true); } catch (...) { // In case of an exception we need to take some special // cleanup actions. Note that if we get here then the // solve cannot have been started and we don't need to // kill or join the asynchronous solve. if ( cplex.getImpl() ) cplex.end(); rng.end(); x.end(); obj.end(); model.end(); throw; } }
/** Get the best incumbent in this worker. * Calling this function before calling join() is an error. */ IloNumArray getX() const { IloNumArray values(cplex.getEnv()); cplex.getValues(x, values); return values; }