diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/InfiniteVehicles.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/InfiniteVehicles.java index 5fbdb93c..1e3551cd 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/InfiniteVehicles.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/InfiniteVehicles.java @@ -86,7 +86,7 @@ class InfiniteVehicles implements VehicleFleetManager { @Override public Collection getAvailableVehicles(Vehicle withoutThisType) { Collection vehicles = new ArrayList(); - VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType.getType().getTypeId(), withoutThisType.getStartLocation().getId(), withoutThisType.getEndLocation().getId(), withoutThisType.getEarliestDeparture(), withoutThisType.getLatestArrival(), withoutThisType.getSkills(), withoutThisType.isReturnToDepot()); + VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType.getType().getTypeId(), withoutThisType.getStartLocation().getId(), withoutThisType.getEndLocation().getId(), withoutThisType.getEarliestDeparture(), withoutThisType.getLatestArrival(), withoutThisType.getSkills(), withoutThisType.getProhibitedTasks(), withoutThisType.isReturnToDepot()); for (VehicleTypeKey key : types.keySet()) { if (!key.equals(thisKey)) { vehicles.add(types.get(key)); diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleImpl.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleImpl.java index f473ab40..2be7e81c 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleImpl.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleImpl.java @@ -370,9 +370,9 @@ public class VehicleImpl extends AbstractVehicle { // setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(),startLocation.getId(),endLocation.getId(),earliestDeparture,latestArrival,skills)); if (builder.aBreak != null) { - setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(), startLocation.getId(), endLocation.getId(), earliestDeparture, latestArrival, skills, returnToDepot, getUserData(), aBreak.getTimeWindow().getStart(), aBreak.getTimeWindow().getEnd(), aBreak.getServiceDuration())); + setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(), startLocation.getId(), endLocation.getId(), earliestDeparture, latestArrival, skills, prohibitedTasks, returnToDepot, getUserData(), aBreak.getTimeWindow().getStart(), aBreak.getTimeWindow().getEnd(), aBreak.getServiceDuration())); } else { - setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(), startLocation.getId(), endLocation.getId(), earliestDeparture, latestArrival, skills, returnToDepot, getUserData())); + setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(), startLocation.getId(), endLocation.getId(), earliestDeparture, latestArrival, skills, prohibitedTasks, returnToDepot, getUserData())); } } diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleTypeKey.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleTypeKey.java index 8d04180e..e0133162 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleTypeKey.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleTypeKey.java @@ -20,7 +20,11 @@ package com.graphhopper.jsprit.core.problem.vehicle; import com.graphhopper.jsprit.core.problem.AbstractVehicle; import com.graphhopper.jsprit.core.problem.Skills; +import java.util.Collection; +import java.util.HashSet; import java.util.Objects; +import java.util.Set; + /** * Key to identify similar vehicles @@ -42,8 +46,9 @@ public class VehicleTypeKey extends AbstractVehicle.AbstractTypeKey { public final double earliestBreakStart; public final double latestBreakStart; public final double breakDuration; + private Set prohibitedTasks = new HashSet<>(); - public VehicleTypeKey(String typeId, String startLocationId, String endLocationId, double earliestStart, double latestEnd, Skills skills, boolean returnToDepot, Object userData, double earliestBreakStart, double latestBreakStart, double breakDuration) { + public VehicleTypeKey(String typeId, String startLocationId, String endLocationId, double earliestStart, double latestEnd, Skills skills, Collection prohibitedTasks, boolean returnToDepot, Object userData, double earliestBreakStart, double latestBreakStart, double breakDuration) { this.type = typeId; this.startLocationId = startLocationId; this.endLocationId = endLocationId; @@ -55,14 +60,15 @@ public class VehicleTypeKey extends AbstractVehicle.AbstractTypeKey { this.earliestBreakStart = earliestBreakStart; this.latestBreakStart = latestBreakStart; this.breakDuration = breakDuration; + this.prohibitedTasks.addAll(prohibitedTasks); } - public VehicleTypeKey(String typeId, String startLocationId, String endLocationId, double earliestStart, double latestEnd, Skills skills, boolean returnToDepot, Object userData) { - this(typeId, startLocationId, endLocationId, earliestStart, latestEnd, skills, returnToDepot, userData, 0, Double.MAX_VALUE, 0); + public VehicleTypeKey(String typeId, String startLocationId, String endLocationId, double earliestStart, double latestEnd, Skills skills, Collection prohibitedTasks, boolean returnToDepot, Object userData) { + this(typeId, startLocationId, endLocationId, earliestStart, latestEnd, skills, prohibitedTasks, returnToDepot, userData, 0, Double.MAX_VALUE, 0); } - public VehicleTypeKey(String typeId, String startLocationId, String endLocationId, double earliestStart, double latestEnd, Skills skills, boolean returnToDepot) { - this(typeId, startLocationId, endLocationId, earliestStart, latestEnd, skills, returnToDepot, null); + public VehicleTypeKey(String typeId, String startLocationId, String endLocationId, double earliestStart, double latestEnd, Skills skills, Collection prohibitedTasks, boolean returnToDepot) { + this(typeId, startLocationId, endLocationId, earliestStart, latestEnd, skills, prohibitedTasks, returnToDepot, null); } @Override @@ -83,6 +89,7 @@ public class VehicleTypeKey extends AbstractVehicle.AbstractTypeKey { if (Double.compare(that.breakDuration, breakDuration) != 0) return false; if (Double.compare(that.earliestBreakStart, earliestBreakStart) != 0) return false; if (Double.compare(that.latestBreakStart, latestBreakStart) != 0) return false; + if (prohibitedTasks.size() != that.prohibitedTasks.size() || !prohibitedTasks.containsAll(that.prohibitedTasks)) return false; return true; } @@ -109,6 +116,7 @@ public class VehicleTypeKey extends AbstractVehicle.AbstractTypeKey { result = 31 * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(latestBreakStart); result = 31 * result + (int) (temp ^ (temp >>> 32)); + result = 31 * result + prohibitedTasks.hashCode(); return result; } @@ -119,7 +127,11 @@ public class VehicleTypeKey extends AbstractVehicle.AbstractTypeKey { stringBuilder.append(type).append("_").append(startLocationId).append("_").append(endLocationId) .append("_").append(Double.toString(earliestStart)).append("_").append(Double.toString(latestEnd)); if (userData != null) - stringBuilder.append("_").append(userData.toString()); + stringBuilder.append("_").append(userData.toString()).append("_"); + + for (String t : prohibitedTasks) + stringBuilder.append(t).append("_"); + return stringBuilder.toString(); } diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleTypeKeyTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleTypeKeyTest.java index 2d85694b..b11bfbc5 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleTypeKeyTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/vehicle/VehicleTypeKeyTest.java @@ -22,6 +22,8 @@ package com.graphhopper.jsprit.core.problem.vehicle; import com.graphhopper.jsprit.core.problem.Location; import org.junit.Test; +import java.util.UUID; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -62,4 +64,32 @@ public class VehicleTypeKeyTest { .setUserData(new String("it's just stupid test")).build(); assertFalse(v1.getVehicleTypeIdentifier().equals(v2.getVehicleTypeIdentifier())); } + + + + @Test + public void typeIdentifierShouldNotBeEqualWithExcludedTasks() { + String taskId1 = UUID.randomUUID().toString(), taskId2 = UUID.randomUUID().toString(), taskId3 = UUID.randomUUID().toString(); + Vehicle v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(Location.newInstance("start")) + .addExcludedTask(taskId1).addExcludedTask(taskId2).addExcludedTask(taskId3) + .setUserData(new String("it's just a test")).build(); + Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("start")) + .addExcludedTask(taskId1).addExcludedTask(taskId2) + .setUserData(new String("it's just stupid test")).build(); + assertFalse(v1.getVehicleTypeIdentifier().equals(v2.getVehicleTypeIdentifier())); + } + + @Test + public void typeIdentifierShouldBeEqualWithExcludedTasks() { + String taskId1 = UUID.randomUUID().toString(), taskId2 = UUID.randomUUID().toString(), taskId3 = UUID.randomUUID().toString(); + Vehicle v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(Location.newInstance("start")) + .addExcludedTask(taskId1).addExcludedTask(taskId2).addExcludedTask(taskId3) + .build(); + Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("start")) + .addExcludedTask(taskId2).addExcludedTask(taskId3).addExcludedTask(taskId1).addExcludedTask(taskId3) + .build(); + assertTrue(v1.getVehicleTypeIdentifier().equals(v2.getVehicleTypeIdentifier())); + } + + }