// 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
ILOBRANCHCALLBACK1(SOSbranch, IloSOS1Array, sos) { IloNumArray x; IloNumVarArray var; try { IloInt i; x = IloNumArray(getEnv()); var = IloNumVarArray(getEnv()); IloNum bestx = EPS; IloInt besti = -1; IloInt bestj = -1; IloInt num = sos.getSize(); for (i = 0; i < num; i++) { if ( getFeasibility(sos[i]) == Infeasible ) { var.clear(); sos[i].getVariables(var); getValues(x, var); IloInt n = var.getSize(); for (IloInt j = 0; j < n; j++) { IloNum inf = IloAbs(x[j] - IloRound(x[j])); if ( inf > bestx ) { bestx = inf; besti = i; bestj = j; } } } } if ( besti >= 0 ) { IloCplex::BranchDirectionArray dir; IloNumArray val; try { dir = IloCplex::BranchDirectionArray(getEnv()); val = IloNumArray(getEnv()); var.clear(); sos[besti].getVariables(var); IloInt n = var.getSize(); for (IloInt j = 0; j < n; j++) { if ( j != bestj ) { dir.add(IloCplex::BranchDown); val.add(0.0); } else { dir.add(IloCplex::BranchUp); val.add(1.0); } } makeBranch(var, val, dir, getObjValue()); makeBranch(var[bestj], 0.0, IloCplex::BranchDown, getObjValue()); } catch (...) { dir.end(); val.end(); throw; } dir.end(); val.end(); } } catch (...) { var.end(); x.end(); throw; } var.end(); x.end(); }