diff --git a/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/AnotherGraphTest.java b/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/AnotherGraphTest.java new file mode 100644 index 00000000..5f0eb3cd --- /dev/null +++ b/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/AnotherGraphTest.java @@ -0,0 +1,27 @@ +package jsprit.analysis.toolbox; + +import jsprit.core.algorithm.VehicleRoutingAlgorithm; +import jsprit.core.algorithm.box.GreedySchrimpfFactory; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.io.VrpXMLReader; + +import java.io.File; + +/** + * Created by stefan on 14.11.14. + */ +public class AnotherGraphTest { + + public static void main(String[] args) { + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); + new VrpXMLReader(vrpBuilder).read("/Users/stefan/Documents/git-repositories/jsprit/jsprit-examples/input/cordeau01.xml"); + VehicleRoutingProblem vrp = vrpBuilder.build(); + +// GraphStreamEventWriter eventWriter = new GraphStreamEventWriter(new File("output/events.txt")); + VehicleRoutingAlgorithm vra = new GreedySchrimpfFactory().createAlgorithm(vrp); +// vra.addListener(eventWriter); + + vra.searchSolutions(); + + } +} diff --git a/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/GraphStreamEventWriter.java b/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/GraphStreamEventWriter.java new file mode 100644 index 00000000..e7c23366 --- /dev/null +++ b/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/GraphStreamEventWriter.java @@ -0,0 +1,321 @@ +package jsprit.analysis.toolbox; + +import jsprit.core.algorithm.listener.AlgorithmEndsListener; +import jsprit.core.algorithm.recreate.InsertionData; +import jsprit.core.algorithm.recreate.listener.BeforeJobInsertionListener; +import jsprit.core.algorithm.recreate.listener.InsertionEndsListener; +import jsprit.core.algorithm.ruin.listener.RuinListener; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.job.Job; +import jsprit.core.problem.job.Service; +import jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import jsprit.core.problem.solution.route.VehicleRoute; +import jsprit.core.problem.solution.route.activity.TourActivity; +import jsprit.core.problem.vehicle.Vehicle; +import jsprit.core.problem.vehicle.VehicleImpl; +import org.graphstream.graph.Edge; +import org.graphstream.graph.Graph; +import org.graphstream.graph.Node; +import org.graphstream.graph.implementations.MultiGraph; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +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 { + + String inEdgeId; + + String outEdgeId; + + Edges(String inEdgeId, String outEdgeId) { + this.inEdgeId = inEdgeId; + this.outEdgeId = outEdgeId; + } + } + + private File outfile; + + private FileWriter writer; + + private Map in_out_edges = new HashMap(); + + private Graph graph; + + private VehicleRoutingProblem vrp; + + private boolean notInitialized = true; + + public GraphStreamEventWriter(VehicleRoutingProblem vrp, File outfile) { + this.outfile = outfile; + this.vrp = vrp; + graph = new MultiGraph("g"); + try { + writer = new FileWriter(outfile); + writeHead(); + } catch (IOException e) { + e.printStackTrace(); + } + initialiseGraph(vrp); + } + + public GraphStreamEventWriter(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution initialSolution, File outfile) { + this.outfile = outfile; + this.vrp = vrp; + graph = new MultiGraph("g"); + try { + writer = new FileWriter(outfile); + writeHead(); + } catch (IOException e) { + e.printStackTrace(); + } + initialiseGraph(vrp,initialSolution); + } + + private void initialiseGraph(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution initialSolution) { + + } + + @Override + public void ruinStarts(Collection routes) { + for(VehicleRoute route : routes){ + String prevNode = makeStartId(route.getVehicle()); + for(TourActivity act : route.getActivities()){ + String actNode = ((TourActivity.JobActivity)act).getJob().getId(); + addEdge(prevNode+"_"+actNode,prevNode,actNode); + prevNode = actNode; + } + String lastNode = makeEndId(route.getVehicle()); + addEdge(prevNode+"_"+lastNode,prevNode,lastNode); + } + } + + 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 + public void ruinEnds(Collection routes, Collection unassignedJobs) { + + } + + @Override + public void removed(Job job, VehicleRoute fromRoute) { + System.out.println("remove job " + job.getId()); + String nodeId = job.getId(); + Node node = graph.getNode(nodeId); + + markRemoved(node); + + Edge entering = node.getEnteringEdge(0); + removeEdge(entering.getId()); + Edge leaving = node.getLeavingEdge(0); + removeEdge((leaving.getId())); + Node from = entering.getNode0(); + Node to = leaving.getNode1(); + if(!fromRoute.getActivities().isEmpty()){ + addEdge(makeEdgeId(from,to),from.getId(),to.getId()); + } + + } + + private void markRemoved(Node node) { + 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) { + return from.getId() + "_" + to.getId(); + } + + @Override + public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection solutions) { + try { + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void writeHead() throws IOException { + writer.write("DGS004\n"); + writer.write("null 0 0\n"); + } + + private void initialiseGraph(VehicleRoutingProblem problem) { + for(Vehicle vehicle : problem.getVehicles()){ + addVehicle(vehicle); + } + for(Job job : problem.getJobs().values()){ + Service service = (Service)job; + addService(service); + } + + } + + private void addVehicle(Vehicle vehicle) { + try { + String startId = makeStartId(vehicle); + String startNodeEventString = "an " + startId + " x:" + vehicle.getStartLocationCoordinate().getX() + " y:" + + vehicle.getStartLocationCoordinate().getY() + " ui.class:depot\n"; + System.out.print(startNodeEventString); + writer.write(startNodeEventString); + graph.addNode(startId); + String endId = makeEndId(vehicle); + if(!startId.equals(endId)){ + String endNodeEventString = "an " + endId + " x:" + vehicle.getEndLocationCoordinate().getX() + " y:" + + vehicle.getEndLocationCoordinate().getY() + " ui.class:depot\n"; + System.out.print(endNodeEventString); + writer.write( endNodeEventString); + graph.addNode(endId); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private String makeStartId(Vehicle vehicle) { + return vehicle.getId() + "_start"; + } + + private String makeEndId(Vehicle vehicle) { + if(vehicle.getStartLocationId().equals(vehicle.getEndLocationId())) return makeStartId(vehicle); + return vehicle.getId() + "_end"; + } + + private void addService(Service service) { + try { + String eventString = "an " + service.getId() + " x:" + service.getCoord().getX() + " y:" + service.getCoord().getY() + "\n"; + System.out.print(eventString); + writer.write(eventString); + graph.addNode(service.getId()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void informInsertionEnds(Collection vehicleRoutes) { + for(VehicleRoute route : vehicleRoutes){ + String prevNode = makeStartId(route.getVehicle()); + for(TourActivity act : route.getActivities()){ + String actNode = ((TourActivity.JobActivity)act).getJob().getId(); + removeEdge(prevNode + "_" + actNode); + prevNode = actNode; + } + String lastNode = makeEndId(route.getVehicle()); + removeEdge(prevNode + "_" + lastNode); + } + } + + @Override + public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route) { + System.out.println("insert job " + job.getId()); + markInserted(job); + boolean vehicleSwitch = false; + if(!(route.getVehicle() instanceof VehicleImpl.NoVehicle)) { + if (!route.getVehicle().getId().equals(data.getSelectedVehicle().getId())) { + vehicleSwitch = true; + } + } + if(vehicleSwitch && !route.getActivities().isEmpty()){ + System.out.println("switch vehicle " + route.getVehicle().getId() + " --> " + data.getSelectedVehicle().getId()); + String oldStart = makeStartId(route.getVehicle()); + 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(); + removeEdge(oldStart + "_" + firstAct); + removeEdge(lastAct + "_" + oldEnd); + String newStart = makeStartId(data.getSelectedVehicle()); + String newEnd = makeEndId(data.getSelectedVehicle()); + addEdge(newStart + "_" + firstAct,newStart,firstAct); + addEdge(lastAct + "_" + newEnd, lastAct,newEnd); + } + String node_i; + + if(isFirst(data,route)) { + node_i = makeStartId(data.getSelectedVehicle()); + } + else { + node_i = ((TourActivity.JobActivity)route.getActivities().get(data.getDeliveryInsertionIndex()-1)).getJob().getId(); + } + String node_k = job.getId(); + String edgeId_1 = node_i + "_" + node_k; + String node_j; + if(isLast(data,route)) { + node_j = makeEndId(data.getSelectedVehicle()); + } + else { + node_j = ((TourActivity.JobActivity)route.getActivities().get(data.getDeliveryInsertionIndex())).getJob().getId(); + } + String edgeId_2 = node_k + "_" + node_j; + + addEdge(edgeId_1, node_i, node_k); + addEdge(edgeId_2, node_k, node_j); + if(!route.getActivities().isEmpty()){ + removeEdge(node_i + "_" + node_j); + } + } + + private void markInserted(Job job) { + 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) { + try { + 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) { + return data.getDeliveryInsertionIndex() == 0; + } + + private boolean isLast(InsertionData data, VehicleRoute route) { + return data.getDeliveryInsertionIndex() == route.getActivities().size(); + } + + private void addEdge(String edgeId, String fromNode, String toNode) { + try { + 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(); + } + } + +} diff --git a/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/GraphStreamViewer.java b/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/GraphStreamViewer.java index 6a85b7dd..c20375a3 100644 --- a/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/GraphStreamViewer.java +++ b/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/GraphStreamViewer.java @@ -27,7 +27,6 @@ import jsprit.core.problem.solution.route.activity.DeliveryActivity; import jsprit.core.problem.solution.route.activity.PickupActivity; import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.problem.solution.route.activity.TourActivity.JobActivity; -import jsprit.core.problem.vehicle.PenaltyVehicleType; import jsprit.core.problem.vehicle.Vehicle; import jsprit.core.util.Time; import org.graphstream.graph.Edge; @@ -44,7 +43,7 @@ import java.awt.*; public class GraphStreamViewer { - protected static String styleSheet = + public static String STYLESHEET = "node {" + " size: 10px, 10px;" + " fill-color: #6CC644;" + @@ -79,6 +78,13 @@ public class GraphStreamViewer { " 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;" + @@ -175,57 +181,72 @@ public class GraphStreamViewer { public void display(){ System.setProperty("org.graphstream.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer"); - - JFrame jframe = new JFrame(); - - JPanel basicPanel = new JPanel(); - basicPanel.setLayout(new BoxLayout(basicPanel, BoxLayout.Y_AXIS)); - - //result-panel - JPanel resultPanel = createResultPanel(); - //graphstream-panel - Graph g = new MultiGraph("g"); - g.addAttribute("ui.quality"); - g.addAttribute("ui.antialias"); - g.addAttribute("ui.stylesheet", styleSheet); - JPanel graphStreamPanel = new JPanel(); - 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.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1)); - graphStreamBackPanel.setBackground(Color.WHITE); - - Viewer viewer = new Viewer(g,Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD); - View view = viewer.addDefaultView(false); - view.setPreferredSize(new Dimension((int)(698*scaling),(int)(440*scaling))); - - graphStreamBackPanel.add(view); - graphStreamPanel.add(graphStreamBackPanel); - - //setup basicPanel - basicPanel.add(resultPanel); - basicPanel.add(graphStreamPanel); -// basicPanel.add(legendPanel); - - //put it together - jframe.add(basicPanel); - - //conf jframe - jframe.setSize((int)(800*scaling),(int)(580*scaling)); - jframe.setLocationRelativeTo(null); - jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - jframe.setVisible(true); - jframe.pack(); - jframe.setTitle("jsprit - GraphStream"); - - //start rendering graph - render(g,view); + Graph g = createMultiGraph("g"); + + View view = createEmbeddedView(g); + + JFrame jframe = createJFrame(view); + + render(g,view); } - private void render(Graph g, View view) { + public JFrame createJFrame(View view) { + JFrame jframe = new JFrame(); + JPanel basicPanel = new JPanel(); + basicPanel.setLayout(new BoxLayout(basicPanel, BoxLayout.Y_AXIS)); + + //result-panel + JPanel resultPanel = createResultPanel(); + //graphstream-panel + + + JPanel graphStreamPanel = new JPanel(); + 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.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1)); + graphStreamBackPanel.setBackground(Color.WHITE); + + graphStreamBackPanel.add(view); + graphStreamPanel.add(graphStreamBackPanel); + + //setup basicPanel + basicPanel.add(resultPanel); + basicPanel.add(graphStreamPanel); +// basicPanel.add(legendPanel); + + //put it together + jframe.add(basicPanel); + + //conf jframe + jframe.setSize((int)(800*scaling),(int)(580*scaling)); + jframe.setLocationRelativeTo(null); + jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jframe.setVisible(true); + jframe.pack(); + jframe.setTitle("jsprit - GraphStream"); + return jframe; + } + + public View createEmbeddedView(Graph g) { + Viewer viewer = new Viewer(g,Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD); + 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) { if(center != null){ view.resizeFrame(view.getWidth(), view.getHeight()); view.getCamera().setViewCenter(center.x, center.y, 0); @@ -284,7 +305,10 @@ public class GraphStreamViewer { jobs.setFont(font); jobs.setPreferredSize(new Dimension((int)(40*scaling),(int)(25*scaling))); - JFormattedTextField nJobs = new JFormattedTextField(this.vrp.getJobs().values().size()); + int noJobs = 0; + 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()); @@ -393,8 +417,7 @@ public class GraphStreamViewer { private void renderVehicle(Graph g, Vehicle vehicle, Label label) { String nodeId = makeId(vehicle.getId(),vehicle.getStartLocationId()); - if(vehicle.getType() instanceof PenaltyVehicleType) nodeId = makeId("pen_"+vehicle.getId(),vehicle.getStartLocationId()); - Node vehicleStart = g.addNode(nodeId); + Node vehicleStart = g.addNode(nodeId); if(label.equals(Label.ID)) vehicleStart.addAttribute("ui.label", "depot"); // if(label.equals(Label.ACTIVITY)) n.addAttribute("ui.label", "start"); vehicleStart.addAttribute("x", vehicle.getStartLocationCoordinate().getX()); diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/listener/BeforeJobInsertionListener.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/listener/BeforeJobInsertionListener.java index befbc0cf..7bc92d88 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/listener/BeforeJobInsertionListener.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/listener/BeforeJobInsertionListener.java @@ -20,7 +20,7 @@ import jsprit.core.algorithm.recreate.InsertionData; import jsprit.core.problem.job.Job; import jsprit.core.problem.solution.route.VehicleRoute; -interface BeforeJobInsertionListener extends InsertionListener{ +public interface BeforeJobInsertionListener extends InsertionListener{ public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route);