public double solve(Instance ins, Solution sol, int timeout) throws IloException { IloCplex solver = new IloCplex(); BiIndexedIntVarMap y = new BiIndexedIntVarMap(solver, 0, 1, "y"); // (k,v) (cluster,node) IndexedNumVarMap d = new IndexedNumVarMap(solver, 0, Double.MAX_VALUE, "dp"); // (k) (cluster) TriIndexedNumVarMap f = new TriIndexedNumVarMap(solver, 0, Double.MAX_VALUE, "f"); // (k,i,j) (cluster,tail,head) BiIndexedIntVarMap r = new BiIndexedIntVarMap(solver, 0, 1, "r"); // (k,i) (cluster,node BiIndexedNumVarMap w = new BiIndexedNumVarMap(solver, 0, 1, "w"); // (i,j) (node1<node2) int superRoot = ins.getNumNodes(); // compute the weights of the objective function double w1 = ins.getW1() / ins.getNumNodes(); double w2 = ins.getW2() / (ins.getLambda() * ins.getMaxClusterNumber()); double w3 = 2 * ins.getW3() / (ins.getNumNodes() * (ins.getNumNodes() - 1) * (ins.getDMax() - ins.getDMin())); Set<OrderedPair> fp = new TreeSet<OrderedPair>(ins.getP()); if (isActiveExtension(Extension.PFILTER)) { fp = ins.filterP(); System.out.println("PFILTER: " + (ins.getP().size() - fp.size()) + " pairs filtered"); } // compute the objective function expression IloNumExpr expr = solver.numExpr(); // O1 IloNumExpr exprO1 = solver.numExpr(); for (int i = 0; i < ins.getNumNodes(); ++i) { expr = solver.numExpr(); expr = solver.sum(expr, 1); for (int k = 0; k < ins.getMaxClusterNumber(); ++k) expr = solver.diff(expr, y.get(k, i)); exprO1 = solver.sum(exprO1, solver.prod(w1, expr)); } // O2 IloNumExpr exprO2 = solver.numExpr(); for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { exprO2 = solver.sum(exprO2, solver.prod(w2, d.get(k))); } // O3 IloNumExpr exprO3 = solver.numExpr(); for (OrderedPair p : fp) { double dmax = ins.getDMax(); double dist = ins.getD(p.i, p.j); IloNumVar wvar = w.get(p.i, p.j); exprO3 = solver.sum(exprO3, solver.prod(w3 * (dmax - dist), wvar)); } expr = solver.sum(exprO1, solver.sum(exprO2, exprO3)); solver.add(solver.objective(IloObjectiveSense.Minimize, expr)); // packing constraints for (int i = 0; i < ins.getNumNodes(); ++i) { expr = solver.numExpr(); for (int k = 0; k < ins.getMaxClusterNumber(); ++k) expr = solver.sum(expr, y.get(k, i)); solver.addLe(expr, 1); } // root uniqueness constraints for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { expr = solver.numExpr(); for (int i = 0; i < ins.getNumNodes(); ++i) expr = solver.sum(expr, r.get(k, i)); solver.addLe(expr, 1); } // f,y linking constraints // OUT for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { for (int i = 0; i < ins.getNumNodes(); ++i) { expr = solver.numExpr(); for (Integer j : ins.getOutcut(i)) { expr = solver.sum(expr, f.get(k, i, j)); } expr = solver.diff(expr, solver.prod(ins.getMaxClusterSize() - 2, y.get(k, i))); solver.addLe(expr, 0); } } // f,r linking constraints for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { for (int i = 0; i < ins.getNumNodes(); ++i) { solver.addLe(f.get(k, superRoot, i), solver.prod(ins.getMaxClusterSize(), r.get(k, i))); } } // //flow generation constraints // for(int k=0;k<ins.getMaxClusterNumber();++k){ // expr=solver.numExpr(); // for(int i=0;i<ins.getNumNodes();++i){ // expr=solver.sum(expr,f.get(k,superRoot,i)); // expr=solver.diff(expr, y.get(k, i)); // } // solver.addEq(expr, 0); // } // flow conservation constraints for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { for (int i = 0; i < ins.getNumNodes(); ++i) { expr = solver.numExpr(); for (Integer j : ins.getOutcut(i)) { expr = solver.diff(expr, f.get(k, i, j)); expr = solver.sum(expr, f.get(k, j, i)); } // i can receive flow also from the super root expr = solver.sum(expr, f.get(k, superRoot, i)); solver.addEq(expr, y.get(k, i)); } } // delta definition constraints for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { expr = solver.numExpr(); for (int i = 0; i < ins.getNumNodes(); ++i) { expr = solver.sum(expr, y.get(k, i)); } solver.addLe(solver.diff(expr, ins.getLambda()), d.get(k)); solver.addGe(solver.diff(expr, ins.getLambda()), solver.prod(-1, d.get(k))); } // w var definition constraints for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { for (OrderedPair p : fp) { expr = solver.numExpr(); expr = solver.sum(expr, w.get(p.i, p.j)); expr = solver.diff(expr, y.get(k, p.i)); expr = solver.diff(expr, y.get(k, p.j)); expr = solver.sum(expr, 1); solver.addGe(expr, 0); } } if (isActiveExtension(Extension.ROOT_MINIMIZATION_CONSTRAINTS)) { for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { for (OrderedPair p : fp) { expr = solver.sum(y.get(k, p.i), r.get(k, p.j)); solver.addLe(expr, 1); } } } if (isActiveExtension(Extension.POLYNOMIAL_ORBITOPE)) { // first family for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { expr = solver.numExpr(); for (int v = 0; v <= k - 1; ++v) { expr = solver.sum(expr, y.get(k, v)); } solver.addEq(expr, 0); } // second family for (int k = 1; k < ins.getMaxClusterNumber(); ++k) { for (int v = k; v < ins.getNumNodes(); ++v) { expr = solver.numExpr(); expr = solver.sum(expr, y.get(k, v)); for (int u = k - 1; u <= v - 1; ++u) { expr = solver.diff(expr, y.get(k - 1, u)); } solver.addLe(expr, 0); } } } if (isActiveExtension(Extension.EXPONENTIAL_ORBITOPE)) { System.err.println("Extension " + Extension.EXPONENTIAL_ORBITOPE + " not implemented yet"); throw new IllegalArgumentException(); } if (isActiveExtension(Extension.FLOW_LB)) { // f,x lower bound for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { for (int i = 0; i < ins.getNumNodes(); ++i) { expr = solver.numExpr(); for (Integer j : ins.getOutcut(i)) { expr = solver.sum(expr, f.get(k, j, i)); } expr = solver.sum(expr, f.get(k, superRoot, i)); solver.addGe(expr, y.get(k, i)); solver.addLe(r.get(k, i), f.get(k, superRoot, i)); } } } solver.setParam(IloCplex.DoubleParam.TiLim, timeout); if (isActiveExtension(Extension.ROOT_BRANCHING_PRIORITY)) { // Add branching priorities to the root variables for (int k = 0; k < ins.getMaxClusterNumber(); ++k) for (int i = 0; i < ins.getNumNodes(); ++i) solver.setPriority(r.get(k, i), 100); } solver.setParam(IloCplex.IntParam.ParallelMode, 1); solver.solve(); System.out.println("STATE=" + solver.getStatus()); System.out.println("NN=" + solver.getNnodes()); System.out.println("LB=" + solver.getBestObjValue()); // If we have a feasible solution we save it if (solver.getStatus() == IloCplex.Status.Feasible || solver.getStatus() == IloCplex.Status.Optimal) { for (int k = 0; k < ins.getMaxClusterNumber(); ++k) { for (int v = 0; v < ins.getNumNodes(); ++v) { if (FloatUtils.eq(solver.getValue(y.get(k, v)), 1.0)) { sol.insert(k, v); } } } } return solver.getObjValue(); }
public static void main(String[] args) throws Exception { int status = 127; try { IloOplFactory.setDebugMode(true); IloOplFactory oplF = new IloOplFactory(); // make master model IloOplErrorHandler errHandler = oplF.createOplErrorHandler(); IloOplSettings settings = oplF.createOplSettings(errHandler); IloOplRunConfiguration masterRC = oplF.createOplRunConfiguration( DATADIR + "/cutstock_change.mod", DATADIR + "/cutstock_change.dat"); masterRC.setErrorHandler(errHandler); IloCplex masterCplex = oplF.createCplex(); masterCplex.setOut(null); masterRC.setCplex(masterCplex); IloOplModel masterOpl = masterRC.getOplModel(); masterOpl.generate(); IloOplDataElements masterDataElements = masterOpl.makeDataElements(); int nWdth = masterDataElements.getElement("Amount").asIntMap().getSize(); ArrayList<IloNumVar> masterVars = new ArrayList<IloNumVar>(); IloNumVarMap cuts = masterOpl.getElement("Cut").asNumVarMap(); for (int i = 1; i <= nWdth; i++) { masterVars.add(cuts.get(i)); } // prepare sub model source, definition and engine IloOplModelSource subSource = oplF.createOplModelSource(DATADIR + "/cutstock-sub.mod"); IloOplModelDefinition subDef = oplF.createOplModelDefinition(subSource, settings); IloCplex subCplex = oplF.createCplex(); subCplex.setOut(null); double best; double curr = Double.MAX_VALUE; do { best = curr; // Make master model System.out.println("Solve master."); if (masterCplex.solve()) { curr = masterCplex.getObjValue(); System.out.println("OBJECTIVE: " + curr); status = 0; } else { System.out.println("No solution!"); status = 1; } // prepare data for sub model IloOplDataElements subDataElements = oplF.createOplDataElements(); subDataElements.addElement(masterDataElements.getElement("RollWidth")); subDataElements.addElement(masterDataElements.getElement("Size")); subDataElements.addElement(masterDataElements.getElement("Duals")); // get reduced costs and set them in sub problem IloNumMap duals = subDataElements.getElement("Duals").asNumMap(); for (int i = 1; i < nWdth + 1; i++) { IloForAllRange forAll = (IloForAllRange) masterOpl.getElement("ctFill").asConstraintMap().get(i); duals.set(i, masterCplex.getDual(forAll)); } // make sub model IloOplModel subOpl = oplF.createOplModel(subDef, subCplex); subOpl.addDataSource(subDataElements); subOpl.generate(); System.out.println("Solve sub."); if (subCplex.solve()) { System.out.println("OBJECTIVE: " + subCplex.getObjValue()); status = 0; } else { System.out.println("No solution!"); status = 1; } if (subCplex.getObjValue() > -RC_EPS) break; // Add variable in master model IloNumVar newVar = masterCplex.numVar(0, Double.MAX_VALUE); IloObjective masterObj = masterOpl.getObjective(); masterCplex.setLinearCoef(masterObj, newVar, 1); for (int i = 1; i < nWdth + 1; i++) { double coef = subCplex.getValue(subOpl.getElement("Use").asIntVarMap().get(i)); IloForAllRange forAll = (IloForAllRange) masterOpl.getElement("ctFill").asConstraintMap().get(i); masterCplex.setLinearCoef(forAll, newVar, coef); } masterVars.add(newVar); subOpl.end(); } while (best != curr && status == 0); IloNumVar[] masterVarsA = new IloNumVar[masterVars.size()]; masterVars.toArray(masterVarsA); masterCplex.add(masterCplex.conversion(masterVarsA, IloNumVarType.Int)); if (masterCplex.solve()) { System.out.println("OBJECTIVE: " + masterCplex.getObjValue()); } oplF.end(); } catch (IloOplException ex) { System.err.println("### OPL exception: " + ex.getMessage()); ex.printStackTrace(); status = 2; } catch (IloException ex) { System.err.println("### CONCERT exception: " + ex.getMessage()); ex.printStackTrace(); status = 3; } catch (Exception ex) { System.err.println("### UNEXPECTED UNKNOWN ERROR ..."); ex.printStackTrace(); status = 4; } System.exit(status); }
public boolean solve( double[] Pmax, double[] PregMax, double[] Emin, double[] Emax, int quartersLeftInFirstBid, int[] bids, int bidSize, ArrayList<FlexGraph> flexGraphs) { double[] Pmin = new double[Pmax.length]; // Pre-process data if ((Pmin.length - quartersLeftInFirstBid) % 4 != 0) { int extraQuarters = 4 - ((Pmin.length - quartersLeftInFirstBid) % 4); Pmin = concat(Pmin, new double[extraQuarters]); Pmax = concat(Pmax, new double[extraQuarters]); PregMax = concat(PregMax, new double[extraQuarters]); double[] endE = new double[extraQuarters]; for (int i = 0; i < endE.length; i++) { endE[i] = Emin[Emin.length - 1]; } Emin = concat(Emin, endE); Emax = concat(Emax, endE); } this.quartersLeftInFirstBid = quartersLeftInFirstBid; // Solve optimization problem try { IloCplex cplex = new IloCplex(); // for all evs ArrayList<IloNumVar[]> flexpowers = new ArrayList<IloNumVar[]>(); ArrayList<IloNumVar[]> flexenergies = new ArrayList<IloNumVar[]>(); for (int i = 0; i < flexGraphs.size(); i++) { FlexGraph flexGraph = flexGraphs.get(i); double[] energyMin = convertToDoubles(flexGraph.getEnergyMin()); double[] energyMax = convertToDoubles(flexGraph.getEnergyMax()); double[] powerMax = convertToDoubles(flexGraph.getPowerMax()); // charging power IloNumVar[] p = cplex.numVarArray(powerMax.length, new double[powerMax.length], powerMax); // path IloNumVar[] e = cplex.numVarArray(energyMin.length, energyMin, energyMax); for (int j = 0; j < p.length; j++) { cplex.addEq(cplex.diff(e[j + 1], e[j]), cplex.prod(1.0 / 4, p[j])); } flexpowers.add(p); flexenergies.add(e); } // total charging power IloNumVar[] p = cplex.numVarArray(Pmin.length, Pmin, Pmax); // individual bin constraints for (int t = 0; t < p.length; t++) { ArrayList<IloNumVar> tempVars = new ArrayList<IloNumVar>(); for (IloNumVar[] var : flexpowers) { if (var.length >= t + 1) { tempVars.add(var[t]); } } IloNumVar[] tempVars_array = new IloNumVar[tempVars.size()]; tempVars.toArray(tempVars_array); cplex.addEq(p[t], cplex.sum(tempVars_array)); } // path IloNumVar[] e = cplex.numVarArray(Emin.length, Emin, Emax); for (int i = 0; i < p.length; i++) { cplex.addEq(cplex.diff(e[i + 1], e[i]), cplex.prod(1.0 / 4, p[i])); } // Emin < path < Emax for (int i = 0; i < e.length; i++) { cplex.addGe(e[i], Emin[i]); cplex.addLe(e[i], Emax[i]); } // regulation power in each optimziation interval IloNumVar[] regPowerQ = cplex.numVarArray(Pmin.length, Pmin, PregMax); // calculate regulation power in each optimization interval for (int i = 0; i < regPowerQ.length; i++) { cplex.addEq(regPowerQ[i], cplex.diff(PregMax[i], p[i])); } // regulation bids in each hour // 1. max nr of bids per houd int hours = (int) Math.ceil(quartersLeftInFirstBid / 4.0) + (int) Math.ceil((regPowerQ.length - quartersLeftInFirstBid) / 4.0); int[] maxNrOfBidsPerHour = new int[hours]; // init with max nr of bids per hour for (int i = 0; i < maxNrOfBidsPerHour.length; i++) { maxNrOfBidsPerHour[i] = Integer.MAX_VALUE; } if (quartersLeftInFirstBid > 0) { maxNrOfBidsPerHour[0] = bids[0]; try { maxNrOfBidsPerHour[1] = bids[1]; } catch (IndexOutOfBoundsException ew) { System.out.print("Emin = "); printArray(Emin); System.out.print("Emax = "); printArray(Emax); System.out.print("Pmax = "); printArray(Pmax); System.out.println("FirstBidQuarter = " + quartersLeftInFirstBid); System.out.print("Bids = "); printArray(bids); System.out.println("Bidsize = " + bidSize); } } else { maxNrOfBidsPerHour[0] = bids[1]; } // 2. bids per hour IloIntVar[] bidsH = cplex.intVarArray(hours, new int[hours], maxNrOfBidsPerHour); // limit bids by provided regulation power for (int i = 0; i < regPowerQ.length; i++) { // convert Q to H int h = (int) Math.ceil(((i + 1) - quartersLeftInFirstBid) / 4.0); if (quartersLeftInFirstBid == 0) { h--; } // bidsH*bidSize <= regPowerQ[i] if (i > 0) { // reserve some extra regulation power cplex.addLe(cplex.prod(bidsH[h], bidSize), cplex.prod(0.95, regPowerQ[i])); } else { cplex.addLe(cplex.prod(bidsH[h], bidSize), cplex.prod(1, regPowerQ[i])); } // System.out.println("h = " + h + ", i=" + i); } // create model and solve it // cplex.addMaximize(cplex.scalProd(p,prices)); double[] rewards = new double[bidsH.length]; // init to rewards = 1 for all, but two first hours for (int i = 0; i < rewards.length; i++) { rewards[i] = 1; } rewards[0] = 100; if (rewards.length > 1) { rewards[1] = 100; } IloLinearNumExpr maximization = cplex.scalProd(bidsH, rewards); IloObjective maxObjective = cplex.addMaximize(maximization); cplex.setOut(null); cplex.solve(); // if(cplex.solve()) { // cplex.output().println("Solution status = " + cplex.getStatus()); // cplex.output().println("Solution value = " + cplex.getObjValue()); // // System.out.print("Emin = "); // printArray(Emin); // // System.out.print("Emax = "); // printArray(Emax); // // System.out.print("Pmax = "); // printArray(Pmax); // // powerPath = cplex.getValues(p); // System.out.print("Power = "); // printArray(powerPath); // // energyPath = cplex.getValues(e); // System.out.print("Energy = "); // printArray(energyPath); // // regPower = cplex.getValues(regPowerQ); // System.out.print("RegPower = "); // printArray(regPower); // // bidsN = new int[bidsH.length]; // for(int i = 0; i < bidsN.length; i++) { // bidsN[i] = (int) Math.round(cplex.getValue(bidsH[i])); // } // shift bids right if no quarter left in current bid slot -- hack-ish if (quartersLeftInFirstBid == 0) { bidsN = concat(new int[1], bidsN); } // // System.out.print("Bids = "); // printArray(bidsN); // // this.bidSize = bidSize; // } // stage two // System.out.println((int) ); // System.out.println("sum = " + cplex.getValue(cplex.sum(bidsH))); // System.out.println(bidsH[0].getUB());; // System.out.println((int) Math.round(cplex.getValue(bidsH[0]))); // bidsH[0].setMin((int) Math.round(cplex.getValue(bidsH[0]))); // .setUB(cplex.getValue(bidsH[0])); // cplex.addEq(bidsH[1], (int) Math.round(cplex.getValue(bidsH[1]))); // cplex.addGe(bidsH[1], (int) Math.round(cplex.getValue(bidsH[1]))); double bid1 = cplex.getValue(bidsH[0]); double bid2 = 0; if (bidsH.length > 1) { bid2 = cplex.getValue(bidsH[1]); } int totalBids = 0; for (int i = 0; i < bidsH.length; i++) { totalBids = totalBids + (int) Math.round(cplex.getValue(bidsH[i])); } cplex.addGe(cplex.sum(bidsH), totalBids); cplex.addLe(bid1, bidsH[0]); // cplex.getValue(bidsH[1]); if (bidsH.length > 1) { cplex.addLe(bid2, bidsH[1]); } cplex.remove(maxObjective); IloQuadNumExpr minimization = cplex.quadNumExpr(); double[] coeff = new double[p.length]; for (int i = 0; i < p.length; i++) { coeff[i] = 1; } minimization.addTerms(coeff, p, p); cplex.addMinimize(minimization); cplex.setOut(null); if (cplex.solve()) { // cplex.output().println("Solution status = " + cplex.getStatus()); // cplex.output().println("Solution value = " + cplex.getObjValue()); // // System.out.print("Emin = "); // printArray(Emin); // // System.out.print("Emax = "); // printArray(Emax); // // System.out.print("Pmax = "); // printArray(Pmax); // powerPath = cplex.getValues(p); System.out.print("Power = "); printArray(powerPath); energyPath = cplex.getValues(e); // System.out.print("Energy = "); // printArray(energyPath); regPower = cplex.getValues(regPowerQ); System.out.print("RegPower = "); printArray(regPower); bidsN = new int[bidsH.length]; for (int i = 0; i < bidsN.length; i++) { bidsN[i] = (int) Math.round(cplex.getValue(bidsH[i])); } // shift bids right if no quarter left in current bid slot -- hack-ish if (quartersLeftInFirstBid == 0) { bidsN = concat(new int[1], bidsN); } System.out.print("Bids = "); printArray(bidsN); this.bidSize = bidSize; } for (int i = 0; i < flexpowers.size(); i++) { flexGraphs.get(i).setSolutionPath(cplex.getValues(flexenergies.get(i))); } return true; } catch (IloException e) { System.err.println("Concert exception caught: " + e); e.printStackTrace(); return false; } }