/* * */ package vroom.optimization.pl.gurobi; import gurobi.GRB; import gurobi.GRB.DoubleAttr; import gurobi.GRBException; import gurobi.GRBLinExpr; import gurobi.GRBVar; /** * <code>CVRPSolvergetCapacity()</code> is a solver for the CVRP problem based on a formulation that keeps track of the * load at each node. * <p> * Creation date: Aug 18, 2010 - 11:25:30 AM * * @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a * href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a * href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a> * @version 1.0 */ public class CVRPCapBasedSolver extends CVRPSolverBase { protected GRBVar[] mLoadVars; /** * Creates a new <code>CVRPSolvergetCapacity()</code> * * @param output * @throws GRBException */ public CVRPCapBasedSolver(boolean output) throws GRBException { super(false, output); } @Override protected void addVariables() throws GRBException { super.addVariables(); // Vehicle load : load[i] stores the load up to client i mLoadVars = new GRBVar[getSize() - 1]; for (int i = 1; i < getSize(); i++) { mLoadVars[i - 1] = getModel().addVar(getDemands()[i], getCapacity(), 0, GRB.CONTINUOUS, String.format("load(%s)", i)); } } @Override protected void addConstraints() throws GRBException { super.addConstraints(); // If i is the first client of a tour, then load(i)=dem(i) // load(i) <= getCapacity() + (dem(i)-getCapacity())*prec(1,i) // load(i) - (dem(i)-getCapacity())*prec(1,i) <= getCapacity() for (int i = 1; i < getSize(); i++) { GRBLinExpr l = new GRBLinExpr(); l.addTerm(1, mLoadVars[i - 1]); l.addTerm(getCapacity() - getDemands()[i], getArcVars()[getArcIdx(0, i)]); getModel().addConstr(l, GRB.LESS_EQUAL, getCapacity(), String.format("resetLoad(%s)", i)); } // If j comes just after i in a tour, then load(j) is greater than the // quantity delivered during the tour up to i plus the quantity to be // delivered at j (to avoid loops and keep getCapacity()acity limit of the tanker) // load(j) >= load(i) + dem(j) - getCapacity() + getCapacity()*prec(i,j) + // (getCapacity()-dem(j)-dem(i))*prec(j,i) // - load(j) + load(i) + getCapacity()*prec(i,j) + (getCapacity()-dem(j)-dem(i))*prec(j,i) <= getCapacity() -dem // (j) for (int i = 1; i < getSize(); i++) { for (int j = 1; j < getSize(); j++) { if (i != j) { GRBLinExpr e = new GRBLinExpr(); e.addTerm(-1, mLoadVars[j - 1]); e.addTerm(1, mLoadVars[i - 1]); e.addTerm(getCapacity(), getArcVars()[getArcIdx(i, j)]); e.addTerm(getCapacity() - getDemands()[i] - getDemands()[j], getArcVars()[getArcIdx(j, i)]); getModel().addConstr(e, GRB.LESS_EQUAL, getCapacity() - getDemands()[j], String.format("load(%s,%s)", i, j)); } } } } /* (non-Javadoc) * @see vroom.optimization.pl.gurobi.CVRPSolverBase#isSolutionFeasible() */ @Override public boolean isSolutionFeasible() { return true; } @Override public void printSolution(boolean printVariables) { if (printVariables) { double[] vars = null; try { vars = getModel().get(DoubleAttr.X, mLoadVars); } catch (GRBException e) { e.printStackTrace(); } finally { if (vars == null) { System.err.println("Solution is not available"); super.printSolution(printVariables); return; } } for (int i = 0; i < vars.length; i++) { if (vars[i] > 0) { System.out.printf("load(%s)=%.3f\n", i + 1, vars[i]); } } } super.printSolution(printVariables); } @Override public int getIterations() { return -1; } }