diff --git a/jsprit-core/src/main/java/jsprit/core/problem/Location.java b/jsprit-core/src/main/java/jsprit/core/problem/Location.java index b3f858a0..ac87ed14 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/Location.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/Location.java @@ -114,4 +114,9 @@ public final class Location implements HasIndex, HasId{ result = 31 * result + (id != null ? id.hashCode() : 0); return result; } + + @Override + public String toString() { + return "[id="+id+"][index="+index+"][coordinate="+coordinate+"]"; + } } 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 e546740f..210bd5c3 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 @@ -299,7 +299,7 @@ public class VehicleRoute { } if(!vehicle.isReturnToDepot()){ if(!tourActivities.isEmpty()){ - end.setLocationId(tourActivities.getActivities().get(tourActivities.getActivities().size()-1).getLocationId()); + end.setLocation(tourActivities.getActivities().get(tourActivities.getActivities().size() - 1).getLocation()); } } return new VehicleRoute(this); @@ -407,8 +407,8 @@ public class VehicleRoute { start.setEndTime(Math.max(vehicleDepTime, vehicle.getEarliestDeparture())); start.setTheoreticalEarliestOperationStartTime(vehicle.getEarliestDeparture()); start.setTheoreticalLatestOperationStartTime(vehicle.getLatestArrival()); - start.setLocationId(vehicle.getStartLocationId()); - end.setLocationId(vehicle.getEndLocationId()); + start.setLocation(vehicle.getStartLocation()); + end.setLocation(vehicle.getEndLocation()); end.setTheoreticalEarliestOperationStartTime(vehicle.getEarliestDeparture()); end.setTheoreticalLatestOperationStartTime(vehicle.getLatestArrival()); } diff --git a/jsprit-core/src/main/java/jsprit/core/util/FastVehicleRoutingTransportCostsMatrix.java b/jsprit-core/src/main/java/jsprit/core/util/FastVehicleRoutingTransportCostsMatrix.java index 73bf69ff..5fbb7f54 100644 --- a/jsprit-core/src/main/java/jsprit/core/util/FastVehicleRoutingTransportCostsMatrix.java +++ b/jsprit-core/src/main/java/jsprit/core/util/FastVehicleRoutingTransportCostsMatrix.java @@ -114,6 +114,7 @@ public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehic @Override public double getTransportTime(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) { + if(from.getIndex() < 0 || to.getIndex() < 0) throw new IllegalArgumentException("index of from " + from + " to " + to + " < 0 "); return get(from.getIndex(),to.getIndex(),1); } @@ -142,7 +143,8 @@ public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehic @Override public double getTransportCost(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) { - if(vehicle == null) return getDistance(from.getIndex(), to.getIndex()); + if(from.getIndex() < 0 || to.getIndex() < 0) throw new IllegalArgumentException("index of from " + from + " to " + to + " < 0 "); + if(vehicle == null) return getDistance(from.getIndex(), to.getIndex()); VehicleCostParams costParams = vehicle.getType().getVehicleCostParams(); return costParams.perDistanceUnit * getDistance(from.getIndex(), to.getIndex()) + costParams.perTimeUnit * getTransportTime(from, to, departureTime, driver, vehicle); } diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java index bbdbbcb8..885ef274 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java @@ -20,6 +20,7 @@ import jsprit.core.algorithm.recreate.listener.InsertionListeners; import jsprit.core.algorithm.state.UpdateEndLocationIfRouteIsOpen; import jsprit.core.problem.AbstractActivity; import jsprit.core.problem.Capacity; +import jsprit.core.problem.Location; import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.driver.Driver; import jsprit.core.problem.job.Service; @@ -48,15 +49,15 @@ public class TestInserter { public void whenInsertingServiceAndRouteIsClosed_itInsertsCorrectly(){ Service service = mock(Service.class); Vehicle vehicle = mock(Vehicle.class); - when(vehicle.getStartLocationId()).thenReturn("vehLoc"); - when(vehicle.getEndLocationId()).thenReturn("vehLoc"); + when(vehicle.getStartLocation()).thenReturn(loc("vehLoc")); + when(vehicle.getEndLocation()).thenReturn(loc("vehLoc")); when(vehicle.isReturnToDepot()).thenReturn(true); when(vehicle.getId()).thenReturn("vehId"); VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addService(service).build(); //start - pick(shipment) - del(shipment) - end Service serviceToInsert = mock(Service.class); - when(serviceToInsert.getLocationId()).thenReturn("delLoc"); + when(serviceToInsert.getLocation()).thenReturn(loc("delLoc")); InsertionData iData = mock(InsertionData.class); when(iData.getDeliveryInsertionIndex()).thenReturn(1); @@ -71,11 +72,15 @@ public class TestInserter { inserter.insertJob(serviceToInsert, iData, route); assertEquals(2,route.getTourActivities().getActivities().size()); - assertEquals(route.getTourActivities().getActivities().get(1).getLocationId(),serviceToInsert.getLocationId()); - assertEquals(route.getEnd().getLocationId(),vehicle.getEndLocationId()); + assertEquals(route.getTourActivities().getActivities().get(1).getLocation().getId(),serviceToInsert.getLocation().getId()); + assertEquals(route.getEnd().getLocation().getId(),vehicle.getEndLocation().getId()); } - - @Test + + private Location loc(String vehLoc) { + return Location.Builder.newInstance().setId(vehLoc).build(); + } + + @Test public void whenInsertingServiceAndRouteIsOpen_itInsertsCorrectlyAndSwitchesEndLocation(){ Service service = mock(Service.class); Vehicle vehicle = mock(Vehicle.class); @@ -116,8 +121,8 @@ public class TestInserter { Capacity capacity = Capacity.Builder.newInstance().build(); when(shipment.getSize()).thenReturn(capacity); Vehicle vehicle = mock(Vehicle.class); - when(vehicle.getStartLocationId()).thenReturn("vehLoc"); - when(vehicle.getEndLocationId()).thenReturn("vehLoc"); + when(vehicle.getStartLocation()).thenReturn(loc("vehLoc")); + when(vehicle.getEndLocation()).thenReturn(loc("vehLoc")); when(vehicle.isReturnToDepot()).thenReturn(true); when(vehicle.getId()).thenReturn("vehId"); @@ -136,9 +141,9 @@ public class TestInserter { inserter.insertJob(shipmentToInsert, iData, route); assertEquals(4,route.getTourActivities().getActivities().size()); - assertEquals(route.getTourActivities().getActivities().get(2).getLocationId(),shipmentToInsert.getPickupLocationId()); - assertEquals(route.getTourActivities().getActivities().get(3).getLocationId(),shipmentToInsert.getDeliveryLocationId()); - assertEquals(route.getEnd().getLocationId(),vehicle.getEndLocationId()); + assertEquals(route.getTourActivities().getActivities().get(2).getLocation().getId(),shipmentToInsert.getPickupLocation().getId()); + assertEquals(route.getTourActivities().getActivities().get(3).getLocation().getId(),shipmentToInsert.getDeliveryLocation().getId()); + assertEquals(route.getEnd().getLocation().getId(),vehicle.getEndLocation().getId()); } private List getTourActivities(Shipment shipmentToInsert) { diff --git a/jsprit-core/src/test/java/jsprit/core/problem/solution/route/VehicleRouteBuilderTest.java b/jsprit-core/src/test/java/jsprit/core/problem/solution/route/VehicleRouteBuilderTest.java index 1b0da9b1..563463a7 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/solution/route/VehicleRouteBuilderTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/solution/route/VehicleRouteBuilderTest.java @@ -17,6 +17,7 @@ package jsprit.core.problem.solution.route; import jsprit.core.problem.Capacity; +import jsprit.core.problem.Location; import jsprit.core.problem.driver.Driver; import jsprit.core.problem.job.Shipment; import jsprit.core.problem.vehicle.Vehicle; @@ -113,20 +114,24 @@ public class VehicleRouteBuilderTest { Capacity capacity = Capacity.Builder.newInstance().build(); when(s.getSize()).thenReturn(capacity); when(s2.getSize()).thenReturn(capacity); - when(s2.getDeliveryLocationId()).thenReturn("delLoc"); + when(s2.getDeliveryLocation()).thenReturn(loc("delLoc")); Vehicle vehicle = mock(Vehicle.class); when(vehicle.isReturnToDepot()).thenReturn(false); - when(vehicle.getStartLocationId()).thenReturn("vehLoc"); + when(vehicle.getStartLocation()).thenReturn(loc("vehLoc")); VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)); builder.addPickup(s); builder.addPickup(s2); builder.addDelivery(s); builder.addDelivery(s2); VehicleRoute route = builder.build(); - assertEquals(route.getEnd().getLocationId(), s2.getDeliveryLocationId()); + assertEquals(route.getEnd().getLocationId(), s2.getDeliveryLocation().getId()); } - - @Test + + private Location loc(String delLoc) { + return Location.Builder.newInstance().setId(delLoc).build(); + } + + @Test public void whenSettingDepartureTime(){ Shipment s = mock(Shipment.class); Shipment s2 = mock(Shipment.class); diff --git a/jsprit-examples/src/main/java/jsprit/examples/RefuseCollectionWithFastMatrixExample.java b/jsprit-examples/src/main/java/jsprit/examples/RefuseCollectionWithFastMatrixExample.java new file mode 100644 index 00000000..a1e1de61 --- /dev/null +++ b/jsprit-examples/src/main/java/jsprit/examples/RefuseCollectionWithFastMatrixExample.java @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (C) 2014 Stefan Schroeder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + ******************************************************************************/ +package jsprit.examples; + +import jsprit.core.algorithm.VehicleRoutingAlgorithm; +import jsprit.core.algorithm.box.GreedySchrimpfFactory; +import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination; +import jsprit.core.problem.Location; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.VehicleRoutingProblem.FleetSize; +import jsprit.core.problem.io.VrpXMLWriter; +import jsprit.core.problem.job.Service; +import jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import jsprit.core.problem.vehicle.VehicleImpl; +import jsprit.core.problem.vehicle.VehicleTypeImpl; +import jsprit.core.reporting.SolutionPrinter; +import jsprit.core.util.FastVehicleRoutingTransportCostsMatrix; +import jsprit.core.util.Solutions; +import jsprit.util.Examples; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Collection; + + +/** + * This example is base on + * http://web.mit.edu/urban_or_book/www/book/chapter6/6.4.12.html + * + * @author stefan schroeder + * + */ +public class RefuseCollectionWithFastMatrixExample { + + static class RelationKey { + + final String from; + final String to; + + public RelationKey(String from, String to) { + super(); + this.from = from; + this.to = to; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((from == null) ? 0 : from.hashCode()); + result = prime * result + ((to == null) ? 0 : to.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RelationKey other = (RelationKey) obj; + if (from == null) { + if (other.from != null) + return false; + } else if (!from.equals(other.from)) + return false; + if (to == null) { + if (other.to != null) + return false; + } else if (!to.equals(other.to)) + return false; + return true; + } + } + + public static void main(String[] args) throws IOException { + /* + * some preparation - create output folder + */ + Examples.createOutputFolder(); + + /* + * create vehicle-type and vehicle + */ + VehicleTypeImpl.Builder typeBuilder = VehicleTypeImpl.Builder.newInstance("vehicle-type").addCapacityDimension(0, 23); + typeBuilder.setCostPerDistance(1.0); + VehicleTypeImpl bigType = typeBuilder.build(); + + VehicleImpl.Builder vehicleBuilder = VehicleImpl.Builder.newInstance("vehicle"); + vehicleBuilder.setStartLocation(Location.Builder.newInstance().setIndex(1).build()); + vehicleBuilder.setType(bigType); + VehicleImpl bigVehicle = vehicleBuilder.build(); + + /* + * start building the problem + */ + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); + vrpBuilder.setFleetSize(FleetSize.INFINITE); + vrpBuilder.addVehicle(bigVehicle); + + /* + * read demand quantities + */ + readDemandQuantities(vrpBuilder); + + /* + * create cost-matrix + */ + FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(11,true); + readDistances(matrixBuilder); + + vrpBuilder.setRoutingCost(matrixBuilder.build()); + + VehicleRoutingProblem vrp = vrpBuilder.build(); + + VehicleRoutingAlgorithm vra = new GreedySchrimpfFactory().createAlgorithm(vrp); + vra.setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(100)); + Collection solutions = vra.searchSolutions(); + + SolutionPrinter.print(Solutions.bestOf(solutions)); + + new VrpXMLWriter(vrp, solutions).write("output/refuseCollectionExampleSolution.xml"); + + } + + + private static void readDemandQuantities(VehicleRoutingProblem.Builder vrpBuilder) throws IOException { + BufferedReader reader = new BufferedReader(new FileReader(new File("input/RefuseCollectionExample_Quantities"))); + String line; + boolean firstLine = true; + while((line = reader.readLine()) != null){ + if(firstLine) { + firstLine = false; + continue; + } + String[] lineTokens = line.split(","); + /* + * build service + */ + Service service = Service.Builder.newInstance(lineTokens[0]) + .addSizeDimension(0, Integer.parseInt(lineTokens[1])) + .setLocation(Location.Builder.newInstance().setIndex(Integer.parseInt(lineTokens[0])).build()) + .build(); + /* + * and add it to problem + */ + vrpBuilder.addJob(service); + } + reader.close(); + } + + + private static void readDistances(FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder) throws IOException { + BufferedReader reader = new BufferedReader(new FileReader(new File("input/RefuseCollectionExample_Distances"))); + String line; + boolean firstLine = true; + while((line = reader.readLine()) != null){ + if(firstLine) { + firstLine = false; + continue; + } + String[] lineTokens = line.split(","); + matrixBuilder.addTransportDistance(Integer.parseInt(lineTokens[0]),Integer.parseInt(lineTokens[1]), Integer.parseInt(lineTokens[2])); + } + reader.close(); + + } + +}