/**
*
*/
package vroom.optimization.pl.gurobi;
import gurobi.GRB.DoubleAttr;
import gurobi.GRBException;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import vroom.common.modeling.dataModel.IVRPInstance;
import vroom.common.modeling.io.ChristofidesPersistenceHelper;
import vroom.common.utilities.StatCollector;
import vroom.common.utilities.StatCollector.Label;
import vroom.common.utilities.gurobi.GRBConstraintManager;
import vroom.common.utilities.gurobi.GRBUtilities;
import vroom.common.utilities.logging.LoggerHelper;
import vroom.common.utilities.lp.SolverStatus;
import vroom.optimization.pl.IVRPSolver;
import vroom.optimization.pl.symphony.vrp.CVRPSymphonySolver;
/**
* <code>CVRPSolverTest</code> is a test class for {@link CVRPSolverCapOld}
* <p>
* Creation date: Jul 6, 2010 - 3:43:31 PM
*
* @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 CVRPSolverTest {
private final static File INSTANCES_DIRECTORY = new File(
"../Instances/cvrp/christodifes-mingozzi-toth");
public static final LoggerHelper LOGGER = LoggerHelper
.getLogger(CVRPSolverTest.class.getSimpleName());
protected static final boolean COMPARE_CAP = false;
/** Time limit (in sec) */
protected static int sTimeLimit = 60;
protected List<IVRPInstance> mInstances;
protected StatCollector mStats;
public static Label<?>[] LABELS = new Label<?>[] {
new Label<String>("instance", String.class),
new Label<Integer>("size", Integer.class),
new Label<Double>("capacity", Double.class),
new Label<String>("solver", String.class),
new Label<Double>("obj", Double.class),
new Label<Integer>("time", Integer.class),
new Label<String>("status", String.class) };
private final CVRPCuttingPlaneSolver mCutSolver, mCutInjSolver;
private final CVRPSymphonySolver mSymSolver;
private final CVRPCapBasedSolver mCapSolver;
public CVRPSolverTest() throws GRBException {
preinit();
mInstances = readInstances();
mStats = newStatCollector();
mCutSolver = new CVRPCuttingPlaneSolver(false, false);
mCutInjSolver = new CVRPCuttingPlaneSolver(false, true);
mSymSolver = new CVRPSymphonySolver();
mCapSolver = new CVRPCapBasedSolver(false);
}
protected StatCollector newStatCollector() {
return new StatCollector("CVRPSolverTest", LABELS);
}
protected void preinit() {
}
protected List<IVRPInstance> readInstances() {
// NovoaPersistenceHelper reader = new NovoaPersistenceHelper();
// try {
// return reader.readInstances(new int[]{20}, new int[]{0,1}, new
// int[]{1}, null);
// // return Collections.singletonList(reader.readInstance(8, 1, 2, 1));
// } catch (IOException e) {
// e.printStackTrace();
// return new LinkedList<DynamicInstance>();
// }
ChristofidesPersistenceHelper reader = new ChristofidesPersistenceHelper();
String[] children = INSTANCES_DIRECTORY.list();
List<IVRPInstance> instances = new LinkedList<IVRPInstance>();
if (children == null) {
// Either dir does not exist or is not a directory
throw new IllegalStateException("Cannot find instances");
} else {
for (String file : children) {
if (!file.contains("info") && !file.equals(".svn")) {
try {
instances.add(reader.readInstance(new File(
INSTANCES_DIRECTORY.getAbsolutePath()
+ File.separator + file)));
} catch (Exception e) {
System.err.printf("Error when reading %s : %s", file,
e.getMessage());
}
}
}
}
return instances;
}
public void run() {
for (IVRPInstance instance : mInstances) {
LOGGER.info("=========================================================");
LOGGER.info(" Solving instance " + instance.getName());
LOGGER.info("=========================================================");
try {
double objBC = solveInstanceCutPlanes(instance, true);
if (objBC != Double.POSITIVE_INFINITY) {
optimalFound(instance, objBC);
} else {
timeLimitReached(instance);
}
} catch (GRBException e) {
LOGGER.exception("CVRPSolverTest.run (instance %s)", e,
instance.getName());
}
LOGGER.info("=========================================================");
}
LOGGER.info("FINISHED");
}
protected void timeLimitReached(IVRPInstance instance) {
}
protected void optimalFound(IVRPInstance instance, double objBC) {
}
public static void main(String[] args) {
LoggerHelper.setupRootLogger(LoggerHelper.LEVEL_LOW_DEBUG,
LoggerHelper.LEVEL_LOW_DEBUG, true);
CVRPSolverBase.LOGGER.setLevel(LoggerHelper.LEVEL_DEBUG);
GRBConstraintManager.LOGGER.setLevel(LoggerHelper.LEVEL_DEBUG);
LOGGER.info("java.library.path");
LOGGER.info(System.getProperty("java.library.path"));
CVRPSolverTest test;
try {
test = new CVRPSolverTest();
test.run();
} catch (GRBException e) {
e.printStackTrace();
}
}
protected void storeStats(String name, SolverStatus status,
IVRPInstance instance, IVRPSolver solver) {
double obj = Double.NaN;
if (status == SolverStatus.OPTIMAL) {
obj = solver.getObjectiveValue();
}
mStats.collect(instance.getName(), instance.getRequestCount(), instance
.getFleet().getVehicle().getCapacity(), name, obj,
(int) solver.getSolveTime(), status);
}
/**
* Solve a {@link IVRPInstance} with the {@link CVRPBranchCutSolverBad}
* solver
*
* @param instance
* @return the value of the objective function
* @throws GRBException
*/
public double solveInstanceCutPlanes(IVRPInstance instance,
boolean solInjection) throws GRBException {
LOGGER.info(" #### Cutting Planes Solver %s ####",
solInjection ? "with solution injection" : "");
CVRPCuttingPlaneSolver solver = solInjection ? mCutInjSolver
: mCutSolver;
solver.readInstance(instance);
solver.setTimeLimit(sTimeLimit);
// solver.printModel();
// System.exit(1);
SolverStatus status = solver.solve();
String name = solInjection ? "cvrp_cut_inj" : "cvrp_cut";
storeStats(name, status, instance, solver);
switch (status) {
case OPTIMAL:
if (!solver.isSolutionFeasible()) {
LOGGER.error("Solution is not feasible : %s",
solver.getSolution());
System.exit(1);
} else {
solver.printSolution(true);
}
break;
case TIME_LIMIT:
LOGGER.info("Solution: %s", solver.getSolution());
return Double.POSITIVE_INFINITY;
default:
LOGGER.error("Solver :"
+ GRBUtilities.solverStatusString(solver.getModel()));
return Double.POSITIVE_INFINITY;
}
double obj = solver.getModel().get(DoubleAttr.ObjVal);
solver = null;
Runtime.getRuntime().gc();
return obj;
}
public double solveInstanceSymphony(IVRPInstance instance)
throws InterruptedException, IOException {
LOGGER.info(" #### Symphony Solver ####");
mSymSolver.readInstance(instance);
mSymSolver.setTimeLimit(sTimeLimit);
// solver.printModel();
// System.exit(1);
SolverStatus status = mSymSolver.solve();
String name = "cvrp_symph";
storeStats(name, status, instance, mSymSolver);
switch (status) {
case OPTIMAL:
if (!mSymSolver.isSolutionFeasible()) {
LOGGER.error("Solution is not feasible : %s",
mSymSolver.getSolution());
System.exit(1);
} else {
mSymSolver.printSolution(true);
}
break;
case TIME_LIMIT:
LOGGER.info("Solution: %s", mSymSolver.getSolution());
return Double.POSITIVE_INFINITY;
default:
LOGGER.error("Status : %s", status);
return Double.POSITIVE_INFINITY;
}
double obj = mSymSolver.getObjectiveValue();
Runtime.getRuntime().gc();
return obj;
}
/**
* Solve a {@link IVRPInstance} with the {@link CVRPSolverCapOld} solver
*
* @param instance
* @return the value of the objective function
* @throws GRBException
*/
public double solveInstanceCap(IVRPInstance instance) throws GRBException {
LOGGER.info(" #### Capacity Based Solver ####");
mCapSolver.setTimeLimit(sTimeLimit);
mCapSolver.readInstance(instance);
// solver.printModel();
SolverStatus status = mCapSolver.solve();
storeStats("cvrp_capBased", status, instance, mCapSolver);
switch (status) {
case OPTIMAL:
mCapSolver.printSolution(true);
break;
default:
LOGGER.error("Solver :"
+ GRBUtilities.solverStatusString(mCapSolver.getModel()));
return Double.POSITIVE_INFINITY;
}
return mCapSolver.getModel().get(DoubleAttr.ObjVal);
}
}