1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

improve vehicle fleet manager

This commit is contained in:
oblonski 2015-10-09 13:06:21 +02:00
parent 75417e57b2
commit df105da98d
2 changed files with 60 additions and 74 deletions

View file

@ -20,7 +20,9 @@ import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
class VehicleFleetManagerImpl implements VehicleFleetManager { class VehicleFleetManagerImpl implements VehicleFleetManager {
@ -51,7 +53,6 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
public Vehicle getVehicle() { public Vehicle getVehicle() {
return vehicleList.get(0); return vehicleList.get(0);
// return vehicleList.getFirst();
} }
public boolean isEmpty() { public boolean isEmpty() {
@ -64,19 +65,21 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
private Collection<Vehicle> vehicles; private Collection<Vehicle> vehicles;
private Set<Vehicle> lockedVehicles; private TypeContainer[] vehicleTypes;
private Map<VehicleTypeKey, TypeContainer> typeMapOfAvailableVehicles; private boolean[] locked;
private Map<VehicleTypeKey, Vehicle> penaltyVehicles = new HashMap<VehicleTypeKey, Vehicle>();
private Vehicle[] vehicleArr;
public VehicleFleetManagerImpl(Collection<Vehicle> vehicles) { public VehicleFleetManagerImpl(Collection<Vehicle> vehicles) {
super(); super();
this.vehicles = vehicles; this.vehicles = vehicles;
this.lockedVehicles = new HashSet<Vehicle>(); int arrSize = vehicles.size() + 2;
makeMap(); locked = new boolean[arrSize];
logger.debug("initialise " + this); vehicleArr = new Vehicle[arrSize];
vehicleTypes = new TypeContainer[arrSize];
initializeVehicleTypes();
logger.debug("initialise {}",this);
} }
@Override @Override
@ -84,10 +87,12 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
return "[name=finiteVehicles]"; return "[name=finiteVehicles]";
} }
private void makeMap() { private void initializeVehicleTypes() {
typeMapOfAvailableVehicles = new HashMap<VehicleTypeKey, TypeContainer>(); for(int i=0;i< vehicleTypes.length;i++){
penaltyVehicles = new HashMap<VehicleTypeKey, Vehicle>(); vehicleTypes[i] = new TypeContainer();
}
for (Vehicle v : vehicles) { for (Vehicle v : vehicles) {
vehicleArr[v.getIndex()]=v;
addVehicle(v); addVehicle(v);
} }
} }
@ -96,19 +101,11 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
if (v.getType() == null) { if (v.getType() == null) {
throw new IllegalStateException("vehicle needs type"); throw new IllegalStateException("vehicle needs type");
} }
VehicleTypeKey typeKey = new VehicleTypeKey(v.getType().getTypeId(), v.getStartLocation().getId(), v.getEndLocation().getId(), v.getEarliestDeparture(), v.getLatestArrival(), v.getSkills(), v.isReturnToDepot()); vehicleTypes[v.getVehicleTypeIdentifier().getIndex()].add(v);
if (!typeMapOfAvailableVehicles.containsKey(typeKey)) {
typeMapOfAvailableVehicles.put(typeKey, new TypeContainer());
}
typeMapOfAvailableVehicles.get(typeKey).add(v);
} }
private void removeVehicle(Vehicle v) { private void removeVehicle(Vehicle v) {
VehicleTypeKey key = new VehicleTypeKey(v.getType().getTypeId(), v.getStartLocation().getId(), v.getEndLocation().getId(), v.getEarliestDeparture(), v.getLatestArrival(), v.getSkills(), v.isReturnToDepot()); vehicleTypes[v.getVehicleTypeIdentifier().getIndex()].remove(v);
if (typeMapOfAvailableVehicles.containsKey(key)) {
typeMapOfAvailableVehicles.get(key).remove(v);
}
} }
@ -121,13 +118,9 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
@Override @Override
public Collection<Vehicle> getAvailableVehicles() { public Collection<Vehicle> getAvailableVehicles() {
List<Vehicle> vehicles = new ArrayList<Vehicle>(); List<Vehicle> vehicles = new ArrayList<Vehicle>();
for (VehicleTypeKey key : typeMapOfAvailableVehicles.keySet()) { for(int i=0;i< vehicleTypes.length;i++){
if (!typeMapOfAvailableVehicles.get(key).isEmpty()) { if(!vehicleTypes[i].isEmpty()){
vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle()); vehicles.add(vehicleTypes[i].getVehicle());
} else {
if (penaltyVehicles.containsKey(key)) {
vehicles.add(penaltyVehicles.get(key));
}
} }
} }
return vehicles; return vehicles;
@ -136,15 +129,9 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
@Override @Override
public Collection<Vehicle> getAvailableVehicles(Vehicle withoutThisType) { public Collection<Vehicle> getAvailableVehicles(Vehicle withoutThisType) {
List<Vehicle> vehicles = new ArrayList<Vehicle>(); List<Vehicle> vehicles = new ArrayList<Vehicle>();
VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType.getType().getTypeId(), withoutThisType.getStartLocation().getId(), withoutThisType.getEndLocation().getId(), withoutThisType.getEarliestDeparture(), withoutThisType.getLatestArrival(), withoutThisType.getSkills(), withoutThisType.isReturnToDepot()); for(int i=0;i< vehicleTypes.length;i++){
for (VehicleTypeKey key : typeMapOfAvailableVehicles.keySet()) { if(!vehicleTypes[i].isEmpty() && i != withoutThisType.getVehicleTypeIdentifier().getIndex()){
if (key.equals(thisKey)) continue; vehicles.add(vehicleTypes[i].getVehicle());
if (!typeMapOfAvailableVehicles.get(key).isEmpty()) {
vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle());
} else {
if (penaltyVehicles.containsKey(key)) {
vehicles.add(penaltyVehicles.get(key));
}
} }
} }
return vehicles; return vehicles;
@ -158,11 +145,13 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
if (vehicles.isEmpty() || vehicle instanceof NoVehicle) { if (vehicles.isEmpty() || vehicle instanceof NoVehicle) {
return; return;
} }
boolean locked = lockedVehicles.add(vehicle); if(locked[vehicle.getIndex()]){
removeVehicle(vehicle);
if (!locked) {
throw new IllegalStateException("cannot lock vehicle twice " + vehicle.getId()); throw new IllegalStateException("cannot lock vehicle twice " + vehicle.getId());
} }
else{
locked[vehicle.getIndex()] = true;
removeVehicle(vehicle);
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -170,11 +159,10 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
*/ */
@Override @Override
public void unlock(Vehicle vehicle) { public void unlock(Vehicle vehicle) {
if (vehicles.isEmpty() || vehicle instanceof NoVehicle) { if (vehicle == null || vehicles.isEmpty() || vehicle instanceof NoVehicle) {
return; return;
} }
if (vehicle == null) return; locked[vehicle.getIndex()] = false;
lockedVehicles.remove(vehicle);
addVehicle(vehicle); addVehicle(vehicle);
} }
@ -183,7 +171,7 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
*/ */
@Override @Override
public boolean isLocked(Vehicle vehicle) { public boolean isLocked(Vehicle vehicle) {
return lockedVehicles.contains(vehicle); return locked[vehicle.getIndex()];
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -191,18 +179,11 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
*/ */
@Override @Override
public void unlockAll() { public void unlockAll() {
Collection<Vehicle> locked = new ArrayList<Vehicle>(lockedVehicles); for(int i=0;i<vehicleArr.length;i++){
for (Vehicle v : locked) { if(locked[i]){
unlock(v); unlock(vehicleArr[i]);
}
} }
if (!lockedVehicles.isEmpty()) {
throw new IllegalStateException("no vehicle must be locked");
}
}
@Deprecated
public int sizeOfLockedVehicles() {
return lockedVehicles.size();
} }
} }

View file

@ -17,6 +17,7 @@
package jsprit.core.problem.vehicle; package jsprit.core.problem.vehicle;
import jsprit.core.problem.Location; import jsprit.core.problem.Location;
import jsprit.core.problem.VehicleRoutingProblem;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -31,9 +32,9 @@ public class TestVehicleFleetManagerImpl {
VehicleFleetManager fleetManager; VehicleFleetManager fleetManager;
Vehicle v1; VehicleImpl v1;
Vehicle v2; VehicleImpl v2;
@Before @Before
public void setUp() { public void setUp() {
@ -42,6 +43,7 @@ public class TestVehicleFleetManagerImpl {
v1 = VehicleImpl.Builder.newInstance("standard").setStartLocation(Location.newInstance("loc")).setType(VehicleTypeImpl.Builder.newInstance("standard").build()).build(); v1 = VehicleImpl.Builder.newInstance("standard").setStartLocation(Location.newInstance("loc")).setType(VehicleTypeImpl.Builder.newInstance("standard").build()).build();
v2 = VehicleImpl.Builder.newInstance("foo").setStartLocation(Location.newInstance("fooLoc")).setType(VehicleTypeImpl.Builder.newInstance("foo").build()).build(); v2 = VehicleImpl.Builder.newInstance("foo").setStartLocation(Location.newInstance("fooLoc")).setType(VehicleTypeImpl.Builder.newInstance("foo").build()).build();
VehicleRoutingProblem.Builder.newInstance().addVehicle(v1).addVehicle(v2).build();
// v1. // v1.
vehicles.add(v1); vehicles.add(v1);
vehicles.add(v2); vehicles.add(v2);
@ -61,6 +63,20 @@ public class TestVehicleFleetManagerImpl {
assertEquals(1, vehicles.size()); assertEquals(1, vehicles.size());
} }
@Test
public void testLock2() {
fleetManager.lock(v1);
fleetManager.lock(v2);
fleetManager.unlock(v2);
assertTrue(fleetManager.isLocked(v1));
}
@Test
public void testIsLocked() {
fleetManager.lock(v1);
assertTrue(fleetManager.isLocked(v1));
}
@Test @Test
public void testLockTwice() { public void testLockTwice() {
fleetManager.lock(v1); fleetManager.lock(v1);
@ -94,22 +110,6 @@ public class TestVehicleFleetManagerImpl {
assertEquals(2, vehicles_.size()); assertEquals(2, vehicles_.size());
} }
@Test
public void testWithPenalty_whenHavingOneRegularVehicleAvailable_noPenaltyVehicleIsReturn() {
Vehicle penalty4standard = VehicleImpl.Builder.newInstance("standard_penalty").setStartLocation(Location.newInstance("loc")).
setType(VehicleTypeImpl.Builder.newInstance("standard").build()).build();
List<Vehicle> vehicles = new ArrayList<Vehicle>();
vehicles.add(v1);
vehicles.add(v2);
vehicles.add(penalty4standard);
VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(vehicles).createFleetManager();
Collection<Vehicle> availableVehicles = fleetManager.getAvailableVehicles();
assertEquals(2, availableVehicles.size());
}
@Test @Test
public void whenAddingTwoVehiclesWithSameTypeIdAndLocation_getAvailableVehicleShouldReturnOnlyOneOfThem() { public void whenAddingTwoVehiclesWithSameTypeIdAndLocation_getAvailableVehicleShouldReturnOnlyOneOfThem() {
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("standard").build(); VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("standard").build();
@ -140,6 +140,7 @@ public class TestVehicleFleetManagerImpl {
.setType(type).setEarliestStart(0.).setLatestArrival(10.).build(); .setType(type).setEarliestStart(0.).setLatestArrival(10.).build();
Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc")) Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc"))
.setType(type2).setEarliestStart(0.).setLatestArrival(10.).build(); .setType(type2).setEarliestStart(0.).setLatestArrival(10.).build();
VehicleRoutingProblem.Builder.newInstance().addVehicle(v1).addVehicle(v2).build();
VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager(); VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager();
Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles(); Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles();
assertEquals(2, vehicles.size()); assertEquals(2, vehicles.size());
@ -154,6 +155,7 @@ public class TestVehicleFleetManagerImpl {
.setType(type).setEarliestStart(0.).setLatestArrival(10.).build(); .setType(type).setEarliestStart(0.).setLatestArrival(10.).build();
Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc")) Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc"))
.setType(type).setEarliestStart(0.).setLatestArrival(10.).build(); .setType(type).setEarliestStart(0.).setLatestArrival(10.).build();
VehicleRoutingProblem.Builder.newInstance().addVehicle(v1).addVehicle(v2).build();
VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager(); VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager();
Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles(); Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles();
assertEquals(2, vehicles.size()); assertEquals(2, vehicles.size());
@ -168,6 +170,7 @@ public class TestVehicleFleetManagerImpl {
.setType(type).setEarliestStart(0.).setLatestArrival(10.).build(); .setType(type).setEarliestStart(0.).setLatestArrival(10.).build();
Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc")) Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc"))
.setType(type).setEarliestStart(0.).setLatestArrival(10.).build(); .setType(type).setEarliestStart(0.).setLatestArrival(10.).build();
VehicleRoutingProblem.Builder.newInstance().addVehicle(v1).addVehicle(v2).build();
VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager(); VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager();
Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles(); Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles();
assertEquals(2, vehicles.size()); assertEquals(2, vehicles.size());
@ -182,6 +185,7 @@ public class TestVehicleFleetManagerImpl {
.setType(type).setEarliestStart(5.).setLatestArrival(10.).build(); .setType(type).setEarliestStart(5.).setLatestArrival(10.).build();
Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc")) Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc"))
.setType(type).setEarliestStart(0.).setLatestArrival(10.).build(); .setType(type).setEarliestStart(0.).setLatestArrival(10.).build();
VehicleRoutingProblem.Builder.newInstance().addVehicle(v1).addVehicle(v2).build();
VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager(); VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager();
Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles(); Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles();
assertEquals(2, vehicles.size()); assertEquals(2, vehicles.size());
@ -196,6 +200,7 @@ public class TestVehicleFleetManagerImpl {
.setType(type).setEarliestStart(0.).setLatestArrival(20.).build(); .setType(type).setEarliestStart(0.).setLatestArrival(20.).build();
Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc")) Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setEndLocation(Location.newInstance("endLoc"))
.setType(type).setEarliestStart(0.).setLatestArrival(10.).build(); .setType(type).setEarliestStart(0.).setLatestArrival(10.).build();
VehicleRoutingProblem.Builder.newInstance().addVehicle(v1).addVehicle(v2).build();
VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager(); VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(Arrays.asList(v1, v2)).createFleetManager();
Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles(); Collection<Vehicle> vehicles = fleetManager.getAvailableVehicles();
assertEquals(2, vehicles.size()); assertEquals(2, vehicles.size());