/**
*
*/
package vroom.trsp.instances;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import umontreal.iro.lecuyer.rng.MRG32k3a;
import umontreal.iro.lecuyer.rng.RandomStream;
import vroom.common.modeling.dataModel.attributes.ITimeWindow;
import vroom.common.utilities.FileBufferedWriter;
import vroom.common.utilities.Utilities;
import vroom.common.utilities.Utilities.Random;
import vroom.common.utilities.dataModel.ObjectWithIdComparator;
import vroom.common.utilities.logging.LoggerHelper;
import vroom.common.utilities.logging.Logging;
import vroom.common.utilities.ssj.RandomSourceBase;
import vroom.trsp.datamodel.TRSPInstance;
import vroom.trsp.datamodel.TRSPRequest;
import vroom.trsp.io.ITRSPPersistenceHelper;
import vroom.trsp.io.PillacSimplePersistenceHelper;
/**
* The class <code>TRSPReleaseDateGenerator</code> is used to generate a release date file for a given instance of the
* VRP
* <p>
* Creation date: Nov 8, 2011 - 10:30:45 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 TRSPReleaseDateGenerator extends RandomSourceBase {
/**
* The format string for the release date file, the first argument is the path to the folder, the second the
* instance name, and the third the proportion of dynamic requests
*/
public static String sNameFormat = "%1$s/%2$s_rd_%3$s.txt";
/**
* Creates a new <code>TRSPReleaseDateGenerator</code>
*
* @param stream
* the random stream that will be used to generate random numbers
*/
public TRSPReleaseDateGenerator(RandomStream stream) {
super(stream);
}
/**
* Generate a release date file and save it in the specified {@code path} using the format defined in
* {@link #sNameFormat}
*
* @param instance
* the static instance
* @param dynProp
* the proportion of dynamic requests (between 0 an 1)
* @param destDir
* the destination folder
* @throws IOException
*/
public void generateRDFile(TRSPInstance instance, double dynProp, String destDir)
throws IOException {
// Get the planning horizon
int hStart = 0;
int hEnd = 0;
ITimeWindow tw = instance.getDepot(0).getTimeWindow();
if (tw != null) {
hStart = (int) tw.startAsDouble();
hEnd = (int) tw.endAsDouble();
} else {
hStart = 0;
hEnd = getHorizonBound(instance);
}
List<TRSPRequest> requests = new ArrayList<TRSPRequest>(instance.getRequests());
Collections.sort(requests, ObjectWithIdComparator.INSTANCE);
int numDynReq = (int) (requests.size() * dynProp);
// Draw the dynamic requests
int[] dynReqIdx = Random.randomIndexes(requests.size(), numDynReq, getRandomStream());
Arrays.sort(dynReqIdx);
// Split the request list in two lists
ArrayList<TRSPRequest> staticReq = new ArrayList<TRSPRequest>(requests.size() - numDynReq);
ArrayList<TRSPRequest> dynReq = new ArrayList<TRSPRequest>(numDynReq);
ListIterator<TRSPRequest> it = requests.listIterator();
int dynIdx = 0;
while (it.hasNext()) {
if (dynIdx < dynReqIdx.length && it.nextIndex() == dynReqIdx[dynIdx]) {
dynReq.add(it.next());
dynIdx++;
} else {
staticReq.add(it.next());
}
}
generateRDFile(instance, staticReq, dynReq, hStart, hEnd, destDir, ""
+ ((int) (100 * dynProp)));
}
/**
* Generate a release date file and save it in the specified {@code path} using the format defined in
* {@link #sNameFormat} with the {@code comment} as third argument
*
* @param instance
* the instance
* @param staticReq
* a list of static requests
* @param dynReq
* a list of dynamic requests
* @param minReleaseDate
* the minimum value for the release date
* @param maxReleaseDate
* the maximum value for the release date
* @param destDir
* the destination folder
* @param comment
* a comment for the file name
* @throws IOException
*/
public void generateRDFile(TRSPInstance instance, List<TRSPRequest> staticReq,
List<TRSPRequest> dynReq, int minReleaseDate, int maxReleaseDate, String destDir,
String comment) throws IOException {
FileBufferedWriter out = new FileBufferedWriter(String.format(sNameFormat, destDir,
instance.getName(), comment));
// Write a comment line
out.writeLine("# Instance %s - %s dynamic requests - %s static requests",
instance.getName(), dynReq.size(), staticReq.size());
// #Dyn/Static Propotions
out.writeLine("%-5s %s", "Dyn", "Stat");
out.writeLine("%-5s %s", dynReq.size(), staticReq.size());
// Headers
out.writeLine("%-5s %s", "ID", "RD");
// Write static requests
for (TRSPRequest r : staticReq) {
out.writeLine("%-5s %s", r.getID(), -1);
}
// Write dynamic requests
for (TRSPRequest r : dynReq) {
// Estimate the latest feasible feasible release date
// as the difference between the time window end and 1.5 the time required to travel from the main depot to
// the request
double rdBound = r.getTimeWindow().endAsDouble()
- 1.5
* instance.getCostDelegate().getTravelTime(instance.getMainDepot().getID(),
r.getID(), instance.getFleet().getVehicle());
int maxRd = Math.min(maxReleaseDate, (int) rdBound);
maxRd = Math.min((int) r.getTimeWindow().startAsDouble(), maxRd);
int rd = maxRd >= minReleaseDate ? getRandomStream().nextInt(minReleaseDate, maxRd)
: minReleaseDate;
out.writeLine("%-5s %s", r.getID(), rd);
}
// Flush and close
out.flush();
out.close();
}
/**
* Estimate a bound on the planning horizon length by constructing a solution and JAVADOC
*
* @param instance
* @return
*/
protected int getHorizonBound(TRSPInstance instance) {
throw new UnsupportedOperationException();
// CWParameters params = new CWParameters();
// params.set(CWParameters.ALGORITHM_CLASS, RandomizedSavingsHeuristic.class);
// params.set(CWParameters.CTR_HANDLER_CLASS, ConstraintHandler.class);
//
// ClarkeAndWrightHeuristic<Solution<ArrayListRoute>> cw = new
// ClarkeAndWrightHeuristic<Solution<ArrayListRoute>>(
// params);
//
// cw.getConstraintHandler().addConstraint(new CapacityConstraint<Solution<ArrayListRoute>>());
//
// cw.initialize(instance);
// cw.run();
//
// // A correction factor in the case of limited fleet (removed for now)
// // -> More routes => underestimated bound => easier problem as more
// // requests will be disclosed early
// double correction = 1;
// if (!instance.getFleet().isUnlimited()) {
// boolean feas = cw.getSavingsAlgo().repairSolutionForLimitedFleet();
// // correction = cw.getSolution().getRouteCount()
// // / instance.getFleet().size();
// }
//
// Solution<ArrayListRoute> sol = cw.getSolution();
// int maxDur = 0;
// for (ArrayListRoute r : sol) {
// if (r.length() < 2)
// continue;
// double dur = 0;
// ListIterator<INodeVisit> it = r.iterator();
// INodeVisit pred = it.next();
// dur += pred.getServiceTime();
// while (it.hasNext()) {
// INodeVisit node = it.next();
// dur += node.getServiceTime();
// dur += instance.getCostDelegate().getTravelTime(pred, node, r.getVehicle());
// pred = node;
// }
// if (dur > maxDur)
// maxDur = (int) dur;
// }
// return (int) (maxDur * correction);
}
/**
* Generate the release date files for a collection of instances
*
* @param instances
* @param dynProp
* @param destDir
* @param stream
*/
public static void generateRDFFiles(Collection<TRSPInstance> instances, double[] dynProp,
String destDir, RandomStream stream) {
TRSPReleaseDateGenerator gen = new TRSPReleaseDateGenerator(stream);
for (TRSPInstance i : instances) {
for (double d : dynProp) {
try {
gen.generateRDFile(i, d, destDir);
System.out
.printf("TRSPReleaseDateGenerator.generateRDFFiles: write rd file for instance %s (dynProp: %s)\n",
i.getName(), d);
} catch (IOException e) {
Logging.getBaseLogger().exception("TRSPReleaseDateGenerator.generateRDFFiles",
e);
}
}
}
}
public static void main(String[] args) {
LoggerHelper.setupRootLogger(LoggerHelper.LEVEL_WARN, LoggerHelper.LEVEL_WARN, false);
String sourceDir = "../Instances/trsp/pillac/crew25";
String filePattern = ".+txt";
ITRSPPersistenceHelper reader = new PillacSimplePersistenceHelper();
// double[] dynProp = new double[] { 0.1, 0.5, 0.9 };
double[] dynProp = new double[] { 0.3, 0.7 };
String destDir = "../Instances/trsp/pillac/crew25/dyn";
MRG32k3a stream = new MRG32k3a();
int firstSeed = sourceDir.hashCode();
if (firstSeed == 0)
firstSeed = 1;
stream.setSeed(new long[] { firstSeed, 2, 3, 4, 5, 6 });
try {
List<File> files = Utilities.listFiles(sourceDir, filePattern);
List<TRSPInstance> instances = new ArrayList<TRSPInstance>(files.size());
for (File f : files) {
try {
instances.add(reader.readInstance(f, false));
// System.out.println("Added instance " + f);
} catch (Exception e) {
e.printStackTrace();
}
}
generateRDFFiles(instances, dynProp, destDir, stream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("FINISHED");
}
}