mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
added helper methods to deal with adding and subtracting of capacities
and multiple dimensions, and their corresponding tests
This commit is contained in:
parent
9f1580927c
commit
ea5fc1a3de
3 changed files with 281 additions and 6 deletions
|
|
@ -1,13 +1,75 @@
|
||||||
package jsprit.core.problem;
|
package jsprit.core.problem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capacity with an arbitrary number of capacity-dimension.
|
||||||
|
*
|
||||||
|
* <p>Note that this assumes the the values of each capacity dimension can be added up and subtracted
|
||||||
|
*
|
||||||
|
* @author schroeder
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class Capacity {
|
public class Capacity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds up two capacities, i.e. sums up each and every capacity dimension, and returns the resulting Capacity.
|
||||||
|
*
|
||||||
|
* <p>Note that this assumes that capacity dimension can be added up.
|
||||||
|
*
|
||||||
|
* @param cap1
|
||||||
|
* @param cap2
|
||||||
|
* @return new capacity
|
||||||
|
* @throws NullPointerException if one of the args is null
|
||||||
|
|
||||||
|
*/
|
||||||
|
public static Capacity addup(Capacity cap1, Capacity cap2){
|
||||||
|
if(cap1==null || cap2==null) throw new NullPointerException("arguments must not be null");
|
||||||
|
Capacity.Builder capacityBuilder= Capacity.Builder.newInstance();
|
||||||
|
for(int i=0;i<Math.max(cap1.getNuOfDimensions(),cap2.getNuOfDimensions());i++){
|
||||||
|
capacityBuilder.addDimension(i, cap1.get(i)+cap2.get(i));
|
||||||
|
}
|
||||||
|
return capacityBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtracts cap2substract from cap and returns the resulting Capacity.
|
||||||
|
*
|
||||||
|
* @param cap
|
||||||
|
* @param cap2substract
|
||||||
|
* @return new capacity
|
||||||
|
* @throws NullPointerException if one of the args is null
|
||||||
|
* @throws IllegalStateException if number of capacityDimensions of cap1 and cap2 are different (i.e. <code>cap1.getNuOfDimension() != cap2.getNuOfDimension()</code>).
|
||||||
|
* @throws IllegalStateException if one of the capacityDimenstions has a negative value after subtracting
|
||||||
|
*/
|
||||||
|
public static Capacity subtract(Capacity cap, Capacity cap2substract){
|
||||||
|
if(cap==null || cap2substract==null) throw new NullPointerException("arguments must not be null");
|
||||||
|
Capacity.Builder capacityBuilder= Capacity.Builder.newInstance();
|
||||||
|
for(int i=0;i<Math.max(cap.getNuOfDimensions(),cap2substract.getNuOfDimensions());i++){
|
||||||
|
int dimValue = cap.get(i)-cap2substract.get(i);
|
||||||
|
if(dimValue<0) throw new IllegalStateException("this must not be. dimension " + i + " has a negative value after subtracting");
|
||||||
|
capacityBuilder.addDimension(i, dimValue);
|
||||||
|
}
|
||||||
|
return capacityBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a deep copy of Capacity.
|
||||||
|
*
|
||||||
|
* @param capacity
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static Capacity copyOf(Capacity capacity){
|
public static Capacity copyOf(Capacity capacity){
|
||||||
if(capacity == null) return null;
|
if(capacity == null) return null;
|
||||||
return new Capacity(capacity);
|
return new Capacity(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder that builds Capacity
|
||||||
|
*
|
||||||
|
* @author schroeder
|
||||||
|
*
|
||||||
|
*/
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -15,6 +77,11 @@ public class Capacity {
|
||||||
*/
|
*/
|
||||||
private int[] dimensions = new int[1];
|
private int[] dimensions = new int[1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new instance of Capacity with one dimension and a value/size of 0
|
||||||
|
*
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
public static Builder newInstance(){
|
public static Builder newInstance(){
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
@ -24,7 +91,8 @@ public class Capacity {
|
||||||
/**
|
/**
|
||||||
* add capacity dimension
|
* add capacity dimension
|
||||||
*
|
*
|
||||||
* <p>if automatically resizes dimensions according to index, i.e. if index=7 there are 8 dimensions.
|
* <p>Note that it automatically resizes dimensions according to index, i.e. if index=7 there are 8 dimensions.
|
||||||
|
* New dimensions then are initialized with 0
|
||||||
*
|
*
|
||||||
* @throw IllegalStateException if dimValue < 0
|
* @throw IllegalStateException if dimValue < 0
|
||||||
* @param index
|
* @param index
|
||||||
|
|
@ -52,6 +120,11 @@ public class Capacity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an immutable Capacity and returns it.
|
||||||
|
*
|
||||||
|
* @return Capacity
|
||||||
|
*/
|
||||||
public Capacity build() {
|
public Capacity build() {
|
||||||
return new Capacity(this);
|
return new Capacity(this);
|
||||||
}
|
}
|
||||||
|
|
@ -77,12 +150,44 @@ public class Capacity {
|
||||||
dimensions = builder.dimensions;
|
dimensions = builder.dimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of specified capacity dimensions.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public int getNuOfDimensions(){
|
public int getNuOfDimensions(){
|
||||||
return dimensions.length;
|
return dimensions.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns value of capacity-dimension with specified index.
|
||||||
|
*
|
||||||
|
* <p>If capacity dimension does not exist, it returns 0 (rather than IndexOutOfBoundsException).
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public int get(int index){
|
public int get(int index){
|
||||||
return dimensions[index];
|
if(index<dimensions.length) return dimensions[index];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this capacity is less or equal than the capacity toCompare, i.e. if none of the capacity dimensions > than the corresponding dimension in toCompare.
|
||||||
|
*
|
||||||
|
* @param toCompare
|
||||||
|
* @return
|
||||||
|
* @throws NullPointerException if one of the args is null
|
||||||
|
* @throws IllegalStateException if number of capacityDimensions of this capacity and toCompare are different.
|
||||||
|
*/
|
||||||
|
public boolean isLessOrEqual(Capacity toCompare){
|
||||||
|
if(toCompare == null) throw new NullPointerException();
|
||||||
|
if(this.getNuOfDimensions() != toCompare.getNuOfDimensions()) throw new IllegalStateException("cap1.getNuOfDimension()="+this.getNuOfDimensions()+
|
||||||
|
"!= cap2.getNuOfDimension()="+toCompare.getNuOfDimensions()+ ". cannot add up capacities with different dimension.");
|
||||||
|
for(int i=0;i<this.getNuOfDimensions();i++){
|
||||||
|
if(this.get(i) > toCompare.get(i)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,11 @@ public interface Job {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public int getCapacityDemand();
|
public int getCapacityDemand();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns capacity of jobs which can consist of an arbitrary number of capacity dimensions.
|
||||||
|
*
|
||||||
|
* @return Capacity
|
||||||
|
*/
|
||||||
public Capacity getCapacity();
|
public Capacity getCapacity();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
package jsprit.core.problem;
|
package jsprit.core.problem;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
@ -45,12 +46,12 @@ public class CapacityTest {
|
||||||
assertEquals(4,cap.get(0));
|
assertEquals(4,cap.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected=IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void whenGettingIndexWhichIsHigherThanNuOfCapDimensions_throwIndexOutOfBoundsException(){
|
public void whenGettingIndexWhichIsHigherThanNuOfCapDimensions_itShouldReturn0(){
|
||||||
Capacity.Builder capBuilder = Capacity.Builder.newInstance();
|
Capacity.Builder capBuilder = Capacity.Builder.newInstance();
|
||||||
capBuilder.addDimension(0, 4);
|
capBuilder.addDimension(0, 4);
|
||||||
Capacity cap = capBuilder.build();
|
Capacity cap = capBuilder.build();
|
||||||
cap.get(2);
|
assertEquals(0,cap.get(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -90,4 +91,168 @@ public class CapacityTest {
|
||||||
assertTrue(nullCap==null);
|
assertTrue(nullCap==null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAddingUpTwoOneDimensionalCapacities_itShouldReturnCorrectCapacityValues(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).build();
|
||||||
|
Capacity result = Capacity.addup(cap1, cap2);
|
||||||
|
assertEquals(3, result.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAddingUpTwoOneDimensionalCapacities_itShouldReturnCorrectNuOfDimensions(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).build();
|
||||||
|
Capacity result = Capacity.addup(cap1, cap2);
|
||||||
|
assertEquals(1, result.getNuOfDimensions());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAddingUpTwoThreeDimensionalCapacities_itShouldReturnCorrectNuOfDimensions(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).addDimension(2, 3).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
Capacity result = Capacity.addup(cap1, cap2);
|
||||||
|
assertEquals(3, result.getNuOfDimensions());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAddingUpTwoThreeDimensionalCapacities_itShouldReturnCorrectCapValues(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).addDimension(2, 3).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
Capacity result = Capacity.addup(cap1, cap2);
|
||||||
|
assertEquals(3, result.get(0));
|
||||||
|
assertEquals(5, result.get(1));
|
||||||
|
assertEquals(7, result.get(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void whenAddingUpTwoCapacitiesWithDifferentNuOfDimensions_itShouldAddThemCorrectly(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).build();
|
||||||
|
Capacity result = Capacity.addup(cap1, cap2);
|
||||||
|
assertEquals(3,result.get(0));
|
||||||
|
assertEquals(2,result.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=NullPointerException.class)
|
||||||
|
public void whenOneOfArgsIsNullWhenAdding_itShouldThrowException(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).build();
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
Capacity result = Capacity.addup(cap1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSubtractingTwoOneDimensionalCapacities_itShouldReturnCorrectCapacityValues(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).build();
|
||||||
|
Capacity result = Capacity.subtract(cap2, cap1);
|
||||||
|
assertEquals(1, result.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSubtractingTwoOneDimensionalCapacities_itShouldReturnCorrectNuOfDimensions(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).build();
|
||||||
|
Capacity result = Capacity.subtract(cap2, cap1);
|
||||||
|
assertEquals(1, result.getNuOfDimensions());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSubtractingTwoThreeDimensionalCapacities_itShouldReturnCorrectNuOfDimensions(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).addDimension(2, 3).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
Capacity result = Capacity.subtract(cap2, cap1);
|
||||||
|
assertEquals(3, result.getNuOfDimensions());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSubtractingTwoThreeDimensionalCapacities_itShouldReturnCorrectCapValues(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).addDimension(2, 3).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
Capacity result = Capacity.subtract(cap2, cap1);
|
||||||
|
assertEquals(1, result.get(0));
|
||||||
|
assertEquals(1, result.get(1));
|
||||||
|
assertEquals(1, result.get(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=IllegalStateException.class)
|
||||||
|
public void whenSubtractingTwoCapacitiesWithDifferentNuOfDimensions_itShouldThrowException(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).build();
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
Capacity result = Capacity.subtract(cap2, cap1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=NullPointerException.class)
|
||||||
|
public void whenOneOfArgsIsNullWhenSubtracting_itShouldThrowException(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).build();
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
Capacity result = Capacity.subtract(cap1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=IllegalStateException.class)
|
||||||
|
public void whenSubtractingBiggerFromLower_itShouldReturnException(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).addDimension(2, 3).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
Capacity result = Capacity.subtract(cap1, cap2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenOneCapIsLessThanAnother_itShouldReturnCorrectBoolean(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 2).addDimension(2, 3).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
assertTrue(cap1.isLessOrEqual(cap2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenOneCapIsLessThanAnother_itShouldReturnCorrectBoolean_v2(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 2).addDimension(2, 4).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
assertTrue(cap1.isLessOrEqual(cap2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenOneCapIsLessThanAnother_itShouldReturnCorrectBoolean_v3(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
assertTrue(cap1.isLessOrEqual(cap2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenOneCapIsBiggerThanAnother_itShouldReturnCorrectBoolean(){
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build();
|
||||||
|
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 4).addDimension(2, 4).build();
|
||||||
|
assertFalse(cap2.isLessOrEqual(cap1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAddingTwo_itShouldReturnCorrectCap(){
|
||||||
|
int wheelChairSpace = 0;
|
||||||
|
int passengerSeats = 1;
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(wheelChairSpace, 2).addDimension(passengerSeats, 10).build();
|
||||||
|
Capacity wheelChair = Capacity.Builder.newInstance().addDimension(wheelChairSpace, 1).build();
|
||||||
|
Capacity passenger = Capacity.Builder.newInstance().addDimension(passengerSeats, 1).build();
|
||||||
|
Capacity wheelChair_plus_passenger = Capacity.addup(wheelChair, passenger);
|
||||||
|
assertEquals(1,wheelChair_plus_passenger.get(wheelChairSpace));
|
||||||
|
assertEquals(1,wheelChair_plus_passenger.get(passengerSeats));
|
||||||
|
assertTrue(wheelChair_plus_passenger.isLessOrEqual(cap1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAddingTwo_itShouldReturnCorrectCap_v2(){
|
||||||
|
int wheelChairSpace = 0;
|
||||||
|
int passengerSeats = 1;
|
||||||
|
int weight = 2;
|
||||||
|
Capacity cap1 = Capacity.Builder.newInstance().addDimension(wheelChairSpace, 2).addDimension(passengerSeats, 10).addDimension(2, 100).build();
|
||||||
|
Capacity wheelChair = Capacity.Builder.newInstance().addDimension(wheelChairSpace, 1).addDimension(weight, 80).build();
|
||||||
|
Capacity passenger = Capacity.Builder.newInstance().addDimension(passengerSeats, 1).addDimension(weight, 30).build();
|
||||||
|
Capacity wheelChair_plus_passenger = Capacity.addup(wheelChair, passenger);
|
||||||
|
assertEquals(1,wheelChair_plus_passenger.get(wheelChairSpace));
|
||||||
|
assertEquals(1,wheelChair_plus_passenger.get(passengerSeats));
|
||||||
|
assertEquals(110,wheelChair_plus_passenger.get(weight));
|
||||||
|
assertFalse(wheelChair_plus_passenger.isLessOrEqual(cap1));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue