diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/DBSCANClusterer.java b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/DBSCANClusterer.java new file mode 100644 index 00000000..d93b0bcb --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/DBSCANClusterer.java @@ -0,0 +1,185 @@ +package jsprit.core.algorithm.ruin; + +import jsprit.core.problem.Location; +import jsprit.core.problem.cost.VehicleRoutingTransportCosts; +import jsprit.core.problem.job.Job; +import jsprit.core.problem.job.Service; +import jsprit.core.problem.job.Shipment; +import jsprit.core.problem.solution.route.VehicleRoute; +import jsprit.core.problem.solution.route.activity.TourActivity; +import jsprit.core.util.RandomNumberGeneration; +import jsprit.core.util.RandomUtils; +import org.apache.commons.math3.ml.clustering.Cluster; +import org.apache.commons.math3.ml.clustering.Clusterable; +import org.apache.commons.math3.ml.distance.DistanceMeasure; + +import java.util.*; + +/** +* Created by schroeder on 04/02/15. +*/ +public class DBSCANClusterer { + + private static class LocationWrapper implements Clusterable { + + private static int objCounter = 0; + + private final Job job; + + private List locations; + + private int id; + + public LocationWrapper(Job job) { + this.locations = getLocations(job); + objCounter++; + this.job = job; + this.id = objCounter; + } + + private List getLocations(Job job){ + List locs = new ArrayList(); + if(job instanceof Service) { + locs.add(((Service) job).getLocation()); + } + else if(job instanceof Shipment){ + locs.add(((Shipment) job).getPickupLocation()); + locs.add(((Shipment) job).getDeliveryLocation()); + } + return locs; + } + + public List getLocations() { + return locations; + } + + @Override + public double[] getPoint() { + return new double[]{ id }; + } + + public Job getJob() { + return job; + } + } + + private static class MyDistance implements DistanceMeasure { + + private Map locations; + + private VehicleRoutingTransportCosts costs; + + public MyDistance(List locations, VehicleRoutingTransportCosts costs) { + this.locations = new HashMap(); + for(LocationWrapper lw : locations){ + this.locations.put((int)lw.getPoint()[0],lw); + } + this.costs = costs; + } + + @Override + public double compute(double[] doubles, double[] doubles1) { + LocationWrapper l1 = locations.get((int)doubles[0]); + LocationWrapper l2 = locations.get((int)doubles1[0]); + int count = 0; + double sum = 0; + for(Location loc_1 : l1.getLocations()){ + for(Location loc_2 : l2.getLocations()){ + sum += costs.getTransportCost(loc_1,loc_2,0,null,null); + count++; + } + } + return sum / (double)count; + } + } + + private VehicleRoutingTransportCosts costs; + + private int minNoOfJobsInCluster = 1; + + private int noDistanceSamples = 10; + + private double epsFactor = 0.8; + + private Double epsDistance; + + public DBSCANClusterer(VehicleRoutingTransportCosts costs) { + this.costs = costs; + } + + public void setMinPts(int pts){ + this.minNoOfJobsInCluster = pts; + } + + public void setEpsFactor(double epsFactor){ + this.epsFactor = epsFactor; + } + + public void setEpsDistance(double epsDistance){ + this.epsDistance = epsDistance; + } + + public List> getClusters(VehicleRoute route){ + List locations = new ArrayList(route.getTourActivities().getJobs().size()); + for(Job j : route.getTourActivities().getJobs()){ + locations.add(new LocationWrapper(j)); + } + List> clusterResults = getClusters(route, locations); + return makeList(clusterResults); + } + + private List> getClusters(VehicleRoute route, List locations) { + double sampledDistance; + if(epsDistance != null) sampledDistance = epsDistance; + else sampledDistance = Math.max(0, sample(costs, route)); + org.apache.commons.math3.ml.clustering.DBSCANClusterer clusterer = new org.apache.commons.math3.ml.clustering.DBSCANClusterer(sampledDistance, minNoOfJobsInCluster, new MyDistance(locations,costs)); + return clusterer.cluster(locations); + } + + private List> makeList(List> clusterResults) { + List> l = new ArrayList>(); + for(Cluster c : clusterResults){ + List l_ = getJobList(c); + l.add(l_); + } + return l; + } + + private List getJobList(Cluster c) { + List l_ = new ArrayList(); + if(c == null) return l_; + for(LocationWrapper lw : c.getPoints()){ + l_.add(lw.getJob()); + } + return l_; + } + + public List getRandomCluster(VehicleRoute route){ + if(route.isEmpty()) return Collections.emptyList(); + List locations = new ArrayList(route.getTourActivities().getJobs().size()); + for(Job j : route.getTourActivities().getJobs()){ + locations.add(new LocationWrapper(j)); + } + List> clusterResults = getClusters(route,locations); + if(clusterResults.isEmpty()) return Collections.emptyList(); + Cluster randomCluster = RandomUtils.nextItem(clusterResults, RandomNumberGeneration.getRandom()); + return getJobList(randomCluster); + } + + private double sample(VehicleRoutingTransportCosts costs, VehicleRoute r) { + double min = Double.MAX_VALUE; + double sum = 0; + Random random = RandomNumberGeneration.getRandom(); + for(int i=0;i cluster = c.getRandomCluster(r); + Assert.assertEquals(2,cluster.size()); + + } + + @Test + public void itShouldReturnOneCluster(){ + Service s1 = Service.Builder.newInstance("s1").setLocation(Location.newInstance(1,1)).build(); + Service s2 = Service.Builder.newInstance("s2").setLocation(Location.newInstance(10,10)).build(); + Service s3 = Service.Builder.newInstance("s3").setLocation(Location.newInstance(9,9)).build(); + + VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build(); + VehicleRoute r = VehicleRoute.Builder.newInstance(v).addService(s1).addService(s2).addService(s3).build(); + + DBSCANClusterer c = new DBSCANClusterer(new EuclideanCosts()); + c.setEpsDistance(3); + List> cluster = c.getClusters(r); + Assert.assertEquals(1,cluster.size()); + + } + + @Test + public void itShouldReturnTwoClusters(){ + Service s0 = Service.Builder.newInstance("s0").setLocation(Location.newInstance(9,0)).build(); + Service s1 = Service.Builder.newInstance("s1").setLocation(Location.newInstance(9,1)).build(); + Service s2 = Service.Builder.newInstance("s2").setLocation(Location.newInstance(9,10)).build(); + Service s3 = Service.Builder.newInstance("s3").setLocation(Location.newInstance(9,9)).build(); + Service s4 = Service.Builder.newInstance("s4").setLocation(Location.newInstance(9,16)).build(); + Service s5 = Service.Builder.newInstance("s5").setLocation(Location.newInstance(9,17)).build(); + + VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build(); + VehicleRoute r = VehicleRoute.Builder.newInstance(v).addService(s1).addService(s2).addService(s3) + .addService(s0).addService(s4).addService(s5).build(); + + DBSCANClusterer c = new DBSCANClusterer(new EuclideanCosts()); + c.setMinPts(1); + c.setEpsDistance(2); + List> cluster = c.getClusters(r); + for(List l : cluster) { + System.out.println("--"); + for (Job j : l) System.out.println(j); + } + Assert.assertEquals(3,cluster.size()); + + } +} diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinClustersTest.java b/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinClustersTest.java new file mode 100644 index 00000000..5bfcc6ad --- /dev/null +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinClustersTest.java @@ -0,0 +1,48 @@ +package jsprit.core.algorithm.ruin; + +import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance; +import jsprit.core.problem.Location; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.job.Job; +import jsprit.core.problem.job.Service; +import jsprit.core.problem.solution.route.VehicleRoute; +import jsprit.core.problem.vehicle.VehicleImpl; +import junit.framework.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collection; + +/** + * Created by schroeder on 06/03/15. + */ +public class RuinClustersTest { + + @Test + public void itShouldRuinTwoObviousClusters(){ + Service s0 = Service.Builder.newInstance("s0").setLocation(Location.newInstance(9, 0)).build(); + Service s1 = Service.Builder.newInstance("s1").setLocation(Location.newInstance(9, 1)).build(); + Service s2 = Service.Builder.newInstance("s2").setLocation(Location.newInstance(9,10)).build(); + Service s3 = Service.Builder.newInstance("s3").setLocation(Location.newInstance(9,9)).build(); + Service s4 = Service.Builder.newInstance("s4").setLocation(Location.newInstance(9,16)).build(); + Service s5 = Service.Builder.newInstance("s5").setLocation(Location.newInstance(9,17)).build(); + Service s6 = Service.Builder.newInstance("s6").setLocation(Location.newInstance(9,15.5)).build(); + Service s7 = Service.Builder.newInstance("s7").setLocation(Location.newInstance(9,30)).build(); + + VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build(); + + VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addJob(s1).addJob(s2) + .addJob(s6).addJob(s7).addJob(s0).addJob(s3).addJob(s4).addJob(s5).addVehicle(v).build(); + + VehicleRoute vr1 = VehicleRoute.Builder.newInstance(v).addService(s0).addService(s1).addService(s2).addService(s3).setJobActivityFactory(vrp.getJobActivityFactory()).build(); + VehicleRoute vr2 = VehicleRoute.Builder.newInstance(v) + .addService(s6).addService(s7).addService(s4).addService(s5).setJobActivityFactory(vrp.getJobActivityFactory()).build(); + + JobNeighborhoods n = new JobNeighborhoodsFactory().createNeighborhoods(vrp,new AvgServiceAndShipmentDistance(vrp.getTransportCosts())); + n.initialise(); + RuinClusters rc = new RuinClusters(vrp,5,n); + Collection ruined = rc.ruinRoutes(Arrays.asList(vr1,vr2)); + Assert.assertEquals(5,ruined.size()); + + } +} diff --git a/jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java b/jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java index 2a588454..08704696 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java +++ b/jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java @@ -16,6 +16,7 @@ ******************************************************************************/ package jsprit.examples; +import jsprit.analysis.toolbox.AlgorithmSearchProgressChartListener; import jsprit.analysis.toolbox.GraphStreamViewer; import jsprit.analysis.toolbox.GraphStreamViewer.Label; import jsprit.analysis.toolbox.Plotter; @@ -272,13 +273,28 @@ public class BicycleMessenger { // vraBuilder.setNuOfThreads(2); vraBuilder.addDefaultCostCalculators(); vraBuilder.setStateAndConstraintManager(stateManager, constraintManager); - vraBuilder.setNuOfThreads(10); +// vraBuilder.setNuOfThreads(10); VehicleRoutingAlgorithm algorithm = vraBuilder.build(); - algorithm.setMaxIterations(10000); + algorithm.setMaxIterations(2000); + +// VehicleRoutingAlgorithm algorithm = Jsprit.Builder.newInstance(bicycleMessengerProblem) +// .setStateAndConstraintManager(stateManager, constraintManager) +// .setProperty(Jsprit.Parameter.THREADS.toString(), "6") +//// .setProperty(Jsprit.Strategy.RADIAL_BEST.toString(), "0.25") +//// .setProperty(Jsprit.Strategy.WORST_BEST.toString(), "0.25") +//// .setProperty(Jsprit.Strategy.CLUSTER_BEST.toString(), "0.25") +//// .setProperty(Jsprit.Strategy.RANDOM_BEST.toString(), "0.") +//// .setProperty(Jsprit.Strategy.RANDOM_REGRET.toString(), "1.") +// .setProperty(Jsprit.Parameter.INSERTION_NOISE_LEVEL.toString(),"0.01") +// .setProperty(Jsprit.Parameter.INSERTION_NOISE_PROB.toString(), "0.2") +//// .setProperty(Jsprit.Parameter.THRESHOLD_ALPHA.toString(),"0.1") +// .buildAlgorithm(); +// algorithm.setMaxIterations(5000); + // VariationCoefficientTermination prematureAlgorithmTermination = new VariationCoefficientTermination(200, 0.001); // algorithm.setPrematureAlgorithmTermination(prematureAlgorithmTermination); // algorithm.addListener(prematureAlgorithmTermination); -// algorithm.addListener(new AlgorithmSearchProgressChartListener("output/progress.png")); + algorithm.addListener(new AlgorithmSearchProgressChartListener("output/progress.png")); //search Collection solutions = algorithm.searchSolutions(); diff --git a/jsprit-examples/src/main/java/jsprit/examples/MultipleProductsWithLoadConstraintExample.java b/jsprit-examples/src/main/java/jsprit/examples/MultipleProductsWithLoadConstraintExample.java index 9c44cbfb..595464d5 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/MultipleProductsWithLoadConstraintExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/MultipleProductsWithLoadConstraintExample.java @@ -19,7 +19,7 @@ package jsprit.examples; import jsprit.analysis.toolbox.GraphStreamViewer; import jsprit.core.algorithm.VehicleRoutingAlgorithm; -import jsprit.core.algorithm.VehicleRoutingAlgorithmBuilder; +import jsprit.core.algorithm.box.Jsprit; import jsprit.core.algorithm.state.InternalStates; import jsprit.core.algorithm.state.StateManager; import jsprit.core.problem.Capacity; @@ -184,21 +184,13 @@ public class MultipleProductsWithLoadConstraintExample { .addVehicle(vehicle) .addJob(bananas).addJob(apples).addJob(bananas_2).addJob(bananas_3).addJob(apples_2).build(); - VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(vrp,"input/algorithmConfig.xml"); - vraBuilder.addCoreConstraints(); - vraBuilder.addDefaultCostCalculators(); - - StateManager stateManager = new StateManager(vrp); //1.3.2-SNAPSHOT & upcoming release v1.4 -// StateManager stateManager = new StateManager(vrp.getTransportCosts()); //v1.3.1 - + StateManager stateManager = new StateManager(vrp); ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager); constraintManager.addConstraint(new NoBananasANDApplesConstraint(stateManager), ConstraintManager.Priority.CRITICAL); // constraintManager.addConstraint(new BananasFirst(),ConstraintManager.Priority.CRITICAL); - vraBuilder.setStateAndConstraintManager(stateManager,constraintManager); - VehicleRoutingAlgorithm vra = vraBuilder.build(); -// vra.setMaxIterations(100); //1.3.2-SNAPSHOT -// vra.setMaxIterations(100); + VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp).setStateAndConstraintManager(stateManager,constraintManager) + .buildAlgorithm(); Collection solutions = vra.searchSolutions(); @@ -206,7 +198,6 @@ public class MultipleProductsWithLoadConstraintExample { new GraphStreamViewer(vrp, Solutions.bestOf(solutions)).labelWith(GraphStreamViewer.Label.ID).setRenderShipments(true).display(); - } private static Location loc(Coordinate coordinate) { diff --git a/jsprit-examples/src/main/java/jsprit/examples/SolomonOpenExample.java b/jsprit-examples/src/main/java/jsprit/examples/SolomonOpenExample.java index 78304895..685a38c7 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/SolomonOpenExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/SolomonOpenExample.java @@ -20,7 +20,7 @@ import jsprit.analysis.toolbox.GraphStreamViewer; import jsprit.analysis.toolbox.GraphStreamViewer.Label; import jsprit.analysis.toolbox.Plotter; import jsprit.core.algorithm.VehicleRoutingAlgorithm; -import jsprit.core.algorithm.io.VehicleRoutingAlgorithms; +import jsprit.core.algorithm.box.Jsprit; import jsprit.core.algorithm.selector.SelectBest; import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.io.VrpXMLReader; @@ -64,7 +64,8 @@ public class SolomonOpenExample { * The algorithm can be defined and configured in an xml-file. */ // VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp); - VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_fix.xml"); +// VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_fix.xml"); + VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp); // vra.setPrematureBreak(100); // vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png")); /* diff --git a/jsprit-examples/src/main/java/jsprit/examples/SolomonWithSkillsExample.java b/jsprit-examples/src/main/java/jsprit/examples/SolomonWithSkillsExample.java index 0551b25d..39b35d3c 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/SolomonWithSkillsExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/SolomonWithSkillsExample.java @@ -21,6 +21,7 @@ package jsprit.examples; import jsprit.analysis.toolbox.Plotter; import jsprit.core.algorithm.VehicleRoutingAlgorithm; import jsprit.core.algorithm.VehicleRoutingAlgorithmBuilder; +import jsprit.core.algorithm.box.Jsprit; import jsprit.core.algorithm.state.StateManager; import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.constraint.ConstraintManager; @@ -90,9 +91,7 @@ public class SolomonWithSkillsExample { ConstraintManager constraintManager = new ConstraintManager(skillProblem,stateManager); constraintManager.addSkillsConstraint(); - VehicleRoutingAlgorithm vra = vraBuilder.build(); -// vra.setMaxIterations(500); - + VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(skillProblem).setStateAndConstraintManager(stateManager,constraintManager).buildAlgorithm(); Collection solutions = vra.searchSolutions(); VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions); diff --git a/jsprit-examples/src/main/java/jsprit/examples/VRPWithBackhaulsExample2.java b/jsprit-examples/src/main/java/jsprit/examples/VRPWithBackhaulsExample2.java index 82ca4426..0f13a5d8 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/VRPWithBackhaulsExample2.java +++ b/jsprit-examples/src/main/java/jsprit/examples/VRPWithBackhaulsExample2.java @@ -16,8 +16,10 @@ ******************************************************************************/ package jsprit.examples; +import jsprit.analysis.toolbox.AlgorithmSearchProgressChartListener; +import jsprit.analysis.toolbox.Plotter; import jsprit.core.algorithm.VehicleRoutingAlgorithm; -import jsprit.core.algorithm.VehicleRoutingAlgorithmBuilder; +import jsprit.core.algorithm.box.Jsprit; import jsprit.core.algorithm.selector.SelectBest; import jsprit.core.algorithm.state.StateManager; import jsprit.core.analysis.SolutionAnalyser; @@ -73,16 +75,25 @@ public class VRPWithBackhaulsExample2 { */ // VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_solomon.xml"); - VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(vrp,"input/algorithmConfig_solomon.xml"); - vraBuilder.addDefaultCostCalculators(); - vraBuilder.addCoreConstraints(); +// VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(vrp,"input/algorithmConfig_solomon.xml"); +// vraBuilder.addDefaultCostCalculators(); +// vraBuilder.addCoreConstraints(); StateManager stateManager = new StateManager(vrp); ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager); constraintManager.addConstraint(new ServiceDeliveriesFirstConstraint(), ConstraintManager.Priority.CRITICAL); - vraBuilder.setStateAndConstraintManager(stateManager,constraintManager); - VehicleRoutingAlgorithm vra = vraBuilder.build(); +// vraBuilder.setStateAndConstraintManager(stateManager,constraintManager); + +// VehicleRoutingAlgorithm vra = vraBuilder.build(); + + + VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp) + .setStateAndConstraintManager(stateManager, constraintManager) + .setProperty(Jsprit.Parameter.FIXED_COST_PARAM.toString(),"0.") + .buildAlgorithm(); + vra.setMaxIterations(2000); + vra.addListener(new AlgorithmSearchProgressChartListener("output/search")); @@ -107,9 +118,9 @@ public class VRPWithBackhaulsExample2 { * Plot solution. */ // SolutionPlotter.plotSolutionAsPNG(vrp, solution, "output/pd_solomon_r101_solution.png","pd_r101"); -// Plotter plotter = new Plotter(vrp, solution); -// plotter.setLabel(Label.SIZE); -// plotter.plot("output/vrpwbh_christophides_vrpnc1_solution.png","vrpwbh_vrpnc1"); + Plotter plotter = new Plotter(vrp, solution); +// plotter.setLabel(Plotter.Label.SIZE); + plotter.plot("output/vrpwbh_christophides_vrpnc1_solution.png","vrpwbh_vrpnc1"); SolutionAnalyser analyser = new SolutionAnalyser(vrp, solution, new SolutionAnalyser.DistanceCalculator() {