diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/box/Jsprit.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/box/Jsprit.java index 83551cc5..0a533515 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/box/Jsprit.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/box/Jsprit.java @@ -368,6 +368,14 @@ public class Jsprit { } } + double fixedCostParam = toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())); + IncreasingAbsoluteFixedCosts increasingAbsoluteFixedCosts = null; + if (fixedCostParam > 0d) { + increasingAbsoluteFixedCosts = new IncreasingAbsoluteFixedCosts(vrp.getJobs().size()); + increasingAbsoluteFixedCosts.setWeightOfFixCost(fixedCostParam); + constraintManager.addConstraint(increasingAbsoluteFixedCosts); + } + double noiseLevel = toDouble(getProperty(Parameter.INSERTION_NOISE_LEVEL.toString())); double noiseProbability = toDouble(getProperty(Parameter.INSERTION_NOISE_PROB.toString())); @@ -598,6 +606,7 @@ public class Jsprit { vra.addListener(noiseConfigurator); vra.addListener(noise); vra.addListener(clusters); + if (increasingAbsoluteFixedCosts != null) vra.addListener(increasingAbsoluteFixedCosts); if(toBoolean(getProperty(Parameter.BREAK_SCHEDULING.toString()))) { vra.addListener(new BreakScheduling(vrp, stateManager, constraintManager)); diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/DecreasingRelativeFixedCosts.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/DecreasingRelativeFixedCosts.java new file mode 100644 index 00000000..f9b45879 --- /dev/null +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/DecreasingRelativeFixedCosts.java @@ -0,0 +1,77 @@ +/* + * Licensed to GraphHopper GmbH under one or more contributor + * license agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * GraphHopper GmbH licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.graphhopper.jsprit.core.algorithm.recreate; + +import com.graphhopper.jsprit.core.algorithm.state.InternalStates; +import com.graphhopper.jsprit.core.problem.Capacity; +import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint; +import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext; +import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; +import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter; +import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public final class DecreasingRelativeFixedCosts extends SolutionCompletenessRatio implements SoftRouteConstraint { + + private static final Logger logger = LoggerFactory.getLogger(DecreasingRelativeFixedCosts.class); + + private double weightDeltaFixCost = 0.5; + + private RouteAndActivityStateGetter stateGetter; + + public DecreasingRelativeFixedCosts(RouteAndActivityStateGetter stateGetter, int noJobs) { + super(noJobs); + this.stateGetter = stateGetter; + logger.debug("initialise {}", this); + } + + + public void setWeightOfFixCost(double weight) { + weightDeltaFixCost = weight; + logger.debug("set weightOfFixCostSaving to {}", weight); + } + + @Override + public String toString() { + return "[name=calculatesServiceInsertionConsideringFixCost][weightOfFixedCostSavings=" + weightDeltaFixCost + "]"; + } + + private Capacity getCurrentMaxLoadInRoute(VehicleRoute route) { + Capacity maxLoad = stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class); + if (maxLoad == null) maxLoad = Capacity.Builder.newInstance().build(); + return maxLoad; + } + + @Override + public double getCosts(JobInsertionContext insertionContext) { + VehicleRoute route = insertionContext.getRoute(); + Capacity currentLoad = getCurrentMaxLoadInRoute(route); + Capacity load = Capacity.addup(currentLoad, insertionContext.getJob().getSize()); + double currentRelFix = 0d; + if (route.getVehicle() != null && !(route.getVehicle() instanceof VehicleImpl.NoVehicle)) { + currentRelFix = route.getVehicle().getType().getVehicleCostParams().fix * Capacity.divide(currentLoad, route.getVehicle().getType().getCapacityDimensions()); + } + double newRelFix = insertionContext.getNewVehicle().getType().getVehicleCostParams().fix * (Capacity.divide(load, insertionContext.getNewVehicle().getType().getCapacityDimensions())); + double decreasingRelativeFixedCosts = (1 - solutionCompletenessRatio) * (newRelFix - currentRelFix); + return weightDeltaFixCost * solutionCompletenessRatio * decreasingRelativeFixedCosts; + } + + +} diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/DellAmicoFixCostCalculator.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/DellAmicoFixCostCalculator.java index 4ed97ed6..a08fe6d7 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/DellAmicoFixCostCalculator.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/DellAmicoFixCostCalculator.java @@ -31,14 +31,14 @@ public class DellAmicoFixCostCalculator implements SoftRouteConstraint, Insertio private int nuOfJobsToRecreate; - private final JobInsertionConsideringFixCostsCalculator calculator; + private final IncreasingAbsoluteFixedCosts calculator; private final int nuOfJobs; public DellAmicoFixCostCalculator(final int nuOfJobs, final RouteAndActivityStateGetter stateGetter) { super(); this.nuOfJobs = nuOfJobs; - calculator = new JobInsertionConsideringFixCostsCalculator(null, stateGetter); + calculator = new IncreasingAbsoluteFixedCosts(nuOfJobs); } @Override diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/IncreasingAbsoluteFixedCosts.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/IncreasingAbsoluteFixedCosts.java new file mode 100644 index 00000000..96854d57 --- /dev/null +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/IncreasingAbsoluteFixedCosts.java @@ -0,0 +1,61 @@ +/* + * Licensed to GraphHopper GmbH under one or more contributor + * license agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * GraphHopper GmbH licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.graphhopper.jsprit.core.algorithm.recreate; + +import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint; +import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext; +import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; +import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public final class IncreasingAbsoluteFixedCosts extends SolutionCompletenessRatio implements SoftRouteConstraint { + + private static final Logger logger = LoggerFactory.getLogger(IncreasingAbsoluteFixedCosts.class); + + private double weightDeltaFixCost = 0.5; + + public IncreasingAbsoluteFixedCosts(int noJobs) { + super(noJobs); + logger.debug("initialise {}", this); + } + + + public void setWeightOfFixCost(double weight) { + weightDeltaFixCost = weight; + logger.debug("set weightOfFixCostSaving to {}", weight); + } + + @Override + public String toString() { + return "[name=calculatesServiceInsertionConsideringFixCost][weightOfFixedCostSavings=" + weightDeltaFixCost + "]"; + } + + @Override + public double getCosts(JobInsertionContext insertionContext) { + final VehicleRoute currentRoute = insertionContext.getRoute(); + double currentFix = 0d; + if (currentRoute.getVehicle() != null && !(currentRoute.getVehicle() instanceof VehicleImpl.NoVehicle)) { + currentFix = currentRoute.getVehicle().getType().getVehicleCostParams().fix; + } + double increasingAbsoluteFixedCosts = solutionCompletenessRatio * (insertionContext.getNewVehicle().getType().getVehicleCostParams().fix - currentFix); + return weightDeltaFixCost * solutionCompletenessRatio * increasingAbsoluteFixedCosts; + } + +} diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionConsideringFixCostsCalculator.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionConsideringFixCostsCalculator.java deleted file mode 100644 index 1ce3d98e..00000000 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionConsideringFixCostsCalculator.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Licensed to GraphHopper GmbH under one or more contributor - * license agreements. See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - * - * GraphHopper GmbH licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.graphhopper.jsprit.core.algorithm.recreate; - -import com.graphhopper.jsprit.core.algorithm.state.InternalStates; -import com.graphhopper.jsprit.core.problem.Capacity; -import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint; -import com.graphhopper.jsprit.core.problem.driver.Driver; -import com.graphhopper.jsprit.core.problem.job.Job; -import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext; -import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; -import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter; -import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; -import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCostsCalculator, SoftRouteConstraint { - - private static final Logger logger = LoggerFactory.getLogger(JobInsertionConsideringFixCostsCalculator.class); - - private final JobInsertionCostsCalculator standardInsertion; - - private double weightDeltaFixCost = 0.5; - - private double solutionCompletenessRatio = 0.5; - - private RouteAndActivityStateGetter stateGetter; - - public JobInsertionConsideringFixCostsCalculator(final JobInsertionCostsCalculator standardCalculator, RouteAndActivityStateGetter stateGetter) { - super(); - this.standardInsertion = standardCalculator; - this.stateGetter = stateGetter; - logger.debug("initialise {}", this); - } - - @Override - public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) { - double fixedCostContribution = getFixCostContribution(currentRoute, jobToInsert, newVehicle); - if (fixedCostContribution > bestKnownPrice) { - return InsertionData.createEmptyInsertionData(); - } - InsertionData iData = standardInsertion.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice); - if (iData instanceof InsertionData.NoInsertionFound) { - return iData; - } - double totalInsertionCost = iData.getInsertionCost() + fixedCostContribution; - InsertionData insertionData = new InsertionData(totalInsertionCost, iData.getPickupInsertionIndex(), iData.getDeliveryInsertionIndex(), newVehicle, newDriver); - insertionData.setVehicleDepartureTime(newVehicleDepartureTime); - insertionData.getEvents().addAll(iData.getEvents()); - return insertionData; - } - - private double getFixCostContribution(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle) { - Capacity currentMaxLoadInRoute = getCurrentMaxLoadInRoute(currentRoute); - double relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert,currentMaxLoadInRoute); - double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle); - double deltaFixCost = (1 - solutionCompletenessRatio) * relFixCost + solutionCompletenessRatio * absFixCost; - return weightDeltaFixCost * solutionCompletenessRatio * deltaFixCost; - } - - public void setWeightOfFixCost(double weight) { - weightDeltaFixCost = weight; - logger.debug("set weightOfFixCostSaving to {}", weight); - } - - @Override - public String toString() { - return "[name=calculatesServiceInsertionConsideringFixCost][weightOfFixedCostSavings=" + weightDeltaFixCost + "]"; - } - - public void setSolutionCompletenessRatio(double ratio) { - solutionCompletenessRatio = ratio; - } - - public double getSolutionCompletenessRatio() { return solutionCompletenessRatio; } - - private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle) { - double currentFix = 0d; - if (route.getVehicle() != null && !(route.getVehicle() instanceof VehicleImpl.NoVehicle)) { - currentFix = route.getVehicle().getType().getVehicleCostParams().fix; - } - return newVehicle.getType().getVehicleCostParams().fix - currentFix; - } - - private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job, Capacity currentLoad) { - Capacity load = Capacity.addup(currentLoad, job.getSize()); - double currentRelFix = 0d; - if (route.getVehicle() != null && !(route.getVehicle() instanceof VehicleImpl.NoVehicle)) { - currentRelFix = route.getVehicle().getType().getVehicleCostParams().fix * Capacity.divide(currentLoad, route.getVehicle().getType().getCapacityDimensions()); - } - return newVehicle.getType().getVehicleCostParams().fix * (Capacity.divide(load, newVehicle.getType().getCapacityDimensions())) - currentRelFix; - } - - private Capacity getCurrentMaxLoadInRoute(VehicleRoute route) { - Capacity maxLoad = stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class); - if (maxLoad == null) maxLoad = Capacity.Builder.newInstance().build(); - return maxLoad; - } - - @Override - public double getCosts(JobInsertionContext insertionContext) { - return getFixCostContribution(insertionContext.getRoute(), insertionContext.getJob(), insertionContext.getNewVehicle()); - } - -} diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionCostsCalculatorBuilder.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionCostsCalculatorBuilder.java index 01284d80..1135adb8 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionCostsCalculatorBuilder.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionCostsCalculatorBuilder.java @@ -218,10 +218,10 @@ public class JobInsertionCostsCalculatorBuilder { addAlgorithmListeners(standardLocal.getAlgorithmListener()); addInsertionListeners(standardLocal.getInsertionListener()); if (considerFixedCost) { - CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost); - baseCalculator = withFixed.getCalculator(); - addAlgorithmListeners(withFixed.getAlgorithmListener()); - addInsertionListeners(withFixed.getInsertionListener()); +// CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost); +// baseCalculator = withFixed.getCalculator(); +// addAlgorithmListeners(withFixed.getAlgorithmListener()); +// addInsertionListeners(withFixed.getInsertionListener()); } if (timeScheduling) { // baseCalculator = new CalculatesServiceInsertionWithTimeSchedulingInSlices(baseCalculator,timeSlice,neighbors); @@ -309,14 +309,6 @@ public class JobInsertionCostsCalculatorBuilder { return calculatorPlusListeners; } - private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, RouteAndActivityStateGetter activityStates2, double weightOfFixedCosts) { - final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2); - withFixCost.setWeightOfFixCost(weightOfFixedCosts); - CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost); - calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost)); - return calcPlusListeners; - } - private CalculatorPlusListeners createStandardRoute(final VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory) { ActivityInsertionCostsCalculator routeLevelCostEstimator; if (activityInsertionCostCalculator == null && addDefaultCostCalc) { diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/ConfigureFixCostCalculator.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/SolutionCompletenessRatio.java similarity index 59% rename from jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/ConfigureFixCostCalculator.java rename to jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/SolutionCompletenessRatio.java index 16c7ab03..9f059088 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/ConfigureFixCostCalculator.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/recreate/SolutionCompletenessRatio.java @@ -15,50 +15,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.graphhopper.jsprit.core.algorithm.recreate; +package com.graphhopper.jsprit.core.algorithm.recreate; import com.graphhopper.jsprit.core.algorithm.recreate.listener.InsertionStartsListener; import com.graphhopper.jsprit.core.algorithm.recreate.listener.JobInsertedListener; -import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; import com.graphhopper.jsprit.core.problem.job.Job; import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; import java.util.Collection; +/** + * Created by schroeder on 11/01/17. + */ +class SolutionCompletenessRatio implements InsertionStartsListener, JobInsertedListener { -final class ConfigureFixCostCalculator implements InsertionStartsListener, JobInsertedListener { + protected double solutionCompletenessRatio = 0.5; - private final VehicleRoutingProblem vrp; - - private final JobInsertionConsideringFixCostsCalculator calcConsideringFix; - - private final double minRatio = 0.5; + private final int nuOfJobs; private int nuOfJobsToRecreate; - public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) { - super(); - this.vrp = vrp; - this.calcConsideringFix = calcConsideringFix; + public SolutionCompletenessRatio(int nuOfJobs) { + this.nuOfJobs = nuOfJobs; } - @Override - public String toString() { - return "[name=configureFixCostCalculator]"; + public void setSolutionCompletenessRatio(double ratio) { + solutionCompletenessRatio = ratio; + } + + public double getSolutionCompletenessRatio() { + return solutionCompletenessRatio; } @Override public void informInsertionStarts(Collection routes, Collection unassignedJobs) { this.nuOfJobsToRecreate = unassignedJobs.size(); - double completenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) vrp.getJobs().values().size())); - calcConsideringFix.setSolutionCompletenessRatio(Math.max(minRatio,completenessRatio)); + solutionCompletenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) nuOfJobs)); } @Override public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { nuOfJobsToRecreate--; - double completenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) vrp.getJobs().values().size())); - calcConsideringFix.setSolutionCompletenessRatio(Math.max(minRatio,completenessRatio)); + solutionCompletenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) nuOfJobs)); } } diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/recreate/ConfigureFixCostCalculatorTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/recreate/ConfigureFixCostCalculatorTest.java deleted file mode 100644 index 5ed06ce6..00000000 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/recreate/ConfigureFixCostCalculatorTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to GraphHopper GmbH under one or more contributor - * license agreements. See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - * - * GraphHopper GmbH licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.graphhopper.jsprit.core.algorithm.recreate; - -import com.graphhopper.jsprit.core.algorithm.state.StateManager; -import com.graphhopper.jsprit.core.problem.AbstractJob; -import com.graphhopper.jsprit.core.problem.Location; -import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; -import com.graphhopper.jsprit.core.problem.job.Job; -import com.graphhopper.jsprit.core.problem.job.Service; -import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.Mockito.mock; - -/** - * Created by schroeder on 15/08/16. - */ -public class ConfigureFixCostCalculatorTest { - - VehicleRoutingProblem vrp; - - @Before - public void before(){ - VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); - for(int i=0;i<100;i++){ - Service service = Service.Builder.newInstance("" + i).setLocation(Location.newInstance(0)).build(); - vrpBuilder.addJob(service); - } - vrp = vrpBuilder.build(); - } - - @Test - public void shouldCalculateCorrectly(){ - List unassigned = new ArrayList<>(); - int count = 1; - for(String key : vrp.getJobs().keySet()) { - if(count <= 25) { - unassigned.add(vrp.getJobs().get(key)); - } - count++; - } - JobInsertionConsideringFixCostsCalculator jicc = new JobInsertionConsideringFixCostsCalculator(mock(JobInsertionCostsCalculator.class),mock(StateManager.class)); - ConfigureFixCostCalculator c = new ConfigureFixCostCalculator(vrp,jicc); - c.informInsertionStarts(new ArrayList(), unassigned); - Assert.assertEquals(0.75, jicc.getSolutionCompletenessRatio(), 0.001); - } - - @Test - public void shouldBeMinRatio(){ - List unassigned = new ArrayList<>(); - int count = 1; - for(String key : vrp.getJobs().keySet()) { - if(count <= 75) { - unassigned.add(vrp.getJobs().get(key)); - } - count++; - } - JobInsertionConsideringFixCostsCalculator jicc = new JobInsertionConsideringFixCostsCalculator(mock(JobInsertionCostsCalculator.class),mock(StateManager.class)); - ConfigureFixCostCalculator c = new ConfigureFixCostCalculator(vrp,jicc); - c.informInsertionStarts(new ArrayList(), unassigned); - Assert.assertEquals(0.5, jicc.getSolutionCompletenessRatio(), 0.001); - } - - @Test - public void shouldBeOne(){ - List unassigned = new ArrayList<>(); - JobInsertionConsideringFixCostsCalculator jicc = new JobInsertionConsideringFixCostsCalculator(mock(JobInsertionCostsCalculator.class),mock(StateManager.class)); - ConfigureFixCostCalculator c = new ConfigureFixCostCalculator(vrp,jicc); - c.informInsertionStarts(new ArrayList(), unassigned); - Assert.assertEquals(1.0, jicc.getSolutionCompletenessRatio(), 0.001); - } -} diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionConsideringFixCostsCalculatorTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionConsideringFixCostsCalculatorTest.java index 7f674c09..e35273a8 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionConsideringFixCostsCalculatorTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/recreate/JobInsertionConsideringFixCostsCalculatorTest.java @@ -20,6 +20,7 @@ package com.graphhopper.jsprit.core.algorithm.recreate; import com.graphhopper.jsprit.core.algorithm.state.InternalStates; import com.graphhopper.jsprit.core.problem.Capacity; import com.graphhopper.jsprit.core.problem.job.Job; +import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext; import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter; import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; @@ -34,7 +35,9 @@ import static org.mockito.Mockito.when; public class JobInsertionConsideringFixCostsCalculatorTest { - private JobInsertionConsideringFixCostsCalculator calc; + private IncreasingAbsoluteFixedCosts absFixedCosts; + + private DecreasingRelativeFixedCosts relFixedCosts; private Vehicle small; @@ -75,168 +78,270 @@ public class JobInsertionConsideringFixCostsCalculatorTest { stateGetter = mock(RouteAndActivityStateGetter.class); when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().build()); - calc = new JobInsertionConsideringFixCostsCalculator(jobInsertionCosts, stateGetter); + absFixedCosts = new IncreasingAbsoluteFixedCosts(10); + relFixedCosts = new DecreasingRelativeFixedCosts(stateGetter, 10); } @Test public void whenOldVehicleIsNullAndSolutionComplete_itShouldReturnFixedCostsOfNewVehicle() { - calc.setSolutionCompletenessRatio(1.0); - calc.setWeightOfFixCost(1.0); + absFixedCosts.setSolutionCompletenessRatio(1.0); + absFixedCosts.setWeightOfFixCost(1.0); + + relFixedCosts.setSolutionCompletenessRatio(1.0); + relFixedCosts.setWeightOfFixCost(1.0); //(1.*absFix + 0.*relFix) * completeness * weight = (1.*100. + 0.*50.) * 1. * 1. = 100. - assertEquals(100., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + assertEquals(100., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNullAndSolutionIs0PercentComplete_itShouldReturnNoFixedCosts() { - calc.setSolutionCompletenessRatio(0.0); - calc.setWeightOfFixCost(1.0); + absFixedCosts.setSolutionCompletenessRatio(0.0); + absFixedCosts.setWeightOfFixCost(1.0); + + relFixedCosts.setSolutionCompletenessRatio(0.0); + relFixedCosts.setWeightOfFixCost(1.0); //(0.*absFix + 1.*relFix) * completeness * weight = 0. - assertEquals(0., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + + assertEquals(0., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.1); } @Test public void whenOldVehicleIsNullAndSolutionIs50PercentComplete_itShouldReturnAvgOfRelFixedAndAbsFixedCostOfNewVehicle() { - calc.setSolutionCompletenessRatio(0.5); - calc.setWeightOfFixCost(1.0); + absFixedCosts.setSolutionCompletenessRatio(0.5); + absFixedCosts.setWeightOfFixCost(1.0); + + relFixedCosts.setSolutionCompletenessRatio(0.5); + relFixedCosts.setWeightOfFixCost(1.0); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.5*absFix + 0.5*relFix) * 0.5 * 1. = (0.5*100+0.5*50)*0.5*1. = 37.5 - assertEquals(37.5, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(37.5, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNullAndSolutionIs75PercentComplete_itShouldReturnAvgOfRelFixedAndAbsFixedCostOfNewVehicle() { - calc.setSolutionCompletenessRatio(0.75); - calc.setWeightOfFixCost(1.0); + absFixedCosts.setSolutionCompletenessRatio(0.75); + absFixedCosts.setWeightOfFixCost(1.0); + + relFixedCosts.setSolutionCompletenessRatio(0.75); + relFixedCosts.setWeightOfFixCost(1.0); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + //(0.75*absFix + 0.25*relFix) * 0.75 * 1.= (0.75*100.+0.25*50.)*0.75*1. = 65.625 - assertEquals(65.625, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(65.625, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNullAndSolutionCompleteAndWeightIs05_itShouldReturnHalfOfFixedCostsOfNewVehicle() { - calc.setSolutionCompletenessRatio(1.0); - calc.setWeightOfFixCost(.5); + absFixedCosts.setSolutionCompletenessRatio(1.0); + absFixedCosts.setWeightOfFixCost(.5); + + relFixedCosts.setSolutionCompletenessRatio(1.0); + relFixedCosts.setWeightOfFixCost(.5); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(1.*absFix + 0.*relFix) * 1. * 0.5 = (1.*100. + 0.*50.) * 1. * 0.5 = 5. - assertEquals(50., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(50., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNullAndSolutionIs0PercentCompleteAndWeightIs05_itShouldReturnHalfOfNoFixedCosts() { - calc.setSolutionCompletenessRatio(0.0); - calc.setWeightOfFixCost(.5); + absFixedCosts.setSolutionCompletenessRatio(0.0); + absFixedCosts.setWeightOfFixCost(.5); + + relFixedCosts.setSolutionCompletenessRatio(0.0); + relFixedCosts.setWeightOfFixCost(.5); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.*absFix + 1.*relFix) * 0. * .5 = 0. - assertEquals(0., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(0., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNullAndSolutionIs50PercentCompleteAndWeightIs05_itShouldReturnHalfOfAvgOfRelFixedAndAbsFixedCostOfNewVehicle() { - calc.setSolutionCompletenessRatio(0.5); - calc.setWeightOfFixCost(.5); + absFixedCosts.setSolutionCompletenessRatio(0.5); + absFixedCosts.setWeightOfFixCost(.5); + + relFixedCosts.setSolutionCompletenessRatio(0.5); + relFixedCosts.setWeightOfFixCost(.5); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + //(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*100+0.5*50)*0.5*0.5 = 18.75 - assertEquals(18.75, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(18.75, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNullAndSolutionIs75PercentCompleteAndWeightIs05_itShouldReturnHalfOfAvgOfRelFixedAndAbsFixedCostOfNewVehicle() { - calc.setSolutionCompletenessRatio(0.75); - calc.setWeightOfFixCost(0.5); + absFixedCosts.setSolutionCompletenessRatio(0.75); + absFixedCosts.setWeightOfFixCost(0.5); + + relFixedCosts.setSolutionCompletenessRatio(0.75); + relFixedCosts.setWeightOfFixCost(0.5); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + //(0.75*absFix + 0.25*relFix) * 0.75 * 0.5 = (0.75*100.+0.25*50.)*0.75*0.5 = 32.8125 - assertEquals(32.8125, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(32.8125, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndSolutionComplete_itShouldReturnHalfOfFixedCostsOfNewVehicle() { - calc.setSolutionCompletenessRatio(1.0); - calc.setWeightOfFixCost(1.0); + absFixedCosts.setSolutionCompletenessRatio(1.0); + absFixedCosts.setWeightOfFixCost(1.0); + + relFixedCosts.setSolutionCompletenessRatio(1.0); + relFixedCosts.setWeightOfFixCost(1.0); + when(route.getVehicle()).thenReturn(small); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + //(1.*absFix + 0.*relFix) * completeness * weight = (1.*(100.-50.) + 0.*(50.-0.)) * 1. * 1. = 50. - assertEquals(50., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(50., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndSolutionIs0PercentComplete_itShouldReturnNoFixedCosts() { - calc.setSolutionCompletenessRatio(0.0); - calc.setWeightOfFixCost(1.0); + absFixedCosts.setSolutionCompletenessRatio(0.0); + absFixedCosts.setWeightOfFixCost(1.0); + + relFixedCosts.setSolutionCompletenessRatio(0.0); + relFixedCosts.setWeightOfFixCost(1.0); + when(route.getVehicle()).thenReturn(small); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.*absFix + 1.*relFix) * completeness * weight = 0. - assertEquals(0., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(0., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndSolutionIs50PercentComplete_itShouldCorrectVal() { - calc.setSolutionCompletenessRatio(0.5); - calc.setWeightOfFixCost(1.0); + absFixedCosts.setSolutionCompletenessRatio(0.5); + absFixedCosts.setWeightOfFixCost(1.0); + + relFixedCosts.setSolutionCompletenessRatio(0.5); + relFixedCosts.setWeightOfFixCost(1.0); + when(route.getVehicle()).thenReturn(small); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.5*absFix + 0.5*relFix) * 0.5 * 1. = (0.5*(100-50)+0.5*(50-0))*0.5*1. = 25. - assertEquals(25., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(25., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndSolutionIs75PercentComplete_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(0.75); - calc.setWeightOfFixCost(1.0); + absFixedCosts.setSolutionCompletenessRatio(0.75); + absFixedCosts.setWeightOfFixCost(1.0); + + relFixedCosts.setSolutionCompletenessRatio(0.75); + relFixedCosts.setWeightOfFixCost(1.0); + when(route.getVehicle()).thenReturn(small); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.75*absFix + 0.25*relFix) * 0.75 * 1.= (0.75*(100.-50.)+0.25*(50.-0.))*0.75*1. = 37.5 - assertEquals(37.5, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(37.5, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndSolutionCompleteAndWeightIs05_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(1.0); - calc.setWeightOfFixCost(.5); + absFixedCosts.setSolutionCompletenessRatio(1.0); + absFixedCosts.setWeightOfFixCost(.5); + + relFixedCosts.setSolutionCompletenessRatio(1.0); + relFixedCosts.setWeightOfFixCost(.5); + when(route.getVehicle()).thenReturn(small); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(1.*absFix + 0.*relFix) * 1. * 0.5 = (1.*(100.-50.) + 0.*(50.-0.)) * 1. * 0.5 = 25. - assertEquals(25., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(25., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndSolutionIs0PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(0.0); - calc.setWeightOfFixCost(.5); + absFixedCosts.setSolutionCompletenessRatio(0.0); + absFixedCosts.setWeightOfFixCost(.5); + + relFixedCosts.setSolutionCompletenessRatio(0.0); + relFixedCosts.setWeightOfFixCost(.5); + when(route.getVehicle()).thenReturn(small); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.*absFix + 1.*relFix) * 0. * .5 = 0. - assertEquals(0., calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(0., absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndSolutionIs50PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(0.5); - calc.setWeightOfFixCost(.5); + absFixedCosts.setSolutionCompletenessRatio(0.5); + absFixedCosts.setWeightOfFixCost(.5); + + relFixedCosts.setSolutionCompletenessRatio(0.5); + relFixedCosts.setWeightOfFixCost(.5); + when(route.getVehicle()).thenReturn(small); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*(100-50)+0.5*(50-0))*0.5*0.5 = 12.5 - assertEquals(12.5, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(12.5, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndSolutionIs75PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(0.75); - calc.setWeightOfFixCost(0.5); + absFixedCosts.setSolutionCompletenessRatio(0.75); + absFixedCosts.setWeightOfFixCost(0.5); + + relFixedCosts.setSolutionCompletenessRatio(0.75); + relFixedCosts.setWeightOfFixCost(0.5); + when(route.getVehicle()).thenReturn(small); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.75*absFix + 0.25*relFix) * 0.75 * 0.5 = (0.75*(100.-50.)+0.25*(50.-0.))*0.75*0.5 = 18.75 - assertEquals(18.75, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(18.75, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndCurrentLoadIs25AndSolutionIs50PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(0.5); - calc.setWeightOfFixCost(.5); + absFixedCosts.setSolutionCompletenessRatio(0.5); + absFixedCosts.setWeightOfFixCost(.5); + + relFixedCosts.setSolutionCompletenessRatio(0.5); + relFixedCosts.setWeightOfFixCost(.5); + when(route.getVehicle()).thenReturn(small); when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).build()); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*(100-50)+0.5*(75-25))*0.5*0.5 = 12.5 - assertEquals(12.5, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(12.5, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndCurrentLoadIs25AndSolutionIs75PercentCompleteAndWeightIs05_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(0.75); - calc.setWeightOfFixCost(0.5); + absFixedCosts.setSolutionCompletenessRatio(0.75); + absFixedCosts.setWeightOfFixCost(0.5); + + relFixedCosts.setSolutionCompletenessRatio(0.75); + relFixedCosts.setWeightOfFixCost(0.5); + when(route.getVehicle()).thenReturn(small); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.75*absFix + 0.25*relFix) * 0.75 * 0.5 = (0.75*(100.-50.)+0.25*(75.-25.))*0.75*0.5 = 18.75 - assertEquals(18.75, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(18.75, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsNotNullAndCurrentLoadIs25AndSolutionIs50PercentCompleteAndWeightIs05WithMultipleCapDims_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(.5); - calc.setWeightOfFixCost(.5); + absFixedCosts.setSolutionCompletenessRatio(.5); + absFixedCosts.setWeightOfFixCost(.5); + + relFixedCosts.setSolutionCompletenessRatio(.5); + relFixedCosts.setWeightOfFixCost(.5); when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).addDimension(1, 0).build()); @@ -248,6 +353,8 @@ public class JobInsertionConsideringFixCostsCalculatorTest { when(route.getVehicle()).thenReturn(small); when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).addDimension(1, 100).build()); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*(100-50)+0.5*(75-25))*0.5*0.5 = 12.5 /* * (0.5*(100-50)+0.5*( @@ -256,13 +363,16 @@ public class JobInsertionConsideringFixCostsCalculatorTest { * = (0.5*(100-50)+0.5*((75/100+100/400)/2.*100 - ((25/50+100/100)/2.*50.)))*0.5*0.5 * = (0.5*(100-50)+0.5*12.5)*0.5*0.5 = 7.8125 */ - assertEquals(7.8125, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(7.8125, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); } @Test public void whenOldVehicleIsMoreExpensive() { - calc.setSolutionCompletenessRatio(1); - calc.setWeightOfFixCost(1); + absFixedCosts.setSolutionCompletenessRatio(1); + absFixedCosts.setWeightOfFixCost(1); + + relFixedCosts.setSolutionCompletenessRatio(1); + relFixedCosts.setWeightOfFixCost(1); when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).addDimension(1, 0).build()); @@ -283,50 +393,77 @@ public class JobInsertionConsideringFixCostsCalculatorTest { * = (0.5*(100-50)+0.5*((75/100+100/400)/2.*100 - ((25/50+100/100)/2.*50.)))*0.5*0.5 * = (0.5*(100-50)+0.5*12.5)*0.5*0.5 = 7.8125 */ - double insertionCost = calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + + double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context); assertEquals(-50d, insertionCost, 0.01); } @Test public void smallVSMediumAbsCosts() { - calc.setSolutionCompletenessRatio(1); - calc.setWeightOfFixCost(1); + absFixedCosts.setSolutionCompletenessRatio(1); + absFixedCosts.setWeightOfFixCost(1); + + relFixedCosts.setSolutionCompletenessRatio(1); + relFixedCosts.setWeightOfFixCost(1); + when(route.getVehicle()).thenReturn(small); - double insertionCost = calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context); assertEquals(50d, insertionCost, 0.01); } @Test public void smallVSLargeAbsCosts() { - calc.setSolutionCompletenessRatio(1); - calc.setWeightOfFixCost(1); + absFixedCosts.setSolutionCompletenessRatio(1); + absFixedCosts.setWeightOfFixCost(1); + + relFixedCosts.setSolutionCompletenessRatio(1); + relFixedCosts.setWeightOfFixCost(1); + when(route.getVehicle()).thenReturn(small); - double insertionCost = calc.getInsertionData(route, job, large, 0.0, null, Double.MAX_VALUE).getInsertionCost(); + JobInsertionContext context = new JobInsertionContext(route, job, large, null, 0d); + double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context); assertEquals(150d, insertionCost, 0.01); } @Test public void largeVSMediumAbsCosts() { - calc.setSolutionCompletenessRatio(1); - calc.setWeightOfFixCost(1); + absFixedCosts.setSolutionCompletenessRatio(1); + absFixedCosts.setWeightOfFixCost(1); + + relFixedCosts.setSolutionCompletenessRatio(1); + relFixedCosts.setWeightOfFixCost(1); + when(route.getVehicle()).thenReturn(large); - double insertionCost = calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(); + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context); assertEquals(-100d, insertionCost, 0.01); } @Test public void mediumVSLargeAbsCosts() { - calc.setSolutionCompletenessRatio(1); - calc.setWeightOfFixCost(1); + absFixedCosts.setSolutionCompletenessRatio(1); + absFixedCosts.setWeightOfFixCost(1); + + relFixedCosts.setSolutionCompletenessRatio(1); + relFixedCosts.setWeightOfFixCost(1); + when(route.getVehicle()).thenReturn(medium); - double insertionCost = calc.getInsertionData(route, job, large, 0.0, null, Double.MAX_VALUE).getInsertionCost(); + JobInsertionContext context = new JobInsertionContext(route, job, large, null, 0d); + + double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context); assertEquals(100d, insertionCost, 0.01); } @Test public void whenOldVehicleIsMoreExpensive2() { - calc.setSolutionCompletenessRatio(0.1); - calc.setWeightOfFixCost(1); + absFixedCosts.setSolutionCompletenessRatio(0.1); + absFixedCosts.setWeightOfFixCost(1); + + relFixedCosts.setSolutionCompletenessRatio(0.1); + relFixedCosts.setWeightOfFixCost(1); when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).addDimension(1, 0).build()); @@ -339,22 +476,27 @@ public class JobInsertionConsideringFixCostsCalculatorTest { when(route.getVehicle()).thenReturn(small); when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).addDimension(1, 100).build()); - //(0.5*absFix + 0.5*relFix) * 0.5 * 0.= (0.5*(100-50)+0.5*(75-25))*0.5*0.5 = 12.5 /* - * (0.5*(100-50)+0.5*( - * relFixNew - relFixOld = (75/100+100/400)/2.*100 - ((25/50+100/100)/2.*50.) = - * )*0.5*0.5 - * = (0.5*(100-50)+0.5*((75/100+100/400)/2.*100 - ((25/50+100/100)/2.*50.)))*0.5*0.5 - * = (0.5*(100-50)+0.5*12.5)*0.5*0.5 = 7.8125 - */ - double insertionCost = calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(); - assertEquals(-50d, insertionCost, 0.01); + job = 50 + abs = (50 - 100) * 0.1 * 0.1 * 1.0 = -0.5 + rel = ( (75/50+100/100)/2 * 50 - (25/100 + 100/400)/2 * 100) * 0.9 * 0.1 = 3.375 + c = -0.5 + 3.375 = 2.875 + + */ + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); + + double insertionCost = absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context); + assertEquals(2.875, insertionCost, 0.01); } @Test public void whenOldVehicleIsNotNullAndCurrentLoadIs25AndSolutionIs75PercentCompleteAndWeightIs05WithMultipleCapDims_itShouldReturnCorrectVal() { - calc.setSolutionCompletenessRatio(0.75); - calc.setWeightOfFixCost(0.5); + absFixedCosts.setSolutionCompletenessRatio(0.75); + absFixedCosts.setWeightOfFixCost(0.5); + + relFixedCosts.setSolutionCompletenessRatio(0.75); + relFixedCosts.setWeightOfFixCost(0.5); + when(job.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 50).addDimension(1, 0).build()); VehicleType oType = VehicleTypeImpl.Builder.newInstance("otype").addCapacityDimension(0, 50).addCapacityDimension(1, 100).setFixedCost(50.0).build(); @@ -365,9 +507,11 @@ public class JobInsertionConsideringFixCostsCalculatorTest { when(route.getVehicle()).thenReturn(small); when(stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class)).thenReturn(Capacity.Builder.newInstance().addDimension(0, 25).addDimension(1, 100).build()); + + JobInsertionContext context = new JobInsertionContext(route, job, medium, null, 0d); //(0.75*absFix + 0.25*relFix) * 0.75 * 0.5 = (0.75*(100.-50.)+0.25*12.5)*0.75*0.5 = 15.234375 - assertEquals(15.234375, calc.getInsertionData(route, job, medium, 0.0, null, Double.MAX_VALUE).getInsertionCost(), 0.01); + assertEquals(15.234375, absFixedCosts.getCosts(context) + relFixedCosts.getCosts(context), 0.01); }