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

modify problem reader/writer to deal vehicles that can start AND end at

specified locations
This commit is contained in:
Stefan Schroeder 2014-01-22 17:02:31 +01:00
parent 6575b6d48e
commit 63060f3b35
10 changed files with 310 additions and 38 deletions

View file

@ -472,20 +472,44 @@ public class VrpXMLReader{
if(type == null) throw new IllegalStateException("vehicleType with typeId " + typeId + " is missing.");
builder.setType(type);
String locationId = vehicleConfig.getString("location.id");
if(locationId == null) {
locationId = vehicleConfig.getString("startLocation.id");
}
if(locationId == null) throw new IllegalStateException("location.id is missing.");
builder.setLocationId(locationId);
builder.setStartLocationId(locationId);
String coordX = vehicleConfig.getString("location.coord[@x]");
String coordY = vehicleConfig.getString("location.coord[@y]");
if(coordX == null || coordY == null) {
coordX = vehicleConfig.getString("startLocation.coord[@x]");
coordY = vehicleConfig.getString("startLocation.coord[@y]");
}
if(coordX == null || coordY == null) {
if(!doNotWarnAgain) {
logger.warn("location.coord is missing. will not warn you again.");
doNotWarnAgain = true;
}
}
else{
Coordinate coordinate = Coordinate.newInstance(Double.parseDouble(coordX), Double.parseDouble(coordY));
builder.setStartLocationCoordinate(coordinate);
}
String endLocationId = vehicleConfig.getString("endLocation.id");
if(endLocationId != null) builder.setEndLocationId(endLocationId);
String endCoordX = vehicleConfig.getString("endLocation.coord[@x]");
String endCoordY = vehicleConfig.getString("endLocation.coord[@y]");
if(endCoordX == null || endCoordY == null) {
if(!doNotWarnAgain) {
logger.warn("location.coord is missing. do not warn you again.");
logger.warn("endLocation.coord is missing. will not warn you again.");
doNotWarnAgain = true;
}
}
else{
Coordinate coordinate = Coordinate.newInstance(Double.parseDouble(coordX), Double.parseDouble(coordY));
builder.setLocationCoord(coordinate);
Coordinate coordinate = Coordinate.newInstance(Double.parseDouble(endCoordX), Double.parseDouble(endCoordY));
builder.setEndLocationCoordinate(coordinate);
}
String start = vehicleConfig.getString("timeSchedule.start");
String end = vehicleConfig.getString("timeSchedule.end");
if(start != null) builder.setEarliestStart(Double.parseDouble(start));

View file

@ -236,10 +236,15 @@ public class VrpXMLWriter {
}
xmlConfig.setProperty(vehiclePathString + "("+counter+").id", vehicle.getId());
xmlConfig.setProperty(vehiclePathString + "("+counter+").typeId", vehicle.getType().getTypeId());
xmlConfig.setProperty(vehiclePathString + "("+counter+").location.id", vehicle.getLocationId());
if(vehicle.getCoord() != null){
xmlConfig.setProperty(vehiclePathString + "("+counter+").location.coord[@x]", vehicle.getCoord().getX());
xmlConfig.setProperty(vehiclePathString + "("+counter+").location.coord[@y]", vehicle.getCoord().getY());
xmlConfig.setProperty(vehiclePathString + "("+counter+").startLocation.id", vehicle.getStartLocationId());
if(vehicle.getStartLocationCoordinate() != null){
xmlConfig.setProperty(vehiclePathString + "("+counter+").startLocation.coord[@x]", vehicle.getStartLocationCoordinate().getX());
xmlConfig.setProperty(vehiclePathString + "("+counter+").startLocation.coord[@y]", vehicle.getStartLocationCoordinate().getY());
}
xmlConfig.setProperty(vehiclePathString + "("+counter+").endLocation.id", vehicle.getEndLocationId());
if(vehicle.getEndLocationCoordinate() != null){
xmlConfig.setProperty(vehiclePathString + "("+counter+").endLocation.coord[@x]", vehicle.getEndLocationCoordinate().getX());
xmlConfig.setProperty(vehiclePathString + "("+counter+").endLocation.coord[@y]", vehicle.getEndLocationCoordinate().getY());
}
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.start", vehicle.getEarliestDeparture());
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.end", vehicle.getLatestArrival());

View file

@ -99,6 +99,7 @@ public interface Vehicle {
/**
* Returns the end-locationId of this vehicle.
*
*/
public abstract String getEndLocationId();

View file

@ -239,8 +239,15 @@ public class VehicleImpl implements Vehicle {
* <p>if {@link VehicleType} is not set, default vehicle-type is set with id="default" and
* capacity=0
*
* <p>if startLocationId || locationId is null (=> startLocationCoordinate || locationCoordinate must be set) then startLocationId=startLocationCoordinate.toString()
* and locationId=locationCoordinate.toString() [coord.toString() --> [x=x_val][y=y_val])
* <p>if endLocationId is null and endLocationCoordinate is set then endLocationId=endLocationCoordinate.toString()
* <p>if endLocationId==null AND endLocationCoordinate==null then endLocationId=startLocationId AND endLocationCoord=startLocationCoord
* Thus endLocationId can never be null even returnToDepot is false.
*
* @return vehicle
* @throw IllegalStateException if both locationId and locationCoord is not set
* @throws IllegalStateException if both locationId and locationCoord is not set or (endLocationCoord!=null AND returnToDepot=false)
* or (endLocationId!=null AND returnToDepot=false)
*/
public VehicleImpl build(){
if(locationId == null && locationCoord != null) {
@ -249,15 +256,13 @@ public class VehicleImpl implements Vehicle {
}
if(locationId == null && locationCoord == null) throw new IllegalStateException("locationId and locationCoord is missing.");
if(locationCoord == null) log.warn("locationCoord for vehicle " + id + " is missing.");
if(endLocationCoord != null && returnToDepot == false) throw new IllegalStateException("this must not be. you specified both endLocationCoord and open-routes. this is contradictory. <br>" +
"if you set endLocation, returnToDepot must be true. if returnToDepot is false, endLocationCoord must not be specified.");
if(endLocationId != null && returnToDepot == false) throw new IllegalStateException("this must not be. you specified both endLocationId and open-routes. this is contradictory. <br>" +
"if you set endLocation, returnToDepot must be true. if returnToDepot is false, endLocationCoord must not be specified.");
if(endLocationId == null && endLocationCoord != null) endLocationId = endLocationCoord.toString();
if(endLocationId == null && endLocationCoord == null) {
endLocationId = startLocationId;
endLocationCoord = startLocationCoord;
}
if( !startLocationId.equals(endLocationId) && returnToDepot == false) throw new IllegalStateException("this must not be. you specified both endLocationId and open-routes. this is contradictory. <br>" +
"if you set endLocation, returnToDepot must be true. if returnToDepot is false, endLocationCoord must not be specified.");
return new VehicleImpl(this);
}

View file

@ -37,18 +37,28 @@
<xs:complexType>
<xs:all>
<xs:element name="id" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="location">
<xs:element name="location" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="id" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="coord" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="x" type="xs:decimal" use="required"/>
<xs:attribute name="y" type="xs:decimal" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="coord" type="coordType" minOccurs="0" maxOccurs="1"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="startLocation" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="id" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="coord" type="coordType" minOccurs="0" maxOccurs="1"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="endLocation" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element name="id" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="coord" type="coordType" minOccurs="0" maxOccurs="1"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="typeId" type="xs:string" minOccurs="1" maxOccurs="1"/>

View file

@ -17,6 +17,7 @@
package jsprit.core.problem.io;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@ -58,7 +59,7 @@ public class VrpReaderV2Test {
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
assertEquals(2,vrp.getVehicles().size());
assertEquals(4,vrp.getVehicles().size());
assertTrue(idsInCollection(Arrays.asList("v1","v2"),vrp.getVehicles()));
}
@ -143,4 +144,127 @@ public class VrpReaderV2Test {
assertEquals(0.0,s1.getServiceDuration(),0.01);
assertEquals(3, vrp.getJobs().size());
}
@Test
public void whenReadingFile_v2MustNotReturnToDepot(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v = getVehicle("v2",vrp.getVehicles());
assertFalse(v.isReturnToDepot());
}
@Test
public void whenReadingFile_v3HasTheCorrectStartLocation(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v3 = getVehicle("v3",vrp.getVehicles());
assertEquals("startLoc",v3.getStartLocationId());
}
@Test
public void whenReadingFile_v3HasTheCorrectEndLocation(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v3 = getVehicle("v3",vrp.getVehicles());
assertEquals("endLoc",v3.getEndLocationId());
}
@Test
public void whenReadingFile_v3HasTheCorrectEndLocationCoordinate(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v3 = getVehicle("v3",vrp.getVehicles());
assertEquals(1000.0,v3.getEndLocationCoordinate().getX(),0.01);
assertEquals(2000.0,v3.getEndLocationCoordinate().getY(),0.01);
}
@Test
public void whenReadingFile_v3HasTheCorrectStartLocationCoordinate(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v3 = getVehicle("v3",vrp.getVehicles());
assertEquals(10.0,v3.getStartLocationCoordinate().getX(),0.01);
assertEquals(100.0,v3.getStartLocationCoordinate().getY(),0.01);
}
@Test
public void whenReadingFile_v3HasTheCorrectLocationCoordinate(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v3 = getVehicle("v3",vrp.getVehicles());
assertEquals(10.0,v3.getCoord().getX(),0.01);
assertEquals(100.0,v3.getCoord().getY(),0.01);
}
@Test
public void whenReadingFile_v3HasTheCorrectLocationId(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v3 = getVehicle("v3",vrp.getVehicles());
assertEquals("startLoc",v3.getLocationId());
}
@Test
public void whenReadingFile_v4HasTheCorrectStartLocation(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v = getVehicle("v4",vrp.getVehicles());
assertEquals("startLoc",v.getStartLocationId());
}
@Test
public void whenReadingFile_v4HasTheCorrectEndLocation(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v = getVehicle("v4",vrp.getVehicles());
assertEquals("endLoc",v.getEndLocationId());
}
@Test
public void whenReadingFile_v4HasTheCorrectEndLocationCoordinate(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v = getVehicle("v4",vrp.getVehicles());
assertEquals(1000.0,v.getEndLocationCoordinate().getX(),0.01);
assertEquals(2000.0,v.getEndLocationCoordinate().getY(),0.01);
}
@Test
public void whenReadingFile_v4HasTheCorrectStartLocationCoordinate(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v = getVehicle("v4",vrp.getVehicles());
assertEquals(10.0,v.getStartLocationCoordinate().getX(),0.01);
assertEquals(100.0,v.getStartLocationCoordinate().getY(),0.01);
}
@Test
public void whenReadingFile_v4HasTheCorrectLocationCoordinate(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v = getVehicle("v4",vrp.getVehicles());
assertEquals(10.0,v.getCoord().getX(),0.01);
assertEquals(100.0,v.getCoord().getY(),0.01);
}
@Test
public void whenReadingFile_v4HasTheCorrectLocationId(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Vehicle v = getVehicle("v4",vrp.getVehicles());
assertEquals("startLoc",v.getStartLocationId());
}
}

View file

@ -17,6 +17,10 @@
package jsprit.core.problem.io;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.util.Collection;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.Builder;
import jsprit.core.problem.VehicleRoutingProblem.FleetSize;
@ -43,11 +47,6 @@ public class VrpWriterV2Test {
public void whenWritingInfiniteVrp_itWritesCorrectly(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
builder.setFleetSize(FleetSize.INFINITE);
// Depot depot = new Depot("depotLoc",Coordinate.newInstance(0, 0));
// Depot depot2 = new Depot("depotLoc2",Coordinate.newInstance(100, 100));
// builder.addDepot(depot2);
// builder.assignVehicleType(depot, VehicleType.Builder.newInstance("vehType", 20).build());
// builder.assignVehicleType(depot, VehicleType.Builder.newInstance("vehType2", 200).build());
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("vehType", 20).build();
Vehicle vehicle = VehicleImpl.Builder.newInstance("myVehicle").setLocationId("loc").setType(type).build();
builder.addVehicle(vehicle);
@ -59,9 +58,6 @@ public class VrpWriterV2Test {
public void whenWritingFiniteVrp_itWritesCorrectly(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
builder.setFleetSize(FleetSize.FINITE);
// Depot depot = new Depot("depotLoc",Coordinate.newInstance(0, 0));
// Depot depot2 = new Depot("depotLoc2",Coordinate.newInstance(100, 100));
// builder.addDepot(depot2);
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType", 20).build();
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2", 200).build();
Vehicle v1 = VehicleImpl.Builder.newInstance("v1").setLocationId("loc").setType(type1).build();
@ -76,9 +72,6 @@ public class VrpWriterV2Test {
public void t(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
builder.setFleetSize(FleetSize.FINITE);
// Depot depot = new Depot("depotLoc",Coordinate.newInstance(0, 0));
// Depot depot2 = new Depot("depotLoc2",Coordinate.newInstance(100, 100));
// builder.addDepot(depot2);
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType", 20).build();
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2", 200).build();
Vehicle v1 = VehicleImpl.Builder.newInstance("v1").setLocationId("loc").setType(type1).build();
@ -122,6 +115,64 @@ public class VrpWriterV2Test {
assertEquals(2.0,s1_read.getServiceDuration(),0.01);
}
@Test
public void whenWritingVehicleV1_itsStartLocationMustBeWrittenCorrectly(){
Builder builder = VehicleRoutingProblem.Builder.newInstance();
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType", 20).build();
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2", 200).build();
Vehicle v1 = VehicleImpl.Builder.newInstance("v1").setLocationId("loc").setType(type1).build();
Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setLocationId("loc").setType(type2).build();
builder.addVehicle(v1);
builder.addVehicle(v2);
Service s1 = Service.Builder.newInstance("1", 1).setLocationId("loc").setServiceTime(2.0).build();
Service s2 = Service.Builder.newInstance("2", 1).setLocationId("loc2").setServiceTime(4.0).build();
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
new VrpXMLWriter(vrp, null).write(infileName);
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
Vehicle v = getVehicle("v1",readVrp.getVehicles());
assertEquals("loc",v.getStartLocationId());
assertEquals("loc",v.getEndLocationId());
}
@Test
public void whenWritingVehicleV1_itDoesNotReturnToDepotMustBeWrittenCorrectly(){
Builder builder = VehicleRoutingProblem.Builder.newInstance();
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType", 20).build();
VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("vehType2", 200).build();
Vehicle v1 = VehicleImpl.Builder.newInstance("v1").setReturnToDepot(false).setLocationId("loc").setType(type1).build();
Vehicle v2 = VehicleImpl.Builder.newInstance("v2").setLocationId("loc").setType(type2).build();
builder.addVehicle(v1);
builder.addVehicle(v2);
Service s1 = Service.Builder.newInstance("1", 1).setLocationId("loc").setServiceTime(2.0).build();
Service s2 = Service.Builder.newInstance("2", 1).setLocationId("loc2").setServiceTime(4.0).build();
VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build();
new VrpXMLWriter(vrp, null).write(infileName);
VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(vrpToReadBuilder, null).read(infileName);
VehicleRoutingProblem readVrp = vrpToReadBuilder.build();
Vehicle v = getVehicle("v1",readVrp.getVehicles());
assertFalse(v.isReturnToDepot());
}
private Vehicle getVehicle(String string, Collection<Vehicle> vehicles) {
for(Vehicle v : vehicles) if(string.equals(v.getId())) return v;
return null;
}
}

View file

@ -200,5 +200,18 @@ public class VehicleImplTest {
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationCoordinate(Coordinate.newInstance(1.0, 2.0)).setReturnToDepot(false).build();
assertEquals(v.getStartLocationCoordinate().toString(),v.getEndLocationId());
}
@Test(expected=IllegalStateException.class)
public void whenStartAndEndAreUnequalANDReturnToDepotIsFalse_itShouldThrowException(){
@SuppressWarnings("unused")
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationId("start").setEndLocationId("end").setReturnToDepot(false).build();
}
@Test
public void whenStartAndEndAreEqualANDReturnToDepotIsFalse_itShouldThrowException(){
@SuppressWarnings("unused")
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocationId("start").setEndLocationId("start").setReturnToDepot(false).build();
assertTrue(true);
}
}

View file

@ -46,6 +46,39 @@
<id>depotLoc</id>
<coord x="10.0" y="100.0"/>
</location>
<returnToDepot>false</returnToDepot>
<typeId>vehType2</typeId>
<timeSchedule>
<start>0.0</start>
<end>1000.0</end>
</timeSchedule>
</vehicle>
<vehicle>
<id>v3</id>
<startLocation>
<id>startLoc</id>
<coord x="10.0" y="100.0"/>
</startLocation>
<endLocation>
<id>endLoc</id>
<coord x="1000.0" y="2000.0"/>
</endLocation>
<typeId>vehType2</typeId>
<timeSchedule>
<start>0.0</start>
<end>1000.0</end>
</timeSchedule>
</vehicle>
<vehicle>
<id>v4</id>
<location>
<id>startLoc</id>
<coord x="10.0" y="100.0"/>
</location>
<endLocation>
<id>endLoc</id>
<coord x="1000.0" y="2000.0"/>
</endLocation>
<typeId>vehType2</typeId>
<timeSchedule>
<start>0.0</start>

View file

@ -9,21 +9,27 @@
<vehicle>
<id>v1</id>
<typeId>vehType</typeId>
<location>
<startLocation>
<id>loc</id>
</location>
</startLocation>
<endLocation>
<id>loc</id>
</endLocation>
<timeSchedule>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeSchedule>
<returnToDepot>true</returnToDepot>
<returnToDepot>false</returnToDepot>
</vehicle>
<vehicle>
<id>v2</id>
<typeId>vehType2</typeId>
<location>
<startLocation>
<id>loc</id>
</location>
</startLocation>
<endLocation>
<id>loc</id>
</endLocation>
<timeSchedule>
<start>0.0</start>
<end>1.7976931348623157E308</end>