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 a1cdf9fb5..d76452834 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 @@ -82,7 +82,10 @@ public enum Strategy { CLUSTER_BEST("cluster_best"), CLUSTER_REGRET("cluster_regret"), STRING_BEST("string_best"), - STRING_REGRET("string_regret"); + STRING_REGRET("string_regret"), + TIME_RELATED_REGRET("time_related_regret"), + TIME_RELATED_BEST("time_related_best"); + String strategyName; @@ -189,6 +192,10 @@ private Properties createDefaultProperties() { Properties defaults = new Properties(); defaults.put(Strategy.RADIAL_BEST.toString(), "0."); defaults.put(Strategy.RADIAL_REGRET.toString(), ".5"); + + defaults.put(Strategy.TIME_RELATED_BEST.toString(), "0."); + defaults.put(Strategy.TIME_RELATED_REGRET.toString(), "0."); + defaults.put(Strategy.RANDOM_BEST.toString(), ".5"); defaults.put(Strategy.RANDOM_REGRET.toString(), ".5"); @@ -466,18 +473,18 @@ private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp) { RuinRadial radial = new RuinRadial(vrp, vrp.getJobs().size(), jobNeighborhoods); radial.setRandom(random); - radial.setRuinShareFactory(new RuinShareFactoryImpl( + RuinShareFactoryImpl radialRuinFactory = new RuinShareFactoryImpl( toInteger(properties.getProperty(Parameter.RADIAL_MIN_SHARE.toString())), toInteger(properties.getProperty(Parameter.RADIAL_MAX_SHARE.toString())), - random) - ); + random); + radial.setRuinShareFactory(radialRuinFactory); final RuinRandom random_for_regret = new RuinRandom(vrp, 0.5); random_for_regret.setRandom(random); random_for_regret.setRuinShareFactory(new RuinShareFactoryImpl( - toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MIN_SHARE.toString())), - toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MAX_SHARE.toString())), - random) + toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MIN_SHARE.toString())), + toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MAX_SHARE.toString())), + random) ); final RuinRandom random_for_best = new RuinRandom(vrp, 0.5); @@ -521,12 +528,16 @@ private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp) { stringRuin.setStringLength(lMin, lMax); stringRuin.setRandom(random); + final RuinTimeRelated ruinTimeRelated = new RuinTimeRelated(vrp); + ruinTimeRelated.setRuinShareFactory(radialRuinFactory); + ruinTimeRelated.setRandom(random); + AbstractInsertionStrategy regret; final ScoringFunction scorer; boolean fastRegret = Boolean.parseBoolean(getProperty(Parameter.FAST_REGRET.toString())); if (es != null) { - if(fastRegret){ + if (fastRegret) { RegretInsertionConcurrentFast regretInsertion = (RegretInsertionConcurrentFast) new InsertionStrategyBuilder(vrp, vehicleFleetManager, stateManager, constraintManager) .setInsertionStrategy(InsertionStrategyBuilder.Strategy.REGRET) .setConcurrentMode(es, noThreads) @@ -624,6 +635,12 @@ private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp) { SearchStrategy radialBest = new SearchStrategy(Strategy.RADIAL_BEST.toString(), new SelectBest(), acceptor, objectiveFunction); radialBest.addModule(configureModule(new RuinAndRecreateModule(Strategy.RADIAL_BEST.toString(), best, radial))); + SearchStrategy timeRelatedRegret = new SearchStrategy(Strategy.TIME_RELATED_REGRET.toString(), new SelectBest(), acceptor, objectiveFunction); + timeRelatedRegret.addModule(configureModule(new RuinAndRecreateModule(Strategy.TIME_RELATED_REGRET.toString(), regret, ruinTimeRelated))); + + SearchStrategy timeRelatedBest = new SearchStrategy(Strategy.TIME_RELATED_BEST.toString(), new SelectBest(), acceptor, objectiveFunction); + timeRelatedBest.addModule(configureModule(new RuinAndRecreateModule(Strategy.TIME_RELATED_BEST.toString(), best, ruinTimeRelated))); + SearchStrategy randomBest = new SearchStrategy(Strategy.RANDOM_BEST.toString(), new SelectBest(), acceptor, objectiveFunction); randomBest.addModule(configureModule(new RuinAndRecreateModule(Strategy.RANDOM_BEST.toString(), best, random_for_best))); @@ -655,6 +672,10 @@ private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp) { } prettyBuilder.withStrategy(radialRegret, toDouble(getProperty(Strategy.RADIAL_REGRET.toString()))) .withStrategy(radialBest, toDouble(getProperty(Strategy.RADIAL_BEST.toString()))) + + .withStrategy(timeRelatedBest, toDouble(getProperty(Strategy.TIME_RELATED_BEST.toString()))) + .withStrategy(timeRelatedRegret, toDouble(getProperty(Strategy.TIME_RELATED_REGRET.toString()))) + .withStrategy(randomBest, toDouble(getProperty(Strategy.RANDOM_BEST.toString()))) .withStrategy(randomRegret, toDouble(getProperty(Strategy.RANDOM_REGRET.toString()))) .withStrategy(worstBest, toDouble(getProperty(Strategy.WORST_BEST.toString()))) diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/RuinTimeRelated.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/RuinTimeRelated.java new file mode 100644 index 000000000..d1982bcad --- /dev/null +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/RuinTimeRelated.java @@ -0,0 +1,156 @@ +/* + * 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.ruin; + +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 com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity; +import com.graphhopper.jsprit.core.util.NoiseMaker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + + +/** + * @author stefan schroeder + */ + +public final class RuinTimeRelated extends AbstractRuinStrategy { + + static class RelatednessToTourActivity { + + final double time; + + final TourActivity tourActivity; + + final VehicleRoute route; + + final double distance; + + public RelatednessToTourActivity(double relatednessToTarget, double distance, TourActivity tourActivity, VehicleRoute route) { + this.time = relatednessToTarget; + this.distance = distance; + this.tourActivity = tourActivity; + this.route = route; + } + } + + private static final Logger logger = LoggerFactory.getLogger(RuinTimeRelated.class); + + private final VehicleRoutingProblem vrp; + + private NoiseMaker noiseMaker = () -> 0; + + public void setNoiseMaker(NoiseMaker noiseMaker) { + this.noiseMaker = noiseMaker; + } + + public RuinTimeRelated(VehicleRoutingProblem vrp) { + super(vrp); + this.vrp = vrp; + this.ruinShareFactory = () -> (int) Math.max(50, Math.round(vrp.getJobs().size() * 0.3)); + logger.debug("initialise {}", this); + } + + /** + * Removes a fraction of jobs from vehicleRoutes. + *
+ *
The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined).
+ */
+ @Override
+ public Collection