From 25fe0838099e968d1dd847f809e7105b4f153593 Mon Sep 17 00:00:00 2001 From: oblonski Date: Wed, 18 Jan 2017 19:43:52 +0100 Subject: [PATCH] refine string removal --- .../jsprit/core/algorithm/box/Jsprit.java | 21 +- .../core/algorithm/ruin/RuinString.java | 231 ++++++++ .../core/algorithm/ruin/StringUtil.java | 52 ++ .../core/algorithm/ruin/StringUtilTest.java | 87 +++ jsprit-examples/input/p01_mod | 56 ++ jsprit-examples/input/p08 | 508 +++++++++--------- .../examples/BuildAlgorithmFromScratch.java | 17 +- .../examples/BuildAlgorithmFromScratch2.java | 252 +++++++++ 8 files changed, 960 insertions(+), 264 deletions(-) create mode 100644 jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/RuinString.java create mode 100644 jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/StringUtil.java create mode 100644 jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/ruin/StringUtilTest.java create mode 100644 jsprit-examples/input/p01_mod create mode 100644 jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/BuildAlgorithmFromScratch2.java 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 3ad56495..c0a243cc 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,9 @@ public class Jsprit { WORST_BEST("worst_best"), WORST_REGRET("worst_regret"), CLUSTER_BEST("cluster_best"), - CLUSTER_REGRET("cluster_regret"); + CLUSTER_REGRET("cluster_regret"), + STRING_BEST("string_best"), + STRING_REGRET("string_regret"); String strategyName; @@ -178,6 +180,10 @@ public class Jsprit { defaults.put(Strategy.RADIAL_REGRET.toString(), ".5"); defaults.put(Strategy.RANDOM_BEST.toString(), ".5"); defaults.put(Strategy.RANDOM_REGRET.toString(), ".5"); + + defaults.put(Strategy.STRING_BEST.toString(), ".5"); + defaults.put(Strategy.STRING_REGRET.toString(), ".5"); + defaults.put(Strategy.WORST_BEST.toString(), "0."); defaults.put(Strategy.WORST_REGRET.toString(), "1."); defaults.put(Strategy.CLUSTER_BEST.toString(), "0."); @@ -472,6 +478,9 @@ public class Jsprit { random) ); + final RuinString stringRuin = new RuinString(vrp, jobNeighborhoods); + stringRuin.setRandom(random); + AbstractInsertionStrategy regret; final ScoringFunction scorer; @@ -592,6 +601,11 @@ public class Jsprit { final SearchStrategy clusters_best = new SearchStrategy(Strategy.CLUSTER_BEST.toString(), new SelectBest(), acceptor, objectiveFunction); clusters_best.addModule(new RuinAndRecreateModule(Strategy.CLUSTER_BEST.toString(), best, clusters)); + SearchStrategy stringRegret = new SearchStrategy(Strategy.STRING_REGRET.toString(), new SelectBest(), acceptor, objectiveFunction); + stringRegret.addModule(new RuinAndRecreateModule(Strategy.STRING_REGRET.toString(), regret, stringRuin)); + + SearchStrategy stringBest = new SearchStrategy(Strategy.STRING_BEST.toString(), new SelectBest(), acceptor, objectiveFunction); + stringBest.addModule(new RuinAndRecreateModule(Strategy.STRING_BEST.toString(), best, stringRuin)); PrettyAlgorithmBuilder prettyBuilder = PrettyAlgorithmBuilder.newInstance(vrp, fm, stateManager, constraintManager); prettyBuilder.setRandom(random); @@ -605,7 +619,10 @@ public class Jsprit { .withStrategy(worst_best, toDouble(getProperty(Strategy.WORST_BEST.toString()))) .withStrategy(worst_regret, toDouble(getProperty(Strategy.WORST_REGRET.toString()))) .withStrategy(clusters_regret, toDouble(getProperty(Strategy.CLUSTER_REGRET.toString()))) - .withStrategy(clusters_best, toDouble(getProperty(Strategy.CLUSTER_BEST.toString()))); + .withStrategy(clusters_best, toDouble(getProperty(Strategy.CLUSTER_BEST.toString()))) + .withStrategy(stringBest, toDouble(getProperty(Strategy.STRING_BEST.toString()))) + .withStrategy(stringRegret, toDouble(getProperty(Strategy.STRING_REGRET.toString()))); + if (getProperty(Parameter.CONSTRUCTION.toString()).equals(Construction.BEST_INSERTION.toString())) { prettyBuilder.constructInitialSolutionWith(best, objectiveFunction); } else { diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/RuinString.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/RuinString.java new file mode 100644 index 00000000..530f103c --- /dev/null +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/RuinString.java @@ -0,0 +1,231 @@ +/* + * 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.algorithm.ruin.distance.JobDistance; +import com.graphhopper.jsprit.core.problem.AbstractActivity; +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.RandomUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + + +/** + * RuinStrategy that ruins the neighborhood of a randomly selected job. The size and the structure of the neighborhood is defined by + * the share of jobs to be removed and the distance between jobs (where distance not necessarily mean Euclidean distance but an arbitrary + * measure). + * + * @author stefan + */ +public final class RuinString extends AbstractRuinStrategy { + + private Logger logger = LoggerFactory.getLogger(RuinString.class); + + private VehicleRoutingProblem vrp; + + private JobNeighborhoods jobNeighborhoods; + + private int Kmin = 1; + + private int Kmax = 6; + + private int Lmin = 1; + + private int Lmax = 40; + + /** + * Constructs RuinRadial. + * + * @param vrp + * @param jobDistance i.e. a measure to define the distance between two jobs and whether they are located close or distant to eachother + * @param Kmin + * @param Kmax + * @param Lmin + * @param Lmax + */ + public RuinString(VehicleRoutingProblem vrp, JobDistance jobDistance, int Kmin, int Kmax, int Lmin, int Lmax) { + super(vrp); + this.vrp = vrp; + JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, Kmax * Lmax); + jobNeighborhoodsImpl.initialise(); + jobNeighborhoods = jobNeighborhoodsImpl; + this.Kmin = Kmin; + this.Kmax = Kmax; + this.Lmin = Lmin; + this.Lmax = Lmax; + logger.debug("initialise {}", this); + } + + public RuinString(VehicleRoutingProblem vrp, JobDistance jobDistance) { + super(vrp); + this.vrp = vrp; + JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, Kmax * Lmax); + jobNeighborhoodsImpl.initialise(); + jobNeighborhoods = jobNeighborhoodsImpl; + logger.debug("initialise {}", this); + } + + public RuinString(VehicleRoutingProblem vrp, JobNeighborhoods jobNeighborhoods) { + super(vrp); + this.vrp = vrp; + this.jobNeighborhoods = jobNeighborhoods; + logger.debug("initialise {}", this); + } + + @Override + public String toString() { + return "[name=splitRuin]"; + } + + /** + * Ruins the collection of vehicleRoutes, i.e. removes a share of jobs. First, it selects a job randomly. Second, it identifies its neighborhood. And finally, it removes + * the neighborhood plus the randomly selected job from the number of vehicleRoutes. All removed jobs are then returned as a collection. + */ + @Override + public Collection ruinRoutes(Collection vehicleRoutes) { + if (vehicleRoutes.isEmpty() || vrp.getJobs().isEmpty()) { + return Collections.emptyList(); + } + int noStrings = Kmin + random.nextInt((Kmax - Kmin)); + noStrings = Math.min(noStrings, vehicleRoutes.size()); + Set unassignedJobs = new HashSet<>(); + Set ruinedRoutes = new HashSet<>(); + Job prevJob = RandomUtils.nextJob(vrp.getJobs().values(), random); + Iterator neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(Kmax * Lmax, prevJob); + while (neighborhoodIterator.hasNext() && ruinedRoutes.size() <= noStrings) { + if (!unassignedJobs.contains(prevJob)) { + VehicleRoute route = getRouteOf(prevJob, vehicleRoutes); + if (route != null && !ruinedRoutes.contains(route)) { + if (random.nextDouble() < .5) { + ruinRouteWithStringRuin(route, prevJob, unassignedJobs); + } else { + ruinRouteWithSplitStringRuin(route, prevJob, unassignedJobs); + } + ruinedRoutes.add(route); + } + } + prevJob = neighborhoodIterator.next(); + } + return unassignedJobs; + } + + private VehicleRoute getRouteOf(Job job, Collection vehicleRoutes) { + for (VehicleRoute route : vehicleRoutes) { + if (route.getTourActivities().servesJob(job)) return route; + } + return null; + } + + private void ruinRouteWithSplitStringRuin(VehicleRoute seedRoute, Job prevJob, Set unassignedJobs) { + int noActivities = seedRoute.getActivities().size(); + int stringLength = Lmin + random.nextInt(Lmax - Lmin); + stringLength = Math.min(stringLength, seedRoute.getActivities().size()); + + int preservedSubstringLength = StringUtil.determineSubstringLength(stringLength, noActivities, random); + + List acts = vrp.getActivities(prevJob); + AbstractActivity randomSeedAct = RandomUtils.nextItem(acts, random); + int seedIndex = 0; + + int index = 0; + for (TourActivity act : seedRoute.getActivities()) { + if (act.getIndex() == randomSeedAct.getIndex()) { + seedIndex = index; + break; + } + index++; + } + + int totalStringLength = stringLength + preservedSubstringLength; + List stringBounds = StringUtil.getLowerBoundsOfAllStrings(totalStringLength, seedIndex, noActivities); + if (stringBounds.isEmpty()) return; + int lowerBound = RandomUtils.nextItem(stringBounds, random); + + List jobs2Remove = new ArrayList<>(); + int startIndexOfPreservedSubstring = random.nextInt(stringLength); + int position = 0; + int noStringsInPreservedSubstring = 0; + boolean isPreservedSubstring = false; + for (int i = lowerBound; i < (lowerBound + totalStringLength); i++) { + if (position == startIndexOfPreservedSubstring) { + isPreservedSubstring = true; + } + if (noStringsInPreservedSubstring >= preservedSubstringLength) { + isPreservedSubstring = false; + } + if (!isPreservedSubstring) { + TourActivity act = seedRoute.getActivities().get(i); + if (act instanceof TourActivity.JobActivity) { + Job job = ((TourActivity.JobActivity) act).getJob(); + if (vrp.getJobs().containsKey(job.getId())) { + jobs2Remove.add(job); + } + } + } else noStringsInPreservedSubstring++; + position++; + } + for (Job job : jobs2Remove) { + removeJob(job, seedRoute); + unassignedJobs.add(job); + } + + } + + + private void ruinRouteWithStringRuin(VehicleRoute seedRoute, Job prevJob, Set unassignedJobs) { + int stringLength = Lmin + random.nextInt(Lmax - Lmin); + stringLength = Math.min(stringLength, seedRoute.getActivities().size()); + List acts = vrp.getActivities(prevJob); + AbstractActivity randomSeedAct = RandomUtils.nextItem(acts, random); + int seedIndex = 0; + int noActivities = seedRoute.getActivities().size(); + int index = 0; + for (TourActivity act : seedRoute.getActivities()) { + if (act.getIndex() == randomSeedAct.getIndex()) { + seedIndex = index; + break; + } + index++; + } + List stringBounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities); + if (stringBounds.isEmpty()) return; + int lowerBound = RandomUtils.nextItem(stringBounds, random); + List jobs2Remove = new ArrayList<>(); + for (int i = lowerBound; i < (lowerBound + stringLength); i++) { + TourActivity act = seedRoute.getActivities().get(i); + if (act instanceof TourActivity.JobActivity) { + Job job = ((TourActivity.JobActivity) act).getJob(); + if (vrp.getJobs().containsKey(job.getId())) { + jobs2Remove.add(job); + } + } + } + for (Job job : jobs2Remove) { + removeJob(job, seedRoute); + unassignedJobs.add(job); + } + + } + + +} diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/StringUtil.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/StringUtil.java new file mode 100644 index 00000000..b9070a1c --- /dev/null +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/ruin/StringUtil.java @@ -0,0 +1,52 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * Created by schroeder on 13/01/17. + */ +class StringUtil { + + static List getLowerBoundsOfAllStrings(int length, int seedIndex, int routeLength) { + List lowerBounds = new ArrayList<>(); + for (int i = 1; i <= length; i++) { + int lower = seedIndex - (length - i); + int upper = seedIndex + (i - 1); + if (lower >= 0 && upper < routeLength) { + lowerBounds.add(lower); + } + } + return lowerBounds; + } + + static int determineSubstringLength(int baseLength, int routeLength, Random random) { + if (baseLength == routeLength) return 0; + int substringLength = 1; + while (baseLength + substringLength < routeLength) { + if (random.nextDouble() < 0.01) { + return substringLength; + } else substringLength++; + } + return substringLength; + } +} diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/ruin/StringUtilTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/ruin/StringUtilTest.java new file mode 100644 index 00000000..9a8cbbf4 --- /dev/null +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/ruin/StringUtilTest.java @@ -0,0 +1,87 @@ +/* + * 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 org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +/** + * Created by schroeder on 13/01/17. + */ +public class StringUtilTest { + + @Test + public void test() { + int stringLength = 4; + int seedIndex = 4; + int noActivities = 10; + List bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities); + Assert.assertEquals(4, bounds.size()); + Assert.assertEquals(1, (int) bounds.get(0)); + Assert.assertEquals(2, (int) bounds.get(1)); + Assert.assertEquals(3, (int) bounds.get(2)); + Assert.assertEquals(4, (int) bounds.get(3)); + + } + + @Test + public void test2() { + int stringLength = 4; + int seedIndex = 2; + int noActivities = 10; + List bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities); + Assert.assertEquals(3, bounds.size()); + Assert.assertEquals(0, (int) bounds.get(0)); + Assert.assertEquals(1, (int) bounds.get(1)); + Assert.assertEquals(2, (int) bounds.get(2)); + } + + @Test + public void test3() { + int stringLength = 4; + int seedIndex = 0; + int noActivities = 10; + List bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities); + Assert.assertEquals(1, bounds.size()); + Assert.assertEquals(0, (int) bounds.get(0)); + } + + @Test + public void test4() { + int stringLength = 4; + int seedIndex = 9; + int noActivities = 10; + List bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities); + Assert.assertEquals(1, bounds.size()); + Assert.assertEquals(6, (int) bounds.get(0)); + } + + @Test + public void test5() { + int stringLength = 4; + int seedIndex = 8; + int noActivities = 10; + List bounds = StringUtil.getLowerBoundsOfAllStrings(stringLength, seedIndex, noActivities); + Assert.assertEquals(2, bounds.size()); + Assert.assertEquals(5, (int) bounds.get(0)); + Assert.assertEquals(6, (int) bounds.get(1)); + } +} diff --git a/jsprit-examples/input/p01_mod b/jsprit-examples/input/p01_mod new file mode 100644 index 00000000..f7126b87 --- /dev/null +++ b/jsprit-examples/input/p01_mod @@ -0,0 +1,56 @@ +2 4 50 4 +0 2000 + 1 37 52 0 7 1 4 1 2 4 8 + 2 49 49 0 30 1 4 1 2 4 8 + 3 52 64 0 16 1 4 1 2 4 8 + 4 20 26 0 9 1 4 1 2 4 8 + 5 40 30 0 21 1 4 1 2 4 8 + 6 21 47 0 15 1 4 1 2 4 8 + 7 17 63 0 19 1 4 1 2 4 8 + 8 31 62 0 23 1 4 1 2 4 8 + 9 52 33 0 11 1 4 1 2 4 8 +10 51 21 0 5 1 4 1 2 4 8 +11 42 41 0 19 1 4 1 2 4 8 +12 31 32 0 29 1 4 1 2 4 8 +13 5 25 0 23 1 4 1 2 4 8 +14 12 42 0 21 1 4 1 2 4 8 +15 36 16 0 10 1 4 1 2 4 8 +16 52 41 0 15 1 4 1 2 4 8 +17 27 23 0 3 1 4 1 2 4 8 +18 17 33 0 41 1 4 1 2 4 8 +19 13 13 0 9 1 4 1 2 4 8 +20 57 58 0 28 1 4 1 2 4 8 +21 62 42 0 8 1 4 1 2 4 8 +22 42 57 0 8 1 4 1 2 4 8 +23 16 57 0 16 1 4 1 2 4 8 +24 8 52 0 10 1 4 1 2 4 8 +25 7 38 0 28 1 4 1 2 4 8 +26 27 68 0 7 1 4 1 2 4 8 +27 30 48 0 15 1 4 1 2 4 8 +28 43 67 0 14 1 4 1 2 4 8 +29 58 48 0 6 1 4 1 2 4 8 +30 58 27 0 19 1 4 1 2 4 8 +31 37 69 0 11 1 4 1 2 4 8 +32 38 46 0 12 1 4 1 2 4 8 +33 46 10 0 23 1 4 1 2 4 8 +34 61 33 0 26 1 4 1 2 4 8 +35 62 63 0 17 1 4 1 2 4 8 +36 63 69 0 6 1 4 1 2 4 8 +37 32 22 0 9 1 4 1 2 4 8 +38 45 35 0 15 1 4 1 2 4 8 +39 59 15 0 14 1 4 1 2 4 8 +40 5 6 0 7 1 4 1 2 4 8 +41 10 17 0 27 1 4 1 2 4 8 +42 21 10 0 13 1 4 1 2 4 8 +43 5 64 0 11 1 4 1 2 4 8 +44 30 15 0 16 1 4 1 2 4 8 +45 39 10 0 10 1 4 1 2 4 8 +46 32 39 0 5 1 4 1 2 4 8 +47 25 32 0 25 1 4 1 2 4 8 +48 25 55 0 17 1 4 1 2 4 8 +49 48 28 0 18 1 4 1 2 4 8 +50 56 37 0 10 1 4 1 2 4 8 +51 20 20 0 0 0 0 +52 30 40 0 0 0 0 +53 50 30 0 0 0 0 +54 60 50 0 0 0 0 diff --git a/jsprit-examples/input/p08 b/jsprit-examples/input/p08 index e272d5d8..a2ab1f28 100644 --- a/jsprit-examples/input/p08 +++ b/jsprit-examples/input/p08 @@ -1,254 +1,254 @@ -2 14 249 2 -310 500 -310 500 - 1 -99 -97 0 6 1 2 1 2 - 2 -59 50 0 72 1 2 1 2 - 3 0 14 0 93 1 2 1 2 - 4 -17 -66 0 28 1 2 1 2 - 5 -69 -19 0 5 1 2 1 2 - 6 31 12 0 43 1 2 1 2 - 7 5 -41 0 1 1 2 1 2 - 8 -12 10 0 36 1 2 1 2 - 9 -64 70 0 53 1 2 1 2 - 10 -12 85 0 63 1 2 1 2 - 11 -18 64 0 25 1 2 1 2 - 12 -77 -16 0 50 1 2 1 2 - 13 -53 88 0 57 1 2 1 2 - 14 83 -24 0 1 1 2 1 2 - 15 24 41 0 66 1 2 1 2 - 16 17 21 0 37 1 2 1 2 - 17 42 96 0 51 1 2 1 2 - 18 -65 0 0 47 1 2 1 2 - 19 -47 -26 0 88 1 2 1 2 - 20 85 36 0 75 1 2 1 2 - 21 -35 -54 0 48 1 2 1 2 - 22 54 -21 0 40 1 2 1 2 - 23 64 -17 0 8 1 2 1 2 - 24 55 89 0 69 1 2 1 2 - 25 17 -25 0 93 1 2 1 2 - 26 -61 66 0 29 1 2 1 2 - 27 -61 26 0 5 1 2 1 2 - 28 17 -72 0 53 1 2 1 2 - 29 79 38 0 8 1 2 1 2 - 30 -62 -2 0 24 1 2 1 2 - 31 -90 -68 0 53 1 2 1 2 - 32 52 66 0 13 1 2 1 2 - 33 -54 -50 0 47 1 2 1 2 - 34 8 -84 0 57 1 2 1 2 - 35 37 -90 0 9 1 2 1 2 - 36 -83 49 0 74 1 2 1 2 - 37 35 -1 0 83 1 2 1 2 - 38 7 59 0 96 1 2 1 2 - 39 12 48 0 42 1 2 1 2 - 40 57 95 0 80 1 2 1 2 - 41 92 28 0 22 1 2 1 2 - 42 -3 97 0 56 1 2 1 2 - 43 -7 52 0 43 1 2 1 2 - 44 42 -15 0 12 1 2 1 2 - 45 77 -43 0 73 1 2 1 2 - 46 59 -49 0 32 1 2 1 2 - 47 25 91 0 8 1 2 1 2 - 48 69 -19 0 79 1 2 1 2 - 49 -82 -14 0 79 1 2 1 2 - 50 74 -70 0 4 1 2 1 2 - 51 69 59 0 14 1 2 1 2 - 52 29 33 0 17 1 2 1 2 - 53 -97 9 0 19 1 2 1 2 - 54 -58 9 0 44 1 2 1 2 - 55 28 93 0 5 1 2 1 2 - 56 7 73 0 37 1 2 1 2 - 57 -28 73 0 100 1 2 1 2 - 58 -76 55 0 62 1 2 1 2 - 59 41 42 0 90 1 2 1 2 - 60 92 40 0 57 1 2 1 2 - 61 -84 -29 0 44 1 2 1 2 - 62 -12 42 0 37 1 2 1 2 - 63 51 -45 0 80 1 2 1 2 - 64 -37 46 0 60 1 2 1 2 - 65 -97 35 0 95 1 2 1 2 - 66 14 89 0 56 1 2 1 2 - 67 60 58 0 56 1 2 1 2 - 68 -63 -75 0 9 1 2 1 2 - 69 -18 34 0 39 1 2 1 2 - 70 -46 -82 0 15 1 2 1 2 - 71 -86 -79 0 4 1 2 1 2 - 72 -43 -30 0 58 1 2 1 2 - 73 -44 7 0 73 1 2 1 2 - 74 -3 -20 0 5 1 2 1 2 - 75 36 41 0 12 1 2 1 2 - 76 -30 -94 0 3 1 2 1 2 - 77 79 -62 0 8 1 2 1 2 - 78 51 70 0 31 1 2 1 2 - 79 -61 -26 0 48 1 2 1 2 - 80 6 94 0 3 1 2 1 2 - 81 -19 -62 0 52 1 2 1 2 - 82 -20 51 0 99 1 2 1 2 - 83 -81 37 0 29 1 2 1 2 - 84 7 31 0 12 1 2 1 2 - 85 52 12 0 50 1 2 1 2 - 86 83 -91 0 98 1 2 1 2 - 87 -7 -92 0 4 1 2 1 2 - 88 82 -74 0 56 1 2 1 2 - 89 -70 85 0 24 1 2 1 2 - 90 -83 -30 0 33 1 2 1 2 - 91 71 -61 0 45 1 2 1 2 - 92 85 11 0 98 1 2 1 2 - 93 66 -48 0 4 1 2 1 2 - 94 78 -87 0 36 1 2 1 2 - 95 9 -79 0 72 1 2 1 2 - 96 -36 4 0 26 1 2 1 2 - 97 66 39 0 71 1 2 1 2 - 98 92 -17 0 84 1 2 1 2 - 99 -46 -79 0 21 1 2 1 2 -100 -30 -63 0 99 1 2 1 2 -101 -42 63 0 33 1 2 1 2 -102 20 42 0 84 1 2 1 2 -103 15 98 0 74 1 2 1 2 -104 1 -17 0 93 1 2 1 2 -105 64 20 0 25 1 2 1 2 -106 -96 85 0 39 1 2 1 2 -107 93 -29 0 42 1 2 1 2 -108 -40 -84 0 77 1 2 1 2 -109 86 35 0 68 1 2 1 2 -110 91 36 0 50 1 2 1 2 -111 62 -8 0 42 1 2 1 2 -112 -24 4 0 71 1 2 1 2 -113 11 96 0 85 1 2 1 2 -114 -53 62 0 78 1 2 1 2 -115 -28 -71 0 64 1 2 1 2 -116 7 -4 0 5 1 2 1 2 -117 95 -9 0 93 1 2 1 2 -118 -3 17 0 18 1 2 1 2 -119 53 -90 0 38 1 2 1 2 -120 58 -19 0 29 1 2 1 2 -121 -83 84 0 81 1 2 1 2 -122 -1 49 0 4 1 2 1 2 -123 -4 17 0 23 1 2 1 2 -124 -82 -3 0 11 1 2 1 2 -125 -43 47 0 86 1 2 1 2 -126 6 -6 0 2 1 2 1 2 -127 70 99 0 31 1 2 1 2 -128 68 -29 0 54 1 2 1 2 -129 -94 -30 0 87 1 2 1 2 -130 -94 -20 0 17 1 2 1 2 -131 -21 77 0 81 1 2 1 2 -132 64 37 0 72 1 2 1 2 -133 -70 -19 0 10 1 2 1 2 -134 88 65 0 50 1 2 1 2 -135 2 29 0 25 1 2 1 2 -136 33 57 0 71 1 2 1 2 -137 -70 6 0 85 1 2 1 2 -138 -38 -56 0 51 1 2 1 2 -139 -80 -95 0 29 1 2 1 2 -140 -5 -39 0 55 1 2 1 2 -141 8 -22 0 45 1 2 1 2 -142 -61 -76 0 100 1 2 1 2 -143 76 -22 0 38 1 2 1 2 -144 49 -71 0 11 1 2 1 2 -145 -30 -68 0 82 1 2 1 2 -146 1 34 0 50 1 2 1 2 -147 77 79 0 39 1 2 1 2 -148 -58 64 0 6 1 2 1 2 -149 82 -97 0 87 1 2 1 2 -150 -80 55 0 83 1 2 1 2 -151 81 -86 0 22 1 2 1 2 -152 39 -49 0 24 1 2 1 2 -153 -67 72 0 69 1 2 1 2 -154 -25 -89 0 97 1 2 1 2 -155 -44 -95 0 65 1 2 1 2 -156 32 -68 0 97 1 2 1 2 -157 -17 49 0 79 1 2 1 2 -158 93 49 0 79 1 2 1 2 -159 99 81 0 46 1 2 1 2 -160 10 -49 0 52 1 2 1 2 -161 63 -41 0 39 1 2 1 2 -162 38 39 0 94 1 2 1 2 -163 -28 39 0 97 1 2 1 2 -164 -2 -47 0 18 1 2 1 2 -165 38 8 0 3 1 2 1 2 -166 -42 -6 0 23 1 2 1 2 -167 -67 88 0 19 1 2 1 2 -168 19 93 0 40 1 2 1 2 -169 40 27 0 49 1 2 1 2 -170 -61 56 0 96 1 2 1 2 -171 43 33 0 58 1 2 1 2 -172 -18 -39 0 15 1 2 1 2 -173 -69 19 0 21 1 2 1 2 -174 75 -18 0 56 1 2 1 2 -175 31 85 0 67 1 2 1 2 -176 25 58 0 10 1 2 1 2 -177 -16 36 0 36 1 2 1 2 -178 91 15 0 84 1 2 1 2 -179 60 -39 0 59 1 2 1 2 -180 49 -47 0 85 1 2 1 2 -181 42 33 0 60 1 2 1 2 -182 16 -81 0 33 1 2 1 2 -183 -78 53 0 62 1 2 1 2 -184 53 -80 0 70 1 2 1 2 -185 -46 -26 0 79 1 2 1 2 -186 -25 -54 0 98 1 2 1 2 -187 69 -46 0 99 1 2 1 2 -188 0 -78 0 18 1 2 1 2 -189 -84 74 0 55 1 2 1 2 -190 -16 16 0 75 1 2 1 2 -191 -63 -14 0 94 1 2 1 2 -192 51 -77 0 89 1 2 1 2 -193 -39 61 0 13 1 2 1 2 -194 5 97 0 19 1 2 1 2 -195 -55 39 0 19 1 2 1 2 -196 70 -14 0 90 1 2 1 2 -197 0 95 0 35 1 2 1 2 -198 -45 7 0 76 1 2 1 2 -199 38 -24 0 3 1 2 1 2 -200 50 -37 0 11 1 2 1 2 -201 59 71 0 98 1 2 1 2 -202 -73 -96 0 92 1 2 1 2 -203 -29 72 0 1 1 2 1 2 -204 -47 12 0 2 1 2 1 2 -205 -88 -61 0 63 1 2 1 2 -206 -88 36 0 57 1 2 1 2 -207 -46 -3 0 50 1 2 1 2 -208 26 -37 0 19 1 2 1 2 -209 -39 -67 0 24 1 2 1 2 -210 92 27 0 14 1 2 1 2 -211 -80 -31 0 18 1 2 1 2 -212 93 -50 0 77 1 2 1 2 -213 -20 -5 0 28 1 2 1 2 -214 -22 73 0 72 1 2 1 2 -215 -4 -7 0 49 1 2 1 2 -216 54 -48 0 58 1 2 1 2 -217 -70 39 0 84 1 2 1 2 -218 54 -82 0 58 1 2 1 2 -219 29 41 0 41 1 2 1 2 -220 -87 51 0 98 1 2 1 2 -221 -96 -36 0 77 1 2 1 2 -222 49 8 0 57 1 2 1 2 -223 -5 54 0 39 1 2 1 2 -224 -26 43 0 99 1 2 1 2 -225 -11 60 0 83 1 2 1 2 -226 40 61 0 54 1 2 1 2 -227 82 35 0 86 1 2 1 2 -228 -92 12 0 2 1 2 1 2 -229 -93 -86 0 14 1 2 1 2 -230 -66 63 0 42 1 2 1 2 -231 -72 -87 0 14 1 2 1 2 -232 -57 -84 0 55 1 2 1 2 -233 23 52 0 2 1 2 1 2 -234 -56 -62 0 18 1 2 1 2 -235 -19 59 0 17 1 2 1 2 -236 63 -14 0 22 1 2 1 2 -237 -13 38 0 28 1 2 1 2 -238 -19 87 0 3 1 2 1 2 -239 44 -84 0 96 1 2 1 2 -240 98 -17 0 53 1 2 1 2 -241 -16 62 0 15 1 2 1 2 -242 3 66 0 36 1 2 1 2 -243 26 22 0 98 1 2 1 2 -244 -38 -81 0 78 1 2 1 2 -245 70 -80 0 92 1 2 1 2 -246 17 -35 0 65 1 2 1 2 -247 96 -83 0 64 1 2 1 2 -248 -77 80 0 43 1 2 1 2 -249 -14 44 0 50 1 2 1 2 -250 -33 33 0 0 0 0 -251 33 -33 0 0 0 0 +2 14 249 2 +310 500 +310 500 + 1 -99 -97 0 6 1 2 1 2 + 2 -59 50 0 72 1 2 1 2 + 3 0 14 0 93 1 2 1 2 + 4 -17 -66 0 28 1 2 1 2 + 5 -69 -19 0 5 1 2 1 2 + 6 31 12 0 43 1 2 1 2 + 7 5 -41 0 1 1 2 1 2 + 8 -12 10 0 36 1 2 1 2 + 9 -64 70 0 53 1 2 1 2 + 10 -12 85 0 63 1 2 1 2 + 11 -18 64 0 25 1 2 1 2 + 12 -77 -16 0 50 1 2 1 2 + 13 -53 88 0 57 1 2 1 2 + 14 83 -24 0 1 1 2 1 2 + 15 24 41 0 66 1 2 1 2 + 16 17 21 0 37 1 2 1 2 + 17 42 96 0 51 1 2 1 2 + 18 -65 0 0 47 1 2 1 2 + 19 -47 -26 0 88 1 2 1 2 + 20 85 36 0 75 1 2 1 2 + 21 -35 -54 0 48 1 2 1 2 + 22 54 -21 0 40 1 2 1 2 + 23 64 -17 0 8 1 2 1 2 + 24 55 89 0 69 1 2 1 2 + 25 17 -25 0 93 1 2 1 2 + 26 -61 66 0 29 1 2 1 2 + 27 -61 26 0 5 1 2 1 2 + 28 17 -72 0 53 1 2 1 2 + 29 79 38 0 8 1 2 1 2 + 30 -62 -2 0 24 1 2 1 2 + 31 -90 -68 0 53 1 2 1 2 + 32 52 66 0 13 1 2 1 2 + 33 -54 -50 0 47 1 2 1 2 + 34 8 -84 0 57 1 2 1 2 + 35 37 -90 0 9 1 2 1 2 + 36 -83 49 0 74 1 2 1 2 + 37 35 -1 0 83 1 2 1 2 + 38 7 59 0 96 1 2 1 2 + 39 12 48 0 42 1 2 1 2 + 40 57 95 0 80 1 2 1 2 + 41 92 28 0 22 1 2 1 2 + 42 -3 97 0 56 1 2 1 2 + 43 -7 52 0 43 1 2 1 2 + 44 42 -15 0 12 1 2 1 2 + 45 77 -43 0 73 1 2 1 2 + 46 59 -49 0 32 1 2 1 2 + 47 25 91 0 8 1 2 1 2 + 48 69 -19 0 79 1 2 1 2 + 49 -82 -14 0 79 1 2 1 2 + 50 74 -70 0 4 1 2 1 2 + 51 69 59 0 14 1 2 1 2 + 52 29 33 0 17 1 2 1 2 + 53 -97 9 0 19 1 2 1 2 + 54 -58 9 0 44 1 2 1 2 + 55 28 93 0 5 1 2 1 2 + 56 7 73 0 37 1 2 1 2 + 57 -28 73 0 100 1 2 1 2 + 58 -76 55 0 62 1 2 1 2 + 59 41 42 0 90 1 2 1 2 + 60 92 40 0 57 1 2 1 2 + 61 -84 -29 0 44 1 2 1 2 + 62 -12 42 0 37 1 2 1 2 + 63 51 -45 0 80 1 2 1 2 + 64 -37 46 0 60 1 2 1 2 + 65 -97 35 0 95 1 2 1 2 + 66 14 89 0 56 1 2 1 2 + 67 60 58 0 56 1 2 1 2 + 68 -63 -75 0 9 1 2 1 2 + 69 -18 34 0 39 1 2 1 2 + 70 -46 -82 0 15 1 2 1 2 + 71 -86 -79 0 4 1 2 1 2 + 72 -43 -30 0 58 1 2 1 2 + 73 -44 7 0 73 1 2 1 2 + 74 -3 -20 0 5 1 2 1 2 + 75 36 41 0 12 1 2 1 2 + 76 -30 -94 0 3 1 2 1 2 + 77 79 -62 0 8 1 2 1 2 + 78 51 70 0 31 1 2 1 2 + 79 -61 -26 0 48 1 2 1 2 + 80 6 94 0 3 1 2 1 2 + 81 -19 -62 0 52 1 2 1 2 + 82 -20 51 0 99 1 2 1 2 + 83 -81 37 0 29 1 2 1 2 + 84 7 31 0 12 1 2 1 2 + 85 52 12 0 50 1 2 1 2 + 86 83 -91 0 98 1 2 1 2 + 87 -7 -92 0 4 1 2 1 2 + 88 82 -74 0 56 1 2 1 2 + 89 -70 85 0 24 1 2 1 2 + 90 -83 -30 0 33 1 2 1 2 + 91 71 -61 0 45 1 2 1 2 + 92 85 11 0 98 1 2 1 2 + 93 66 -48 0 4 1 2 1 2 + 94 78 -87 0 36 1 2 1 2 + 95 9 -79 0 72 1 2 1 2 + 96 -36 4 0 26 1 2 1 2 + 97 66 39 0 71 1 2 1 2 + 98 92 -17 0 84 1 2 1 2 + 99 -46 -79 0 21 1 2 1 2 +100 -30 -63 0 99 1 2 1 2 +101 -42 63 0 33 1 2 1 2 +102 20 42 0 84 1 2 1 2 +103 15 98 0 74 1 2 1 2 +104 1 -17 0 93 1 2 1 2 +105 64 20 0 25 1 2 1 2 +106 -96 85 0 39 1 2 1 2 +107 93 -29 0 42 1 2 1 2 +108 -40 -84 0 77 1 2 1 2 +109 86 35 0 68 1 2 1 2 +110 91 36 0 50 1 2 1 2 +111 62 -8 0 42 1 2 1 2 +112 -24 4 0 71 1 2 1 2 +113 11 96 0 85 1 2 1 2 +114 -53 62 0 78 1 2 1 2 +115 -28 -71 0 64 1 2 1 2 +116 7 -4 0 5 1 2 1 2 +117 95 -9 0 93 1 2 1 2 +118 -3 17 0 18 1 2 1 2 +119 53 -90 0 38 1 2 1 2 +120 58 -19 0 29 1 2 1 2 +121 -83 84 0 81 1 2 1 2 +122 -1 49 0 4 1 2 1 2 +123 -4 17 0 23 1 2 1 2 +124 -82 -3 0 11 1 2 1 2 +125 -43 47 0 86 1 2 1 2 +126 6 -6 0 2 1 2 1 2 +127 70 99 0 31 1 2 1 2 +128 68 -29 0 54 1 2 1 2 +129 -94 -30 0 87 1 2 1 2 +130 -94 -20 0 17 1 2 1 2 +131 -21 77 0 81 1 2 1 2 +132 64 37 0 72 1 2 1 2 +133 -70 -19 0 10 1 2 1 2 +134 88 65 0 50 1 2 1 2 +135 2 29 0 25 1 2 1 2 +136 33 57 0 71 1 2 1 2 +137 -70 6 0 85 1 2 1 2 +138 -38 -56 0 51 1 2 1 2 +139 -80 -95 0 29 1 2 1 2 +140 -5 -39 0 55 1 2 1 2 +141 8 -22 0 45 1 2 1 2 +142 -61 -76 0 100 1 2 1 2 +143 76 -22 0 38 1 2 1 2 +144 49 -71 0 11 1 2 1 2 +145 -30 -68 0 82 1 2 1 2 +146 1 34 0 50 1 2 1 2 +147 77 79 0 39 1 2 1 2 +148 -58 64 0 6 1 2 1 2 +149 82 -97 0 87 1 2 1 2 +150 -80 55 0 83 1 2 1 2 +151 81 -86 0 22 1 2 1 2 +152 39 -49 0 24 1 2 1 2 +153 -67 72 0 69 1 2 1 2 +154 -25 -89 0 97 1 2 1 2 +155 -44 -95 0 65 1 2 1 2 +156 32 -68 0 97 1 2 1 2 +157 -17 49 0 79 1 2 1 2 +158 93 49 0 79 1 2 1 2 +159 99 81 0 46 1 2 1 2 +160 10 -49 0 52 1 2 1 2 +161 63 -41 0 39 1 2 1 2 +162 38 39 0 94 1 2 1 2 +163 -28 39 0 97 1 2 1 2 +164 -2 -47 0 18 1 2 1 2 +165 38 8 0 3 1 2 1 2 +166 -42 -6 0 23 1 2 1 2 +167 -67 88 0 19 1 2 1 2 +168 19 93 0 40 1 2 1 2 +169 40 27 0 49 1 2 1 2 +170 -61 56 0 96 1 2 1 2 +171 43 33 0 58 1 2 1 2 +172 -18 -39 0 15 1 2 1 2 +173 -69 19 0 21 1 2 1 2 +174 75 -18 0 56 1 2 1 2 +175 31 85 0 67 1 2 1 2 +176 25 58 0 10 1 2 1 2 +177 -16 36 0 36 1 2 1 2 +178 91 15 0 84 1 2 1 2 +179 60 -39 0 59 1 2 1 2 +180 49 -47 0 85 1 2 1 2 +181 42 33 0 60 1 2 1 2 +182 16 -81 0 33 1 2 1 2 +183 -78 53 0 62 1 2 1 2 +184 53 -80 0 70 1 2 1 2 +185 -46 -26 0 79 1 2 1 2 +186 -25 -54 0 98 1 2 1 2 +187 69 -46 0 99 1 2 1 2 +188 0 -78 0 18 1 2 1 2 +189 -84 74 0 55 1 2 1 2 +190 -16 16 0 75 1 2 1 2 +191 -63 -14 0 94 1 2 1 2 +192 51 -77 0 89 1 2 1 2 +193 -39 61 0 13 1 2 1 2 +194 5 97 0 19 1 2 1 2 +195 -55 39 0 19 1 2 1 2 +196 70 -14 0 90 1 2 1 2 +197 0 95 0 35 1 2 1 2 +198 -45 7 0 76 1 2 1 2 +199 38 -24 0 3 1 2 1 2 +200 50 -37 0 11 1 2 1 2 +201 59 71 0 98 1 2 1 2 +202 -73 -96 0 92 1 2 1 2 +203 -29 72 0 1 1 2 1 2 +204 -47 12 0 2 1 2 1 2 +205 -88 -61 0 63 1 2 1 2 +206 -88 36 0 57 1 2 1 2 +207 -46 -3 0 50 1 2 1 2 +208 26 -37 0 19 1 2 1 2 +209 -39 -67 0 24 1 2 1 2 +210 92 27 0 14 1 2 1 2 +211 -80 -31 0 18 1 2 1 2 +212 93 -50 0 77 1 2 1 2 +213 -20 -5 0 28 1 2 1 2 +214 -22 73 0 72 1 2 1 2 +215 -4 -7 0 49 1 2 1 2 +216 54 -48 0 58 1 2 1 2 +217 -70 39 0 84 1 2 1 2 +218 54 -82 0 58 1 2 1 2 +219 29 41 0 41 1 2 1 2 +220 -87 51 0 98 1 2 1 2 +221 -96 -36 0 77 1 2 1 2 +222 49 8 0 57 1 2 1 2 +223 -5 54 0 39 1 2 1 2 +224 -26 43 0 99 1 2 1 2 +225 -11 60 0 83 1 2 1 2 +226 40 61 0 54 1 2 1 2 +227 82 35 0 86 1 2 1 2 +228 -92 12 0 2 1 2 1 2 +229 -93 -86 0 14 1 2 1 2 +230 -66 63 0 42 1 2 1 2 +231 -72 -87 0 14 1 2 1 2 +232 -57 -84 0 55 1 2 1 2 +233 23 52 0 2 1 2 1 2 +234 -56 -62 0 18 1 2 1 2 +235 -19 59 0 17 1 2 1 2 +236 63 -14 0 22 1 2 1 2 +237 -13 38 0 28 1 2 1 2 +238 -19 87 0 3 1 2 1 2 +239 44 -84 0 96 1 2 1 2 +240 98 -17 0 53 1 2 1 2 +241 -16 62 0 15 1 2 1 2 +242 3 66 0 36 1 2 1 2 +243 26 22 0 98 1 2 1 2 +244 -38 -81 0 78 1 2 1 2 +245 70 -80 0 92 1 2 1 2 +246 17 -35 0 65 1 2 1 2 +247 96 -83 0 64 1 2 1 2 +248 -77 80 0 43 1 2 1 2 +249 -14 44 0 50 1 2 1 2 +250 -33 33 0 0 0 0 +251 33 -33 0 0 0 0 diff --git a/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/BuildAlgorithmFromScratch.java b/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/BuildAlgorithmFromScratch.java index df30c0ee..72cd3426 100644 --- a/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/BuildAlgorithmFromScratch.java +++ b/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/BuildAlgorithmFromScratch.java @@ -20,7 +20,6 @@ package com.graphhopper.jsprit.examples; import com.graphhopper.jsprit.analysis.toolbox.AlgorithmEventsRecorder; -import com.graphhopper.jsprit.analysis.toolbox.AlgorithmEventsViewer; import com.graphhopper.jsprit.core.algorithm.PrettyAlgorithmBuilder; import com.graphhopper.jsprit.core.algorithm.SearchStrategy; import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm; @@ -116,17 +115,18 @@ public class BuildAlgorithmFromScratch { final VehicleRoutingProblem vrp = vrpBuilder.build(); VehicleRoutingAlgorithm vra = createAlgorithm(vrp); - vra.setMaxIterations(100); + vra.setMaxIterations(2000); AlgorithmEventsRecorder eventsRecorder = new AlgorithmEventsRecorder(vrp, "output/events.dgs.gz"); eventsRecorder.setRecordingRange(90, 100); vra.addListener(eventsRecorder); VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions()); SolutionPrinter.print(vrp, solution, SolutionPrinter.Print.VERBOSE); - AlgorithmEventsViewer viewer = new AlgorithmEventsViewer(); - viewer.setRuinDelay(3); - viewer.setRecreationDelay(1); - viewer.display("output/events.dgs.gz"); + +// AlgorithmEventsViewer viewer = new AlgorithmEventsViewer(); +// viewer.setRuinDelay(3); +// viewer.setRecreationDelay(1); +// viewer.display("output/events.dgs.gz"); } @@ -146,10 +146,11 @@ public class BuildAlgorithmFromScratch { //regret insertion InsertionBuilder iBuilder = new InsertionBuilder(vrp, fleetManager, stateManager, constraintManager); iBuilder.setInsertionStrategy(InsertionBuilder.Strategy.REGRET); + iBuilder.setFastRegret(true); RegretInsertionFast regret = (RegretInsertionFast) iBuilder.build(); DefaultScorer scoringFunction = new DefaultScorer(vrp); - scoringFunction.setDepotDistanceParam(0.2); - scoringFunction.setTimeWindowParam(-.2); + scoringFunction.setDepotDistanceParam(0.0); + scoringFunction.setTimeWindowParam(0.0); regret.setScoringFunction(scoringFunction); /* diff --git a/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/BuildAlgorithmFromScratch2.java b/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/BuildAlgorithmFromScratch2.java new file mode 100644 index 00000000..88544ec4 --- /dev/null +++ b/jsprit-examples/src/main/java/com/graphhopper/jsprit/examples/BuildAlgorithmFromScratch2.java @@ -0,0 +1,252 @@ +/* + * 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.examples; + + +import com.graphhopper.jsprit.analysis.toolbox.AlgorithmEventsRecorder; +import com.graphhopper.jsprit.analysis.toolbox.GraphStreamViewer; +import com.graphhopper.jsprit.core.algorithm.PrettyAlgorithmBuilder; +import com.graphhopper.jsprit.core.algorithm.SearchStrategy; +import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm; +import com.graphhopper.jsprit.core.algorithm.acceptor.SchrimpfAcceptance; +import com.graphhopper.jsprit.core.algorithm.box.Jsprit; +import com.graphhopper.jsprit.core.algorithm.listener.IterationStartsListener; +import com.graphhopper.jsprit.core.algorithm.module.RuinAndRecreateModule; +import com.graphhopper.jsprit.core.algorithm.recreate.*; +import com.graphhopper.jsprit.core.algorithm.ruin.RadialRuinStrategyFactory; +import com.graphhopper.jsprit.core.algorithm.ruin.RandomRuinStrategyFactory; +import com.graphhopper.jsprit.core.algorithm.ruin.RuinStrategy; +import com.graphhopper.jsprit.core.algorithm.ruin.RuinString; +import com.graphhopper.jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance; +import com.graphhopper.jsprit.core.algorithm.selector.SelectBest; +import com.graphhopper.jsprit.core.algorithm.state.StateManager; +import com.graphhopper.jsprit.core.analysis.SolutionAnalyser; +import com.graphhopper.jsprit.core.problem.Location; +import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; +import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager; +import com.graphhopper.jsprit.core.problem.cost.TransportDistance; +import com.graphhopper.jsprit.core.problem.job.Job; +import com.graphhopper.jsprit.core.problem.solution.SolutionCostCalculator; +import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; +import com.graphhopper.jsprit.core.problem.vehicle.FiniteFleetManagerFactory; +import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; +import com.graphhopper.jsprit.core.problem.vehicle.VehicleFleetManager; +import com.graphhopper.jsprit.core.reporting.SolutionPrinter; +import com.graphhopper.jsprit.core.util.Solutions; +import com.graphhopper.jsprit.instance.reader.CordeauReader; +import com.graphhopper.jsprit.util.Examples; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class BuildAlgorithmFromScratch2 { + + + public static class MyBestStrategy extends AbstractInsertionStrategy { + + private JobInsertionCostsCalculatorLight insertionCalculator; + + + public MyBestStrategy(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager) { + super(vrp); + insertionCalculator = JobInsertionCostsCalculatorLightFactory.createStandardCalculator(vrp, fleetManager, stateManager, constraintManager); + } + + @Override + public Collection insertUnassignedJobs(Collection vehicleRoutes, Collection unassignedJobs) { + List badJobs = new ArrayList(); + List unassigned = new ArrayList(unassignedJobs); + Collections.shuffle(unassigned, random); + + for (Job j : unassigned) { + + InsertionData bestInsertionData = InsertionData.createEmptyInsertionData(); + VehicleRoute bestRoute = null; + //look for inserting unassigned job into existing route + for (VehicleRoute r : vehicleRoutes) { + InsertionData insertionData = insertionCalculator.getInsertionData(j, r, bestInsertionData.getInsertionCost()); + if (insertionData instanceof InsertionData.NoInsertionFound) continue; + if (insertionData.getInsertionCost() < bestInsertionData.getInsertionCost()) { + bestInsertionData = insertionData; + bestRoute = r; + } + } + //try whole new route + VehicleRoute empty = VehicleRoute.emptyRoute(); + InsertionData insertionData = insertionCalculator.getInsertionData(j, empty, bestInsertionData.getInsertionCost()); + if (!(insertionData instanceof InsertionData.NoInsertionFound)) { + if (insertionData.getInsertionCost() < bestInsertionData.getInsertionCost()) { + vehicleRoutes.add(empty); + insertJob(j, insertionData, empty); + } + } else { + if (bestRoute != null) insertJob(j, bestInsertionData, bestRoute); + else badJobs.add(j); + } + } + return badJobs; + } + + + } + + + public static void main(String[] args) { + Examples.createOutputFolder(); + + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); + new CordeauReader(vrpBuilder).read("input/p11"); + final VehicleRoutingProblem vrp = vrpBuilder.build(); + +// VehicleRoutingAlgorithm vra = createAlgorithm(vrp); + VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp).setProperty(Jsprit.Parameter.FAST_REGRET, "true") + .setProperty(Jsprit.Parameter.THREADS, "4") + .setProperty(Jsprit.Parameter.REGRET_DISTANCE_SCORER, "0.0001") + .setProperty(Jsprit.Strategy.STRING_BEST, "0.2") + .setProperty(Jsprit.Strategy.STRING_REGRET, "0.2") + .buildAlgorithm(); + + vra.setMaxIterations(15000); + AlgorithmEventsRecorder eventsRecorder = new AlgorithmEventsRecorder(vrp, "output/events.dgs.gz"); + eventsRecorder.setRecordingRange(40, 100); +// vra.addListener(eventsRecorder); + + VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions()); + SolutionPrinter.print(vrp, solution, SolutionPrinter.Print.VERBOSE); + + new GraphStreamViewer(vrp, solution).display(); +// AlgorithmEventsViewer viewer = new AlgorithmEventsViewer(); +// viewer.setRuinDelay(6); +// viewer.setRecreationDelay(1); +// viewer.display("output/events.dgs.gz"); + + } + + + public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp) { + + VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager(); + StateManager stateManager = new StateManager(vrp); + ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager); + + /* + * insertion strategies + */ + //my custom best insertion + MyBestStrategy best = new MyBestStrategy(vrp, fleetManager, stateManager, constraintManager); + + //regret insertion + InsertionBuilder iBuilder = new InsertionBuilder(vrp, fleetManager, stateManager, constraintManager); + iBuilder.setInsertionStrategy(InsertionBuilder.Strategy.REGRET); + iBuilder.setFastRegret(true); + + RegretInsertionFast regret = (RegretInsertionFast) iBuilder.build(); + DefaultScorer scoringFunction = new DefaultScorer(vrp); + scoringFunction.setDepotDistanceParam(0.00001); + scoringFunction.setTimeWindowParam(0); + regret.setScoringFunction(scoringFunction); + + /* + * ruin strategies + */ + RuinStrategy randomRuin = new RandomRuinStrategyFactory(0.5).createStrategy(vrp); + RuinStrategy radialRuin = new RadialRuinStrategyFactory(0.3, new AvgServiceAndShipmentDistance(vrp.getTransportCosts())).createStrategy(vrp); + + /* + * objective function + */ + + RuinStrategy stringRuin = new RuinString(vrp, new AvgServiceAndShipmentDistance(vrp.getTransportCosts())); + + SolutionCostCalculator objectiveFunction = getObjectiveFunction(vrp); + + final SchrimpfAcceptance schrimpfAcceptance = new SchrimpfAcceptance(1, 0.15); + IterationStartsListener schrimpfThreshold = new IterationStartsListener() { + @Override + public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection solutions) { + if (i == 1) { + double initialThreshold = Solutions.bestOf(solutions).getCost() * 0.03; + schrimpfAcceptance.setInitialThreshold(initialThreshold); + } + } + }; + + SearchStrategy firstStrategy = new SearchStrategy("firstStrategy", new SelectBest(), schrimpfAcceptance, objectiveFunction); + firstStrategy.addModule(new RuinAndRecreateModule("randRuinRegretIns", regret, stringRuin)); + +// SearchStrategy secondStrategy = new SearchStrategy("secondStrategy", new SelectBest(), new GreedyAcceptance(1), objectiveFunction); +// secondStrategy.addModule(new RuinAndRecreateModule("radRuinRegretIns", regret, radialRuin)); + +// SearchStrategy thirdStrategy = new SearchStrategy("thirdStrategy", new SelectBest(), new GreedyAcceptance(1), objectiveFunction); +// secondStrategy.addModule(new RuinAndRecreateModule("radRuinBestIns", regret, radialRuin)); + + PrettyAlgorithmBuilder prettyAlgorithmBuilder = PrettyAlgorithmBuilder.newInstance(vrp, fleetManager, stateManager, constraintManager); + final VehicleRoutingAlgorithm vra = prettyAlgorithmBuilder + .withStrategy(firstStrategy, 0.5) +// .withStrategy(secondStrategy, 0.5).withStrategy(thirdStrategy, 0.2) + .addCoreStateAndConstraintStuff() + .constructInitialSolutionWith(regret, objectiveFunction) + .build(); + + //if you want to switch on/off strategies or adapt their weight within the search, you can do the following + //e.g. from iteration 50 on, switch off first strategy + //switch on again at iteration 90 with slightly higher weight +// IterationStartsListener strategyAdaptor = new IterationStartsListener() { +// @Override +// public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection solutions) { +// if (i == 50) { +// vra.getSearchStrategyManager().informStrategyWeightChanged("firstStrategy", 0.0); +// System.out.println("switched off firstStrategy"); +// } +// if (i == 90) { +// vra.getSearchStrategyManager().informStrategyWeightChanged("firstStrategy", 0.7); +// System.out.println("switched on firstStrategy again with higher weight"); +// } +// } +// }; +// vra.addListener(strategyAdaptor); + vra.addListener(schrimpfThreshold); + vra.addListener(schrimpfAcceptance); + return vra; + + } + + private static SolutionCostCalculator getObjectiveFunction(final VehicleRoutingProblem vrp) { + return new SolutionCostCalculator() { + + + @Override + public double getCosts(VehicleRoutingProblemSolution solution) { + SolutionAnalyser analyser = new SolutionAnalyser(vrp, solution, new TransportDistance() { + @Override + public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) { + return vrp.getTransportCosts().getTransportCost(from, to, 0., null, null); + } + }); + return analyser.getVariableTransportCosts() + solution.getUnassignedJobs().size() * 500.; + } + + }; + } + + +}