mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
make ClusterRuin deal with jobs without location - #170
This commit is contained in:
parent
11eb5dc983
commit
87bc74e180
5 changed files with 77 additions and 30 deletions
|
|
@ -3,8 +3,6 @@ package jsprit.core.algorithm.ruin;
|
||||||
import jsprit.core.problem.Location;
|
import jsprit.core.problem.Location;
|
||||||
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
import jsprit.core.problem.job.Job;
|
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.VehicleRoute;
|
||||||
import jsprit.core.problem.solution.route.activity.TourActivity;
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
import jsprit.core.util.RandomNumberGeneration;
|
import jsprit.core.util.RandomNumberGeneration;
|
||||||
|
|
@ -30,24 +28,24 @@ public class DBSCANClusterer {
|
||||||
|
|
||||||
private int id;
|
private int id;
|
||||||
|
|
||||||
public LocationWrapper(Job job) {
|
public LocationWrapper(Job job, List<Location> locations) {
|
||||||
this.locations = getLocations(job);
|
this.locations = locations;
|
||||||
objCounter++;
|
objCounter++;
|
||||||
this.job = job;
|
this.job = job;
|
||||||
this.id = objCounter;
|
this.id = objCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Location> getLocations(Job job){
|
// private List<Location> getLocations(Job job){
|
||||||
List<Location> locs = new ArrayList<Location>();
|
// List<Location> locs = new ArrayList<Location>();
|
||||||
if(job instanceof Service) {
|
// if(job instanceof Service) {
|
||||||
locs.add(((Service) job).getLocation());
|
// locs.add(((Service) job).getLocation());
|
||||||
}
|
// }
|
||||||
else if(job instanceof Shipment){
|
// else if(job instanceof Shipment){
|
||||||
locs.add(((Shipment) job).getPickupLocation());
|
// locs.add(((Shipment) job).getPickupLocation());
|
||||||
locs.add(((Shipment) job).getDeliveryLocation());
|
// locs.add(((Shipment) job).getDeliveryLocation());
|
||||||
}
|
// }
|
||||||
return locs;
|
// return locs;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public List<Location> getLocations() {
|
public List<Location> getLocations() {
|
||||||
return locations;
|
return locations;
|
||||||
|
|
@ -126,14 +124,29 @@ public class DBSCANClusterer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<List<Job>> getClusters(VehicleRoute route){
|
public List<List<Job>> getClusters(VehicleRoute route){
|
||||||
List<LocationWrapper> locations = new ArrayList<LocationWrapper>(route.getTourActivities().getJobs().size());
|
List<LocationWrapper> locations = getLocationWrappers(route);
|
||||||
for(Job j : route.getTourActivities().getJobs()){
|
|
||||||
locations.add(new LocationWrapper(j));
|
|
||||||
}
|
|
||||||
List<Cluster<LocationWrapper>> clusterResults = getClusters(route, locations);
|
List<Cluster<LocationWrapper>> clusterResults = getClusters(route, locations);
|
||||||
return makeList(clusterResults);
|
return makeList(clusterResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<LocationWrapper> getLocationWrappers(VehicleRoute route) {
|
||||||
|
List<LocationWrapper> locations = new ArrayList<LocationWrapper>(route.getTourActivities().getJobs().size());
|
||||||
|
Map<Job,List<Location>> jobs2locations = new HashMap<Job, List<Location>>();
|
||||||
|
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<Location>());
|
||||||
|
}
|
||||||
|
jobs2locations.get(job).add(act.getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(Job j : jobs2locations.keySet()){
|
||||||
|
locations.add(new LocationWrapper(j,jobs2locations.get(j)));
|
||||||
|
}
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
private List<Cluster<LocationWrapper>> getClusters(VehicleRoute route, List<LocationWrapper> locations) {
|
private List<Cluster<LocationWrapper>> getClusters(VehicleRoute route, List<LocationWrapper> locations) {
|
||||||
double sampledDistance;
|
double sampledDistance;
|
||||||
if(epsDistance != null) sampledDistance = epsDistance;
|
if(epsDistance != null) sampledDistance = epsDistance;
|
||||||
|
|
@ -162,10 +175,7 @@ public class DBSCANClusterer {
|
||||||
|
|
||||||
public List<Job> getRandomCluster(VehicleRoute route){
|
public List<Job> getRandomCluster(VehicleRoute route){
|
||||||
if(route.isEmpty()) return Collections.emptyList();
|
if(route.isEmpty()) return Collections.emptyList();
|
||||||
List<LocationWrapper> locations = new ArrayList<LocationWrapper>(route.getTourActivities().getJobs().size());
|
List<LocationWrapper> locations = getLocationWrappers(route);
|
||||||
for(Job j : route.getTourActivities().getJobs()){
|
|
||||||
locations.add(new LocationWrapper(j));
|
|
||||||
}
|
|
||||||
List<Cluster<LocationWrapper>> clusterResults = getClusters(route,locations);
|
List<Cluster<LocationWrapper>> clusterResults = getClusters(route,locations);
|
||||||
if(clusterResults.isEmpty()) return Collections.emptyList();
|
if(clusterResults.isEmpty()) return Collections.emptyList();
|
||||||
Cluster<LocationWrapper> randomCluster = RandomUtils.nextItem(clusterResults, random);
|
Cluster<LocationWrapper> randomCluster = RandomUtils.nextItem(clusterResults, random);
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,10 @@ public class VehicleRoute {
|
||||||
@Override
|
@Override
|
||||||
public List<AbstractActivity> createActivities(Job job) {
|
public List<AbstractActivity> createActivities(Job job) {
|
||||||
List<AbstractActivity> acts = new ArrayList<AbstractActivity>();
|
List<AbstractActivity> acts = new ArrayList<AbstractActivity>();
|
||||||
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));
|
acts.add(serviceActivityFactory.createActivity((Service) job));
|
||||||
}
|
}
|
||||||
else if(job instanceof Shipment){
|
else if(job instanceof Shipment){
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ import java.util.List;
|
||||||
public class RuinBreakTest {
|
public class RuinBreakTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test(){
|
public void itShouldRuinBreaks(){
|
||||||
Break aBreak = Break.Builder.newInstance("break").build();
|
Break aBreak = Break.Builder.newInstance("break").build();
|
||||||
VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("loc"))
|
VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("loc"))
|
||||||
.setBreak(aBreak).build();
|
.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();
|
VehicleRoute route = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()).addService(aBreak).build();
|
||||||
TourActivity tourActivity = route.getActivities().get(0);
|
TourActivity tourActivity = route.getActivities().get(0);
|
||||||
System.out.println(tourActivity);
|
System.out.println(tourActivity);
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,12 @@ package jsprit.core.algorithm.ruin;
|
||||||
import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance;
|
import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance;
|
||||||
import jsprit.core.problem.Location;
|
import jsprit.core.problem.Location;
|
||||||
import jsprit.core.problem.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.problem.job.Break;
|
||||||
import jsprit.core.problem.job.Job;
|
import jsprit.core.problem.job.Job;
|
||||||
import jsprit.core.problem.job.Service;
|
import jsprit.core.problem.job.Service;
|
||||||
import jsprit.core.problem.solution.route.VehicleRoute;
|
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 jsprit.core.problem.vehicle.VehicleImpl;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -45,4 +48,35 @@ public class RuinClustersTest {
|
||||||
Assert.assertEquals(5,ruined.size());
|
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<Job> ruined = rc.ruinRoutes(Arrays.asList(vr1,vr2));
|
||||||
|
Assert.assertEquals(5,ruined.size());
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,11 +55,11 @@ public class VariableStartAndWaitingTimeExample {
|
||||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setType(type).setReturnToDepot(true)
|
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setType(type).setReturnToDepot(true)
|
||||||
.setStartLocation(Location.newInstance(0, 0))
|
.setStartLocation(Location.newInstance(0, 0))
|
||||||
.setEarliestStart(0).setLatestArrival(500)
|
.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();
|
.build();
|
||||||
VehicleImpl v3 = VehicleImpl.Builder.newInstance("v3").setType(type2).setReturnToDepot(true)
|
VehicleImpl v3 = VehicleImpl.Builder.newInstance("v3").setType(type2).setReturnToDepot(true)
|
||||||
.setStartLocation(Location.newInstance(0.5, 10.5))
|
.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)
|
.setEarliestStart(0).setLatestArrival(500)
|
||||||
.build();
|
.build();
|
||||||
// VehicleImpl v4 = VehicleImpl.Builder.newInstance("v4").setType(type3).setReturnToDepot(true)
|
// VehicleImpl v4 = VehicleImpl.Builder.newInstance("v4").setType(type3).setReturnToDepot(true)
|
||||||
|
|
@ -124,8 +124,8 @@ public class VariableStartAndWaitingTimeExample {
|
||||||
.addCoreStateAndConstraintStuff(true)
|
.addCoreStateAndConstraintStuff(true)
|
||||||
.setStateAndConstraintManager(stateManager, constraintManager)
|
.setStateAndConstraintManager(stateManager, constraintManager)
|
||||||
.setProperty(Jsprit.Parameter.THRESHOLD_INI, "0.1")
|
.setProperty(Jsprit.Parameter.THRESHOLD_INI, "0.1")
|
||||||
.setProperty(Jsprit.Strategy.CLUSTER_REGRET, "0.")
|
// .setProperty(Jsprit.Strategy.CLUSTER_REGRET, "0.")
|
||||||
.setProperty(Jsprit.Strategy.CLUSTER_BEST, "0.")
|
// .setProperty(Jsprit.Strategy.CLUSTER_BEST, "0.")
|
||||||
// .setProperty(Jsprit.Strategy.WORST_REGRET, "0.")
|
// .setProperty(Jsprit.Strategy.WORST_REGRET, "0.")
|
||||||
// .setProperty(Jsprit.Strategy.RANDOM_REGRET, "0.")
|
// .setProperty(Jsprit.Strategy.RANDOM_REGRET, "0.")
|
||||||
// .setProperty(Jsprit.Strategy.RADIAL_REGRET, "0.")
|
// .setProperty(Jsprit.Strategy.RADIAL_REGRET, "0.")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue