/**
*
*/
package vroom.trsp.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import vroom.common.modeling.dataModel.Depot;
import vroom.common.modeling.dataModel.Node;
import vroom.common.modeling.dataModel.attributes.ITimeWindow;
import vroom.common.modeling.dataModel.attributes.NodeAttributeKey;
import vroom.common.modeling.dataModel.attributes.PointLocation;
import vroom.common.modeling.dataModel.attributes.SimpleTimeWindow;
import vroom.common.utilities.Utilities;
import vroom.common.utilities.dataModel.ObjectWithIdComparator;
import vroom.common.utilities.gis.MapPointDist;
import vroom.trsp.datamodel.TRSPDistTimeMatrix;
import vroom.trsp.datamodel.TRSPInstance;
import vroom.trsp.datamodel.TRSPRequest;
import vroom.trsp.datamodel.Technician;
/**
* The Class <code>PillacSimplePersistenceHelper</code> is responsible for the parsing of TRSP instances between a flat
* file Solomon format and instances of {@link TRSPInstance}
* <p>
* Creation date: Feb 23, 2011 - 2:08:57 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 PillacSimplePersistenceHelper implements ITRSPPersistenceHelper {
public static final PillacSimplePersistenceHelper INSTANCE = new PillacSimplePersistenceHelper();
/** The default file name pattern for instances */
public static final String DEFAULT_FILE_PATTERN = "\\d+\\-R?C?\\d+_\\d+\\-\\d+\\-\\d+\\-\\d+.txt";
/*
* (non-Javadoc)
* @see vroom.trsp.io.ITRSPPersistenceHelper#readInstance(java.io.File)
*/
@Override
public TRSPInstance readInstance(File file, Object... params) throws IOException {
if (!file.exists())
throw new FileNotFoundException("Instance file " + file.getPath() + " does not exist");
boolean cvrptw = params.length > 0 ? (boolean) params[0] : false;
BufferedReader r = new BufferedReader(new FileReader(file));
// Instance name
String name = r.readLine();
r.readLine();// Empty line
r.readLine();// TECHNICIANS
r.readLine();// HEADER
// Fleet info
String line = r.readLine();
if (line.startsWith(" "))
line = line.replaceFirst("\\s+", "");
String[] values = line.split("\\s+");
int numTec = Integer.parseInt(values[0]);
int numSkills = Integer.parseInt(values[1]);
int numTools = Integer.parseInt(values[2]);
int numSpareParts = Integer.parseInt(values[3]);
r.readLine();// Empty line
r.readLine();// REQUESTS
r.readLine();// HEADER
// Depots and technicians
ArrayList<Depot> depots = new ArrayList<Depot>(numTec + 1);
ArrayList<Technician> technicians = new ArrayList<Technician>(numTec);
for (int d = 0; d <= numTec; d++) {
values = r.readLine().split("\\s+");
int id = Integer.valueOf(values[0]);
double x = Double.valueOf(values[1]);
double y = Double.valueOf(values[2]);
double tws = Double.valueOf(values[3]);
double twe = Double.valueOf(values[4]);
int[] skills = Utilities.toIntArray(values[6]);
int[] tools = Utilities.toIntArray(values[7]);
int[] spare = Utilities.toIntArray(values[8]);
Depot depot = new Depot(id, new PointLocation(x, y));
depot.setAttribute(NodeAttributeKey.TIME_WINDOW, new SimpleTimeWindow(tws, twe));
depots.add(id, depot);
if (id > 0) {
id--;
technicians.add(id, new Technician(id, "tech-" + id, 0, 1, 1, skills, tools, spare,
depot));
}
}
// Requests
ArrayList<TRSPRequest> requests = new ArrayList<TRSPRequest>();
line = r.readLine();
while (line != null && !line.startsWith("DISTANCES")) {
values = line.split("\\s+");
int id = Integer.valueOf(values[0]);
double x = Double.valueOf(values[1]);
double y = Double.valueOf(values[2]);
double tws = Double.valueOf(values[3]);
double twe = Double.valueOf(values[4]);
double serv = Double.valueOf(values[5]);
int[] skills = Utilities.toIntArray(values[6]);
int[] tools = Utilities.toIntArray(values[7]);
int[] spare = Utilities.toIntArray(values[8]);
TRSPRequest req = new TRSPRequest(id, new Node(id, new PointLocation(x, y)), skills,
tools, spare, new SimpleTimeWindow(tws, twe), serv);
requests.add(id - depots.size(), req);
line = r.readLine();
}
TRSPInstance instance = new TRSPInstance(name, technicians, numSkills, numTools,
numSpareParts, depots, requests, cvrptw);
if (line != null && line.startsWith("DISTANCES")) {
// Read the distance/time matrix
double[][][] distTimeMatrix = MapPointDist.loadDistanceTimeMatrix(
file.getAbsolutePath(), instance.getMaxId(), false);
instance.setCostDelegate(new TRSPDistTimeMatrix(instance, distTimeMatrix));
}
r.close();
return instance;
}
/*
* (non-Javadoc)
* @see vroom.trsp.io.ITRSPPersistenceHelper#writeInstance(vroom.trsp.datamodel.TRSPInstance, java.io.File)
*/
@Override
public boolean writeInstance(TRSPInstance instance, File file) throws IOException {
Locale.setDefault(Locale.US);
boolean distOnly = instance.getCostDelegate() instanceof TRSPDistTimeMatrix;
BufferedWriter w = new BufferedWriter(new FileWriter(file));
w.write(instance.getName());
w.write("\n\nINFO\n");
w.write("CREW COUNT SKILLS TOOLS SPARE PARTS\n");
w.write(String.format(" %8s %8s %8s %13s\n", instance.getFleet().size(),
instance.getSkillCount(), instance.getToolCount(), instance.getSpareCount()));
// w.write("ID SKILLS TOOLS SPARE PARTS\n");
// for (Technician t : instance.getFleet()) {
// w.write(String.format(" %5s%s \t%s \t%s\n", t.getID(), t.getSkillSet(), t.getToolSet(),
// Arrays.toString(t.getAvailableSpareParts())));
// }
w.write("\nDEPOT TECHNICIANS AND REQUESTS\n");
w.write("ID X Y TWS TWE Serv SKILLS TOOLS SPARE PARTS\n");
// Depot
Depot d = instance.getDepot(0);
ITimeWindow tw = d.getTimeWindow();
double tws = tw != null ? tw.startAsDouble() : 0;
double twe = tw != null ? tw.endAsDouble() : 0;
w.write(String.format("%-5s %8.1f %8.1f %7.1f %7.1f %7.1f \t%s \t%s \t%s\n", d.getID(),
distOnly ? 0 : d.getLocation().getX(), distOnly ? 0 : d.getLocation().getY(), tws,
twe, 0d, "[]", "[]", "[]"));
// Technicians
for (Technician t : instance.getFleet()) {
d = t.getHome();
tw = t.getHome().getTimeWindow();
tws = tw != null ? tw.startAsDouble() : 0;
twe = tw != null ? tw.endAsDouble() : 0;
w.write(String.format("%-5s %8.1f %8.1f %7.1f %7.1f %7.1f \t%s \t%s \t%s\n", d.getID(),
distOnly ? 0 : d.getLocation().getX(), distOnly ? 0 : d.getLocation().getY(),
tws, twe, 0d, t.getSkillSet(), t.getToolSet(),
Utilities.toShortString(t.getSpareParts())));
}
// Requests
List<TRSPRequest> requests = new ArrayList<TRSPRequest>(instance.getRequests());
Collections.sort(requests, new ObjectWithIdComparator());
for (TRSPRequest r : requests) {
tw = r.getTimeWindow();
tws = tw != null ? tw.startAsDouble() : 0;
twe = tw != null ? tw.endAsDouble() : 0;
w.write(String.format("%-5s %8.1f %8.1f %7.1f %7.1f %7.1f \t%s \t%s \t%s\n", r.getID(),
distOnly ? 0 : r.getNode().getLocation().getX(), distOnly ? 0 : r.getNode()
.getLocation().getY(), tws, twe, r.getServiceTime(), r.getSkillSet(),
r.getToolSet(), Utilities.toShortString(r.getSparePartRequirements())));
}
// Distance and time matrices
if (distOnly) {
w.write("DISTANCES\n");
for (int i = 0; i < instance.getMaxId(); i++) {
w.write("" + i);
for (int j = 0; j < instance.getMaxId(); j++) {
w.write(String.format(";%.4f", instance.getCostDelegate().getDistance(i, j)));
}
w.write("\n");
}
w.write("TRAVEL TIMES\n");
for (int i = 0; i < instance.getMaxId(); i++) {
w.write("" + i);
for (int j = 0; j < instance.getMaxId(); j++) {
w.write(String.format(";%.4f",
instance.getCostDelegate().getTravelTime(i, j, null)));
}
w.write("\n");
}
}
w.flush();
w.close();
return true;
}
}