mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
vis
This commit is contained in:
parent
006aa561cf
commit
99b30c460f
2 changed files with 84 additions and 124 deletions
|
|
@ -1,9 +1,27 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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
|
||||||
|
* 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
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
package jsprit.analysis.toolbox;
|
package jsprit.analysis.toolbox;
|
||||||
|
|
||||||
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
|
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
|
||||||
import jsprit.core.algorithm.recreate.InsertionData;
|
import jsprit.core.algorithm.recreate.InsertionData;
|
||||||
import jsprit.core.algorithm.recreate.listener.BeforeJobInsertionListener;
|
import jsprit.core.algorithm.recreate.listener.BeforeJobInsertionListener;
|
||||||
import jsprit.core.algorithm.recreate.listener.InsertionEndsListener;
|
import jsprit.core.algorithm.recreate.listener.InsertionEndsListener;
|
||||||
|
import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
|
||||||
import jsprit.core.algorithm.ruin.listener.RuinListener;
|
import jsprit.core.algorithm.ruin.listener.RuinListener;
|
||||||
import jsprit.core.problem.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import jsprit.core.problem.job.Job;
|
import jsprit.core.problem.job.Job;
|
||||||
|
|
@ -17,52 +35,37 @@ import org.graphstream.graph.Edge;
|
||||||
import org.graphstream.graph.Graph;
|
import org.graphstream.graph.Graph;
|
||||||
import org.graphstream.graph.Node;
|
import org.graphstream.graph.Node;
|
||||||
import org.graphstream.graph.implementations.MultiGraph;
|
import org.graphstream.graph.implementations.MultiGraph;
|
||||||
|
import org.graphstream.stream.file.FileSinkDGS;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by stefan on 14.11.14.
|
|
||||||
*/
|
|
||||||
public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionListener, InsertionEndsListener, AlgorithmEndsListener {
|
|
||||||
|
|
||||||
|
|
||||||
static class Edges {
|
public class GraphStreamEventWriter implements RuinListener, InsertionStartsListener, BeforeJobInsertionListener, InsertionEndsListener, AlgorithmEndsListener {
|
||||||
|
|
||||||
String inEdgeId;
|
public static final int BEFORE_RUIN_RENDER_SOLUTION = 2;
|
||||||
|
|
||||||
String outEdgeId;
|
public static final int RUIN = 0;
|
||||||
|
|
||||||
Edges(String inEdgeId, String outEdgeId) {
|
public static final int RECREATE = 1;
|
||||||
this.inEdgeId = inEdgeId;
|
|
||||||
this.outEdgeId = outEdgeId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private File outfile;
|
public static final int CLEAR_SOLUTION = 3;
|
||||||
|
|
||||||
private FileWriter writer;
|
private FileWriter writer;
|
||||||
|
|
||||||
private Map<String,Edges> in_out_edges = new HashMap<String,Edges>();
|
|
||||||
|
|
||||||
private Graph graph;
|
private Graph graph;
|
||||||
|
|
||||||
private VehicleRoutingProblem vrp;
|
private FileSinkDGS fileSink;
|
||||||
|
|
||||||
private boolean notInitialized = true;
|
|
||||||
|
|
||||||
public GraphStreamEventWriter(VehicleRoutingProblem vrp, File outfile) {
|
public GraphStreamEventWriter(VehicleRoutingProblem vrp, File outfile) {
|
||||||
this.outfile = outfile;
|
|
||||||
this.vrp = vrp;
|
|
||||||
graph = new MultiGraph("g");
|
graph = new MultiGraph("g");
|
||||||
try {
|
try {
|
||||||
writer = new FileWriter(outfile);
|
writer = new FileWriter(outfile);
|
||||||
writeHead();
|
fileSink = new FileSinkDGS();
|
||||||
|
fileSink.begin(writer);
|
||||||
|
graph.addSink(fileSink);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
@ -70,16 +73,16 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphStreamEventWriter(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution initialSolution, File outfile) {
|
public GraphStreamEventWriter(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution initialSolution, File outfile) {
|
||||||
this.outfile = outfile;
|
// this.outfile = outfile;
|
||||||
this.vrp = vrp;
|
// this.vrp = vrp;
|
||||||
graph = new MultiGraph("g");
|
// graph = new MultiGraph("g");
|
||||||
try {
|
// try {
|
||||||
writer = new FileWriter(outfile);
|
// writer = new FileWriter(outfile);
|
||||||
writeHead();
|
// writeHead();
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
// }
|
||||||
initialiseGraph(vrp,initialSolution);
|
// initialiseGraph(vrp,initialSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialiseGraph(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution initialSolution) {
|
private void initialiseGraph(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution initialSolution) {
|
||||||
|
|
@ -88,6 +91,7 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ruinStarts(Collection<VehicleRoute> routes) {
|
public void ruinStarts(Collection<VehicleRoute> routes) {
|
||||||
|
fileSink.stepBegins(graph.getId(),0,BEFORE_RUIN_RENDER_SOLUTION);
|
||||||
for(VehicleRoute route : routes){
|
for(VehicleRoute route : routes){
|
||||||
String prevNode = makeStartId(route.getVehicle());
|
String prevNode = makeStartId(route.getVehicle());
|
||||||
for(TourActivity act : route.getActivities()){
|
for(TourActivity act : route.getActivities()){
|
||||||
|
|
@ -98,18 +102,7 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
String lastNode = makeEndId(route.getVehicle());
|
String lastNode = makeEndId(route.getVehicle());
|
||||||
addEdge(prevNode+"_"+lastNode,prevNode,lastNode);
|
addEdge(prevNode+"_"+lastNode,prevNode,lastNode);
|
||||||
}
|
}
|
||||||
}
|
fileSink.stepBegins(graph.getId(),0,RUIN);
|
||||||
|
|
||||||
private void removeNode(Node node) {
|
|
||||||
graph.removeNode(node);
|
|
||||||
String eventString = "dn " + node.getId() + "\n";
|
|
||||||
System.out.print(eventString);
|
|
||||||
try {
|
|
||||||
writer.write(eventString);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -119,12 +112,9 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removed(Job job, VehicleRoute fromRoute) {
|
public void removed(Job job, VehicleRoute fromRoute) {
|
||||||
System.out.println("remove job " + job.getId());
|
|
||||||
String nodeId = job.getId();
|
String nodeId = job.getId();
|
||||||
Node node = graph.getNode(nodeId);
|
Node node = graph.getNode(nodeId);
|
||||||
|
|
||||||
markRemoved(node);
|
markRemoved(node);
|
||||||
|
|
||||||
Edge entering = node.getEnteringEdge(0);
|
Edge entering = node.getEnteringEdge(0);
|
||||||
removeEdge(entering.getId());
|
removeEdge(entering.getId());
|
||||||
Edge leaving = node.getLeavingEdge(0);
|
Edge leaving = node.getLeavingEdge(0);
|
||||||
|
|
@ -139,11 +129,6 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
|
|
||||||
private void markRemoved(Node node) {
|
private void markRemoved(Node node) {
|
||||||
node.setAttribute("ui.class","removed");
|
node.setAttribute("ui.class","removed");
|
||||||
try {
|
|
||||||
writer.write("cn " + node.getId() + " ui.class:removed\n");
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String makeEdgeId(Node from, Node to) {
|
private String makeEdgeId(Node from, Node to) {
|
||||||
|
|
@ -153,17 +138,13 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
@Override
|
@Override
|
||||||
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||||
try {
|
try {
|
||||||
|
fileSink.end();
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeHead() throws IOException {
|
|
||||||
writer.write("DGS004\n");
|
|
||||||
writer.write("null 0 0\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initialiseGraph(VehicleRoutingProblem problem) {
|
private void initialiseGraph(VehicleRoutingProblem problem) {
|
||||||
for(Vehicle vehicle : problem.getVehicles()){
|
for(Vehicle vehicle : problem.getVehicles()){
|
||||||
addVehicle(vehicle);
|
addVehicle(vehicle);
|
||||||
|
|
@ -176,23 +157,18 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addVehicle(Vehicle vehicle) {
|
private void addVehicle(Vehicle vehicle) {
|
||||||
try {
|
String startId = makeStartId(vehicle);
|
||||||
String startId = makeStartId(vehicle);
|
Node node = graph.addNode(startId);
|
||||||
String startNodeEventString = "an " + startId + " x:" + vehicle.getStartLocationCoordinate().getX() + " y:"
|
node.addAttribute("x",vehicle.getStartLocationCoordinate().getX());
|
||||||
+ vehicle.getStartLocationCoordinate().getY() + " ui.class:depot\n";
|
node.addAttribute("y",vehicle.getStartLocationCoordinate().getY());
|
||||||
System.out.print(startNodeEventString);
|
node.addAttribute("ui.class","depot");
|
||||||
writer.write(startNodeEventString);
|
|
||||||
graph.addNode(startId);
|
String endId = makeEndId(vehicle);
|
||||||
String endId = makeEndId(vehicle);
|
if(!startId.equals(endId)){
|
||||||
if(!startId.equals(endId)){
|
Node endNode = graph.addNode(endId);
|
||||||
String endNodeEventString = "an " + endId + " x:" + vehicle.getEndLocationCoordinate().getX() + " y:"
|
endNode.addAttribute("x",vehicle.getEndLocationCoordinate().getX());
|
||||||
+ vehicle.getEndLocationCoordinate().getY() + " ui.class:depot\n";
|
endNode.addAttribute("y",vehicle.getEndLocationCoordinate().getY());
|
||||||
System.out.print(endNodeEventString);
|
endNode.addAttribute("ui.class","depot");
|
||||||
writer.write( endNodeEventString);
|
|
||||||
graph.addNode(endId);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,18 +182,14 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addService(Service service) {
|
private void addService(Service service) {
|
||||||
try {
|
Node serviceNode = graph.addNode(service.getId());
|
||||||
String eventString = "an " + service.getId() + " x:" + service.getCoord().getX() + " y:" + service.getCoord().getY() + "\n";
|
serviceNode.addAttribute("x", service.getCoord().getX());
|
||||||
System.out.print(eventString);
|
serviceNode.addAttribute("y", service.getCoord().getY());
|
||||||
writer.write(eventString);
|
|
||||||
graph.addNode(service.getId());
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
||||||
|
fileSink.stepBegins(graph.getId(),0,CLEAR_SOLUTION);
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
String prevNode = makeStartId(route.getVehicle());
|
String prevNode = makeStartId(route.getVehicle());
|
||||||
for(TourActivity act : route.getActivities()){
|
for(TourActivity act : route.getActivities()){
|
||||||
|
|
@ -232,7 +204,6 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route) {
|
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route) {
|
||||||
System.out.println("insert job " + job.getId());
|
|
||||||
markInserted(job);
|
markInserted(job);
|
||||||
boolean vehicleSwitch = false;
|
boolean vehicleSwitch = false;
|
||||||
if(!(route.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
if(!(route.getVehicle() instanceof VehicleImpl.NoVehicle)) {
|
||||||
|
|
@ -241,7 +212,6 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(vehicleSwitch && !route.getActivities().isEmpty()){
|
if(vehicleSwitch && !route.getActivities().isEmpty()){
|
||||||
System.out.println("switch vehicle " + route.getVehicle().getId() + " --> " + data.getSelectedVehicle().getId());
|
|
||||||
String oldStart = makeStartId(route.getVehicle());
|
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 oldEnd = makeEndId(route.getVehicle());
|
||||||
|
|
@ -281,22 +251,10 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
|
|
||||||
private void markInserted(Job job) {
|
private void markInserted(Job job) {
|
||||||
graph.getNode(job.getId()).removeAttribute("ui.class");
|
graph.getNode(job.getId()).removeAttribute("ui.class");
|
||||||
try {
|
|
||||||
writer.write("cn " + job.getId() + " -ui.class\n");
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeEdge(String edgeId) {
|
private void removeEdge(String edgeId) {
|
||||||
try {
|
graph.removeEdge(edgeId);
|
||||||
String eventString = "de " + edgeId + "\n";
|
|
||||||
System.out.print(eventString);
|
|
||||||
writer.write(eventString);
|
|
||||||
graph.removeEdge(edgeId);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFirst(InsertionData data, VehicleRoute route) {
|
private boolean isFirst(InsertionData data, VehicleRoute route) {
|
||||||
|
|
@ -308,14 +266,11 @@ public class GraphStreamEventWriter implements RuinListener, BeforeJobInsertionL
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addEdge(String edgeId, String fromNode, String toNode) {
|
private void addEdge(String edgeId, String fromNode, String toNode) {
|
||||||
try {
|
graph.addEdge(edgeId,fromNode,toNode,true);
|
||||||
String eventString = "ae " + edgeId + " " + fromNode + " > " + toNode + "\n";
|
|
||||||
System.out.print(eventString);
|
|
||||||
writer.write(eventString);
|
|
||||||
graph.addEdge(edgeId,fromNode,toNode,true);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
|
fileSink.stepBegins(graph.getId(),0,RECREATE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,22 @@ import java.awt.*;
|
||||||
|
|
||||||
public class GraphStreamViewer {
|
public class GraphStreamViewer {
|
||||||
|
|
||||||
|
|
||||||
|
public static Graph createMultiGraph(String name, String style){
|
||||||
|
Graph g = new MultiGraph(name);
|
||||||
|
g.addAttribute("ui.quality");
|
||||||
|
g.addAttribute("ui.antialias");
|
||||||
|
g.addAttribute("ui.stylesheet", style);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static View createEmbeddedView(Graph graph, double scaling){
|
||||||
|
Viewer viewer = new Viewer(graph,Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
|
||||||
|
View view = viewer.addDefaultView(false);
|
||||||
|
view.setPreferredSize(new Dimension((int)(698*scaling),(int)(440*scaling)));
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
public static String STYLESHEET =
|
public static String STYLESHEET =
|
||||||
"node {" +
|
"node {" +
|
||||||
" size: 10px, 10px;" +
|
" size: 10px, 10px;" +
|
||||||
|
|
@ -184,14 +200,14 @@ public class GraphStreamViewer {
|
||||||
|
|
||||||
Graph g = createMultiGraph("g");
|
Graph g = createMultiGraph("g");
|
||||||
|
|
||||||
View view = createEmbeddedView(g);
|
View view = createEmbeddedView(g,scaling);
|
||||||
|
|
||||||
JFrame jframe = createJFrame(view);
|
JFrame jframe = createJFrame(view,scaling);
|
||||||
|
|
||||||
render(g,view);
|
render(g,view);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JFrame createJFrame(View view) {
|
private JFrame createJFrame(View view, double scaling) {
|
||||||
JFrame jframe = new JFrame();
|
JFrame jframe = new JFrame();
|
||||||
JPanel basicPanel = new JPanel();
|
JPanel basicPanel = new JPanel();
|
||||||
basicPanel.setLayout(new BoxLayout(basicPanel, BoxLayout.Y_AXIS));
|
basicPanel.setLayout(new BoxLayout(basicPanel, BoxLayout.Y_AXIS));
|
||||||
|
|
@ -231,19 +247,8 @@ public class GraphStreamViewer {
|
||||||
return jframe;
|
return jframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public View createEmbeddedView(Graph g) {
|
private Graph createMultiGraph(String name) {
|
||||||
Viewer viewer = new Viewer(g,Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
|
return GraphStreamViewer.createMultiGraph(name,STYLESHEET);
|
||||||
View view = viewer.addDefaultView(false);
|
|
||||||
view.setPreferredSize(new Dimension((int)(698*scaling),(int)(440*scaling)));
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Graph createMultiGraph(String name) {
|
|
||||||
Graph g = new MultiGraph(name);
|
|
||||||
g.addAttribute("ui.quality");
|
|
||||||
g.addAttribute("ui.antialias");
|
|
||||||
g.addAttribute("ui.stylesheet", STYLESHEET);
|
|
||||||
return g;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void render(Graph g, View view) {
|
private void render(Graph g, View view) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue