mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
merged master into multiple tw branch
This commit is contained in:
parent
0b3b07a7de
commit
02c3c96e9c
523 changed files with 77426 additions and 74576 deletions
|
|
@ -1,74 +1,75 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>jsprit</groupId>
|
||||
<artifactId>jsprit</artifactId>
|
||||
<version>1.6.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jsprit-analysis</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.m2e</groupId>
|
||||
<artifactId>lifecycle-mapping</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<lifecycleMappingMetadata>
|
||||
<pluginExecutions>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<versionRange>[1.0.0,)</versionRange>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore />
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jfree</groupId>
|
||||
<artifactId>jfreechart</artifactId>
|
||||
<version>1.0.14</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jsprit-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>gs-core</artifactId>
|
||||
<groupId>org.graphstream</groupId>
|
||||
<version>1.3</version>
|
||||
<optional>false</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>gs-ui</artifactId>
|
||||
<groupId>org.graphstream</groupId>
|
||||
<version>1.3</version>
|
||||
<optional>false</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>jsprit</groupId>
|
||||
<artifactId>jsprit</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jsprit-analysis</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.m2e</groupId>
|
||||
<artifactId>lifecycle-mapping</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<lifecycleMappingMetadata>
|
||||
<pluginExecutions>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<versionRange>[1.0.0,)</versionRange>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore/>
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jfree</groupId>
|
||||
<artifactId>jfreechart</artifactId>
|
||||
<version>1.0.19</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jsprit-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>gs-core</artifactId>
|
||||
<groupId>org.graphstream</groupId>
|
||||
<version>1.3</version>
|
||||
<optional>false</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>gs-ui</artifactId>
|
||||
<groupId>org.graphstream</groupId>
|
||||
<version>1.3</version>
|
||||
<optional>false</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -89,11 +89,10 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
File dgsFile = new File(dgsFileLocation);
|
||||
fos = new FileOutputStream(dgsFile);
|
||||
fileSink = new FileSinkDGS();
|
||||
if(dgsFile.getName().endsWith("gz")){
|
||||
if (dgsFile.getName().endsWith("gz")) {
|
||||
gzipOs = new GZIPOutputStream(fos);
|
||||
fileSink.begin(gzipOs);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
fileSink.begin(fos);
|
||||
}
|
||||
graph.addSink(fileSink);
|
||||
|
|
@ -109,37 +108,37 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
new AlgorithmEventsRecorder(vrp, dgsFileLocation);
|
||||
}
|
||||
|
||||
public void setRecordingRange(int startIteration, int endIteration){
|
||||
public void setRecordingRange(int startIteration, int endIteration) {
|
||||
this.start_recording_at = startIteration;
|
||||
this.end_recording_at = endIteration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ruinStarts(Collection<VehicleRoute> routes) {
|
||||
if(!record()) return;
|
||||
fileSink.stepBegins(graph.getId(),0,BEFORE_RUIN_RENDER_SOLUTION);
|
||||
if (!record()) return;
|
||||
fileSink.stepBegins(graph.getId(), 0, BEFORE_RUIN_RENDER_SOLUTION);
|
||||
markAllNodesAsInserted();
|
||||
addRoutes(routes);
|
||||
fileSink.stepBegins(graph.getId(),0,RUIN);
|
||||
fileSink.stepBegins(graph.getId(), 0, RUIN);
|
||||
}
|
||||
|
||||
private void markAllNodesAsInserted() {
|
||||
for(Job j : vrp.getJobs().values()){
|
||||
for (Job j : vrp.getJobs().values()) {
|
||||
markInserted(j);
|
||||
}
|
||||
}
|
||||
|
||||
private void addRoutes(Collection<VehicleRoute> routes) {
|
||||
for(VehicleRoute route : routes){
|
||||
for (VehicleRoute route : routes) {
|
||||
String prevNode = makeStartId(route.getVehicle());
|
||||
for(TourActivity act : route.getActivities()){
|
||||
for (TourActivity act : route.getActivities()) {
|
||||
String actNodeId = getNodeId(act);
|
||||
addEdge(prevNode+"_"+actNodeId,prevNode,actNodeId);
|
||||
addEdge(prevNode + "_" + actNodeId, prevNode, actNodeId);
|
||||
prevNode = actNodeId;
|
||||
}
|
||||
if(route.getVehicle().isReturnToDepot()) {
|
||||
if (route.getVehicle().isReturnToDepot()) {
|
||||
String lastNode = makeEndId(route.getVehicle());
|
||||
addEdge(prevNode+"_"+lastNode,prevNode,lastNode);
|
||||
addEdge(prevNode + "_" + lastNode, prevNode, lastNode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -147,13 +146,12 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
|
||||
private String getNodeId(TourActivity act) {
|
||||
String nodeId = null;
|
||||
if(act instanceof TourActivity.JobActivity){
|
||||
if (act instanceof TourActivity.JobActivity) {
|
||||
Job job = ((TourActivity.JobActivity) act).getJob();
|
||||
if(job instanceof Service){
|
||||
if (job instanceof Service) {
|
||||
nodeId = job.getId();
|
||||
}
|
||||
else if(job instanceof Shipment){
|
||||
if(act.getName().equals("pickupShipment")) nodeId = getFromNodeId((Shipment) job);
|
||||
} else if (job instanceof Shipment) {
|
||||
if (act.getName().equals("pickupShipment")) nodeId = getFromNodeId((Shipment) job);
|
||||
else nodeId = getToNodeId((Shipment) job);
|
||||
}
|
||||
}
|
||||
|
|
@ -171,28 +169,29 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
|
||||
@Override
|
||||
public void removed(Job job, VehicleRoute fromRoute) {
|
||||
if(!record()) return;
|
||||
if(job instanceof Service) removeService(job, fromRoute);
|
||||
else if(job instanceof Shipment) removeShipment(job,fromRoute);
|
||||
if (!record()) return;
|
||||
if (job instanceof Service) removeService(job, fromRoute);
|
||||
else if (job instanceof Shipment) removeShipment(job, fromRoute);
|
||||
}
|
||||
|
||||
private void removeShipment(Job job, VehicleRoute fromRoute) {
|
||||
Shipment shipment = (Shipment)job;
|
||||
Shipment shipment = (Shipment) job;
|
||||
String fromNodeId = getFromNodeId(shipment);
|
||||
String toNodeId = getToNodeId(shipment);
|
||||
// removeNodeAndBelongingEdges(fromNodeId,fromRoute);
|
||||
// removeNodeAndBelongingEdges(toNodeId,fromRoute);
|
||||
|
||||
Edge enteringToNode = getEnteringEdge(toNodeId);
|
||||
if(enteringToNode.getNode0().getId().equals(fromNodeId)){
|
||||
if (enteringToNode.getNode0().getId().equals(fromNodeId)) {
|
||||
markRemoved(graph.getNode(fromNodeId));
|
||||
markRemoved(graph.getNode(toNodeId));
|
||||
// i -> from -> to -> j: rem(i,from), rem(from,to), rem(to,j), add(i,j)
|
||||
Edge enteringFromNode = getEnteringEdge(fromNodeId);
|
||||
removeEdge(enteringFromNode.getId());
|
||||
removeEdge(enteringToNode.getId());
|
||||
if(graph.getNode(toNodeId).getLeavingEdgeSet().isEmpty()){
|
||||
if(fromRoute.getVehicle().isReturnToDepot()) throw new IllegalStateException("leaving edge is missing");
|
||||
if (graph.getNode(toNodeId).getLeavingEdgeSet().isEmpty()) {
|
||||
if (fromRoute.getVehicle().isReturnToDepot())
|
||||
throw new IllegalStateException("leaving edge is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -200,22 +199,23 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
removeEdge(leavingToNode.getId());
|
||||
Node from = enteringFromNode.getNode0();
|
||||
Node to = leavingToNode.getNode1();
|
||||
if(!fromRoute.getActivities().isEmpty()){
|
||||
addEdge(makeEdgeId(from,to),from.getId(),to.getId());
|
||||
if (!fromRoute.getActivities().isEmpty()) {
|
||||
addEdge(makeEdgeId(from, to), from.getId(), to.getId());
|
||||
}
|
||||
}
|
||||
else{
|
||||
removeNodeAndBelongingEdges(fromNodeId,fromRoute);
|
||||
removeNodeAndBelongingEdges(toNodeId,fromRoute);
|
||||
} else {
|
||||
removeNodeAndBelongingEdges(fromNodeId, fromRoute);
|
||||
removeNodeAndBelongingEdges(toNodeId, fromRoute);
|
||||
}
|
||||
}
|
||||
|
||||
private Edge getLeavingEdge(String toNodeId) {
|
||||
Collection<Edge> edges = graph.getNode(toNodeId).getLeavingEdgeSet();
|
||||
if(edges.size()==1) return edges.iterator().next();
|
||||
else{
|
||||
for(Edge e : edges){
|
||||
if(e.getId().startsWith("shipment")){ continue; }
|
||||
if (edges.size() == 1) return edges.iterator().next();
|
||||
else {
|
||||
for (Edge e : edges) {
|
||||
if (e.getId().startsWith("shipment")) {
|
||||
continue;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
|
@ -224,10 +224,12 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
|
||||
private Edge getEnteringEdge(String toNodeId) {
|
||||
Collection<Edge> enteringEdges = graph.getNode(toNodeId).getEnteringEdgeSet();
|
||||
if(enteringEdges.size()==1) return enteringEdges.iterator().next();
|
||||
else{
|
||||
for(Edge e : enteringEdges){
|
||||
if(e.getId().startsWith("shipment")){ continue; }
|
||||
if (enteringEdges.size() == 1) return enteringEdges.iterator().next();
|
||||
else {
|
||||
for (Edge e : enteringEdges) {
|
||||
if (e.getId().startsWith("shipment")) {
|
||||
continue;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
|
@ -253,8 +255,8 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
Edge entering = getEnteringEdge(nodeId);
|
||||
removeEdge(entering.getId());
|
||||
|
||||
if(node.getLeavingEdgeSet().isEmpty()){
|
||||
if(fromRoute.getVehicle().isReturnToDepot()) throw new IllegalStateException("leaving edge is missing");
|
||||
if (node.getLeavingEdgeSet().isEmpty()) {
|
||||
if (fromRoute.getVehicle().isReturnToDepot()) throw new IllegalStateException("leaving edge is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -262,13 +264,13 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
removeEdge((leaving.getId()));
|
||||
Node from = entering.getNode0();
|
||||
Node to = leaving.getNode1();
|
||||
if(!fromRoute.getActivities().isEmpty()){
|
||||
addEdge(makeEdgeId(from,to),from.getId(),to.getId());
|
||||
if (!fromRoute.getActivities().isEmpty()) {
|
||||
addEdge(makeEdgeId(from, to), from.getId(), to.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void markRemoved(Node node) {
|
||||
node.setAttribute("ui.class","removed");
|
||||
node.setAttribute("ui.class", "removed");
|
||||
}
|
||||
|
||||
private String makeEdgeId(Node from, Node to) {
|
||||
|
|
@ -278,7 +280,7 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
@Override
|
||||
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions);
|
||||
fileSink.stepBegins(graph.getId(),0,BEFORE_RUIN_RENDER_SOLUTION);
|
||||
fileSink.stepBegins(graph.getId(), 0, BEFORE_RUIN_RENDER_SOLUTION);
|
||||
addRoutes(solution.getRoutes());
|
||||
finish();
|
||||
}
|
||||
|
|
@ -287,7 +289,7 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
try {
|
||||
fileSink.end();
|
||||
fos.close();
|
||||
if(gzipOs != null) gzipOs.close();
|
||||
if (gzipOs != null) gzipOs.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
@ -299,28 +301,27 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
}
|
||||
|
||||
private void initialiseGraph(VehicleRoutingProblem problem) {
|
||||
for(Vehicle vehicle : problem.getVehicles()){
|
||||
for (Vehicle vehicle : problem.getVehicles()) {
|
||||
addVehicle(vehicle);
|
||||
}
|
||||
for(Job job : problem.getJobs().values()){
|
||||
for (Job job : problem.getJobs().values()) {
|
||||
addJob(job);
|
||||
}
|
||||
}
|
||||
|
||||
private void addJob(Job job) {
|
||||
if(job instanceof Service){
|
||||
Service service = (Service)job;
|
||||
if (job instanceof Service) {
|
||||
Service service = (Service) job;
|
||||
addNode(service.getId(), service.getLocation().getCoordinate());
|
||||
markService(service);
|
||||
}
|
||||
else if(job instanceof Shipment){
|
||||
Shipment shipment = (Shipment)job;
|
||||
} else if (job instanceof Shipment) {
|
||||
Shipment shipment = (Shipment) job;
|
||||
String fromNodeId = getFromNodeId(shipment);
|
||||
addNode(fromNodeId, shipment.getPickupLocation().getCoordinate());
|
||||
String toNodeId = getToNodeId(shipment);
|
||||
addNode(toNodeId,shipment.getDeliveryLocation().getCoordinate());
|
||||
addNode(toNodeId, shipment.getDeliveryLocation().getCoordinate());
|
||||
markShipment(shipment);
|
||||
if(renderShipments) {
|
||||
if (renderShipments) {
|
||||
Edge e = graph.addEdge("shipment_" + fromNodeId + "_" + toNodeId, fromNodeId, toNodeId, true);
|
||||
e.addAttribute("ui.class", "shipment");
|
||||
}
|
||||
|
|
@ -333,35 +334,34 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
}
|
||||
|
||||
private void markService(Service service) {
|
||||
if(service instanceof Delivery){
|
||||
if (service instanceof Delivery) {
|
||||
markDelivery(service.getId());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
markPickup(service.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void markPickup(String id) {
|
||||
graph.getNode(id).addAttribute("ui.class","pickup");
|
||||
graph.getNode(id).addAttribute("ui.class", "pickup");
|
||||
}
|
||||
|
||||
private void markDelivery(String id) {
|
||||
graph.getNode(id).addAttribute("ui.class","delivery");
|
||||
graph.getNode(id).addAttribute("ui.class", "delivery");
|
||||
}
|
||||
|
||||
private void addVehicle(Vehicle vehicle) {
|
||||
String startId = makeStartId(vehicle);
|
||||
Node node = graph.addNode(startId);
|
||||
node.addAttribute("x",vehicle.getStartLocation().getCoordinate().getX());
|
||||
node.addAttribute("x", vehicle.getStartLocation().getCoordinate().getX());
|
||||
node.addAttribute("y", vehicle.getStartLocation().getCoordinate().getY());
|
||||
node.addAttribute("ui.class","depot");
|
||||
node.addAttribute("ui.class", "depot");
|
||||
|
||||
String endId = makeEndId(vehicle);
|
||||
if(!startId.equals(endId)){
|
||||
if (!startId.equals(endId)) {
|
||||
Node endNode = graph.addNode(endId);
|
||||
endNode.addAttribute("x", vehicle.getEndLocation().getCoordinate().getX());
|
||||
endNode.addAttribute("y", vehicle.getEndLocation().getCoordinate().getY());
|
||||
endNode.addAttribute("ui.class","depot");
|
||||
endNode.addAttribute("ui.class", "depot");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -370,7 +370,7 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
}
|
||||
|
||||
private String makeEndId(Vehicle vehicle) {
|
||||
if(vehicle.getStartLocation().getId().equals(vehicle.getEndLocation().getId())) return makeStartId(vehicle);
|
||||
if (vehicle.getStartLocation().getId().equals(vehicle.getEndLocation().getId())) return makeStartId(vehicle);
|
||||
return vehicle.getId() + "_end";
|
||||
}
|
||||
|
||||
|
|
@ -382,20 +382,20 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
|
||||
@Override
|
||||
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
||||
if(!record()) return;
|
||||
fileSink.stepBegins(graph.getId(),0,CLEAR_SOLUTION);
|
||||
if (!record()) return;
|
||||
fileSink.stepBegins(graph.getId(), 0, CLEAR_SOLUTION);
|
||||
removeRoutes(vehicleRoutes);
|
||||
}
|
||||
|
||||
private void removeRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
for(VehicleRoute route : vehicleRoutes){
|
||||
for (VehicleRoute route : vehicleRoutes) {
|
||||
String prevNode = makeStartId(route.getVehicle());
|
||||
for(TourActivity act : route.getActivities()){
|
||||
for (TourActivity act : route.getActivities()) {
|
||||
String actNode = getNodeId(act);
|
||||
removeEdge(prevNode + "_" + actNode);
|
||||
prevNode = actNode;
|
||||
}
|
||||
if(route.getVehicle().isReturnToDepot()) {
|
||||
if (route.getVehicle().isReturnToDepot()) {
|
||||
String lastNode = makeEndId(route.getVehicle());
|
||||
removeEdge(prevNode + "_" + lastNode);
|
||||
}
|
||||
|
|
@ -404,25 +404,25 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
|
||||
@Override
|
||||
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route) {
|
||||
if(!record()) return;
|
||||
if (!record()) return;
|
||||
markInserted(job);
|
||||
handleVehicleSwitch(data, route);
|
||||
insertJob(job, data, route);
|
||||
}
|
||||
|
||||
private void insertJob(Job job, InsertionData data, VehicleRoute route) {
|
||||
if(job instanceof Service) insertService(job,data,route);
|
||||
else if(job instanceof Shipment) insertShipment(job,data,route);
|
||||
if (job instanceof Service) insertService(job, data, route);
|
||||
else if (job instanceof Shipment) insertShipment(job, data, route);
|
||||
}
|
||||
|
||||
private void insertShipment(Job job, InsertionData data, VehicleRoute route) {
|
||||
String fromNodeId = getFromNodeId((Shipment) job);
|
||||
String toNodeId = getToNodeId((Shipment) job);
|
||||
insertNode(toNodeId,data.getDeliveryInsertionIndex(),data,route);
|
||||
insertNode(toNodeId, data.getDeliveryInsertionIndex(), data, route);
|
||||
|
||||
List<AbstractActivity> del = vrp.getActivities(job);
|
||||
VehicleRoute copied = VehicleRoute.copyOf(route);
|
||||
copied.getTourActivities().addActivity(data.getDeliveryInsertionIndex(),del.get(1));
|
||||
copied.getTourActivities().addActivity(data.getDeliveryInsertionIndex(), del.get(1));
|
||||
|
||||
insertNode(fromNodeId, data.getPickupInsertionIndex(), data, copied);
|
||||
}
|
||||
|
|
@ -436,19 +436,17 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
|
||||
String node_i;
|
||||
|
||||
if(isFirst(insertionIndex)) {
|
||||
if (isFirst(insertionIndex)) {
|
||||
node_i = makeStartId(data.getSelectedVehicle());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TourActivity.JobActivity jobActivity = (TourActivity.JobActivity) route.getActivities().get(insertionIndex - 1);
|
||||
node_i = getNodeId(jobActivity);
|
||||
}
|
||||
String edgeId_1 = node_i + "_" + nodeId;
|
||||
String edgeId_1 = node_i + "_" + nodeId;
|
||||
String node_j;
|
||||
if(isLast(insertionIndex,route)) {
|
||||
if (isLast(insertionIndex, route)) {
|
||||
node_j = makeEndId(data.getSelectedVehicle());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TourActivity.JobActivity jobActivity = (TourActivity.JobActivity) route.getActivities().get(insertionIndex);
|
||||
node_j = getNodeId(jobActivity);
|
||||
}
|
||||
|
|
@ -456,7 +454,7 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
|
||||
addEdge(edgeId_1, node_i, nodeId);
|
||||
|
||||
if(!(isLast(insertionIndex,route) && !data.getSelectedVehicle().isReturnToDepot())) {
|
||||
if (!(isLast(insertionIndex, route) && !data.getSelectedVehicle().isReturnToDepot())) {
|
||||
addEdge(edgeId_2, nodeId, node_j);
|
||||
if (!route.getActivities().isEmpty()) {
|
||||
removeEdge(node_i + "_" + node_j);
|
||||
|
|
@ -466,38 +464,37 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
|
||||
private void handleVehicleSwitch(InsertionData data, VehicleRoute route) {
|
||||
boolean vehicleSwitch = false;
|
||||
if(!(route.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||
if (!(route.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||
if (!route.getVehicle().getId().equals(data.getSelectedVehicle().getId())) {
|
||||
vehicleSwitch = true;
|
||||
}
|
||||
}
|
||||
if(vehicleSwitch && !route.getActivities().isEmpty()){
|
||||
if (vehicleSwitch && !route.getActivities().isEmpty()) {
|
||||
String oldStart = makeStartId(route.getVehicle());
|
||||
String firstAct = ((TourActivity.JobActivity)route.getActivities().get(0)).getJob().getId();
|
||||
String firstAct = ((TourActivity.JobActivity) route.getActivities().get(0)).getJob().getId();
|
||||
String oldEnd = makeEndId(route.getVehicle());
|
||||
String lastAct = ((TourActivity.JobActivity)route.getActivities().get(route.getActivities().size()-1)).getJob().getId();
|
||||
String lastAct = ((TourActivity.JobActivity) route.getActivities().get(route.getActivities().size() - 1)).getJob().getId();
|
||||
removeEdge(oldStart + "_" + firstAct);
|
||||
|
||||
if(route.getVehicle().isReturnToDepot()) {
|
||||
if (route.getVehicle().isReturnToDepot()) {
|
||||
removeEdge(lastAct + "_" + oldEnd);
|
||||
}
|
||||
|
||||
String newStart = makeStartId(data.getSelectedVehicle());
|
||||
String newEnd = makeEndId(data.getSelectedVehicle());
|
||||
addEdge(newStart + "_" + firstAct,newStart,firstAct);
|
||||
addEdge(newStart + "_" + firstAct, newStart, firstAct);
|
||||
|
||||
if(data.getSelectedVehicle().isReturnToDepot()) {
|
||||
if (data.getSelectedVehicle().isReturnToDepot()) {
|
||||
addEdge(lastAct + "_" + newEnd, lastAct, newEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void markInserted(Job job) {
|
||||
if(job instanceof Service){
|
||||
if (job instanceof Service) {
|
||||
markService((Service) job);
|
||||
}
|
||||
else{
|
||||
markShipment((Shipment)job);
|
||||
} else {
|
||||
markShipment((Shipment) job);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -507,7 +504,7 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
}
|
||||
|
||||
private void markEdgeRemoved(String edgeId) {
|
||||
graph.getEdge(edgeId).addAttribute("ui.class","removed");
|
||||
graph.getEdge(edgeId).addAttribute("ui.class", "removed");
|
||||
}
|
||||
|
||||
private boolean isFirst(int index) {
|
||||
|
|
@ -518,19 +515,19 @@ public class AlgorithmEventsRecorder implements RuinListener, IterationStartsLis
|
|||
return index == route.getActivities().size();
|
||||
}
|
||||
|
||||
private void addEdge(String edgeId, String fromNode, String toNode) {
|
||||
graph.addEdge(edgeId,fromNode,toNode,true);
|
||||
private void addEdge(String edgeId, String fromNode, String toNode) {
|
||||
graph.addEdge(edgeId, fromNode, toNode, true);
|
||||
markEdgeInserted(edgeId);
|
||||
}
|
||||
|
||||
private void markEdgeInserted(String edgeId) {
|
||||
graph.getEdge(edgeId).addAttribute("ui.class","inserted");
|
||||
graph.getEdge(edgeId).addAttribute("ui.class", "inserted");
|
||||
graph.getEdge(edgeId).removeAttribute("ui.class");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
if(!record()) return;
|
||||
fileSink.stepBegins(graph.getId(),0,RECREATE);
|
||||
if (!record()) return;
|
||||
fileSink.stepBegins(graph.getId(), 0, RECREATE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public class AlgorithmEventsViewer {
|
|||
this.delayContainer = delayContainer;
|
||||
}
|
||||
|
||||
public void setRuinDelay(long ruinDelay){
|
||||
public void setRuinDelay(long ruinDelay) {
|
||||
this.ruinDelay = ruinDelay;
|
||||
}
|
||||
|
||||
|
|
@ -131,16 +131,14 @@ public class AlgorithmEventsViewer {
|
|||
|
||||
@Override
|
||||
public void stepBegins(String sourceId, long timeId, double step) {
|
||||
if(step == AlgorithmEventsRecorder.RECREATE) {
|
||||
if (step == AlgorithmEventsRecorder.RECREATE) {
|
||||
delayContainer.delay = recreateDelay;
|
||||
}
|
||||
if(step == AlgorithmEventsRecorder.RUIN){
|
||||
if (step == AlgorithmEventsRecorder.RUIN) {
|
||||
delayContainer.delay = ruinDelay;
|
||||
}
|
||||
else if(step == AlgorithmEventsRecorder.CLEAR_SOLUTION){
|
||||
} else if (step == AlgorithmEventsRecorder.CLEAR_SOLUTION) {
|
||||
delayContainer.delay = delay;
|
||||
}
|
||||
else if(step == AlgorithmEventsRecorder.BEFORE_RUIN_RENDER_SOLUTION){
|
||||
} else if (step == AlgorithmEventsRecorder.BEFORE_RUIN_RENDER_SOLUTION) {
|
||||
delayContainer.delay = delay;
|
||||
}
|
||||
}
|
||||
|
|
@ -156,15 +154,15 @@ public class AlgorithmEventsViewer {
|
|||
|
||||
private long delay = 2;
|
||||
|
||||
public void setRecreationDelay(long delay_in_ms){
|
||||
public void setRecreationDelay(long delay_in_ms) {
|
||||
this.delayRecreation = delay_in_ms;
|
||||
}
|
||||
|
||||
public void setRuinDelay(long delay_in_ms){
|
||||
public void setRuinDelay(long delay_in_ms) {
|
||||
this.delayRuin = delay_in_ms;
|
||||
}
|
||||
|
||||
public void display(String dgsFile){
|
||||
public void display(String dgsFile) {
|
||||
System.setProperty("org.graphstream.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer");
|
||||
Graph graph = GraphStreamViewer.createMultiGraph("g", GraphStreamViewer.StyleSheets.BLUE_FOREST);
|
||||
Viewer viewer = graph.display();
|
||||
|
|
@ -185,13 +183,13 @@ public class AlgorithmEventsViewer {
|
|||
while (fs.nextEvents()) {
|
||||
sleep(delayContainer.delay);
|
||||
}
|
||||
} catch( IOException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
fs.end();
|
||||
} catch( IOException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
fs.removeSink(graph);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2013 Stefan Schroeder
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.analysis.toolbox;
|
||||
|
|
@ -30,59 +30,58 @@ import java.util.Collection;
|
|||
|
||||
/**
|
||||
* VehicleRoutingAlgorithm-Listener to record the solution-search-progress.
|
||||
*
|
||||
* <p/>
|
||||
* <p>Register this listener in VehicleRoutingAlgorithm.
|
||||
*
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
|
||||
public class AlgorithmSearchProgressChartListener implements IterationEndsListener, AlgorithmEndsListener, AlgorithmStartsListener {
|
||||
|
||||
private static Logger log = LogManager.getLogger(AlgorithmSearchProgressChartListener.class);
|
||||
private static Logger log = LogManager.getLogger(AlgorithmSearchProgressChartListener.class);
|
||||
|
||||
private String filename;
|
||||
|
||||
private XYLineChartBuilder chartBuilder;
|
||||
private String filename;
|
||||
|
||||
/**
|
||||
* Constructs chart listener with target png-file (filename plus path).
|
||||
*
|
||||
* @param pngFileName
|
||||
*/
|
||||
public AlgorithmSearchProgressChartListener(String pngFileName) {
|
||||
super();
|
||||
this.filename = pngFileName;
|
||||
if(!this.filename.endsWith("png")){
|
||||
this.filename += ".png";
|
||||
}
|
||||
}
|
||||
private XYLineChartBuilder chartBuilder;
|
||||
|
||||
@Override
|
||||
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
log.info("create chart " + filename);
|
||||
XYLineChartBuilder.saveChartAsPNG(chartBuilder.build(), filename);
|
||||
}
|
||||
/**
|
||||
* Constructs chart listener with target png-file (filename plus path).
|
||||
*
|
||||
* @param pngFileName
|
||||
*/
|
||||
public AlgorithmSearchProgressChartListener(String pngFileName) {
|
||||
super();
|
||||
this.filename = pngFileName;
|
||||
if (!this.filename.endsWith("png")) {
|
||||
this.filename += ".png";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informIterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
double worst = 0.0;
|
||||
double best = Double.MAX_VALUE;
|
||||
double sum = 0.0;
|
||||
for(VehicleRoutingProblemSolution sol : solutions){
|
||||
if(sol.getCost() > worst) worst = Math.min(sol.getCost(),Double.MAX_VALUE);
|
||||
if(sol.getCost() < best) best = sol.getCost();
|
||||
sum += Math.min(sol.getCost(),Double.MAX_VALUE);
|
||||
}
|
||||
chartBuilder.addData("best", i, best);
|
||||
chartBuilder.addData("worst", i, worst);
|
||||
chartBuilder.addData("avg", i, sum/(double)solutions.size());
|
||||
}
|
||||
@Override
|
||||
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
log.info("create chart {}", filename);
|
||||
XYLineChartBuilder.saveChartAsPNG(chartBuilder.build(), filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informIterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
double worst = 0.0;
|
||||
double best = Double.MAX_VALUE;
|
||||
double sum = 0.0;
|
||||
for (VehicleRoutingProblemSolution sol : solutions) {
|
||||
if (sol.getCost() > worst) worst = Math.min(sol.getCost(), Double.MAX_VALUE);
|
||||
if (sol.getCost() < best) best = sol.getCost();
|
||||
sum += Math.min(sol.getCost(), Double.MAX_VALUE);
|
||||
}
|
||||
chartBuilder.addData("best", i, best);
|
||||
chartBuilder.addData("worst", i, worst);
|
||||
chartBuilder.addData("avg", i, sum / (double) solutions.size());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem,VehicleRoutingAlgorithm algorithm,Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
chartBuilder = XYLineChartBuilder.newInstance("search-progress", "iterations", "results");
|
||||
}
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
chartBuilder = XYLineChartBuilder.newInstance("search-progress", "iterations", "results");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 Stefan Schroeder.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
|
@ -33,433 +33,444 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
public class ComputationalLaboratory {
|
||||
|
||||
public static interface LabListener {
|
||||
public static interface LabListener {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener-interface to listen to calculation.
|
||||
*
|
||||
* <p>Note that calculations are run concurrently, i.e. a unique task that is distributed to an available thread is
|
||||
* {algorithm, instance, run}.
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
*/
|
||||
public static interface CalculationListener extends LabListener{
|
||||
|
||||
public void calculationStarts(final BenchmarkInstance p, final String algorithmName, final VehicleRoutingAlgorithm algorithm, final int run);
|
||||
|
||||
public void calculationEnds(final BenchmarkInstance p, final String algorithmName, final VehicleRoutingAlgorithm algorithm, final int run, final Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
}
|
||||
/**
|
||||
* Listener-interface to listen to calculation.
|
||||
* <p/>
|
||||
* <p>Note that calculations are run concurrently, i.e. a unique task that is distributed to an available thread is
|
||||
* {algorithm, instance, run}.
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public static interface CalculationListener extends LabListener {
|
||||
|
||||
public static interface LabStartsAndEndsListener extends LabListener {
|
||||
public void calculationStarts(final BenchmarkInstance p, final String algorithmName, final VehicleRoutingAlgorithm algorithm, final int run);
|
||||
|
||||
public void labStarts(List<BenchmarkInstance> instances, int noAlgorithms, int runs);
|
||||
public void calculationEnds(final BenchmarkInstance p, final String algorithmName, final VehicleRoutingAlgorithm algorithm, final int run, final Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
public void labEnds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects whatever indicators you require by algorithmName, instanceName, run and indicator.
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
*/
|
||||
public static class DataCollector {
|
||||
|
||||
public static class Key {
|
||||
private String instanceName;
|
||||
private String algorithmName;
|
||||
private int run;
|
||||
private String indicatorName;
|
||||
|
||||
public Key(String instanceName, String algorithmName, int run,String indicatorName) {
|
||||
super();
|
||||
this.instanceName = instanceName;
|
||||
this.algorithmName = algorithmName;
|
||||
this.run = run;
|
||||
this.indicatorName = indicatorName;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime
|
||||
* result
|
||||
+ ((algorithmName == null) ? 0 : algorithmName
|
||||
.hashCode());
|
||||
result = prime
|
||||
* result
|
||||
+ ((indicatorName == null) ? 0 : indicatorName
|
||||
.hashCode());
|
||||
result = prime
|
||||
* result
|
||||
+ ((instanceName == null) ? 0 : instanceName.hashCode());
|
||||
result = prime * result + run;
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Key other = (Key) obj;
|
||||
if (algorithmName == null) {
|
||||
if (other.algorithmName != null)
|
||||
return false;
|
||||
} else if (!algorithmName.equals(other.algorithmName))
|
||||
return false;
|
||||
if (indicatorName == null) {
|
||||
if (other.indicatorName != null)
|
||||
return false;
|
||||
} else if (!indicatorName.equals(other.indicatorName))
|
||||
return false;
|
||||
if (instanceName == null) {
|
||||
if (other.instanceName != null)
|
||||
return false;
|
||||
} else if (!instanceName.equals(other.instanceName))
|
||||
return false;
|
||||
if (run != other.run)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public String getInstanceName() {
|
||||
return instanceName;
|
||||
}
|
||||
public String getAlgorithmName() {
|
||||
return algorithmName;
|
||||
}
|
||||
public int getRun() {
|
||||
return run;
|
||||
}
|
||||
public String getIndicatorName() {
|
||||
return indicatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[algorithm="+algorithmName+"][instance="+instanceName+"][run="+run+"][indicator="+indicatorName+"]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final static String SOLUTION_INDICATOR_NAME = "vehicle-routing-problem-solution";
|
||||
|
||||
private ConcurrentHashMap<Key, Double> data = new ConcurrentHashMap<ComputationalLaboratory.DataCollector.Key, Double>();
|
||||
|
||||
private ConcurrentHashMap<Key, VehicleRoutingProblemSolution> solutions = new ConcurrentHashMap<ComputationalLaboratory.DataCollector.Key, VehicleRoutingProblemSolution>();
|
||||
/**
|
||||
* Adds a single date by instanceName, algorithmName, run and indicatorName.
|
||||
* <p>If there is already an entry for this instance, algorithm, run and indicatorName, it is overwritten.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param run
|
||||
* @param indicatorName
|
||||
* @param value
|
||||
*/
|
||||
public void addDate(String instanceName, String algorithmName, int run, String indicatorName, double value){
|
||||
if(indicatorName.equals(SOLUTION_INDICATOR_NAME)) throw new IllegalArgumentException(indicatorName + " is already used internally. please choose another indicator-name.");
|
||||
Key key = new Key(instanceName,algorithmName,run,indicatorName);
|
||||
data.put(key, value);
|
||||
}
|
||||
|
||||
public void addSolution(String instanceName, String algorithmName, int run, VehicleRoutingProblemSolution solution){
|
||||
Key key = new Key(instanceName,algorithmName,run,SOLUTION_INDICATOR_NAME);
|
||||
solutions.put(key, solution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collections of indicator values representing the calculated values of individual runs.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param indicator
|
||||
* @return
|
||||
*/
|
||||
public Collection<Double> getData(String instanceName, String algorithmName, String indicator){
|
||||
List<Double> values = new ArrayList<Double>();
|
||||
for(Key key : data.keySet()){
|
||||
if(key.getAlgorithmName().equals(algorithmName) && key.getInstanceName().equals(instanceName) && key.getIndicatorName().equals(indicator)){
|
||||
values.add(data.get(key));
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns indicator value.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param run
|
||||
* @param indicator
|
||||
* @return
|
||||
*/
|
||||
public Double getDate(String instanceName, String algorithmName, int run, String indicator){
|
||||
return data.get(new Key(instanceName,algorithmName,run,indicator));
|
||||
}
|
||||
|
||||
public VehicleRoutingProblemSolution getSolution(String instanceName, String algorithmName, int run){
|
||||
return solutions.get(new Key(instanceName,algorithmName,run,"solution"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all keys that have been created. A key is a unique combination of algorithmName, instanceName, run and indicator.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<Key> getDataKeySet(){
|
||||
return data.keySet();
|
||||
}
|
||||
|
||||
public Set<Key> getSolutionKeySet(){
|
||||
return solutions.keySet();
|
||||
}
|
||||
|
||||
public VehicleRoutingProblemSolution getSolution(Key solutionKey){
|
||||
return solutions.get(solutionKey);
|
||||
}
|
||||
|
||||
public Collection<VehicleRoutingProblemSolution> getSolutions(){
|
||||
return solutions.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns date associated to specified key.
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Double getData(Key key){
|
||||
return data.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class Algorithm {
|
||||
|
||||
private String name;
|
||||
|
||||
private VehicleRoutingAlgorithmFactory factory;
|
||||
public static interface LabStartsAndEndsListener extends LabListener {
|
||||
|
||||
public Algorithm(String name, VehicleRoutingAlgorithmFactory factory) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<BenchmarkInstance> benchmarkInstances = new ArrayList<BenchmarkInstance>();
|
||||
public void labStarts(List<BenchmarkInstance> instances, int noAlgorithms, int runs);
|
||||
|
||||
private int runs = 1;
|
||||
|
||||
private Collection<CalculationListener> listeners = new ArrayList<ComputationalLaboratory.CalculationListener>();
|
||||
public void labEnds();
|
||||
}
|
||||
|
||||
private Collection<LabStartsAndEndsListener> startsAndEndslisteners = new ArrayList<LabStartsAndEndsListener>();
|
||||
|
||||
private List<Algorithm> algorithms = new ArrayList<ComputationalLaboratory.Algorithm>();
|
||||
|
||||
private Set<String> algorithmNames = new HashSet<String>();
|
||||
|
||||
private Set<String> instanceNames = new HashSet<String>();
|
||||
|
||||
private int threads = 1;
|
||||
|
||||
public ComputationalLaboratory() {
|
||||
/**
|
||||
* Collects whatever indicators you require by algorithmName, instanceName, run and indicator.
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public static class DataCollector {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds algorithmFactory by name.
|
||||
*
|
||||
* @param name
|
||||
* @param factory
|
||||
* @throws IllegalStateException if there is already an algorithmFactory with the same name
|
||||
*/
|
||||
public void addAlgorithmFactory(String name, VehicleRoutingAlgorithmFactory factory){
|
||||
if(algorithmNames.contains(name)) throw new IllegalStateException("there is already a algorithmFactory with the same name (algorithmName="+name+"). unique names are required.");
|
||||
algorithms.add(new Algorithm(name,factory));
|
||||
algorithmNames.add(name);
|
||||
}
|
||||
|
||||
public Collection<String> getAlgorithmNames() {
|
||||
return algorithmNames;
|
||||
}
|
||||
|
||||
public Collection<String> getInstanceNames(){
|
||||
return instanceNames;
|
||||
}
|
||||
public static class Key {
|
||||
private String instanceName;
|
||||
private String algorithmName;
|
||||
private int run;
|
||||
private String indicatorName;
|
||||
|
||||
/**
|
||||
* Adds instance by name.
|
||||
*
|
||||
* @param name
|
||||
* @param problem
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(String name, VehicleRoutingProblem problem){
|
||||
if(benchmarkInstances.contains(name)) throw new IllegalStateException("there is already an instance with the same name (instanceName="+name+"). unique names are required.");
|
||||
benchmarkInstances.add(new BenchmarkInstance(name,problem,null,null));
|
||||
instanceNames.add(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds instance.
|
||||
*
|
||||
* @param instance the instance to be added
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(BenchmarkInstance instance){
|
||||
if(benchmarkInstances.contains(instance.name)) throw new IllegalStateException("there is already an instance with the same name (instanceName="+instance.name+"). unique names are required.");
|
||||
benchmarkInstances.add(instance);
|
||||
instanceNames.add(instance.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds collection of instances.
|
||||
*
|
||||
* @param instances collection of instances to be added
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addAllInstances(Collection<BenchmarkInstance> instances){
|
||||
for(BenchmarkInstance i : instances){
|
||||
addInstance(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds instance by name, and with best known results.
|
||||
*
|
||||
* @param name
|
||||
* @param problem
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(String name, VehicleRoutingProblem problem, Double bestKnownResult, Double bestKnownVehicles){
|
||||
addInstance(new BenchmarkInstance(name,problem,bestKnownResult,bestKnownVehicles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds listener to listen computational experiments.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void addListener(LabListener listener){
|
||||
if(listener instanceof CalculationListener) {
|
||||
listeners.add((CalculationListener) listener);
|
||||
}
|
||||
if(listener instanceof LabStartsAndEndsListener){
|
||||
startsAndEndslisteners.add((LabStartsAndEndsListener) listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets nuOfRuns with same algorithm on same instance.
|
||||
* <p>Default is 1
|
||||
*
|
||||
* @param runs
|
||||
*/
|
||||
public void setNuOfRuns(int runs){
|
||||
this.runs = runs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs experiments.
|
||||
*
|
||||
* <p>If nuThreads > 1 it runs them concurrently, i.e. individual runs are distributed to available threads. Therefore
|
||||
* a unique task is defined by its algorithmName, instanceName and its runNumber.
|
||||
* <p>If you have one algorithm called "myAlgorithm" and one instance called "myInstance", and you need to run "myAlgorithm" on "myInstance" three times
|
||||
* with three threads then "myAlgorithm","myInstance",run1 runs on the first thread, "myAlgorithm", "myInstance", run2 on the second etc.
|
||||
* <p>You can register whatever analysisTool you require by implementing and registering CalculationListener. Then your tool is informed just
|
||||
* before a calculation starts as well as just after a calculation has been finished.
|
||||
*
|
||||
* @see CalculationListener
|
||||
* @throws IllegalStateException if either no algorithm or no instance has been specified
|
||||
*/
|
||||
public void run(){
|
||||
if(algorithms.isEmpty()){
|
||||
throw new IllegalStateException("no algorithm specified. at least one algorithm needs to be specified.");
|
||||
}
|
||||
if(benchmarkInstances.isEmpty()){
|
||||
throw new IllegalStateException("no instance specified. at least one instance needs to be specified.");
|
||||
}
|
||||
informStart();
|
||||
System.out.println("start benchmarking [nuAlgorithms="+algorithms.size()+"][nuInstances=" + benchmarkInstances.size() + "][runsPerInstance=" + runs + "]");
|
||||
double startTime = System.currentTimeMillis();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threads);
|
||||
for(final Algorithm algorithm : algorithms){
|
||||
for(final BenchmarkInstance p : benchmarkInstances){
|
||||
for(int run=0;run<runs;run++){
|
||||
final int r = run;
|
||||
// runAlgorithm(p, algorithm, r+1);
|
||||
public Key(String instanceName, String algorithmName, int run, String indicatorName) {
|
||||
super();
|
||||
this.instanceName = instanceName;
|
||||
this.algorithmName = algorithmName;
|
||||
this.run = run;
|
||||
this.indicatorName = indicatorName;
|
||||
}
|
||||
|
||||
executor.submit(new Runnable(){
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime
|
||||
* result
|
||||
+ ((algorithmName == null) ? 0 : algorithmName
|
||||
.hashCode());
|
||||
result = prime
|
||||
* result
|
||||
+ ((indicatorName == null) ? 0 : indicatorName
|
||||
.hashCode());
|
||||
result = prime
|
||||
* result
|
||||
+ ((instanceName == null) ? 0 : instanceName.hashCode());
|
||||
result = prime * result + run;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
runAlgorithm(p, algorithm, r+1);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Key other = (Key) obj;
|
||||
if (algorithmName == null) {
|
||||
if (other.algorithmName != null)
|
||||
return false;
|
||||
} else if (!algorithmName.equals(other.algorithmName))
|
||||
return false;
|
||||
if (indicatorName == null) {
|
||||
if (other.indicatorName != null)
|
||||
return false;
|
||||
} else if (!indicatorName.equals(other.indicatorName))
|
||||
return false;
|
||||
if (instanceName == null) {
|
||||
if (other.instanceName != null)
|
||||
return false;
|
||||
} else if (!instanceName.equals(other.instanceName))
|
||||
return false;
|
||||
if (run != other.run)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("benchmarking done [time="+(System.currentTimeMillis()-startTime)/1000 + "sec]");
|
||||
informEnd();
|
||||
}
|
||||
public String getInstanceName() {
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
private void informEnd() {
|
||||
for(LabStartsAndEndsListener l : startsAndEndslisteners){
|
||||
l.labEnds();
|
||||
}
|
||||
}
|
||||
public String getAlgorithmName() {
|
||||
return algorithmName;
|
||||
}
|
||||
|
||||
private void informStart() {
|
||||
for(LabStartsAndEndsListener l : startsAndEndslisteners){
|
||||
l.labStarts(benchmarkInstances, algorithms.size(),runs);
|
||||
}
|
||||
}
|
||||
public int getRun() {
|
||||
return run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets number of threads.
|
||||
* <p>By default: <code>nuThreads = Runtime.getRuntime().availableProcessors()+1</code>
|
||||
*
|
||||
* @param threads
|
||||
*/
|
||||
public void setThreads(int threads) {
|
||||
this.threads = threads;
|
||||
}
|
||||
public String getIndicatorName() {
|
||||
return indicatorName;
|
||||
}
|
||||
|
||||
private void runAlgorithm(BenchmarkInstance p, Algorithm algorithm, int run) {
|
||||
System.out.println("[algorithm=" + algorithm.name + "][instance="+p.name+"][run="+run+"][status=start]");
|
||||
VehicleRoutingAlgorithm vra = algorithm.factory.createAlgorithm(p.vrp);
|
||||
informCalculationStarts(p, algorithm.name, vra, run);
|
||||
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||
System.out.println("[algorithm=" + algorithm.name + "][instance="+p.name+"][run="+run+"][status=finished]");
|
||||
informCalculationsEnds(p, algorithm.name, vra, run, solutions);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[algorithm=" + algorithmName + "][instance=" + instanceName + "][run=" + run + "][indicator=" + indicatorName + "]";
|
||||
}
|
||||
|
||||
private void informCalculationStarts(BenchmarkInstance p, String name, VehicleRoutingAlgorithm vra, int run) {
|
||||
for(CalculationListener l : listeners) l.calculationStarts(p, name, vra, run);
|
||||
}
|
||||
}
|
||||
|
||||
private void informCalculationsEnds(BenchmarkInstance p, String name, VehicleRoutingAlgorithm vra, int run,
|
||||
Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for(CalculationListener l : listeners) l.calculationEnds(p, name, vra, run, solutions);
|
||||
}
|
||||
private final static String SOLUTION_INDICATOR_NAME = "vehicle-routing-problem-solution";
|
||||
|
||||
private ConcurrentHashMap<Key, Double> data = new ConcurrentHashMap<ComputationalLaboratory.DataCollector.Key, Double>();
|
||||
|
||||
private ConcurrentHashMap<Key, VehicleRoutingProblemSolution> solutions = new ConcurrentHashMap<ComputationalLaboratory.DataCollector.Key, VehicleRoutingProblemSolution>();
|
||||
|
||||
/**
|
||||
* Adds a single date by instanceName, algorithmName, run and indicatorName.
|
||||
* <p>If there is already an entry for this instance, algorithm, run and indicatorName, it is overwritten.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param run
|
||||
* @param indicatorName
|
||||
* @param value
|
||||
*/
|
||||
public void addDate(String instanceName, String algorithmName, int run, String indicatorName, double value) {
|
||||
if (indicatorName.equals(SOLUTION_INDICATOR_NAME))
|
||||
throw new IllegalArgumentException(indicatorName + " is already used internally. please choose another indicator-name.");
|
||||
Key key = new Key(instanceName, algorithmName, run, indicatorName);
|
||||
data.put(key, value);
|
||||
}
|
||||
|
||||
public void addSolution(String instanceName, String algorithmName, int run, VehicleRoutingProblemSolution solution) {
|
||||
Key key = new Key(instanceName, algorithmName, run, SOLUTION_INDICATOR_NAME);
|
||||
solutions.put(key, solution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collections of indicator values representing the calculated values of individual runs.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param indicator
|
||||
* @return
|
||||
*/
|
||||
public Collection<Double> getData(String instanceName, String algorithmName, String indicator) {
|
||||
List<Double> values = new ArrayList<Double>();
|
||||
for (Key key : data.keySet()) {
|
||||
if (key.getAlgorithmName().equals(algorithmName) && key.getInstanceName().equals(instanceName) && key.getIndicatorName().equals(indicator)) {
|
||||
values.add(data.get(key));
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns indicator value.
|
||||
*
|
||||
* @param instanceName
|
||||
* @param algorithmName
|
||||
* @param run
|
||||
* @param indicator
|
||||
* @return
|
||||
*/
|
||||
public Double getDate(String instanceName, String algorithmName, int run, String indicator) {
|
||||
return data.get(new Key(instanceName, algorithmName, run, indicator));
|
||||
}
|
||||
|
||||
public VehicleRoutingProblemSolution getSolution(String instanceName, String algorithmName, int run) {
|
||||
return solutions.get(new Key(instanceName, algorithmName, run, "solution"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all keys that have been created. A key is a unique combination of algorithmName, instanceName, run and indicator.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<Key> getDataKeySet() {
|
||||
return data.keySet();
|
||||
}
|
||||
|
||||
public Set<Key> getSolutionKeySet() {
|
||||
return solutions.keySet();
|
||||
}
|
||||
|
||||
public VehicleRoutingProblemSolution getSolution(Key solutionKey) {
|
||||
return solutions.get(solutionKey);
|
||||
}
|
||||
|
||||
public Collection<VehicleRoutingProblemSolution> getSolutions() {
|
||||
return solutions.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns date associated to specified key.
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Double getData(Key key) {
|
||||
return data.get(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class Algorithm {
|
||||
|
||||
private String name;
|
||||
|
||||
private VehicleRoutingAlgorithmFactory factory;
|
||||
|
||||
public Algorithm(String name, VehicleRoutingAlgorithmFactory factory) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<BenchmarkInstance> benchmarkInstances = new ArrayList<BenchmarkInstance>();
|
||||
|
||||
private int runs = 1;
|
||||
|
||||
private Collection<CalculationListener> listeners = new ArrayList<ComputationalLaboratory.CalculationListener>();
|
||||
|
||||
private Collection<LabStartsAndEndsListener> startsAndEndslisteners = new ArrayList<LabStartsAndEndsListener>();
|
||||
|
||||
private List<Algorithm> algorithms = new ArrayList<ComputationalLaboratory.Algorithm>();
|
||||
|
||||
private Set<String> algorithmNames = new HashSet<String>();
|
||||
|
||||
private Set<String> instanceNames = new HashSet<String>();
|
||||
|
||||
private int threads = 1;
|
||||
|
||||
public ComputationalLaboratory() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds algorithmFactory by name.
|
||||
*
|
||||
* @param name
|
||||
* @param factory
|
||||
* @throws IllegalStateException if there is already an algorithmFactory with the same name
|
||||
*/
|
||||
public void addAlgorithmFactory(String name, VehicleRoutingAlgorithmFactory factory) {
|
||||
if (algorithmNames.contains(name))
|
||||
throw new IllegalStateException("there is already a algorithmFactory with the same name (algorithmName=" + name + "). unique names are required.");
|
||||
algorithms.add(new Algorithm(name, factory));
|
||||
algorithmNames.add(name);
|
||||
}
|
||||
|
||||
public Collection<String> getAlgorithmNames() {
|
||||
return algorithmNames;
|
||||
}
|
||||
|
||||
public Collection<String> getInstanceNames() {
|
||||
return instanceNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds instance by name.
|
||||
*
|
||||
* @param name
|
||||
* @param problem
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(String name, VehicleRoutingProblem problem) {
|
||||
if (benchmarkInstances.contains(name))
|
||||
throw new IllegalStateException("there is already an instance with the same name (instanceName=" + name + "). unique names are required.");
|
||||
benchmarkInstances.add(new BenchmarkInstance(name, problem, null, null));
|
||||
instanceNames.add(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds instance.
|
||||
*
|
||||
* @param instance the instance to be added
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(BenchmarkInstance instance) {
|
||||
if (benchmarkInstances.contains(instance.name))
|
||||
throw new IllegalStateException("there is already an instance with the same name (instanceName=" + instance.name + "). unique names are required.");
|
||||
benchmarkInstances.add(instance);
|
||||
instanceNames.add(instance.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds collection of instances.
|
||||
*
|
||||
* @param instances collection of instances to be added
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addAllInstances(Collection<BenchmarkInstance> instances) {
|
||||
for (BenchmarkInstance i : instances) {
|
||||
addInstance(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds instance by name, and with best known results.
|
||||
*
|
||||
* @param name
|
||||
* @param problem
|
||||
* @throws IllegalStateException if there is already an instance with the same name.
|
||||
*/
|
||||
public void addInstance(String name, VehicleRoutingProblem problem, Double bestKnownResult, Double bestKnownVehicles) {
|
||||
addInstance(new BenchmarkInstance(name, problem, bestKnownResult, bestKnownVehicles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds listener to listen computational experiments.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void addListener(LabListener listener) {
|
||||
if (listener instanceof CalculationListener) {
|
||||
listeners.add((CalculationListener) listener);
|
||||
}
|
||||
if (listener instanceof LabStartsAndEndsListener) {
|
||||
startsAndEndslisteners.add((LabStartsAndEndsListener) listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets nuOfRuns with same algorithm on same instance.
|
||||
* <p>Default is 1
|
||||
*
|
||||
* @param runs
|
||||
*/
|
||||
public void setNuOfRuns(int runs) {
|
||||
this.runs = runs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs experiments.
|
||||
* <p/>
|
||||
* <p>If nuThreads > 1 it runs them concurrently, i.e. individual runs are distributed to available threads. Therefore
|
||||
* a unique task is defined by its algorithmName, instanceName and its runNumber.
|
||||
* <p>If you have one algorithm called "myAlgorithm" and one instance called "myInstance", and you need to run "myAlgorithm" on "myInstance" three times
|
||||
* with three threads then "myAlgorithm","myInstance",run1 runs on the first thread, "myAlgorithm", "myInstance", run2 on the second etc.
|
||||
* <p>You can register whatever analysisTool you require by implementing and registering CalculationListener. Then your tool is informed just
|
||||
* before a calculation starts as well as just after a calculation has been finished.
|
||||
*
|
||||
* @throws IllegalStateException if either no algorithm or no instance has been specified
|
||||
* @see CalculationListener
|
||||
*/
|
||||
public void run() {
|
||||
if (algorithms.isEmpty()) {
|
||||
throw new IllegalStateException("no algorithm specified. at least one algorithm needs to be specified.");
|
||||
}
|
||||
if (benchmarkInstances.isEmpty()) {
|
||||
throw new IllegalStateException("no instance specified. at least one instance needs to be specified.");
|
||||
}
|
||||
informStart();
|
||||
System.out.println("start benchmarking [nuAlgorithms=" + algorithms.size() + "][nuInstances=" + benchmarkInstances.size() + "][runsPerInstance=" + runs + "]");
|
||||
double startTime = System.currentTimeMillis();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threads);
|
||||
for (final Algorithm algorithm : algorithms) {
|
||||
for (final BenchmarkInstance p : benchmarkInstances) {
|
||||
for (int run = 0; run < runs; run++) {
|
||||
final int r = run;
|
||||
try {
|
||||
executor.submit(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
runAlgorithm(p, algorithm, r + 1);
|
||||
}
|
||||
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println("benchmarking done [time=" + (System.currentTimeMillis() - startTime) / 1000 + "sec]");
|
||||
informEnd();
|
||||
}
|
||||
|
||||
private void informEnd() {
|
||||
for (LabStartsAndEndsListener l : startsAndEndslisteners) {
|
||||
l.labEnds();
|
||||
}
|
||||
}
|
||||
|
||||
private void informStart() {
|
||||
for (LabStartsAndEndsListener l : startsAndEndslisteners) {
|
||||
l.labStarts(benchmarkInstances, algorithms.size(), runs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets number of threads.
|
||||
* <p>By default: <code>nuThreads = Runtime.getRuntime().availableProcessors()+1</code>
|
||||
*
|
||||
* @param threads
|
||||
*/
|
||||
public void setThreads(int threads) {
|
||||
this.threads = threads;
|
||||
}
|
||||
|
||||
private void runAlgorithm(BenchmarkInstance p, Algorithm algorithm, int run) {
|
||||
System.out.println("[algorithm=" + algorithm.name + "][instance=" + p.name + "][run=" + run + "][status=start]");
|
||||
VehicleRoutingAlgorithm vra = algorithm.factory.createAlgorithm(p.vrp);
|
||||
informCalculationStarts(p, algorithm.name, vra, run);
|
||||
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||
System.out.println("[algorithm=" + algorithm.name + "][instance=" + p.name + "][run=" + run + "][status=finished]");
|
||||
informCalculationsEnds(p, algorithm.name, vra, run, solutions);
|
||||
}
|
||||
|
||||
private void informCalculationStarts(BenchmarkInstance p, String name, VehicleRoutingAlgorithm vra, int run) {
|
||||
for (CalculationListener l : listeners) l.calculationStarts(p, name, vra, run);
|
||||
}
|
||||
|
||||
private void informCalculationsEnds(BenchmarkInstance p, String name, VehicleRoutingAlgorithm vra, int run,
|
||||
Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for (CalculationListener l : listeners) l.calculationEnds(p, name, vra, run, solutions);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2013 Stefan Schroeder
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.analysis.toolbox;
|
||||
|
|
@ -35,185 +35,185 @@ import java.util.concurrent.*;
|
|||
|
||||
|
||||
public class ConcurrentBenchmarker {
|
||||
|
||||
public static interface Cost {
|
||||
public double getCost(VehicleRoutingProblemSolution sol);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String algorithmConfig = null;
|
||||
|
||||
private List<BenchmarkInstance> benchmarkInstances = new ArrayList<BenchmarkInstance>();
|
||||
|
||||
private int runs = 1;
|
||||
|
||||
private Collection<BenchmarkWriter> writers = new ArrayList<BenchmarkWriter>();
|
||||
|
||||
private Collection<BenchmarkResult> results = new ArrayList<BenchmarkResult>();
|
||||
|
||||
private Cost cost = new Cost(){
|
||||
public static interface Cost {
|
||||
public double getCost(VehicleRoutingProblemSolution sol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCost(VehicleRoutingProblemSolution sol) {
|
||||
return sol.getCost();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private VehicleRoutingAlgorithmFactory algorithmFactory;
|
||||
|
||||
public void setCost(Cost cost){ this.cost = cost; }
|
||||
|
||||
public ConcurrentBenchmarker(String algorithmConfig) {
|
||||
super();
|
||||
this.algorithmConfig = algorithmConfig;
|
||||
private String algorithmConfig = null;
|
||||
|
||||
private List<BenchmarkInstance> benchmarkInstances = new ArrayList<BenchmarkInstance>();
|
||||
|
||||
private int runs = 1;
|
||||
|
||||
private Collection<BenchmarkWriter> writers = new ArrayList<BenchmarkWriter>();
|
||||
|
||||
private Collection<BenchmarkResult> results = new ArrayList<BenchmarkResult>();
|
||||
|
||||
private Cost cost = new Cost() {
|
||||
|
||||
@Override
|
||||
public double getCost(VehicleRoutingProblemSolution sol) {
|
||||
return sol.getCost();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private VehicleRoutingAlgorithmFactory algorithmFactory;
|
||||
|
||||
public void setCost(Cost cost) {
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
public ConcurrentBenchmarker(String algorithmConfig) {
|
||||
super();
|
||||
this.algorithmConfig = algorithmConfig;
|
||||
// LogManager.getRootLogger().setLevel(Level.ERROR);
|
||||
}
|
||||
|
||||
public ConcurrentBenchmarker(VehicleRoutingAlgorithmFactory algorithmFactory){
|
||||
this.algorithmFactory = algorithmFactory;
|
||||
}
|
||||
|
||||
public void addBenchmarkWriter(BenchmarkWriter writer){
|
||||
writers.add(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public void addInstance(String name, VehicleRoutingProblem problem){
|
||||
benchmarkInstances.add(new BenchmarkInstance(name,problem,null,null));
|
||||
}
|
||||
|
||||
public void addInstane(BenchmarkInstance instance){
|
||||
benchmarkInstances.add(instance);
|
||||
}
|
||||
|
||||
public void addAllInstances(Collection<BenchmarkInstance> instances){
|
||||
benchmarkInstances.addAll(instances);
|
||||
}
|
||||
|
||||
public void addInstance(String name, VehicleRoutingProblem problem, Double bestKnownResult, Double bestKnownVehicles){
|
||||
benchmarkInstances.add(new BenchmarkInstance(name,problem,bestKnownResult,bestKnownVehicles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets nuOfRuns with same algorithm on same instance.
|
||||
* <p>Default is 1
|
||||
*
|
||||
* @param runs
|
||||
*/
|
||||
public void setNuOfRuns(int runs){
|
||||
this.runs = runs;
|
||||
}
|
||||
|
||||
public void run(){
|
||||
System.out.println("start benchmarking [nuOfInstances=" + benchmarkInstances.size() + "][runsPerInstance=" + runs + "]");
|
||||
double startTime = System.currentTimeMillis();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()+1);
|
||||
List<Future<BenchmarkResult>> futures = new ArrayList<Future<BenchmarkResult>>();
|
||||
for(final BenchmarkInstance p : benchmarkInstances){
|
||||
|
||||
Future<BenchmarkResult> futureResult = executor.submit(new Callable<BenchmarkResult>(){
|
||||
public ConcurrentBenchmarker(VehicleRoutingAlgorithmFactory algorithmFactory) {
|
||||
this.algorithmFactory = algorithmFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BenchmarkResult call() throws Exception {
|
||||
return runAlgoAndGetResult(p);
|
||||
}
|
||||
public void addBenchmarkWriter(BenchmarkWriter writer) {
|
||||
writers.add(writer);
|
||||
}
|
||||
|
||||
});
|
||||
futures.add(futureResult);
|
||||
|
||||
}
|
||||
try {
|
||||
int count = 1;
|
||||
for(Future<BenchmarkResult> f : futures){
|
||||
BenchmarkResult r = f.get();
|
||||
print(r,count);
|
||||
results.add(f.get());
|
||||
count++;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
executor.shutdown();
|
||||
print(results);
|
||||
System.out.println("done [time="+(System.currentTimeMillis()-startTime)/1000 + "sec]");
|
||||
}
|
||||
public void addInstance(String name, VehicleRoutingProblem problem) {
|
||||
benchmarkInstances.add(new BenchmarkInstance(name, problem, null, null));
|
||||
}
|
||||
|
||||
private BenchmarkResult runAlgoAndGetResult(BenchmarkInstance p) {
|
||||
double[] vehicles = new double[runs];
|
||||
double[] results = new double[runs];
|
||||
double[] times = new double[runs];
|
||||
|
||||
for(int run=0;run<runs;run++){
|
||||
VehicleRoutingAlgorithm vra = createAlgorithm(p);
|
||||
StopWatch stopwatch = new StopWatch();
|
||||
vra.getAlgorithmListeners().addListener(stopwatch,Priority.HIGH);
|
||||
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||
VehicleRoutingProblemSolution best = Solutions.bestOf(solutions);
|
||||
vehicles[run] = best.getRoutes().size();
|
||||
results[run] = cost.getCost(best);
|
||||
times[run] = stopwatch.getCompTimeInSeconds();
|
||||
}
|
||||
|
||||
return new BenchmarkResult(p, runs, results, times, vehicles);
|
||||
}
|
||||
public void addInstane(BenchmarkInstance instance) {
|
||||
benchmarkInstances.add(instance);
|
||||
}
|
||||
|
||||
private VehicleRoutingAlgorithm createAlgorithm(BenchmarkInstance p) {
|
||||
if(algorithmConfig != null){
|
||||
return VehicleRoutingAlgorithms.readAndCreateAlgorithm(p.vrp, algorithmConfig);
|
||||
}
|
||||
else{
|
||||
return algorithmFactory.createAlgorithm(p.vrp);
|
||||
}
|
||||
|
||||
}
|
||||
public void addAllInstances(Collection<BenchmarkInstance> instances) {
|
||||
benchmarkInstances.addAll(instances);
|
||||
}
|
||||
|
||||
private void print(Collection<BenchmarkResult> results) {
|
||||
double sumTime=0.0;
|
||||
double sumResult=0.0;
|
||||
for(BenchmarkResult r : results){
|
||||
sumTime+=r.getTimesStats().getMean();
|
||||
sumResult+=r.getResultStats().getMean();
|
||||
public void addInstance(String name, VehicleRoutingProblem problem, Double bestKnownResult, Double bestKnownVehicles) {
|
||||
benchmarkInstances.add(new BenchmarkInstance(name, problem, bestKnownResult, bestKnownVehicles));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets nuOfRuns with same algorithm on same instance.
|
||||
* <p>Default is 1
|
||||
*
|
||||
* @param runs
|
||||
*/
|
||||
public void setNuOfRuns(int runs) {
|
||||
this.runs = runs;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
System.out.println("start benchmarking [nuOfInstances=" + benchmarkInstances.size() + "][runsPerInstance=" + runs + "]");
|
||||
double startTime = System.currentTimeMillis();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
|
||||
List<Future<BenchmarkResult>> futures = new ArrayList<Future<BenchmarkResult>>();
|
||||
for (final BenchmarkInstance p : benchmarkInstances) {
|
||||
|
||||
Future<BenchmarkResult> futureResult = executor.submit(new Callable<BenchmarkResult>() {
|
||||
|
||||
@Override
|
||||
public BenchmarkResult call() throws Exception {
|
||||
return runAlgoAndGetResult(p);
|
||||
}
|
||||
|
||||
});
|
||||
futures.add(futureResult);
|
||||
|
||||
}
|
||||
try {
|
||||
int count = 1;
|
||||
for (Future<BenchmarkResult> f : futures) {
|
||||
BenchmarkResult r = f.get();
|
||||
print(r, count);
|
||||
results.add(f.get());
|
||||
count++;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
executor.shutdown();
|
||||
print(results);
|
||||
System.out.println("done [time=" + (System.currentTimeMillis() - startTime) / 1000 + "sec]");
|
||||
}
|
||||
|
||||
private BenchmarkResult runAlgoAndGetResult(BenchmarkInstance p) {
|
||||
double[] vehicles = new double[runs];
|
||||
double[] results = new double[runs];
|
||||
double[] times = new double[runs];
|
||||
|
||||
for (int run = 0; run < runs; run++) {
|
||||
VehicleRoutingAlgorithm vra = createAlgorithm(p);
|
||||
StopWatch stopwatch = new StopWatch();
|
||||
vra.getAlgorithmListeners().addListener(stopwatch, Priority.HIGH);
|
||||
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||
VehicleRoutingProblemSolution best = Solutions.bestOf(solutions);
|
||||
vehicles[run] = best.getRoutes().size();
|
||||
results[run] = cost.getCost(best);
|
||||
times[run] = stopwatch.getCompTimeInSeconds();
|
||||
}
|
||||
|
||||
return new BenchmarkResult(p, runs, results, times, vehicles);
|
||||
}
|
||||
|
||||
private VehicleRoutingAlgorithm createAlgorithm(BenchmarkInstance p) {
|
||||
if (algorithmConfig != null) {
|
||||
return VehicleRoutingAlgorithms.readAndCreateAlgorithm(p.vrp, algorithmConfig);
|
||||
} else {
|
||||
return algorithmFactory.createAlgorithm(p.vrp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void print(Collection<BenchmarkResult> results) {
|
||||
double sumTime = 0.0;
|
||||
double sumResult = 0.0;
|
||||
for (BenchmarkResult r : results) {
|
||||
sumTime += r.getTimesStats().getMean();
|
||||
sumResult += r.getResultStats().getMean();
|
||||
// print(r);
|
||||
}
|
||||
System.out.println("[avgTime="+round(sumTime/(double)results.size(),2)+"][avgResult="+round(sumResult/(double)results.size(),2)+"]");
|
||||
for(BenchmarkWriter writer : writers){
|
||||
writer.write(results);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("[avgTime=" + round(sumTime / (double) results.size(), 2) + "][avgResult=" + round(sumResult / (double) results.size(), 2) + "]");
|
||||
for (BenchmarkWriter writer : writers) {
|
||||
writer.write(results);
|
||||
}
|
||||
}
|
||||
|
||||
private void print(BenchmarkResult r, int count) {
|
||||
Double avgDelta = null;
|
||||
Double bestDelta = null;
|
||||
Double worstDelta = null;
|
||||
if(r.instance.bestKnownResult != null){
|
||||
avgDelta = (r.getResultStats().getMean() / r.instance.bestKnownResult - 1) * 100;
|
||||
bestDelta = (r.getResultStats().getMin() / r.instance.bestKnownResult - 1) * 100;
|
||||
worstDelta = (r.getResultStats().getMax() / r.instance.bestKnownResult - 1) * 100;
|
||||
}
|
||||
System.out.println("("+count+"/"+benchmarkInstances.size() +")"+ "\t[instance="+r.instance.name+
|
||||
"][avgTime="+round(r.getTimesStats().getMean(),2)+"]" +
|
||||
"[Result=" + getString(r.getResultStats()) + "]" +
|
||||
"[Vehicles=" + getString(r.getVehicleStats()) + "]" +
|
||||
"[Delta[%]=" + getString(bestDelta,avgDelta,worstDelta) + "]");
|
||||
}
|
||||
|
||||
private String getString(Double bestDelta, Double avgDelta,Double worstDelta) {
|
||||
return "[best="+round(bestDelta,2)+"][avg="+round(avgDelta,2)+"][worst="+round(worstDelta,2)+"]";
|
||||
}
|
||||
private void print(BenchmarkResult r, int count) {
|
||||
Double avgDelta = null;
|
||||
Double bestDelta = null;
|
||||
Double worstDelta = null;
|
||||
if (r.instance.bestKnownResult != null) {
|
||||
avgDelta = (r.getResultStats().getMean() / r.instance.bestKnownResult - 1) * 100;
|
||||
bestDelta = (r.getResultStats().getMin() / r.instance.bestKnownResult - 1) * 100;
|
||||
worstDelta = (r.getResultStats().getMax() / r.instance.bestKnownResult - 1) * 100;
|
||||
}
|
||||
System.out.println("(" + count + "/" + benchmarkInstances.size() + ")" + "\t[instance=" + r.instance.name +
|
||||
"][avgTime=" + round(r.getTimesStats().getMean(), 2) + "]" +
|
||||
"[Result=" + getString(r.getResultStats()) + "]" +
|
||||
"[Vehicles=" + getString(r.getVehicleStats()) + "]" +
|
||||
"[Delta[%]=" + getString(bestDelta, avgDelta, worstDelta) + "]");
|
||||
}
|
||||
|
||||
private String getString(DescriptiveStatistics stats){
|
||||
return "[best="+round(stats.getMin(),2)+"][avg="+round(stats.getMean(),2)+"][worst="+round(stats.getMax(),2)+"][stdDev=" + round(stats.getStandardDeviation(),2)+"]";
|
||||
}
|
||||
private String getString(Double bestDelta, Double avgDelta, Double worstDelta) {
|
||||
return "[best=" + round(bestDelta, 2) + "][avg=" + round(avgDelta, 2) + "][worst=" + round(worstDelta, 2) + "]";
|
||||
}
|
||||
|
||||
private Double round(Double value, int i) {
|
||||
if(value==null) return null;
|
||||
long roundedVal = Math.round(value*Math.pow(10, i));
|
||||
return (double)roundedVal/(double)(Math.pow(10, i));
|
||||
}
|
||||
private String getString(DescriptiveStatistics stats) {
|
||||
return "[best=" + round(stats.getMin(), 2) + "][avg=" + round(stats.getMean(), 2) + "][worst=" + round(stats.getMax(), 2) + "][stdDev=" + round(stats.getStandardDeviation(), 2) + "]";
|
||||
}
|
||||
|
||||
private Double round(Double value, int i) {
|
||||
if (value == null) return null;
|
||||
long roundedVal = Math.round(value * Math.pow(10, i));
|
||||
return (double) roundedVal / (double) (Math.pow(10, i));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,55 +46,55 @@ public class GraphStreamViewer {
|
|||
public static class StyleSheets {
|
||||
|
||||
public static String BLUE_FOREST =
|
||||
"graph { fill-color: #141F2E; }" +
|
||||
"node {" +
|
||||
" size: 7px, 7px;" +
|
||||
" fill-color: #A0FFA0;" +
|
||||
" text-alignment: at-right;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #999;" +
|
||||
" stroke-width: 1.0;" +
|
||||
" text-font: couriernew;" +
|
||||
" text-offset: 2,-5;" +
|
||||
" text-size: 8;" +
|
||||
"}" +
|
||||
"node.pickup {" +
|
||||
" fill-color: #6CC644;" +
|
||||
"}" +
|
||||
"node.delivery {" +
|
||||
" fill-color: #f93;" +
|
||||
"}" +
|
||||
"node.pickupInRoute {" +
|
||||
" fill-color: #6CC644;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.deliveryInRoute {" +
|
||||
" fill-color: #f93;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.depot {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" shape: box;" +
|
||||
"}" +
|
||||
"node.removed {" +
|
||||
" fill-color: #FF8080;" +
|
||||
" size: 10px, 10px;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #CCF;" +
|
||||
" stroke-width: 2.0;" +
|
||||
" shadow-mode: gradient-radial;" +
|
||||
" shadow-width: 10px; shadow-color: #EEF, #000; shadow-offset: 0px;" +
|
||||
"}" +
|
||||
"graph { fill-color: #141F2E; }" +
|
||||
"node {" +
|
||||
" size: 7px, 7px;" +
|
||||
" fill-color: #A0FFA0;" +
|
||||
" text-alignment: at-right;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #999;" +
|
||||
" stroke-width: 1.0;" +
|
||||
" text-font: couriernew;" +
|
||||
" text-offset: 2,-5;" +
|
||||
" text-size: 8;" +
|
||||
"}" +
|
||||
"node.pickup {" +
|
||||
" fill-color: #6CC644;" +
|
||||
"}" +
|
||||
"node.delivery {" +
|
||||
" fill-color: #f93;" +
|
||||
"}" +
|
||||
"node.pickupInRoute {" +
|
||||
" fill-color: #6CC644;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.deliveryInRoute {" +
|
||||
" fill-color: #f93;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.depot {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" shape: box;" +
|
||||
"}" +
|
||||
"node.removed {" +
|
||||
" fill-color: #FF8080;" +
|
||||
" size: 10px, 10px;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #CCF;" +
|
||||
" stroke-width: 2.0;" +
|
||||
" shadow-mode: gradient-radial;" +
|
||||
" shadow-width: 10px; shadow-color: #EEF, #000; shadow-offset: 0px;" +
|
||||
"}" +
|
||||
|
||||
"edge {" +
|
||||
" fill-color: #D3D3D3;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" +
|
||||
"edge {" +
|
||||
" fill-color: #D3D3D3;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" +
|
||||
// "edge.inserted {" +
|
||||
// " fill-color: #A0FFA0;" +
|
||||
// " arrow-size: 6px,3px;" +
|
||||
|
|
@ -107,69 +107,68 @@ public class GraphStreamViewer {
|
|||
// " shadow-mode: gradient-radial;" +
|
||||
// " shadow-width: 10px; shadow-color: #EEF, #000; shadow-offset: 0px;" +
|
||||
// "}" +
|
||||
"edge.shipment {" +
|
||||
" fill-color: #999;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" ;
|
||||
|
||||
"edge.shipment {" +
|
||||
" fill-color: #999;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}";
|
||||
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static String SIMPLE_WHITE =
|
||||
"node {" +
|
||||
" size: 10px, 10px;" +
|
||||
" fill-color: #6CC644;" +
|
||||
" text-alignment: at-right;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #999;" +
|
||||
" stroke-width: 1.0;" +
|
||||
" text-font: couriernew;" +
|
||||
" text-offset: 2,-5;" +
|
||||
" text-size: 8;" +
|
||||
"}" +
|
||||
"node.pickup {" +
|
||||
" fill-color: #6CC644;" +
|
||||
"}" +
|
||||
"node.delivery {" +
|
||||
" fill-color: #f93;" +
|
||||
"}" +
|
||||
"node.pickupInRoute {" +
|
||||
" fill-color: #6CC644;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.deliveryInRoute {" +
|
||||
" fill-color: #f93;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.depot {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" shape: box;" +
|
||||
"}" +
|
||||
"node.removed {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node {" +
|
||||
" size: 10px, 10px;" +
|
||||
" fill-color: #6CC644;" +
|
||||
" text-alignment: at-right;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #999;" +
|
||||
" stroke-width: 1.0;" +
|
||||
" text-font: couriernew;" +
|
||||
" text-offset: 2,-5;" +
|
||||
" text-size: 8;" +
|
||||
"}" +
|
||||
"node.pickup {" +
|
||||
" fill-color: #6CC644;" +
|
||||
"}" +
|
||||
"node.delivery {" +
|
||||
" fill-color: #f93;" +
|
||||
"}" +
|
||||
"node.pickupInRoute {" +
|
||||
" fill-color: #6CC644;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.deliveryInRoute {" +
|
||||
" fill-color: #f93;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.depot {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" shape: box;" +
|
||||
"}" +
|
||||
"node.removed {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
|
||||
"edge {" +
|
||||
" fill-color: #333;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" +
|
||||
"edge.shipment {" +
|
||||
" fill-color: #999;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" ;
|
||||
"edge {" +
|
||||
" fill-color: #333;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" +
|
||||
"edge.shipment {" +
|
||||
" fill-color: #999;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}";
|
||||
|
||||
}
|
||||
|
||||
public static Graph createMultiGraph(String name, String style){
|
||||
public static Graph createMultiGraph(String name, String style) {
|
||||
Graph g = new MultiGraph(name);
|
||||
g.addAttribute("ui.quality");
|
||||
g.addAttribute("ui.antialias");
|
||||
|
|
@ -177,162 +176,162 @@ public class GraphStreamViewer {
|
|||
return g;
|
||||
}
|
||||
|
||||
public static ViewPanel createEmbeddedView(Graph graph, double scaling){
|
||||
Viewer viewer = new Viewer(graph,Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
|
||||
public static ViewPanel createEmbeddedView(Graph graph, double scaling) {
|
||||
Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
|
||||
ViewPanel view = viewer.addDefaultView(false);
|
||||
view.setPreferredSize(new Dimension((int) (698 * scaling), (int) (440 * scaling)));
|
||||
return view;
|
||||
}
|
||||
|
||||
public static String STYLESHEET =
|
||||
"node {" +
|
||||
" size: 10px, 10px;" +
|
||||
" fill-color: #6CC644;" +
|
||||
" text-alignment: at-right;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #999;" +
|
||||
" stroke-width: 1.0;" +
|
||||
" text-font: couriernew;" +
|
||||
" text-offset: 2,-5;" +
|
||||
" text-size: 8;" +
|
||||
"}" +
|
||||
"node.pickup {" +
|
||||
" fill-color: #6CC644;" +
|
||||
"}" +
|
||||
"node.delivery {" +
|
||||
" fill-color: #f93;" +
|
||||
"}" +
|
||||
"node.pickupInRoute {" +
|
||||
" fill-color: #6CC644;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.deliveryInRoute {" +
|
||||
" fill-color: #f93;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.depot {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" shape: box;" +
|
||||
"}" +
|
||||
"node.removed {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
|
||||
"edge {" +
|
||||
" fill-color: #333;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" +
|
||||
"edge.shipment {" +
|
||||
" fill-color: #999;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" ;
|
||||
public static String STYLESHEET =
|
||||
"node {" +
|
||||
" size: 10px, 10px;" +
|
||||
" fill-color: #6CC644;" +
|
||||
" text-alignment: at-right;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #999;" +
|
||||
" stroke-width: 1.0;" +
|
||||
" text-font: couriernew;" +
|
||||
" text-offset: 2,-5;" +
|
||||
" text-size: 8;" +
|
||||
"}" +
|
||||
"node.pickup {" +
|
||||
" fill-color: #6CC644;" +
|
||||
"}" +
|
||||
"node.delivery {" +
|
||||
" fill-color: #f93;" +
|
||||
"}" +
|
||||
"node.pickupInRoute {" +
|
||||
" fill-color: #6CC644;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.deliveryInRoute {" +
|
||||
" fill-color: #f93;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.depot {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" shape: box;" +
|
||||
"}" +
|
||||
"node.removed {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
|
||||
public static enum Label {
|
||||
NO_LABEL, ID, JOB_NAME, ARRIVAL_TIME, DEPARTURE_TIME, ACTIVITY
|
||||
}
|
||||
|
||||
private static class Center {
|
||||
final double x;
|
||||
final double y;
|
||||
|
||||
public Center(double x, double y) {
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}
|
||||
"edge {" +
|
||||
" fill-color: #333;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" +
|
||||
"edge.shipment {" +
|
||||
" fill-color: #999;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}";
|
||||
|
||||
private Label label = Label.NO_LABEL;
|
||||
public static enum Label {
|
||||
NO_LABEL, ID, JOB_NAME, ARRIVAL_TIME, DEPARTURE_TIME, ACTIVITY
|
||||
}
|
||||
|
||||
private long renderDelay_in_ms = 0;
|
||||
private static class Center {
|
||||
final double x;
|
||||
final double y;
|
||||
|
||||
private boolean renderShipments = false;
|
||||
|
||||
private Center center;
|
||||
public Center(double x, double y) {
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
}
|
||||
|
||||
private VehicleRoutingProblemSolution solution;
|
||||
private Label label = Label.NO_LABEL;
|
||||
|
||||
private double zoomFactor;
|
||||
|
||||
private double scaling = 1.0;
|
||||
private long renderDelay_in_ms = 0;
|
||||
|
||||
private boolean renderShipments = false;
|
||||
|
||||
private Center center;
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private VehicleRoutingProblemSolution solution;
|
||||
|
||||
private double zoomFactor;
|
||||
|
||||
private double scaling = 1.0;
|
||||
|
||||
|
||||
public GraphStreamViewer(VehicleRoutingProblem vrp) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
}
|
||||
public GraphStreamViewer(VehicleRoutingProblem vrp) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
}
|
||||
|
||||
public GraphStreamViewer(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.solution = solution;
|
||||
}
|
||||
public GraphStreamViewer(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.solution = solution;
|
||||
}
|
||||
|
||||
public GraphStreamViewer labelWith(Label label){
|
||||
this.label=label;
|
||||
return this;
|
||||
}
|
||||
public GraphStreamViewer labelWith(Label label) {
|
||||
this.label = label;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GraphStreamViewer setRenderDelay(long ms){
|
||||
this.renderDelay_in_ms=ms;
|
||||
return this;
|
||||
}
|
||||
public GraphStreamViewer setRenderDelay(long ms) {
|
||||
this.renderDelay_in_ms = ms;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public GraphStreamViewer setEnableAutoLayout(boolean enableAutoLayout) {
|
||||
return this;
|
||||
}
|
||||
public GraphStreamViewer setEnableAutoLayout(boolean enableAutoLayout) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public GraphStreamViewer setRenderShipments(boolean renderShipments){
|
||||
this.renderShipments = renderShipments;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GraphStreamViewer setGraphStreamFrameScalingFactor(double factor){
|
||||
this.scaling=factor;
|
||||
return this;
|
||||
}
|
||||
public GraphStreamViewer setRenderShipments(boolean renderShipments) {
|
||||
this.renderShipments = renderShipments;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the camera-view. Center describes the center-focus of the camera and zoomFactor its
|
||||
* zoomFactor.
|
||||
*
|
||||
* <p>a zoomFactor < 1 zooms in and > 1 out.
|
||||
*
|
||||
* @param centerX x coordinate of center
|
||||
* @param centerY y coordinate of center
|
||||
* @param zoomFactor zoom factor
|
||||
* @return the viewer
|
||||
*/
|
||||
public GraphStreamViewer setCameraView(double centerX, double centerY, double zoomFactor){
|
||||
center = new Center(centerX,centerY);
|
||||
this.zoomFactor = zoomFactor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void display(){
|
||||
System.setProperty("org.graphstream.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer");
|
||||
public GraphStreamViewer setGraphStreamFrameScalingFactor(double factor) {
|
||||
this.scaling = factor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the camera-view. Center describes the center-focus of the camera and zoomFactor its
|
||||
* zoomFactor.
|
||||
* <p/>
|
||||
* <p>a zoomFactor < 1 zooms in and > 1 out.
|
||||
*
|
||||
* @param centerX x coordinate of center
|
||||
* @param centerY y coordinate of center
|
||||
* @param zoomFactor zoom factor
|
||||
* @return the viewer
|
||||
*/
|
||||
public GraphStreamViewer setCameraView(double centerX, double centerY, double zoomFactor) {
|
||||
center = new Center(centerX, centerY);
|
||||
this.zoomFactor = zoomFactor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void display() {
|
||||
System.setProperty("org.graphstream.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer");
|
||||
|
||||
Graph g = createMultiGraph("g");
|
||||
|
||||
ViewPanel view = createEmbeddedView(g,scaling);
|
||||
ViewPanel view = createEmbeddedView(g, scaling);
|
||||
|
||||
createJFrame(view,scaling);
|
||||
createJFrame(view, scaling);
|
||||
|
||||
render(g, view);
|
||||
}
|
||||
}
|
||||
|
||||
private JFrame createJFrame(ViewPanel view, double scaling) {
|
||||
JFrame jframe = new JFrame();
|
||||
|
|
@ -345,11 +344,11 @@ public class GraphStreamViewer {
|
|||
|
||||
|
||||
JPanel graphStreamPanel = new JPanel();
|
||||
graphStreamPanel.setPreferredSize(new Dimension((int)(800*scaling),(int)(460*scaling)));
|
||||
graphStreamPanel.setPreferredSize(new Dimension((int) (800 * scaling), (int) (460 * scaling)));
|
||||
graphStreamPanel.setBackground(Color.WHITE);
|
||||
|
||||
JPanel graphStreamBackPanel = new JPanel();
|
||||
graphStreamBackPanel.setPreferredSize(new Dimension((int)(700*scaling),(int)(450*scaling)));
|
||||
graphStreamBackPanel.setPreferredSize(new Dimension((int) (700 * scaling), (int) (450 * scaling)));
|
||||
graphStreamBackPanel.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
|
||||
graphStreamBackPanel.setBackground(Color.WHITE);
|
||||
|
||||
|
|
@ -365,7 +364,7 @@ public class GraphStreamViewer {
|
|||
jframe.add(basicPanel);
|
||||
|
||||
//conf jframe
|
||||
jframe.setSize((int)(800*scaling),(int)(580*scaling));
|
||||
jframe.setSize((int) (800 * scaling), (int) (580 * scaling));
|
||||
jframe.setLocationRelativeTo(null);
|
||||
jframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
jframe.setVisible(true);
|
||||
|
|
@ -375,40 +374,39 @@ public class GraphStreamViewer {
|
|||
}
|
||||
|
||||
private Graph createMultiGraph(String name) {
|
||||
return GraphStreamViewer.createMultiGraph(name,STYLESHEET);
|
||||
return GraphStreamViewer.createMultiGraph(name, STYLESHEET);
|
||||
}
|
||||
|
||||
private void render(Graph g, ViewPanel view) {
|
||||
if(center != null){
|
||||
view.resizeFrame(view.getWidth(), view.getHeight());
|
||||
if (center != null) {
|
||||
view.resizeFrame(view.getWidth(), view.getHeight());
|
||||
alignCamera(view);
|
||||
}
|
||||
}
|
||||
|
||||
for(Vehicle vehicle : vrp.getVehicles()){
|
||||
renderVehicle(g,vehicle,label);
|
||||
sleep(renderDelay_in_ms);
|
||||
}
|
||||
for (Vehicle vehicle : vrp.getVehicles()) {
|
||||
renderVehicle(g, vehicle, label);
|
||||
sleep(renderDelay_in_ms);
|
||||
}
|
||||
|
||||
for(Job j : vrp.getJobs().values()){
|
||||
if(j instanceof Service){
|
||||
renderService(g,(Service)j,label);
|
||||
}
|
||||
else if(j instanceof Shipment){
|
||||
renderShipment(g,(Shipment)j,label,renderShipments);
|
||||
}
|
||||
sleep(renderDelay_in_ms);
|
||||
}
|
||||
for (Job j : vrp.getJobs().values()) {
|
||||
if (j instanceof Service) {
|
||||
renderService(g, (Service) j, label);
|
||||
} else if (j instanceof Shipment) {
|
||||
renderShipment(g, (Shipment) j, label, renderShipments);
|
||||
}
|
||||
sleep(renderDelay_in_ms);
|
||||
}
|
||||
|
||||
if(solution != null){
|
||||
int routeId = 1;
|
||||
for(VehicleRoute route : solution.getRoutes()){
|
||||
renderRoute(g,route,routeId,renderDelay_in_ms,label);
|
||||
sleep(renderDelay_in_ms);
|
||||
routeId++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (solution != null) {
|
||||
int routeId = 1;
|
||||
for (VehicleRoute route : solution.getRoutes()) {
|
||||
renderRoute(g, route, routeId, renderDelay_in_ms, label);
|
||||
sleep(renderDelay_in_ms);
|
||||
routeId++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void alignCamera(View view) {
|
||||
view.getCamera().setViewCenter(center.x, center.y, 0);
|
||||
|
|
@ -416,204 +414,202 @@ public class GraphStreamViewer {
|
|||
}
|
||||
|
||||
private JLabel createEmptyLabel() {
|
||||
JLabel emptyLabel1 = new JLabel();
|
||||
emptyLabel1.setPreferredSize(new Dimension((int)(40*scaling),(int)(25*scaling)));
|
||||
return emptyLabel1;
|
||||
}
|
||||
JLabel emptyLabel1 = new JLabel();
|
||||
emptyLabel1.setPreferredSize(new Dimension((int) (40 * scaling), (int) (25 * scaling)));
|
||||
return emptyLabel1;
|
||||
}
|
||||
|
||||
private JPanel createResultPanel() {
|
||||
int width = 800;
|
||||
int height = 50;
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.setPreferredSize(new Dimension((int)(width*scaling),(int)(height*scaling)));
|
||||
private JPanel createResultPanel() {
|
||||
int width = 800;
|
||||
int height = 50;
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.setPreferredSize(new Dimension((int) (width * scaling), (int) (height * scaling)));
|
||||
panel.setBackground(Color.WHITE);
|
||||
|
||||
|
||||
JPanel subpanel = new JPanel();
|
||||
subpanel.setLayout(new FlowLayout());
|
||||
subpanel.setPreferredSize(new Dimension((int)(700*scaling),(int)(40*scaling)));
|
||||
subpanel.setPreferredSize(new Dimension((int) (700 * scaling), (int) (40 * scaling)));
|
||||
subpanel.setBackground(Color.WHITE);
|
||||
subpanel.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY,1));
|
||||
|
||||
subpanel.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1));
|
||||
|
||||
Font font = Font.decode("couriernew");
|
||||
|
||||
JLabel jobs = new JLabel("jobs");
|
||||
jobs.setFont(font);
|
||||
jobs.setPreferredSize(new Dimension((int)(40*scaling),(int)(25*scaling)));
|
||||
jobs.setPreferredSize(new Dimension((int) (40 * scaling), (int) (25 * scaling)));
|
||||
|
||||
int noJobs = 0;
|
||||
if(this.vrp != null) noJobs = this.vrp.getJobs().values().size();
|
||||
if (this.vrp != null) noJobs = this.vrp.getJobs().values().size();
|
||||
|
||||
JFormattedTextField nJobs = new JFormattedTextField(noJobs);
|
||||
nJobs.setFont(font);
|
||||
nJobs.setEditable(false);
|
||||
nJobs.setBorder(BorderFactory.createEmptyBorder());
|
||||
nJobs.setBackground(new Color(230,230,230));
|
||||
|
||||
nJobs.setBackground(new Color(230, 230, 230));
|
||||
|
||||
JLabel costs = new JLabel("costs");
|
||||
costs.setFont(font);
|
||||
costs.setPreferredSize(new Dimension((int)(40*scaling),(int)(25*scaling)));
|
||||
costs.setPreferredSize(new Dimension((int) (40 * scaling), (int) (25 * scaling)));
|
||||
|
||||
JFormattedTextField costsVal = new JFormattedTextField(getSolutionCosts());
|
||||
costsVal.setFont(font);
|
||||
costsVal.setEditable(false);
|
||||
costsVal.setBorder(BorderFactory.createEmptyBorder());
|
||||
costsVal.setBackground(new Color(230,230,230));
|
||||
|
||||
costsVal.setBackground(new Color(230, 230, 230));
|
||||
|
||||
JLabel vehicles = new JLabel("routes");
|
||||
vehicles.setFont(font);
|
||||
vehicles.setPreferredSize(new Dimension((int)(40*scaling),(int)(25*scaling)));
|
||||
vehicles.setPreferredSize(new Dimension((int) (40 * scaling), (int) (25 * scaling)));
|
||||
// vehicles.setForeground(Color.DARK_GRAY);
|
||||
|
||||
|
||||
JFormattedTextField vehVal = new JFormattedTextField(getNoRoutes());
|
||||
vehVal.setFont(font);
|
||||
vehVal.setEditable(false);
|
||||
vehVal.setBorder(BorderFactory.createEmptyBorder());
|
||||
// vehVal.setForeground(Color.DARK_GRAY);
|
||||
vehVal.setBackground(new Color(230,230,230));
|
||||
|
||||
vehVal.setBackground(new Color(230, 230, 230));
|
||||
|
||||
//platzhalter
|
||||
JLabel placeholder1 = new JLabel();
|
||||
placeholder1.setPreferredSize(new Dimension((int)(60*scaling),(int)(25*scaling)));
|
||||
|
||||
placeholder1.setPreferredSize(new Dimension((int) (60 * scaling), (int) (25 * scaling)));
|
||||
|
||||
JLabel emptyLabel1 = createEmptyLabel();
|
||||
|
||||
|
||||
subpanel.add(jobs);
|
||||
subpanel.add(nJobs);
|
||||
|
||||
|
||||
subpanel.add(emptyLabel1);
|
||||
|
||||
|
||||
subpanel.add(costs);
|
||||
subpanel.add(costsVal);
|
||||
|
||||
JLabel emptyLabel2 = createEmptyLabel();
|
||||
subpanel.add(emptyLabel2);
|
||||
|
||||
|
||||
subpanel.add(vehicles);
|
||||
subpanel.add(vehVal);
|
||||
|
||||
panel.add(subpanel);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private Integer getNoRoutes() {
|
||||
if(solution!=null) return solution.getRoutes().size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private Double getSolutionCosts() {
|
||||
if(solution!=null) return solution.getCost();
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private void renderShipment(Graph g, Shipment shipment, Label label, boolean renderShipments) {
|
||||
|
||||
Node n1 = g.addNode(makeId(shipment.getId(),shipment.getPickupLocation().getId()));
|
||||
if(label.equals(Label.ID)) n1.addAttribute("ui.label", shipment.getId());
|
||||
n1.addAttribute("x", shipment.getPickupLocation().getCoordinate().getX());
|
||||
n1.addAttribute("y", shipment.getPickupLocation().getCoordinate().getY());
|
||||
n1.setAttribute("ui.class", "pickup");
|
||||
|
||||
Node n2 = g.addNode(makeId(shipment.getId(),shipment.getDeliveryLocation().getId()));
|
||||
if(label.equals(Label.ID)) n2.addAttribute("ui.label", shipment.getId());
|
||||
n2.addAttribute("x", shipment.getDeliveryLocation().getCoordinate().getX());
|
||||
n2.addAttribute("y", shipment.getDeliveryLocation().getCoordinate().getY());
|
||||
n2.setAttribute("ui.class", "delivery");
|
||||
|
||||
if(renderShipments){
|
||||
Edge s = g.addEdge(shipment.getId(), makeId(shipment.getId(),shipment.getPickupLocation().getId()),
|
||||
makeId(shipment.getId(),shipment.getDeliveryLocation().getId()), true);
|
||||
s.addAttribute("ui.class", "shipment");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sleep(long renderDelay_in_ms2) {
|
||||
try {
|
||||
Thread.sleep(renderDelay_in_ms2);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void renderService(Graph g, Service service, Label label) {
|
||||
Node n = g.addNode(makeId(service.getId(),service.getLocation().getId()));
|
||||
if(label.equals(Label.ID)) n.addAttribute("ui.label", service.getId());
|
||||
n.addAttribute("x", service.getLocation().getCoordinate().getX());
|
||||
n.addAttribute("y", service.getLocation().getCoordinate().getY());
|
||||
if(service.getType().equals("pickup")) n.setAttribute("ui.class", "pickup");
|
||||
if(service.getType().equals("delivery")) n.setAttribute("ui.class", "delivery");
|
||||
}
|
||||
private Integer getNoRoutes() {
|
||||
if (solution != null) return solution.getRoutes().size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private String makeId(String id, String locationId) {
|
||||
return id + "_" + locationId;
|
||||
}
|
||||
private Double getSolutionCosts() {
|
||||
if (solution != null) return solution.getCost();
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private void renderVehicle(Graph g, Vehicle vehicle, Label label) {
|
||||
String nodeId = makeId(vehicle.getId(),vehicle.getStartLocation().getId());
|
||||
private void renderShipment(Graph g, Shipment shipment, Label label, boolean renderShipments) {
|
||||
|
||||
Node n1 = g.addNode(makeId(shipment.getId(), shipment.getPickupLocation().getId()));
|
||||
if (label.equals(Label.ID)) n1.addAttribute("ui.label", shipment.getId());
|
||||
n1.addAttribute("x", shipment.getPickupLocation().getCoordinate().getX());
|
||||
n1.addAttribute("y", shipment.getPickupLocation().getCoordinate().getY());
|
||||
n1.setAttribute("ui.class", "pickup");
|
||||
|
||||
Node n2 = g.addNode(makeId(shipment.getId(), shipment.getDeliveryLocation().getId()));
|
||||
if (label.equals(Label.ID)) n2.addAttribute("ui.label", shipment.getId());
|
||||
n2.addAttribute("x", shipment.getDeliveryLocation().getCoordinate().getX());
|
||||
n2.addAttribute("y", shipment.getDeliveryLocation().getCoordinate().getY());
|
||||
n2.setAttribute("ui.class", "delivery");
|
||||
|
||||
if (renderShipments) {
|
||||
Edge s = g.addEdge(shipment.getId(), makeId(shipment.getId(), shipment.getPickupLocation().getId()),
|
||||
makeId(shipment.getId(), shipment.getDeliveryLocation().getId()), true);
|
||||
s.addAttribute("ui.class", "shipment");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sleep(long renderDelay_in_ms2) {
|
||||
try {
|
||||
Thread.sleep(renderDelay_in_ms2);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void renderService(Graph g, Service service, Label label) {
|
||||
Node n = g.addNode(makeId(service.getId(), service.getLocation().getId()));
|
||||
if (label.equals(Label.ID)) n.addAttribute("ui.label", service.getId());
|
||||
n.addAttribute("x", service.getLocation().getCoordinate().getX());
|
||||
n.addAttribute("y", service.getLocation().getCoordinate().getY());
|
||||
if (service.getType().equals("pickup")) n.setAttribute("ui.class", "pickup");
|
||||
if (service.getType().equals("delivery")) n.setAttribute("ui.class", "delivery");
|
||||
}
|
||||
|
||||
private String makeId(String id, String locationId) {
|
||||
return id + "_" + locationId;
|
||||
}
|
||||
|
||||
private void renderVehicle(Graph g, Vehicle vehicle, Label label) {
|
||||
String nodeId = makeId(vehicle.getId(), vehicle.getStartLocation().getId());
|
||||
Node vehicleStart = g.addNode(nodeId);
|
||||
if(label.equals(Label.ID)) vehicleStart.addAttribute("ui.label", "depot");
|
||||
if (label.equals(Label.ID)) vehicleStart.addAttribute("ui.label", "depot");
|
||||
// if(label.equals(Label.ACTIVITY)) n.addAttribute("ui.label", "start");
|
||||
vehicleStart.addAttribute("x", vehicle.getStartLocation().getCoordinate().getX());
|
||||
vehicleStart.addAttribute("y", vehicle.getStartLocation().getCoordinate().getY());
|
||||
vehicleStart.setAttribute("ui.class", "depot");
|
||||
|
||||
if(!vehicle.getStartLocation().getId().equals(vehicle.getEndLocation().getId())){
|
||||
Node vehicleEnd = g.addNode(makeId(vehicle.getId(),vehicle.getEndLocation().getId()));
|
||||
if(label.equals(Label.ID)) vehicleEnd.addAttribute("ui.label", "depot");
|
||||
vehicleEnd.addAttribute("x", vehicle.getEndLocation().getCoordinate().getX());
|
||||
vehicleEnd.addAttribute("y", vehicle.getEndLocation().getCoordinate().getY());
|
||||
vehicleEnd.setAttribute("ui.class", "depot");
|
||||
|
||||
}
|
||||
}
|
||||
vehicleStart.addAttribute("x", vehicle.getStartLocation().getCoordinate().getX());
|
||||
vehicleStart.addAttribute("y", vehicle.getStartLocation().getCoordinate().getY());
|
||||
vehicleStart.setAttribute("ui.class", "depot");
|
||||
|
||||
private void renderRoute(Graph g, VehicleRoute route, int routeId, long renderDelay_in_ms, Label label) {
|
||||
int vehicle_edgeId = 1;
|
||||
String prevIdentifier = makeId(route.getVehicle().getId(),route.getVehicle().getStartLocation().getId());
|
||||
if(label.equals(Label.ACTIVITY) || label.equals(Label.JOB_NAME)){
|
||||
Node n = g.getNode(prevIdentifier);
|
||||
n.addAttribute("ui.label", "start");
|
||||
}
|
||||
for(TourActivity act : route.getActivities()){
|
||||
if (!vehicle.getStartLocation().getId().equals(vehicle.getEndLocation().getId())) {
|
||||
Node vehicleEnd = g.addNode(makeId(vehicle.getId(), vehicle.getEndLocation().getId()));
|
||||
if (label.equals(Label.ID)) vehicleEnd.addAttribute("ui.label", "depot");
|
||||
vehicleEnd.addAttribute("x", vehicle.getEndLocation().getCoordinate().getX());
|
||||
vehicleEnd.addAttribute("y", vehicle.getEndLocation().getCoordinate().getY());
|
||||
vehicleEnd.setAttribute("ui.class", "depot");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void renderRoute(Graph g, VehicleRoute route, int routeId, long renderDelay_in_ms, Label label) {
|
||||
int vehicle_edgeId = 1;
|
||||
String prevIdentifier = makeId(route.getVehicle().getId(), route.getVehicle().getStartLocation().getId());
|
||||
if (label.equals(Label.ACTIVITY) || label.equals(Label.JOB_NAME)) {
|
||||
Node n = g.getNode(prevIdentifier);
|
||||
n.addAttribute("ui.label", "start");
|
||||
}
|
||||
for (TourActivity act : route.getActivities()) {
|
||||
Job job = ((JobActivity) act).getJob();
|
||||
String currIdentifier = makeId(job.getId(),act.getLocation().getId());
|
||||
if(label.equals(Label.ACTIVITY)){
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", act.getName());
|
||||
}
|
||||
else if(label.equals(Label.JOB_NAME)){
|
||||
String currIdentifier = makeId(job.getId(), act.getLocation().getId());
|
||||
if (label.equals(Label.ACTIVITY)) {
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", act.getName());
|
||||
} else if (label.equals(Label.JOB_NAME)) {
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", job.getName());
|
||||
}
|
||||
else if(label.equals(Label.ARRIVAL_TIME)){
|
||||
} else if (label.equals(Label.ARRIVAL_TIME)) {
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", Time.parseSecondsToTime(act.getArrTime()));
|
||||
}
|
||||
else if(label.equals(Label.DEPARTURE_TIME)){
|
||||
} else if (label.equals(Label.DEPARTURE_TIME)) {
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", Time.parseSecondsToTime(act.getEndTime()));
|
||||
}
|
||||
g.addEdge(makeEdgeId(routeId,vehicle_edgeId), prevIdentifier, currIdentifier, true);
|
||||
if(act instanceof PickupActivity) g.getNode(currIdentifier).addAttribute("ui.class", "pickupInRoute");
|
||||
else if (act instanceof DeliveryActivity) g.getNode(currIdentifier).addAttribute("ui.class", "deliveryInRoute");
|
||||
prevIdentifier = currIdentifier;
|
||||
vehicle_edgeId++;
|
||||
sleep(renderDelay_in_ms);
|
||||
}
|
||||
if(route.getVehicle().isReturnToDepot()){
|
||||
String lastIdentifier = makeId(route.getVehicle().getId(),route.getVehicle().getEndLocation().getId());
|
||||
g.addEdge(makeEdgeId(routeId,vehicle_edgeId), prevIdentifier, lastIdentifier, true);
|
||||
}
|
||||
}
|
||||
g.addEdge(makeEdgeId(routeId, vehicle_edgeId), prevIdentifier, currIdentifier, true);
|
||||
if (act instanceof PickupActivity) g.getNode(currIdentifier).addAttribute("ui.class", "pickupInRoute");
|
||||
else if (act instanceof DeliveryActivity)
|
||||
g.getNode(currIdentifier).addAttribute("ui.class", "deliveryInRoute");
|
||||
prevIdentifier = currIdentifier;
|
||||
vehicle_edgeId++;
|
||||
sleep(renderDelay_in_ms);
|
||||
}
|
||||
if (route.getVehicle().isReturnToDepot()) {
|
||||
String lastIdentifier = makeId(route.getVehicle().getId(), route.getVehicle().getEndLocation().getId());
|
||||
g.addEdge(makeEdgeId(routeId, vehicle_edgeId), prevIdentifier, lastIdentifier, true);
|
||||
}
|
||||
}
|
||||
|
||||
private String makeEdgeId(int routeId, int vehicle_edgeId) {
|
||||
return Integer.valueOf(routeId).toString() + "." + Integer.valueOf(vehicle_edgeId).toString();
|
||||
}
|
||||
private String makeEdgeId(int routeId, int vehicle_edgeId) {
|
||||
return Integer.valueOf(routeId).toString() + "." + Integer.valueOf(vehicle_edgeId).toString();
|
||||
}
|
||||
|
||||
// public void saveAsPNG(String filename){
|
||||
//
|
||||
// }
|
||||
// public void saveAsPNG(String filename){
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 Stefan Schroeder.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
package jsprit.analysis.toolbox;
|
||||
|
||||
class NoLocationFoundException extends Exception{
|
||||
class NoLocationFoundException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2013 Stefan Schroeder
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.analysis.toolbox;
|
||||
|
|
@ -27,51 +27,51 @@ import org.apache.logging.log4j.Logger;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
public class StopWatch implements AlgorithmStartsListener, AlgorithmEndsListener{
|
||||
|
||||
private static Logger log = LogManager.getLogger(StopWatch.class);
|
||||
|
||||
private double ran;
|
||||
|
||||
private double startTime;
|
||||
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
reset();
|
||||
start();
|
||||
}
|
||||
|
||||
public double getCompTimeInSeconds(){
|
||||
return (ran)/1000.0;
|
||||
}
|
||||
public class StopWatch implements AlgorithmStartsListener, AlgorithmEndsListener {
|
||||
|
||||
@Override
|
||||
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
stop();
|
||||
log.info("computation time [in sec]: " + getCompTimeInSeconds());
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
ran += System.currentTimeMillis() - startTime;
|
||||
}
|
||||
|
||||
public void start(){
|
||||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
startTime = 0;
|
||||
ran = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "stopWatch: " + getCompTimeInSeconds() + " sec";
|
||||
}
|
||||
private static Logger log = LogManager.getLogger(StopWatch.class);
|
||||
|
||||
private double ran;
|
||||
|
||||
private double startTime;
|
||||
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
reset();
|
||||
start();
|
||||
}
|
||||
|
||||
public double getCompTimeInSeconds() {
|
||||
return (ran) / 1000.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
stop();
|
||||
log.info("computation time [in sec]: {}", getCompTimeInSeconds());
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
ran += System.currentTimeMillis() - startTime;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
startTime = 0;
|
||||
ran = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "stopWatch: " + getCompTimeInSeconds() + " sec";
|
||||
}
|
||||
|
||||
public double getCurrTimeInSeconds() {
|
||||
return (System.currentTimeMillis() - startTime) / 1000.0;
|
||||
}
|
||||
|
||||
public double getCurrTimeInSeconds() {
|
||||
return (System.currentTimeMillis()-startTime)/1000.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 Stefan Schroeder.
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
|
@ -32,82 +32,80 @@ import java.io.IOException;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
*/
|
||||
public class XYLineChartBuilder {
|
||||
|
||||
/**
|
||||
* Helper that just saves the chart as specified png-file. The width of the image is 1000 and height 600.
|
||||
*
|
||||
* @param chart
|
||||
* @param pngFilename
|
||||
*/
|
||||
public static void saveChartAsPNG(JFreeChart chart, String pngFilename){
|
||||
try {
|
||||
ChartUtilities.saveChartAsPNG(new File(pngFilename), chart, 1000, 600);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of the builder.
|
||||
*
|
||||
* @param chartTitle appears on top of the XYLineChart
|
||||
* @param xDomainName appears below the xAxis
|
||||
* @param yDomainName appears beside the yAxis
|
||||
*
|
||||
* @return the builder
|
||||
*/
|
||||
public static XYLineChartBuilder newInstance(String chartTitle, String xDomainName, String yDomainName){
|
||||
return new XYLineChartBuilder(chartTitle, xDomainName, yDomainName);
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<String,XYSeries> seriesMap = new ConcurrentHashMap<String, XYSeries>();
|
||||
|
||||
private final String xDomain;
|
||||
|
||||
private final String yDomain;
|
||||
|
||||
private final String chartName;
|
||||
|
||||
private XYLineChartBuilder(String chartName, String xDomainName, String yDomainName) {
|
||||
this.xDomain=xDomainName;
|
||||
this.yDomain=yDomainName;
|
||||
this.chartName=chartName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds data to the according series (i.e. XYLine).
|
||||
*
|
||||
* @param seriesName
|
||||
* @param xVal
|
||||
* @param yVal
|
||||
*/
|
||||
public void addData(String seriesName, double xVal, double yVal){
|
||||
if(!seriesMap.containsKey(seriesName)){
|
||||
seriesMap.put(seriesName, new XYSeries(seriesName,true,true));
|
||||
}
|
||||
seriesMap.get(seriesName).add(xVal, yVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns JFreeChart.
|
||||
* @return
|
||||
*/
|
||||
public JFreeChart build(){
|
||||
XYSeriesCollection collection = new XYSeriesCollection();
|
||||
for(XYSeries s : seriesMap.values()){
|
||||
collection.addSeries(s);
|
||||
}
|
||||
JFreeChart chart = ChartFactory.createXYLineChart(chartName, xDomain, yDomain, collection, PlotOrientation.VERTICAL, true, true, false);
|
||||
XYPlot plot = chart.getXYPlot();
|
||||
plot.setBackgroundPaint(Color.WHITE);
|
||||
plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
|
||||
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
|
||||
return chart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that just saves the chart as specified png-file. The width of the image is 1000 and height 600.
|
||||
*
|
||||
* @param chart
|
||||
* @param pngFilename
|
||||
*/
|
||||
public static void saveChartAsPNG(JFreeChart chart, String pngFilename) {
|
||||
try {
|
||||
ChartUtilities.saveChartAsPNG(new File(pngFilename), chart, 1000, 600);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of the builder.
|
||||
*
|
||||
* @param chartTitle appears on top of the XYLineChart
|
||||
* @param xDomainName appears below the xAxis
|
||||
* @param yDomainName appears beside the yAxis
|
||||
* @return the builder
|
||||
*/
|
||||
public static XYLineChartBuilder newInstance(String chartTitle, String xDomainName, String yDomainName) {
|
||||
return new XYLineChartBuilder(chartTitle, xDomainName, yDomainName);
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<String, XYSeries> seriesMap = new ConcurrentHashMap<String, XYSeries>();
|
||||
|
||||
private final String xDomain;
|
||||
|
||||
private final String yDomain;
|
||||
|
||||
private final String chartName;
|
||||
|
||||
private XYLineChartBuilder(String chartName, String xDomainName, String yDomainName) {
|
||||
this.xDomain = xDomainName;
|
||||
this.yDomain = yDomainName;
|
||||
this.chartName = chartName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds data to the according series (i.e. XYLine).
|
||||
*
|
||||
* @param seriesName
|
||||
* @param xVal
|
||||
* @param yVal
|
||||
*/
|
||||
public void addData(String seriesName, double xVal, double yVal) {
|
||||
if (!seriesMap.containsKey(seriesName)) {
|
||||
seriesMap.put(seriesName, new XYSeries(seriesName, true, true));
|
||||
}
|
||||
seriesMap.get(seriesName).add(xVal, yVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns JFreeChart.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public JFreeChart build() {
|
||||
XYSeriesCollection collection = new XYSeriesCollection();
|
||||
for (XYSeries s : seriesMap.values()) {
|
||||
collection.addSeries(s);
|
||||
}
|
||||
JFreeChart chart = ChartFactory.createXYLineChart(chartName, xDomain, yDomain, collection, PlotOrientation.VERTICAL, true, true, false);
|
||||
XYPlot plot = chart.getXYPlot();
|
||||
plot.setBackgroundPaint(Color.WHITE);
|
||||
plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
|
||||
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
|
||||
return chart;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2013 Stefan Schroeder
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.analysis.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import jsprit.core.util.BenchmarkResult;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface BenchmarkWriter {
|
||||
public void write(Collection<BenchmarkResult> results);
|
||||
public void write(Collection<BenchmarkResult> results);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,259 +1,256 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2013 Stefan Schroeder
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.analysis.util;
|
||||
|
||||
import jsprit.core.util.BenchmarkResult;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import jsprit.core.util.BenchmarkResult;
|
||||
public class HtmlBenchmarkTableWriter implements BenchmarkWriter {
|
||||
|
||||
public class HtmlBenchmarkTableWriter implements BenchmarkWriter{
|
||||
private String filename;
|
||||
|
||||
private String filename;
|
||||
|
||||
public HtmlBenchmarkTableWriter(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
public HtmlBenchmarkTableWriter(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Collection<BenchmarkResult> results) {
|
||||
|
||||
try {
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(new File(filename)));
|
||||
writer.write(openTable() + newline());
|
||||
//table head
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(head("inst") + newline());
|
||||
writer.write(head("runs") + newline());
|
||||
writer.write(head("Ø time [sec]") + newline());
|
||||
writer.write(head("results",4));
|
||||
writer.write(head("vehicles",4));
|
||||
writer.write(head("res*") + newline());
|
||||
writer.write(head("veh*") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("best") + newline());
|
||||
writer.write(head("avg") + newline());
|
||||
writer.write(head("worst") + newline());
|
||||
writer.write(head("stdev") + newline());
|
||||
writer.write(head("best") + newline());
|
||||
writer.write(head("avg") + newline());
|
||||
writer.write(head("worst") + newline());
|
||||
writer.write(head("stdev") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
//data
|
||||
double sum_avg_time = 0.0;
|
||||
double sum_best_result = 0.0;
|
||||
double sum_avg_result = 0.0;
|
||||
double sum_worst_result = 0.0;
|
||||
double sum_dev_result = 0.0;
|
||||
|
||||
double sum_best_veh = 0.0;
|
||||
double sum_avg_veh = 0.0;
|
||||
double sum_worst_veh = 0.0;
|
||||
double sum_dev_veh = 0.0;
|
||||
|
||||
Integer runs = null;
|
||||
Double sum_res_star=null;
|
||||
Double sum_veh_star=null;
|
||||
|
||||
for(BenchmarkResult result : results){
|
||||
if(runs==null) runs=result.runs;
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date(result.instance.name) + newline());
|
||||
writer.write(date(Integer.valueOf(result.runs).toString()) + newline());
|
||||
|
||||
Double avg_time = round(result.getTimesStats().getMean(),2);
|
||||
writer.write(date(Double.valueOf(avg_time).toString()) + newline());
|
||||
//bestRes
|
||||
Double best_result = round(result.getResultStats().getMin(),2);
|
||||
writer.write(date(Double.valueOf(best_result).toString()) + newline());
|
||||
//avgRes
|
||||
Double avg_result = round(result.getResultStats().getMean(),2);
|
||||
writer.write(date(Double.valueOf(avg_result).toString()) + newline());
|
||||
//worstRes
|
||||
Double worst_result = round(result.getResultStats().getMax(),2);
|
||||
writer.write(date(Double.valueOf(worst_result).toString()) + newline());
|
||||
//stdevRes
|
||||
Double std_result = round(result.getResultStats().getStandardDeviation(),2);
|
||||
writer.write(date(Double.valueOf(std_result).toString()) + newline());
|
||||
//bestVeh
|
||||
Double best_vehicle = round(result.getVehicleStats().getMin(),2);
|
||||
writer.write(date(Double.valueOf(best_vehicle).toString()) + newline());
|
||||
//avgVeh
|
||||
Double avg_vehicle = round(result.getVehicleStats().getMean(),2);
|
||||
writer.write(date(Double.valueOf(avg_vehicle).toString()) + newline());
|
||||
//worstVeh
|
||||
Double worst_vehicle = round(result.getVehicleStats().getMax(),2);
|
||||
writer.write(date(Double.valueOf(worst_vehicle).toString()) + newline());
|
||||
//stdevVeh
|
||||
Double std_vehicle = round(result.getVehicleStats().getStandardDeviation(),2);
|
||||
writer.write(date(Double.valueOf(std_vehicle).toString()) + newline());
|
||||
//bestKnownRes
|
||||
writer.write(date("" + result.instance.bestKnownResult + newline()));
|
||||
//bestKnownVeh
|
||||
writer.write(date("" + result.instance.bestKnownVehicles + newline()));
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
sum_avg_time+=avg_time;
|
||||
sum_best_result+=best_result;
|
||||
sum_avg_result+=avg_result;
|
||||
sum_worst_result+=worst_result;
|
||||
sum_dev_result+=std_result;
|
||||
|
||||
sum_best_veh+=best_vehicle;
|
||||
sum_avg_veh+=avg_vehicle;
|
||||
sum_worst_veh+=worst_vehicle;
|
||||
sum_dev_veh+=std_vehicle;
|
||||
|
||||
if(result.instance.bestKnownResult != null){
|
||||
if(sum_res_star==null) sum_res_star=result.instance.bestKnownResult;
|
||||
else sum_res_star+=result.instance.bestKnownResult;
|
||||
}
|
||||
if(result.instance.bestKnownVehicles != null){
|
||||
if(sum_veh_star==null) sum_veh_star=result.instance.bestKnownVehicles;
|
||||
else sum_veh_star+=result.instance.bestKnownVehicles;
|
||||
}
|
||||
|
||||
}
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date("Ø") + newline());
|
||||
writer.write(date(""+runs) + newline());
|
||||
|
||||
Double average_time = round(sum_avg_time/(double)results.size(),2);
|
||||
writer.write(date(Double.valueOf(average_time).toString()) + newline());
|
||||
//bestRes
|
||||
writer.write(date(Double.valueOf(round(sum_best_result/(double)results.size(),2)).toString()) + newline());
|
||||
//avgRes
|
||||
Double average_result = round(sum_avg_result/(double)results.size(),2);
|
||||
writer.write(date(Double.valueOf(average_result).toString()) + newline());
|
||||
//worstRes
|
||||
writer.write(date(Double.valueOf(round(sum_worst_result/(double)results.size(),2)).toString()) + newline());
|
||||
//stdevRes
|
||||
writer.write(date(Double.valueOf(round(sum_dev_result/(double)results.size(),2)).toString()) + newline());
|
||||
//bestVeh
|
||||
writer.write(date(Double.valueOf(round(sum_best_veh/(double)results.size(),2)).toString()) + newline());
|
||||
//avgVeh
|
||||
Double average_vehicles = round(sum_avg_veh/(double)results.size(),2);
|
||||
writer.write(date(Double.valueOf(average_vehicles).toString()) + newline());
|
||||
//worstVeh
|
||||
writer.write(date(Double.valueOf(round(sum_worst_veh/(double)results.size(),2)).toString()) + newline());
|
||||
//stdevVeh
|
||||
writer.write(date(Double.valueOf(round(sum_dev_veh/(double)results.size(),2)).toString()) + newline());
|
||||
//bestKnownRes
|
||||
Double delta_res = null;
|
||||
if(sum_res_star != null){
|
||||
writer.write(date(Double.valueOf(round(sum_res_star.doubleValue()/(double)results.size(),2)).toString()) + newline());
|
||||
delta_res = (sum_avg_result/sum_res_star - 1)*100;
|
||||
}
|
||||
else writer.write(date("null") + newline());
|
||||
//bestKnownVeh
|
||||
Double delta_veh = null;
|
||||
if(sum_veh_star != null){
|
||||
writer.write(date(Double.valueOf(round(sum_veh_star.doubleValue()/(double)results.size(),2)).toString()) + newline());
|
||||
delta_veh = (sum_avg_veh - sum_veh_star)/(double)results.size();
|
||||
}
|
||||
else writer.write(date("null") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
writer.write(closeTable() + newline());
|
||||
|
||||
writer.write("avg. percentage deviation to best-known result: " + round(delta_res,2) + newline() + newline());
|
||||
writer.write("avg. absolute deviation to best-known vehicles: " + round(delta_veh,2) + newline());
|
||||
|
||||
writer.write(openTable() + newline());
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date(Double.valueOf(average_time).toString(),"align=\"right\"") + newline());
|
||||
writer.write(date(Double.valueOf(average_result).toString(),"align=\"right\"") + newline());
|
||||
writer.write(date(Double.valueOf(average_vehicles).toString(),"align=\"right\"") + newline());
|
||||
if(delta_res != null){
|
||||
writer.write(date(Double.valueOf(round(delta_res,2)).toString(),"align=\"right\"") + newline());
|
||||
}else writer.write(date("n.a.") + newline());
|
||||
if(delta_veh != null){
|
||||
writer.write(date(Double.valueOf(round(delta_veh,2)).toString(),"align=\"right\"") + newline());
|
||||
}else writer.write(date("n.a.") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
writer.write(closeTable() + newline());
|
||||
|
||||
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String head(String string, int i) {
|
||||
return "<th colspan=\""+i+"\">"+string+"</th>";
|
||||
}
|
||||
@Override
|
||||
public void write(Collection<BenchmarkResult> results) {
|
||||
|
||||
private Double round(Double value, int i) {
|
||||
if(value==null) return null;
|
||||
long roundedVal = Math.round(value*Math.pow(10, i));
|
||||
return (double)roundedVal/(double)(Math.pow(10, i));
|
||||
}
|
||||
try {
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(new File(filename)));
|
||||
writer.write(openTable() + newline());
|
||||
//table head
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(head("inst") + newline());
|
||||
writer.write(head("runs") + newline());
|
||||
writer.write(head("Ø time [sec]") + newline());
|
||||
writer.write(head("results", 4));
|
||||
writer.write(head("vehicles", 4));
|
||||
writer.write(head("res*") + newline());
|
||||
writer.write(head("veh*") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
private String head(String head) {
|
||||
return "<th>"+head+"</th>";
|
||||
}
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("best") + newline());
|
||||
writer.write(head("avg") + newline());
|
||||
writer.write(head("worst") + newline());
|
||||
writer.write(head("stdev") + newline());
|
||||
writer.write(head("best") + newline());
|
||||
writer.write(head("avg") + newline());
|
||||
writer.write(head("worst") + newline());
|
||||
writer.write(head("stdev") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(head("") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
private String closeTable() {
|
||||
return "</table>";
|
||||
}
|
||||
//data
|
||||
double sum_avg_time = 0.0;
|
||||
double sum_best_result = 0.0;
|
||||
double sum_avg_result = 0.0;
|
||||
double sum_worst_result = 0.0;
|
||||
double sum_dev_result = 0.0;
|
||||
|
||||
private String openTable() {
|
||||
return "<table>";
|
||||
}
|
||||
double sum_best_veh = 0.0;
|
||||
double sum_avg_veh = 0.0;
|
||||
double sum_worst_veh = 0.0;
|
||||
double sum_dev_veh = 0.0;
|
||||
|
||||
private String closeRow() {
|
||||
return "</tr>";
|
||||
}
|
||||
Integer runs = null;
|
||||
Double sum_res_star = null;
|
||||
Double sum_veh_star = null;
|
||||
|
||||
private String date(String date) {
|
||||
return "<td>"+date+"</td>";
|
||||
}
|
||||
|
||||
private String date(String date, String metaData) {
|
||||
return "<td " + metaData + ">"+date+"</td>";
|
||||
}
|
||||
for (BenchmarkResult result : results) {
|
||||
if (runs == null) runs = result.runs;
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date(result.instance.name) + newline());
|
||||
writer.write(date(Integer.valueOf(result.runs).toString()) + newline());
|
||||
|
||||
private String newline() {
|
||||
return "\n";
|
||||
}
|
||||
Double avg_time = round(result.getTimesStats().getMean(), 2);
|
||||
writer.write(date(Double.valueOf(avg_time).toString()) + newline());
|
||||
//bestRes
|
||||
Double best_result = round(result.getResultStats().getMin(), 2);
|
||||
writer.write(date(Double.valueOf(best_result).toString()) + newline());
|
||||
//avgRes
|
||||
Double avg_result = round(result.getResultStats().getMean(), 2);
|
||||
writer.write(date(Double.valueOf(avg_result).toString()) + newline());
|
||||
//worstRes
|
||||
Double worst_result = round(result.getResultStats().getMax(), 2);
|
||||
writer.write(date(Double.valueOf(worst_result).toString()) + newline());
|
||||
//stdevRes
|
||||
Double std_result = round(result.getResultStats().getStandardDeviation(), 2);
|
||||
writer.write(date(Double.valueOf(std_result).toString()) + newline());
|
||||
//bestVeh
|
||||
Double best_vehicle = round(result.getVehicleStats().getMin(), 2);
|
||||
writer.write(date(Double.valueOf(best_vehicle).toString()) + newline());
|
||||
//avgVeh
|
||||
Double avg_vehicle = round(result.getVehicleStats().getMean(), 2);
|
||||
writer.write(date(Double.valueOf(avg_vehicle).toString()) + newline());
|
||||
//worstVeh
|
||||
Double worst_vehicle = round(result.getVehicleStats().getMax(), 2);
|
||||
writer.write(date(Double.valueOf(worst_vehicle).toString()) + newline());
|
||||
//stdevVeh
|
||||
Double std_vehicle = round(result.getVehicleStats().getStandardDeviation(), 2);
|
||||
writer.write(date(Double.valueOf(std_vehicle).toString()) + newline());
|
||||
//bestKnownRes
|
||||
writer.write(date("" + result.instance.bestKnownResult + newline()));
|
||||
//bestKnownVeh
|
||||
writer.write(date("" + result.instance.bestKnownVehicles + newline()));
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
private String openRow() {
|
||||
return "<tr>";
|
||||
}
|
||||
sum_avg_time += avg_time;
|
||||
sum_best_result += best_result;
|
||||
sum_avg_result += avg_result;
|
||||
sum_worst_result += worst_result;
|
||||
sum_dev_result += std_result;
|
||||
|
||||
sum_best_veh += best_vehicle;
|
||||
sum_avg_veh += avg_vehicle;
|
||||
sum_worst_veh += worst_vehicle;
|
||||
sum_dev_veh += std_vehicle;
|
||||
|
||||
if (result.instance.bestKnownResult != null) {
|
||||
if (sum_res_star == null) sum_res_star = result.instance.bestKnownResult;
|
||||
else sum_res_star += result.instance.bestKnownResult;
|
||||
}
|
||||
if (result.instance.bestKnownVehicles != null) {
|
||||
if (sum_veh_star == null) sum_veh_star = result.instance.bestKnownVehicles;
|
||||
else sum_veh_star += result.instance.bestKnownVehicles;
|
||||
}
|
||||
|
||||
}
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date("Ø") + newline());
|
||||
writer.write(date("" + runs) + newline());
|
||||
|
||||
Double average_time = round(sum_avg_time / (double) results.size(), 2);
|
||||
writer.write(date(Double.valueOf(average_time).toString()) + newline());
|
||||
//bestRes
|
||||
writer.write(date(Double.valueOf(round(sum_best_result / (double) results.size(), 2)).toString()) + newline());
|
||||
//avgRes
|
||||
Double average_result = round(sum_avg_result / (double) results.size(), 2);
|
||||
writer.write(date(Double.valueOf(average_result).toString()) + newline());
|
||||
//worstRes
|
||||
writer.write(date(Double.valueOf(round(sum_worst_result / (double) results.size(), 2)).toString()) + newline());
|
||||
//stdevRes
|
||||
writer.write(date(Double.valueOf(round(sum_dev_result / (double) results.size(), 2)).toString()) + newline());
|
||||
//bestVeh
|
||||
writer.write(date(Double.valueOf(round(sum_best_veh / (double) results.size(), 2)).toString()) + newline());
|
||||
//avgVeh
|
||||
Double average_vehicles = round(sum_avg_veh / (double) results.size(), 2);
|
||||
writer.write(date(Double.valueOf(average_vehicles).toString()) + newline());
|
||||
//worstVeh
|
||||
writer.write(date(Double.valueOf(round(sum_worst_veh / (double) results.size(), 2)).toString()) + newline());
|
||||
//stdevVeh
|
||||
writer.write(date(Double.valueOf(round(sum_dev_veh / (double) results.size(), 2)).toString()) + newline());
|
||||
//bestKnownRes
|
||||
Double delta_res = null;
|
||||
if (sum_res_star != null) {
|
||||
writer.write(date(Double.valueOf(round(sum_res_star.doubleValue() / (double) results.size(), 2)).toString()) + newline());
|
||||
delta_res = (sum_avg_result / sum_res_star - 1) * 100;
|
||||
} else writer.write(date("null") + newline());
|
||||
//bestKnownVeh
|
||||
Double delta_veh = null;
|
||||
if (sum_veh_star != null) {
|
||||
writer.write(date(Double.valueOf(round(sum_veh_star.doubleValue() / (double) results.size(), 2)).toString()) + newline());
|
||||
delta_veh = (sum_avg_veh - sum_veh_star) / (double) results.size();
|
||||
} else writer.write(date("null") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
|
||||
writer.write(closeTable() + newline());
|
||||
|
||||
writer.write("avg. percentage deviation to best-known result: " + round(delta_res, 2) + newline() + newline());
|
||||
writer.write("avg. absolute deviation to best-known vehicles: " + round(delta_veh, 2) + newline());
|
||||
|
||||
writer.write(openTable() + newline());
|
||||
writer.write(openRow() + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date("") + newline());
|
||||
writer.write(date(Double.valueOf(average_time).toString(), "align=\"right\"") + newline());
|
||||
writer.write(date(Double.valueOf(average_result).toString(), "align=\"right\"") + newline());
|
||||
writer.write(date(Double.valueOf(average_vehicles).toString(), "align=\"right\"") + newline());
|
||||
if (delta_res != null) {
|
||||
writer.write(date(Double.valueOf(round(delta_res, 2)).toString(), "align=\"right\"") + newline());
|
||||
} else writer.write(date("n.a.") + newline());
|
||||
if (delta_veh != null) {
|
||||
writer.write(date(Double.valueOf(round(delta_veh, 2)).toString(), "align=\"right\"") + newline());
|
||||
} else writer.write(date("n.a.") + newline());
|
||||
writer.write(closeRow() + newline());
|
||||
writer.write(closeTable() + newline());
|
||||
|
||||
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String head(String string, int i) {
|
||||
return "<th colspan=\"" + i + "\">" + string + "</th>";
|
||||
}
|
||||
|
||||
private Double round(Double value, int i) {
|
||||
if (value == null) return null;
|
||||
long roundedVal = Math.round(value * Math.pow(10, i));
|
||||
return (double) roundedVal / (double) (Math.pow(10, i));
|
||||
}
|
||||
|
||||
private String head(String head) {
|
||||
return "<th>" + head + "</th>";
|
||||
}
|
||||
|
||||
private String closeTable() {
|
||||
return "</table>";
|
||||
}
|
||||
|
||||
private String openTable() {
|
||||
return "<table>";
|
||||
}
|
||||
|
||||
private String closeRow() {
|
||||
return "</tr>";
|
||||
}
|
||||
|
||||
private String date(String date) {
|
||||
return "<td>" + date + "</td>";
|
||||
}
|
||||
|
||||
private String date(String date, String metaData) {
|
||||
return "<td " + metaData + ">" + date + "</td>";
|
||||
}
|
||||
|
||||
private String newline() {
|
||||
return "\n";
|
||||
}
|
||||
|
||||
private String openRow() {
|
||||
return "<tr>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue