mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
include driver can serve task count (#59)
* include driver can serve task count * . * remove back * can serve fix
This commit is contained in:
parent
0124986886
commit
7cc8cf1838
2 changed files with 157 additions and 29 deletions
|
|
@ -3,7 +3,10 @@ package com.graphhopper.jsprit.core.algorithm.recreate;
|
|||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Break;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -27,9 +30,10 @@ public class RandomInsertion extends AbstractInsertionStrategy {
|
|||
void initJobsCanBeServedByNumDrivers() {
|
||||
for (Job job : vrp.getJobs().values()) {
|
||||
int count = 0;
|
||||
for (Vehicle vehicle : vrp.getVehicles())
|
||||
if (vehicle.getSkills().values().containsAll(job.getRequiredSkills().values()))
|
||||
for (Vehicle vehicle : vrp.getVehicles()) {
|
||||
if (cabBeServedByVehicle(job, vehicle))
|
||||
count++;
|
||||
}
|
||||
|
||||
jobCanBeServedByDriversCount.put(job.getId(), count);
|
||||
}
|
||||
|
|
@ -52,14 +56,7 @@ public class RandomInsertion extends AbstractInsertionStrategy {
|
|||
List<Job> unassignedJobList = new ArrayList<>(unassignedJobs);
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
|
||||
final double p = random.nextDouble();
|
||||
if (p < .25)
|
||||
Collections.sort(unassignedJobList, new AccordingToPriorities());
|
||||
else if (p < .5)
|
||||
Collections.sort(unassignedJobList, new Comparator<Job>() {
|
||||
@Override
|
||||
public int compare(Job o1, Job o2) {return jobCanBeServedByDriversCount.get(o1.getId()) - jobCanBeServedByDriversCount.get(o2.getId());}
|
||||
});
|
||||
sortJobs(unassignedJobList);
|
||||
|
||||
for (Job unassignedJob : unassignedJobList) {
|
||||
List<VehicleRoute> routes = new ArrayList<>(vehicleRoutes);
|
||||
|
|
@ -99,4 +96,37 @@ public class RandomInsertion extends AbstractInsertionStrategy {
|
|||
return badJobs;
|
||||
}
|
||||
|
||||
void sortJobs(List<Job> unassignedJobList) {
|
||||
final double p = random.nextDouble();
|
||||
if (p < .25)
|
||||
Collections.sort(unassignedJobList, new AccordingToPriorities());
|
||||
else if (p < .75)
|
||||
Collections.sort(unassignedJobList, new Comparator<Job>() {
|
||||
@Override
|
||||
public int compare(Job o1, Job o2) {return jobCanBeServedByDriversCount.get(o1.getId()) - jobCanBeServedByDriversCount.get(o2.getId());}
|
||||
});
|
||||
}
|
||||
|
||||
protected static boolean inTimeWindow(Job job, double earliestDeparture, double latestArrival) {
|
||||
if (job instanceof Service) {
|
||||
return inTimeWindow(((Service) job).getTimeWindows(), earliestDeparture, latestArrival);
|
||||
} else if (job instanceof Shipment) {
|
||||
Shipment shipment = (Shipment) job;
|
||||
return inTimeWindow(shipment.getDeliveryTimeWindows(), earliestDeparture, latestArrival) && inTimeWindow(shipment.getPickupTimeWindows(), earliestDeparture, latestArrival);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean cabBeServedByVehicle(Job job, Vehicle vehicle) {
|
||||
return inTimeWindow(job, vehicle.getEarliestDeparture(), vehicle.getLatestArrival()) && vehicle.getSkills().values().containsAll(job.getRequiredSkills().values()) && vehicle.isTaskPermited(job.getId());
|
||||
}
|
||||
|
||||
private static boolean inTimeWindow(Collection<TimeWindow> timeWindows, double earliestDeparture, double latestArrival) {
|
||||
for (TimeWindow timeWindow : timeWindows) {
|
||||
if (timeWindow.getStart() < latestArrival && timeWindow.getEnd() > earliestDeparture)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,21 +2,16 @@ package com.graphhopper.jsprit.core.algorithm.recreate;
|
|||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Break;
|
||||
import com.graphhopper.jsprit.core.problem.job.Delivery;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.job.*;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class RandomInsertionTest {
|
||||
|
||||
|
|
@ -25,8 +20,8 @@ public class RandomInsertionTest {
|
|||
final HashSet<String> first = new HashSet<>(); first.add("C");
|
||||
final HashSet<String> second = new HashSet<>(); second.add("A");second.add("B");
|
||||
final VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE)
|
||||
.addVehicle(getVehicle("v1", Location.newInstance(0, 0), 0, 100, 20, first, false, 1, 1, false))
|
||||
.addVehicle(getVehicle("v2", Location.newInstance(0, 14), 0, 100, 20, second, false, 1, 1, false))
|
||||
.addVehicle(getVehicle("v1", Location.newInstance(0, 0), 0, 100, 20, first, false, 1, 1, false, null))
|
||||
.addVehicle(getVehicle("v2", Location.newInstance(0, 14), 0, 100, 20, second, false, 1, 1, false, null))
|
||||
.addJob(getService(Location.newInstance(0, 5), 0, 20, new HashSet<String>(), 1))
|
||||
.addJob(getService(Location.newInstance(0, 6), 0, 20, new HashSet<String>(), 1));
|
||||
|
||||
|
|
@ -34,7 +29,7 @@ public class RandomInsertionTest {
|
|||
final Map<String, Integer> jobCanBeServedByDriversCount = randomInsertion.jobCanBeServedByDriversCount;
|
||||
|
||||
for (int numCanServe : jobCanBeServedByDriversCount.values())
|
||||
assertEquals(numCanServe, 2);
|
||||
assertEquals(2, numCanServe);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -42,8 +37,8 @@ public class RandomInsertionTest {
|
|||
final HashSet<String> first = new HashSet<>(); first.add("C");
|
||||
final HashSet<String> second = new HashSet<>(); second.add("A");second.add("B");
|
||||
final VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE)
|
||||
.addVehicle(getVehicle("v1", Location.newInstance(0, 0), 0, 100, 20, first, false, 1, 1, true))
|
||||
.addVehicle(getVehicle("v2", Location.newInstance(0, 14), 0, 100, 20, second, false, 1, 1, true))
|
||||
.addVehicle(getVehicle("v1", Location.newInstance(0, 0), 0, 100, 20, first, false, 1, 1, true, null))
|
||||
.addVehicle(getVehicle("v2", Location.newInstance(0, 14), 0, 100, 20, second, false, 1, 1, true, null))
|
||||
.addJob(getService(Location.newInstance(0, 5), 0, 20, new HashSet<String>(), 1))
|
||||
.addJob(getService(Location.newInstance(0, 6), 0, 20, new HashSet<String>(), 1));
|
||||
|
||||
|
|
@ -58,7 +53,7 @@ public class RandomInsertionTest {
|
|||
}
|
||||
}
|
||||
|
||||
assertEquals(numBreaks, 2);
|
||||
assertEquals(2, numBreaks);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -66,8 +61,8 @@ public class RandomInsertionTest {
|
|||
final HashSet<String> first = new HashSet<>(); first.add("C");
|
||||
final HashSet<String> second = new HashSet<>(); second.add("A");second.add("B");
|
||||
final VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE)
|
||||
.addVehicle(getVehicle("v1", Location.newInstance(0, 0), 0, 100, 20, first, false, 1, 1, false))
|
||||
.addVehicle(getVehicle("v2", Location.newInstance(0, 14), 0, 100, 20, second, false, 1, 1, false))
|
||||
.addVehicle(getVehicle("v1", Location.newInstance(0, 0), 0, 100, 20, first, false, 1, 1, false, null))
|
||||
.addVehicle(getVehicle("v2", Location.newInstance(0, 14), 0, 100, 20, second, false, 1, 1, false, null))
|
||||
.addJob(getService(Location.newInstance(0, 5), 0, 20, first, 1))
|
||||
.addJob(getService(Location.newInstance(0, 6), 0, 20, second, 1));
|
||||
|
||||
|
|
@ -75,7 +70,28 @@ public class RandomInsertionTest {
|
|||
final Map<String, Integer> jobCanBeServedByDriversCount = randomInsertion.jobCanBeServedByDriversCount;
|
||||
|
||||
for (int numCanServe : jobCanBeServedByDriversCount.values())
|
||||
assertEquals(numCanServe, 1);
|
||||
assertEquals(1, numCanServe);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initJobsCanBeServedByNumDrivers3() {
|
||||
final Service service1 = getService(Location.newInstance(0, 5), 0, 20, new HashSet<String>(), 1);
|
||||
final Service service2 = getService(Location.newInstance(0, 6), 0, 20, new HashSet<String>(), 1);
|
||||
final Vehicle v1 = getVehicle("v1", Location.newInstance(0, 0), 0, 100, 20, new HashSet<String>(), false, 1, 1, false, service1.getId());
|
||||
final Vehicle v2 = getVehicle("v2", Location.newInstance(0, 14), 0, 100, 20, new HashSet<String>(), false, 1, 1, false, service2.getId());
|
||||
|
||||
|
||||
final VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE)
|
||||
.addVehicle(v1)
|
||||
.addVehicle(v2)
|
||||
.addJob(service1)
|
||||
.addJob(service2);
|
||||
|
||||
final RandomInsertion randomInsertion = new RandomInsertion(null, builder.build());
|
||||
final Map<String, Integer> jobCanBeServedByDriversCount = randomInsertion.jobCanBeServedByDriversCount;
|
||||
|
||||
for (int numCanServe : jobCanBeServedByDriversCount.values())
|
||||
assertEquals(1, numCanServe);
|
||||
}
|
||||
|
||||
private static Service getService(Location location, int start, int end, Set<String> requiredSkills, int priority) {
|
||||
|
|
@ -87,20 +103,102 @@ public class RandomInsertionTest {
|
|||
.addAllRequiredSkills(requiredSkills)
|
||||
.setPriority(priority)
|
||||
.setName(UUID.randomUUID().toString()).build();
|
||||
|
||||
}
|
||||
|
||||
private static Vehicle getVehicle(String id, Location location, int start, int end, int capacity, Set<String> skills, boolean returnToDepot, int fixedCost, int costPerDistance, boolean aBreak) {
|
||||
private static Vehicle getVehicle(String id, Location location, int start, int end, int capacity, Set<String> skills, boolean returnToDepot, int fixedCost, int costPerDistance, boolean aBreak, String excludeTask) {
|
||||
final VehicleImpl.Builder builder = VehicleImpl.Builder.newInstance(id)
|
||||
.setStartLocation(location).setLatestArrival(end).setEarliestStart(start).setType(
|
||||
VehicleTypeImpl.Builder.newInstance(UUID.randomUUID().toString()).setFixedCost(fixedCost).setCostPerDistance(costPerDistance).addCapacityDimension(0, capacity).build()
|
||||
)
|
||||
.addAllSkills(skills).setReturnToDepot(returnToDepot);
|
||||
|
||||
if (excludeTask != null)
|
||||
builder.addExcludedTask(excludeTask);
|
||||
if (aBreak)
|
||||
builder.setBreak(Break.Builder.newInstance("break_" + id).build());
|
||||
return builder.build();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inTimeWindowShipment() {
|
||||
assertTrue(RandomInsertion.inTimeWindow(getShipment(50, 100, 120, 200), 75, 170));
|
||||
assertTrue(RandomInsertion.inTimeWindow(getShipment(50, 100, 120, 200), 0, 170));
|
||||
assertTrue(RandomInsertion.inTimeWindow(getShipment(50, 100, 120, 200), 75, 150));
|
||||
assertTrue(RandomInsertion.inTimeWindow(getShipment(50, 100, 120, 200), 90, 250));
|
||||
|
||||
assertFalse(RandomInsertion.inTimeWindow(getShipment(50, 100, 120, 200), 90, 110));
|
||||
assertFalse(RandomInsertion.inTimeWindow(getShipment(50, 100, 120, 200), 110, 250));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inTimeWindowService() {
|
||||
assertTrue(RandomInsertion.inTimeWindow(getService(50, 100), 75, 170));
|
||||
assertTrue(RandomInsertion.inTimeWindow(getService(50, 100), 0, 75));
|
||||
assertTrue(RandomInsertion.inTimeWindow(getService(50, 100), 50, 100));
|
||||
|
||||
assertFalse(RandomInsertion.inTimeWindow(getService(50, 100), 110, 250));
|
||||
assertFalse(RandomInsertion.inTimeWindow(getService(50, 100), 0, 25));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortTest() {
|
||||
final HashSet<String> skillsService1 = new HashSet<>();
|
||||
skillsService1.add("a"); skillsService1.add("b");
|
||||
final HashSet<String> skillsService2 = new HashSet<>();
|
||||
skillsService2.add("c"); skillsService2.add("b");
|
||||
final HashSet<String> skillsDriver1 = new HashSet<>();
|
||||
skillsDriver1.add("a"); skillsDriver1.add("b");
|
||||
final HashSet<String> skillsDriver2 = new HashSet<>();
|
||||
skillsDriver2.add("c"); skillsDriver2.add("b");
|
||||
final HashSet<String> skillsDriver3 = new HashSet<>();
|
||||
skillsDriver3.add("c"); skillsDriver3.add("b"); skillsDriver3.add("a");
|
||||
final Service service1 = getService(Location.newInstance(0, 5), 0, 20, skillsService1, 1);
|
||||
final Service service2 = getService(Location.newInstance(0, 6), 0, 20, skillsService2, 1);
|
||||
final Vehicle v1 = getVehicle("v1", Location.newInstance(0, 0), 0, 100, 20, skillsDriver1, false, 1, 1, false, service2.getId());
|
||||
final Vehicle v2 = getVehicle("v2", Location.newInstance(0, 14), 0, 100, 20, skillsDriver2, false, 1, 1, false, service1.getId());
|
||||
final Vehicle v3 = getVehicle("v3", Location.newInstance(0, 14), 0, 100, 20, skillsDriver3, false, 1, 1, false, service2.getId());
|
||||
|
||||
|
||||
final VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.FINITE)
|
||||
.addVehicle(v1)
|
||||
.addVehicle(v2)
|
||||
.addVehicle(v3)
|
||||
.addJob(service1)
|
||||
.addJob(service2);
|
||||
final RandomInsertion randomInsertion = new RandomInsertion(null, builder.build());
|
||||
|
||||
randomInsertion.random = new Random() {
|
||||
@Override
|
||||
public double nextDouble() {
|
||||
return 0.5;
|
||||
}
|
||||
};
|
||||
|
||||
final List<Job> unassigned = new ArrayList<>();
|
||||
unassigned.add(service1); unassigned.add(service2);
|
||||
Collections.shuffle(unassigned);
|
||||
randomInsertion.sortJobs(unassigned);
|
||||
assertEquals(1, (int) randomInsertion.jobCanBeServedByDriversCount.get(service2.getId()));
|
||||
assertEquals(2, (int) randomInsertion.jobCanBeServedByDriversCount.get(service1.getId()));
|
||||
assertEquals(service2, unassigned.get(0));
|
||||
assertEquals(service1, unassigned.get(1));
|
||||
}
|
||||
|
||||
private Shipment getShipment(int pStart, int pEnd, int dStart, int dEnd) {
|
||||
return Shipment.Builder.newInstance(UUID.randomUUID().toString())
|
||||
.setPickupLocation(Location.newInstance(UUID.randomUUID().toString()))
|
||||
.setDeliveryLocation(Location.newInstance(UUID.randomUUID().toString()))
|
||||
.setPickupTimeWindow(new TimeWindow(pStart, pEnd))
|
||||
.setDeliveryTimeWindow(new TimeWindow(dStart, dEnd))
|
||||
.build();
|
||||
}
|
||||
|
||||
private Service getService(int start, int end) {
|
||||
return Service.Builder.newInstance(UUID.randomUUID().toString())
|
||||
.setLocation(Location.newInstance(UUID.randomUUID().toString()))
|
||||
.setTimeWindow(new TimeWindow(start, end))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue