From 87bc74e1801ca56ad6b4e46a5dd3b3c7f32e98d5 Mon Sep 17 00:00:00 2001 From: oblonski Date: Thu, 6 Aug 2015 18:13:34 +0200 Subject: [PATCH] make ClusterRuin deal with jobs without location - #170 --- .../core/algorithm/ruin/DBSCANClusterer.java | 56 +++++++++++-------- .../problem/solution/route/VehicleRoute.java | 5 +- .../core/algorithm/ruin/RuinBreakTest.java | 4 +- .../core/algorithm/ruin/RuinClustersTest.java | 34 +++++++++++ .../VariableStartAndWaitingTimeExample.java | 8 +-- 5 files changed, 77 insertions(+), 30 deletions(-) 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 index a0ad4b9f..991fefb2 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/DBSCANClusterer.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/DBSCANClusterer.java @@ -3,8 +3,6 @@ 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; @@ -30,24 +28,24 @@ public class DBSCANClusterer { private int id; - public LocationWrapper(Job job) { - this.locations = getLocations(job); + public LocationWrapper(Job job, List locations) { + this.locations = locations; 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; - } +// 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; @@ -126,14 +124,29 @@ public class DBSCANClusterer { } 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 locations = getLocationWrappers(route); List> clusterResults = getClusters(route, locations); return makeList(clusterResults); } + private List getLocationWrappers(VehicleRoute route) { + List locations = new ArrayList(route.getTourActivities().getJobs().size()); + Map> jobs2locations = new HashMap>(); + for(TourActivity act : route.getActivities()){ + if(act instanceof TourActivity.JobActivity){ + Job job = ((TourActivity.JobActivity) act).getJob(); + if(!jobs2locations.containsKey(job)){ + jobs2locations.put(job,new ArrayList()); + } + jobs2locations.get(job).add(act.getLocation()); + } + } + for(Job j : jobs2locations.keySet()){ + locations.add(new LocationWrapper(j,jobs2locations.get(j))); + } + return locations; + } + private List> getClusters(VehicleRoute route, List locations) { double sampledDistance; if(epsDistance != null) sampledDistance = epsDistance; @@ -162,10 +175,7 @@ public class DBSCANClusterer { 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 locations = getLocationWrappers(route); List> clusterResults = getClusters(route,locations); if(clusterResults.isEmpty()) return Collections.emptyList(); Cluster randomCluster = RandomUtils.nextItem(clusterResults, random); diff --git a/jsprit-core/src/main/java/jsprit/core/problem/solution/route/VehicleRoute.java b/jsprit-core/src/main/java/jsprit/core/problem/solution/route/VehicleRoute.java index 210bd5c3..b576ea92 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/solution/route/VehicleRoute.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/solution/route/VehicleRoute.java @@ -128,7 +128,10 @@ public class VehicleRoute { @Override public List createActivities(Job job) { List acts = new ArrayList(); - if(job instanceof Service){ + if(job instanceof Break){ + acts.add(BreakActivity.newInstance((Break)job)); + } + else if(job instanceof Service){ acts.add(serviceActivityFactory.createActivity((Service) job)); } else if(job instanceof Shipment){ diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinBreakTest.java b/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinBreakTest.java index 3c554ecc..d83d5ebb 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinBreakTest.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinBreakTest.java @@ -21,11 +21,11 @@ import java.util.List; public class RuinBreakTest { @Test - public void test(){ + public void itShouldRuinBreaks(){ Break aBreak = Break.Builder.newInstance("break").build(); VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("loc")) .setBreak(aBreak).build(); - VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(v).build(); + VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).addVehicle(v).build(); VehicleRoute route = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()).addService(aBreak).build(); TourActivity tourActivity = route.getActivities().get(0); System.out.println(tourActivity); 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 index 5bfcc6ad..3d42d7b3 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinClustersTest.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/ruin/RuinClustersTest.java @@ -3,9 +3,12 @@ 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.Break; import jsprit.core.problem.job.Job; import jsprit.core.problem.job.Service; import jsprit.core.problem.solution.route.VehicleRoute; +import jsprit.core.problem.solution.route.activity.BreakActivity; +import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.problem.vehicle.VehicleImpl; import junit.framework.Assert; import org.junit.Test; @@ -45,4 +48,35 @@ public class RuinClustersTest { Assert.assertEquals(5,ruined.size()); } + + @Test + public void itShouldRuinTwoObviousClustersEvenThereAreBreaks(){ + 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") + .setBreak((Break) Break.Builder.newInstance("break").setServiceTime(10).setTimeWindow(TimeWindow.newInstance(20,30)).build()) + .setStartLocation(Location.newInstance(0, 0)).build(); + + VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addJob(s1).addJob(s2).setFleetSize(VehicleRoutingProblem.FleetSize.FINITE) + .addJob(s6).addJob(s7).addJob(s0).addJob(s3).addJob(s4).addJob(s5).addVehicle(v).build(); + + VehicleRoute vr1 = VehicleRoute.Builder.newInstance(v).addService(s0).addService(v.getBreak()).addService(s1).addService(s2).addService(s3).setJobActivityFactory(vrp.getJobActivityFactory()).build(); + ((BreakActivity)vr1.getActivities().get(1)).setLocation(Location.newInstance(9,1)); + 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/VariableStartAndWaitingTimeExample.java b/jsprit-examples/src/main/java/jsprit/examples/VariableStartAndWaitingTimeExample.java index 041db797..842a71e3 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/VariableStartAndWaitingTimeExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/VariableStartAndWaitingTimeExample.java @@ -55,11 +55,11 @@ public class VariableStartAndWaitingTimeExample { VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setType(type).setReturnToDepot(true) .setStartLocation(Location.newInstance(0, 0)) .setEarliestStart(0).setLatestArrival(500) - .setBreak((Break) Break.Builder.newInstance("v2-break").setTimeWindow(TimeWindow.newInstance(100,150)).setServiceTime(50).build()) + .setBreak((Break) Break.Builder.newInstance("v2-break").setTimeWindow(TimeWindow.newInstance(60,80)).setServiceTime(50).build()) .build(); VehicleImpl v3 = VehicleImpl.Builder.newInstance("v3").setType(type2).setReturnToDepot(true) .setStartLocation(Location.newInstance(0.5, 10.5)) - .setBreak((Break) Break.Builder.newInstance("v3-break").setTimeWindow(TimeWindow.newInstance(100,150)).setServiceTime(50).build()) + .setBreak((Break) Break.Builder.newInstance("v3-break").setTimeWindow(TimeWindow.newInstance(60,80)).setServiceTime(50).build()) .setEarliestStart(0).setLatestArrival(500) .build(); // VehicleImpl v4 = VehicleImpl.Builder.newInstance("v4").setType(type3).setReturnToDepot(true) @@ -124,8 +124,8 @@ public class VariableStartAndWaitingTimeExample { .addCoreStateAndConstraintStuff(true) .setStateAndConstraintManager(stateManager, constraintManager) .setProperty(Jsprit.Parameter.THRESHOLD_INI, "0.1") - .setProperty(Jsprit.Strategy.CLUSTER_REGRET, "0.") - .setProperty(Jsprit.Strategy.CLUSTER_BEST, "0.") +// .setProperty(Jsprit.Strategy.CLUSTER_REGRET, "0.") +// .setProperty(Jsprit.Strategy.CLUSTER_BEST, "0.") // .setProperty(Jsprit.Strategy.WORST_REGRET, "0.") // .setProperty(Jsprit.Strategy.RANDOM_REGRET, "0.") // .setProperty(Jsprit.Strategy.RADIAL_REGRET, "0.")