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

adding multiple capacity obj to jobs and vehicleType

This commit is contained in:
oblonski 2014-01-11 16:53:40 +01:00
parent 878442fe80
commit c2377252ea
13 changed files with 388 additions and 19 deletions

View file

@ -0,0 +1,71 @@
package jsprit.core.problem;
public class Capacity {
public static class Builder {
/**
* default is 1 dimension with size of zero
*/
private int[] dimensions = new int[1];
public static Builder newInstance(){
return new Builder();
}
Builder(){}
/**
* add capacity dimension
*
* <p>if automatically resizes dimensions according to index, i.e. if index=7 there are 8 dimensions.
*
* @throw IllegalStateException if dimValue < 0
* @param index
* @param dimValue
* @return
*/
public Builder addDimension(int index, int dimValue){
if(dimValue<0) throw new IllegalStateException("dimValue can never be negative");
if(index < dimensions.length){
dimensions[index] = dimValue;
}
else{
int requiredSize = index + 1;
int[] newDimensions = new int[requiredSize];
copy(dimensions,newDimensions);
newDimensions[index]=dimValue;
this.dimensions=newDimensions;
}
return this;
}
private void copy(int[] from, int[] to) {
for(int i=0;i<dimensions.length;i++){
to[i]=from[i];
}
}
public Capacity build() {
return new Capacity(this);
}
}
private int[] dimensions;
Capacity(Builder builder) {
dimensions = builder.dimensions;
}
public int getNuOfDimensions(){
return dimensions.length;
}
public int get(int index){
return dimensions[index];
}
}

View file

@ -36,6 +36,10 @@ public class PickupAndDeliverShipmentLoadActivityLevelConstraint implements Hard
this.stateManager = stateManager;
}
/**
* Checks whether there is enough capacity to insert newAct between prevAct and nextAct.
*
*/
@Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(!(newAct instanceof PickupShipment) && !(newAct instanceof DeliverShipment)){

View file

@ -16,11 +16,15 @@
******************************************************************************/
package jsprit.core.problem.job;
import jsprit.core.problem.Capacity;
public interface Job {
public String getId();
@Deprecated
public int getCapacityDemand();
public Capacity getCapacity();
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.job;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.util.Coordinate;
@ -25,7 +26,13 @@ public class Service implements Job {
public static class Builder {
public static Builder newInstance(String id, int size){
return new Builder(id,size);
Builder builder = new Builder(id,size);
builder.addCapacityDimension(0, size);
return builder;
}
public static Builder newInstance(String id){
return new Builder(id);
}
private String id;
@ -35,6 +42,8 @@ public class Service implements Job {
protected double serviceTime;
protected TimeWindow timeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
protected int demand;
protected Capacity.Builder capacityBuilder = Capacity.Builder.newInstance();
protected Capacity capacity;
Builder(String id, int size) {
if(size < 0) throw new IllegalArgumentException("size must be greater than or equal to zero");
@ -42,6 +51,10 @@ public class Service implements Job {
this.demand = size;
}
Builder(String id){
this.id = id;
}
protected Builder setType(String name){
this.type = name;
return this;
@ -63,6 +76,11 @@ public class Service implements Job {
return this;
}
public Builder addCapacityDimension(int dimensionIndex, int dimensionValue){
capacityBuilder.addDimension(dimensionIndex, dimensionValue);
return this;
}
public Builder setTimeWindow(TimeWindow tw){
this.timeWindow = tw;
return this;
@ -74,6 +92,7 @@ public class Service implements Job {
locationId = coord.toString();
}
this.setType("service");
capacity = capacityBuilder.build();
return new Service(this);
}
@ -94,6 +113,8 @@ public class Service implements Job {
private final int demand;
private final Capacity capacity;
Service(Builder builder){
id = builder.id;
locationId = builder.locationId;
@ -102,6 +123,7 @@ public class Service implements Job {
timeWindow = builder.timeWindow;
demand = builder.demand;
type = builder.type;
capacity = builder.capacity;
}
@Override
@ -173,6 +195,9 @@ public class Service implements Job {
return true;
}
@Override
public Capacity getCapacity() {
return capacity;
}
}

View file

@ -1,5 +1,6 @@
package jsprit.core.problem.job;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.util.Coordinate;
@ -25,10 +26,20 @@ public class Shipment implements Job{
private TimeWindow deliveryTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
private TimeWindow pickupTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);;
private TimeWindow pickupTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
private Capacity.Builder capacityBuilder = Capacity.Builder.newInstance();
private Capacity capacity;
public static Builder newInstance(String id, int size){
return new Builder(id,size);
Builder builder = new Builder(id,size);
builder.addCapacityDimension(0, size);
return builder;
}
public static Builder newInstance(String id){
return new Builder(id);
}
Builder(String id, int size) {
@ -37,6 +48,10 @@ public class Shipment implements Job{
this.demand = size;
}
Builder(String id){
this.id = id;
}
public Builder setPickupLocation(String pickupLocation){
this.pickupLocation = pickupLocation;
return this;
@ -77,6 +92,11 @@ public class Shipment implements Job{
return this;
}
public Builder addCapacityDimension(int dimIndex, int dimVal) {
capacityBuilder.addDimension(dimIndex, dimVal);
return this;
}
public Shipment build(){
if(pickupLocation == null) {
if(pickupCoord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not.");
@ -86,29 +106,34 @@ public class Shipment implements Job{
if(deliveryCoord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not.");
deliveryLocation = deliveryCoord.toString();
}
capacity = capacityBuilder.build();
return new Shipment(this);
}
}
private int demand;
private final int demand;
private String id;
private final String id;
private String pickupLocation;
private final String pickupLocation;
private Coordinate pickupCoord;
private final Coordinate pickupCoord;
private double pickupServiceTime;
private final double pickupServiceTime;
private String deliveryLocation;
private final String deliveryLocation;
private Coordinate deliveryCoord;
private final Coordinate deliveryCoord;
private double deliveryServiceTime;
private final double deliveryServiceTime;
private TimeWindow deliveryTimeWindow;
private final TimeWindow deliveryTimeWindow;
private TimeWindow pickupTimeWindow;
private final TimeWindow pickupTimeWindow;
private final Capacity capacity;
Shipment(Builder builder){
this.id = builder.id;
@ -121,6 +146,7 @@ public class Shipment implements Job{
this.deliveryCoord = builder.deliveryCoord;
this.deliveryServiceTime = builder.deliveryServiceTime;
this.deliveryTimeWindow = builder.deliveryTimeWindow;
this.capacity = builder.capacity;
}
@Override
@ -190,5 +216,10 @@ public class Shipment implements Job{
return true;
}
@Override
public Capacity getCapacity() {
return capacity;
}
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.vehicle;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.vehicle.VehicleTypeImpl.VehicleCostParams;
public class PenaltyVehicleType implements VehicleType{
@ -59,6 +60,11 @@ public class PenaltyVehicleType implements VehicleType{
return type.getMaxVelocity();
}
@Override
public Capacity getCapacityDimensions() {
return type.getCapacityDimensions();
}
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.vehicle;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.vehicle.VehicleTypeImpl.VehicleCostParams;
@ -25,6 +26,8 @@ public interface VehicleType {
public int getCapacity();
public Capacity getCapacityDimensions();
public double getMaxVelocity();
public VehicleCostParams getVehicleCostParams();

View file

@ -16,6 +16,8 @@
******************************************************************************/
package jsprit.core.problem.vehicle;
import jsprit.core.problem.Capacity;
public class VehicleTypeImpl implements VehicleType {
@ -46,11 +48,18 @@ public class VehicleTypeImpl implements VehicleType {
public static class Builder{
public static VehicleTypeImpl.Builder newInstance(String id, int capacity){
return new Builder(id,capacity);
Builder builder = new Builder(id,capacity);
builder.addCapacityDimension(0, capacity);
return builder;
}
public static VehicleTypeImpl.Builder newInstance(String id) {
return new Builder(id);
}
private String id;
private int capacity;
private int capacity = 0;
private double maxVelo = Double.MAX_VALUE;
/**
* default cost values for default vehicle type
@ -59,12 +68,20 @@ public class VehicleTypeImpl implements VehicleType {
private double perDistance = 1.0;
private double perTime = 0.0;
private Capacity.Builder capacityBuilder = Capacity.Builder.newInstance();
private Capacity capacityDimensions;
public Builder(String id, int capacity) {
super();
this.id = id;
this.capacity = capacity;
}
public Builder(String id) {
this.id = id;
}
public VehicleTypeImpl.Builder setMaxVelocity(double inMeterPerSeconds){ this.maxVelo = inMeterPerSeconds; return this; }
public VehicleTypeImpl.Builder setFixedCost(double fixedCost) { this.fixedCost = fixedCost; return this; }
@ -74,9 +91,16 @@ public class VehicleTypeImpl implements VehicleType {
public VehicleTypeImpl.Builder setCostPerTime(double perTime){ this.perTime = perTime; return this; }
public VehicleTypeImpl build(){
capacityDimensions = capacityBuilder.build();
return new VehicleTypeImpl(this);
}
public Builder addCapacityDimension(int dimIndex, int dimVal) {
capacityBuilder.addDimension(dimIndex,dimVal);
return this;
}
}
@Override
@ -113,6 +137,8 @@ public class VehicleTypeImpl implements VehicleType {
private double maxVelocity;
private Capacity capacityDimensions;
/**
* @deprecated use builder instead
*/
@ -126,6 +152,7 @@ public class VehicleTypeImpl implements VehicleType {
capacity = builder.capacity;
maxVelocity = builder.maxVelo;
vehicleCostParams = new VehicleCostParams(builder.fixedCost, builder.perTime, builder.perDistance);
capacityDimensions = builder.capacityDimensions;
}
public VehicleTypeImpl(String typeId, int capacity,VehicleTypeImpl.VehicleCostParams vehicleCostParams) {
@ -133,6 +160,8 @@ public class VehicleTypeImpl implements VehicleType {
this.typeId = typeId;
this.capacity = capacity;
this.vehicleCostParams = vehicleCostParams;
capacityDimensions = Capacity.Builder.newInstance().addDimension(0, capacity).build();
}
/* (non-Javadoc)
@ -168,4 +197,9 @@ public class VehicleTypeImpl implements VehicleType {
public double getMaxVelocity() {
return maxVelocity;
}
@Override
public Capacity getCapacityDimensions() {
return capacityDimensions;
}
}

View file

@ -0,0 +1,66 @@
package jsprit.core.problem.job;
import static org.junit.Assert.assertEquals;
import java.util.Random;
import jsprit.core.problem.Capacity;
import org.junit.Test;
public class CapacityTest {
@Test
public void whenSettingSimplyOneCapDimension_nuOfDimensionMustBeCorrect(){
Capacity.Builder capBuilder = Capacity.Builder.newInstance();
capBuilder.addDimension(0, 4);
Capacity cap = capBuilder.build();
assertEquals(1,cap.getNuOfDimensions());
}
@Test
public void whenSettingTwoCapDimension_nuOfDimensionMustBeCorrect(){
Capacity.Builder capBuilder = Capacity.Builder.newInstance();
capBuilder.addDimension(0, 4);
capBuilder.addDimension(1,10);
Capacity cap = capBuilder.build();
assertEquals(2,cap.getNuOfDimensions());
}
@Test
public void whenSettingRandomNuOfCapDimension_nuOfDimensionMustBeCorrect(){
Random rand = new Random();
int nuOfCapDimensions = rand.nextInt(100);
Capacity.Builder capBuilder = Capacity.Builder.newInstance();
capBuilder.addDimension(nuOfCapDimensions-1, 4);
Capacity cap = capBuilder.build();
assertEquals(nuOfCapDimensions,cap.getNuOfDimensions());
}
@Test
public void whenSettingOneDimValue_valueMustBeCorrect(){
Capacity.Builder capBuilder = Capacity.Builder.newInstance();
capBuilder.addDimension(0, 4);
Capacity cap = capBuilder.build();
assertEquals(4,cap.get(0));
}
@Test(expected=IndexOutOfBoundsException.class)
public void whenGettingIndexWhichIsHigherThanNuOfCapDimensions_throwIndexOutOfBoundsException(){
Capacity.Builder capBuilder = Capacity.Builder.newInstance();
capBuilder.addDimension(0, 4);
Capacity cap = capBuilder.build();
cap.get(2);
}
@Test
public void whenSettingNoDim_DefaultIsOneDimWithDimValueOfZero(){
Capacity.Builder capBuilder = Capacity.Builder.newInstance();
Capacity cap = capBuilder.build();
assertEquals(1, cap.getNuOfDimensions());
assertEquals(0, cap.get(0));
}
}

View file

@ -16,13 +16,12 @@
******************************************************************************/
package jsprit.core.problem.job;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.HashSet;
import java.util.Set;
import jsprit.core.problem.job.Service;
import org.junit.Test;
@ -53,6 +52,38 @@ public class ServiceTest {
// assertTrue(serviceSet.contains(two));
serviceSet.remove(two);
assertTrue(serviceSet.isEmpty());
}
@Test(expected=IllegalStateException.class)
public void whenCapacityDimValueIsNegative_throwIllegalStateExpception(){
@SuppressWarnings("unused")
Service s = Service.Builder.newInstance("s").setLocationId("foo").addCapacityDimension(0, -10).build();
}
@Test
public void whenAddingTwoCapDimension_nuOfDimsShouldBeTwo(){
Service one = Service.Builder.newInstance("s").setLocationId("foofoo")
.addCapacityDimension(0,2)
.addCapacityDimension(1,4)
.build();
assertEquals(2,one.getCapacity().getNuOfDimensions());
}
@Test
public void whenShipmentIsBuiltWithoutSpecifyingCapacity_itShouldHvCapWithOneDimAndDimValOfZero(){
Service one = Service.Builder.newInstance("s").setLocationId("foofoo")
.build();
assertEquals(1,one.getCapacity().getNuOfDimensions());
assertEquals(0,one.getCapacity().get(0));
}
@Test
public void whenShipmentIsBuiltWithConstructorWhereSizeIsSpecified_capacityShouldBeSetCorrectly(){
Service one = Service.Builder.newInstance("s",1).setLocationId("foofoo")
.build();
assertEquals(1,one.getCapacityDemand());
assertEquals(1,one.getCapacity().getNuOfDimensions());
assertEquals(1,one.getCapacity().get(0));
}
}
}

View file

@ -54,4 +54,38 @@ public class ShipmentTest {
assertEquals(1.0,one.getDeliveryCoord().getX(),0.01);
assertEquals(1.0,one.getDeliveryTimeWindow().getStart(),0.01);
}
@Test(expected=IllegalStateException.class)
public void whenShipmentHasNegativeCapacityVal_throwIllegalStateExpception(){
@SuppressWarnings("unused")
Shipment one = Shipment.Builder.newInstance("s").setPickupLocation("foo").setDeliveryLocation("foofoo")
.addCapacityDimension(0, -2)
.build();
}
@Test
public void whenAddingTwoCapDimension_nuOfDimsShouldBeTwo(){
Shipment one = Shipment.Builder.newInstance("s").setPickupLocation("foo").setDeliveryLocation("foofoo")
.addCapacityDimension(0,2)
.addCapacityDimension(1,4)
.build();
assertEquals(2,one.getCapacity().getNuOfDimensions());
}
@Test
public void whenShipmentIsBuiltWithoutSpecifyingCapacity_itShouldHvCapWithOneDimAndDimValOfZero(){
Shipment one = Shipment.Builder.newInstance("s").setPickupLocation("foo").setPickupCoord(Coordinate.newInstance(0, 0))
.setDeliveryLocation("foofoo").build();
assertEquals(1,one.getCapacity().getNuOfDimensions());
assertEquals(0,one.getCapacity().get(0));
}
@Test
public void whenShipmentIsBuiltWithConstructorWhereSizeIsSpecified_capacityShouldBeSetCorrectly(){
Shipment one = Shipment.Builder.newInstance("s",1).setPickupLocation("foo").setPickupCoord(Coordinate.newInstance(0, 0))
.setDeliveryLocation("foofoo").build();
assertEquals(1,one.getCapacityDemand());
assertEquals(1,one.getCapacity().getNuOfDimensions());
assertEquals(1,one.getCapacity().get(0));
}
}

View file

@ -0,0 +1,7 @@
package jsprit.core.problem.vehicle;
public class VehicleImplTest {
}

View file

@ -0,0 +1,53 @@
package jsprit.core.problem.vehicle;
import static org.junit.Assert.*;
import org.junit.Test;
public class VehicleTypeImplTest {
@Test(expected=IllegalStateException.class)
public void whenTypeHasNegativeCapacityVal_throwIllegalStateExpception(){
@SuppressWarnings("unused")
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("t").addCapacityDimension(0,-10).build();
}
@Test
public void whenAddingTwoCapDimension_nuOfDimsShouldBeTwo(){
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("t")
.addCapacityDimension(0,2)
.addCapacityDimension(1, 4)
.build();
assertEquals(2,type.getCapacityDimensions().getNuOfDimensions());
}
@Test
public void whenAddingTwoCapDimension_dimValuesMustBeCorrect(){
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("t")
.addCapacityDimension(0,2)
.addCapacityDimension(1,4)
.build();
assertEquals(2,type.getCapacityDimensions().get(0));
assertEquals(4,type.getCapacityDimensions().get(1));
}
@Test
public void whenTypeIsBuiltWithoutSpecifyingCapacity_itShouldHvCapWithOneDim(){
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("t").build();
assertEquals(1,type.getCapacityDimensions().getNuOfDimensions());
}
@Test
public void whenTypeIsBuiltWithoutSpecifyingCapacity_itShouldHvCapDimValOfZero(){
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("t").build();
assertEquals(0,type.getCapacityDimensions().get(0));
}
@Test
public void whenTypeIsBuiltWithConstructorWhereSizeIsSpecified_capacityShouldBeSetCorrectly(){
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("t",20).build();
assertEquals(20,type.getCapacity());
assertEquals(20,type.getCapacityDimensions().get(0));
}
}