From 917e4a732a4b0c2c479d94de27f143c914a3d473 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Sat, 2 Nov 2013 07:46:38 +0100 Subject: [PATCH 1/5] bugfix: issue #51 --- .../algorithms/CalculatesServiceInsertionOnRouteLevel.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java index 88a848a1..5d5c2e98 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java @@ -283,7 +283,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul } } if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.noInsertionFound(); - return new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver); + InsertionData insertionData = new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver); + insertionData.setVehicleDepartureTime(newVehicleDepartureTime); + return insertionData; } /** From d9b5d8ee96abb61495d754da40be1386e4d5a77b Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Sat, 2 Nov 2013 07:47:03 +0100 Subject: [PATCH 2/5] experimental timeScheduler --- ...lculatesServiceInsertionWithTimeScheduling.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTimeScheduling.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTimeScheduling.java index b96999ec..d813dfeb 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTimeScheduling.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTimeScheduling.java @@ -27,6 +27,12 @@ import basics.route.Driver; import basics.route.Vehicle; import basics.route.VehicleRoute; +/** + * This is experimental. It ignores vehicles' earliestStartTime. + * + * @author schroeder + * + */ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalculator{ private static Logger log = Logger.getLogger(CalculatesServiceInsertionWithTimeScheduling.class); @@ -67,9 +73,13 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul for(int i=0;i earliestDeparture) vehicleDepartureTimes.add(neighborStartTime_earlier); +// if(neighborStartTime_earlier > earliestDeparture) { + vehicleDepartureTimes.add(neighborStartTime_earlier); +// } double neighborStartTime_later = currentStart + (i+1)*timeSlice; - if(neighborStartTime_later < latestEnd) vehicleDepartureTimes.add(neighborStartTime_later); +// if(neighborStartTime_later < latestEnd) { + vehicleDepartureTimes.add(neighborStartTime_later); +// } } InsertionData bestIData = null; From db888e5c1ef649f2d2eca13dc4d0cdc5bacd7bce Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Sun, 3 Nov 2013 04:26:59 +0100 Subject: [PATCH 3/5] add example 'ConfigureAlgorithInCodeInsteadOfPerXml' - issue #52 --- ...nfigureAlgorithmInCodeInsteadOfPerXml.java | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 jsprit-examples/src/main/java/examples/ConfigureAlgorithmInCodeInsteadOfPerXml.java diff --git a/jsprit-examples/src/main/java/examples/ConfigureAlgorithmInCodeInsteadOfPerXml.java b/jsprit-examples/src/main/java/examples/ConfigureAlgorithmInCodeInsteadOfPerXml.java new file mode 100644 index 00000000..96497237 --- /dev/null +++ b/jsprit-examples/src/main/java/examples/ConfigureAlgorithmInCodeInsteadOfPerXml.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (C) 2013 Stefan Schroeder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + ******************************************************************************/ +package examples; + +import java.io.File; +import java.util.Collection; + +import org.apache.commons.configuration.XMLConfiguration; + +import util.Coordinate; +import util.Solutions; +import algorithms.VehicleRoutingAlgorithms; +import analysis.SolutionPlotter; +import analysis.SolutionPrinter; +import analysis.SolutionPrinter.Print; +import basics.Service; +import basics.VehicleRoutingAlgorithm; +import basics.VehicleRoutingProblem; +import basics.VehicleRoutingProblemSolution; +import basics.io.AlgorithmConfig; +import basics.io.VrpXMLWriter; +import basics.route.Vehicle; +import basics.route.VehicleImpl; +import basics.route.VehicleImpl.Builder; +import basics.route.VehicleType; +import basics.route.VehicleTypeImpl; + +public class ConfigureAlgorithmInCodeInsteadOfPerXml { + + public static void main(String[] args) { + /* + * some preparation - create output folder + */ + File dir = new File("output"); + // if the directory does not exist, create it + if (!dir.exists()){ + System.out.println("creating directory ./output"); + boolean result = dir.mkdir(); + if(result) System.out.println("./output created"); + } + + /* + * get a vehicle type-builder and build a type with the typeId "vehicleType" and a capacity of 2 + */ + VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder.newInstance("vehicleType", 2); + VehicleType vehicleType = vehicleTypeBuilder.build(); + + /* + * get a vehicle-builder and build a vehicle located at (10,10) with type "vehicleType" + */ + Builder vehicleBuilder = VehicleImpl.Builder.newInstance("vehicle"); + vehicleBuilder.setLocationCoord(Coordinate.newInstance(10, 10)); + vehicleBuilder.setType(vehicleType); + Vehicle vehicle = vehicleBuilder.build(); + + /* + * build services at the required locations, each with a capacity-demand of 1. + */ + Service service1 = Service.Builder.newInstance("1", 1).setCoord(Coordinate.newInstance(5, 7)).build(); + Service service2 = Service.Builder.newInstance("2", 1).setCoord(Coordinate.newInstance(5, 13)).build(); + + Service service3 = Service.Builder.newInstance("3", 1).setCoord(Coordinate.newInstance(15, 7)).build(); + Service service4 = Service.Builder.newInstance("4", 1).setCoord(Coordinate.newInstance(15, 13)).build(); + + + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); + vrpBuilder.addVehicle(vehicle); + vrpBuilder.addService(service1).addService(service2).addService(service3).addService(service4); + + VehicleRoutingProblem problem = vrpBuilder.build(); + + /* + * get the algorithm out-of-the-box. + */ + AlgorithmConfig algorithmConfig = getAlgorithmConfig(); + VehicleRoutingAlgorithm algorithm = VehicleRoutingAlgorithms.createAlgorithm(problem,algorithmConfig); + + /* + * and search a solution + */ + Collection solutions = algorithm.searchSolutions(); + + /* + * get the best + */ + VehicleRoutingProblemSolution bestSolution = Solutions.getBest(solutions); + + new VrpXMLWriter(problem, solutions).write("output/problem-with-solution.xml"); + + SolutionPrinter.print(bestSolution,Print.VERBOSE); + + /* + * plot + */ + SolutionPlotter.plotSolutionAsPNG(problem, bestSolution, "output/solution.png", "solution"); + } + + private static AlgorithmConfig getAlgorithmConfig() { + AlgorithmConfig config = new AlgorithmConfig(); + XMLConfiguration xmlConfig = config.getXMLConfiguration(); + xmlConfig.setProperty("iterations", 2000); + xmlConfig.setProperty("construction.insertion[@name]","bestInsertion"); + + xmlConfig.setProperty("strategy.memory", 1); + String searchStrategy = "strategy.searchStrategies.searchStrategy"; + + xmlConfig.setProperty(searchStrategy + "(0).selector[@name]","selectBest"); + xmlConfig.setProperty(searchStrategy + "(0).acceptor[@name]","acceptNewRemoveWorst"); + xmlConfig.setProperty(searchStrategy + "(0).modules.module(0)[@name]","ruin_and_recreate"); + xmlConfig.setProperty(searchStrategy + "(0).modules.module(0).ruin[@name]","randomRuin"); + xmlConfig.setProperty(searchStrategy + "(0).modules.module(0).ruin.share","0.3"); + xmlConfig.setProperty(searchStrategy + "(0).modules.module(0).insertion[@name]","bestInsertion"); + xmlConfig.setProperty(searchStrategy + "(0).probability","0.5"); + + xmlConfig.setProperty(searchStrategy + "(1).selector[@name]","selectBest"); + xmlConfig.setProperty(searchStrategy + "(1).acceptor[@name]","acceptNewRemoveWorst"); + xmlConfig.setProperty(searchStrategy + "(1).modules.module(0)[@name]","ruin_and_recreate"); + xmlConfig.setProperty(searchStrategy + "(1).modules.module(0).ruin[@name]","radialRuin"); + xmlConfig.setProperty(searchStrategy + "(1).modules.module(0).ruin.share","0.15"); + xmlConfig.setProperty(searchStrategy + "(1).modules.module(0).insertion[@name]","bestInsertion"); + xmlConfig.setProperty(searchStrategy + "(1).probability","0.5"); + + return config; + } + +} From 8f4f4b6c48e45a7ff3d2c07e590d140580709c25 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Mon, 18 Nov 2013 22:33:10 +0100 Subject: [PATCH 4/5] make RuinRadial more memory efficient and make NeighborhoodCreation independent from RuinRadial --- .../src/main/java/algorithms/RuinRadial.java | 267 ++++++++++++++---- .../algorithms/JobNeighborhoodsImplTest.java | 110 ++++++++ ...ighborhoodsWithCapRestrictionImplTest.java | 111 ++++++++ 3 files changed, 435 insertions(+), 53 deletions(-) create mode 100644 jsprit-core/src/test/java/algorithms/JobNeighborhoodsImplTest.java create mode 100644 jsprit-core/src/test/java/algorithms/JobNeighborhoodsWithCapRestrictionImplTest.java diff --git a/jsprit-core/src/main/java/algorithms/RuinRadial.java b/jsprit-core/src/main/java/algorithms/RuinRadial.java index 7b9c5edf..6f198537 100644 --- a/jsprit-core/src/main/java/algorithms/RuinRadial.java +++ b/jsprit-core/src/main/java/algorithms/RuinRadial.java @@ -47,6 +47,194 @@ import basics.route.VehicleRoute; */ final class RuinRadial implements RuinStrategy { + static interface JobNeighborhoods { + + public Iterator getNearestNeighborsIterator(int nNeighbors, Job neighborTo); + + } + + static class NeighborhoodIterator implements Iterator{ + + private static Logger log = Logger.getLogger(NeighborhoodIterator.class); + + private Iterator jobIter; + + private int nJobs; + + private int jobCount = 0; + + public NeighborhoodIterator(Iterator jobIter, int nJobs) { + super(); + this.jobIter = jobIter; + this.nJobs = nJobs; + } + + @Override + public boolean hasNext() { + if(jobCount < nJobs){ + boolean hasNext = jobIter.hasNext(); + if(!hasNext) log.warn("more jobs are requested then iterator can iterate over. probably the number of neighbors memorized in JobNeighborhoods is too small"); + return hasNext; + } + return false; + } + + @Override + public Job next() { + ReferencedJob next = jobIter.next(); + jobCount++; + return next.getJob(); + } + + @Override + public void remove() { + jobIter.remove(); + } + + } + + static class JobNeighborhoodsImpl implements JobNeighborhoods { + + private static Logger logger = Logger.getLogger(JobNeighborhoodsImpl.class); + + private VehicleRoutingProblem vrp; + + private Map> distanceNodeTree = new HashMap>(); + + private JobDistance jobDistance; + + public JobNeighborhoodsImpl(VehicleRoutingProblem vrp, JobDistance jobDistance) { + super(); + this.vrp = vrp; + this.jobDistance = jobDistance; + logger.info("intialise " + this); + } + + public Iterator getNearestNeighborsIterator(int nNeighbors, Job neighborTo){ + TreeSet tree = distanceNodeTree.get(neighborTo.getId()); + Iterator descendingIterator = tree.iterator(); + return new NeighborhoodIterator(descendingIterator, nNeighbors); + } + + public void initialise(){ + logger.info("calculates and memorizes distances from EACH job to EACH job --> n^2 calculations"); + calculateDistancesFromJob2Job(); + } + + private void calculateDistancesFromJob2Job() { + logger.info("preprocess distances between locations ..."); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + int nuOfDistancesStored = 0; + for (Job i : vrp.getJobs().values()) { + TreeSet treeSet = new TreeSet( + new Comparator() { + @Override + public int compare(ReferencedJob o1, ReferencedJob o2) { + if (o1.getDistance() <= o2.getDistance()) { + return -1; + } else { + return 1; + } + } + }); + distanceNodeTree.put(i.getId(), treeSet); + for (Job j : vrp.getJobs().values()) { + if(i==j) continue; + double distance = jobDistance.calculateDistance(i, j); + ReferencedJob refNode = new ReferencedJob(j, distance); + treeSet.add(refNode); + nuOfDistancesStored++; + } + + } + stopWatch.stop(); + logger.info("preprocessing comp-time: " + stopWatch + "; nuOfDistances stored: " + nuOfDistancesStored + "; estimated memory: " + + (distanceNodeTree.keySet().size()*64+nuOfDistancesStored*92) + " bytes"); + } + + } + + static class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods { + + private static Logger logger = Logger.getLogger(JobNeighborhoodsImpl.class); + + private VehicleRoutingProblem vrp; + + private Map> distanceNodeTree = new HashMap>(); + + private JobDistance jobDistance; + + private int capacity; + + public JobNeighborhoodsImplWithCapRestriction(VehicleRoutingProblem vrp, JobDistance jobDistance, int capacity) { + super(); + this.vrp = vrp; + this.jobDistance = jobDistance; + this.capacity = capacity; + logger.info("intialise " + this); + } + + public Iterator getNearestNeighborsIterator(int nNeighbors, Job neighborTo){ + TreeSet tree = distanceNodeTree.get(neighborTo.getId()); + Iterator descendingIterator = tree.iterator(); + return new NeighborhoodIterator(descendingIterator, nNeighbors); + } + + public void initialise(){ + logger.info("calculates distances from EACH job to EACH job --> n^2="+Math.pow(vrp.getJobs().values().size(), 2) + " calculations, but 'only' "+(vrp.getJobs().values().size()*capacity)+ " are cached."); + calculateDistancesFromJob2Job(); + } + + private void calculateDistancesFromJob2Job() { + logger.info("preprocess distances between locations ..."); + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + int nuOfDistancesStored = 0; + for (Job i : vrp.getJobs().values()) { + TreeSet treeSet = new TreeSet( + new Comparator() { + @Override + public int compare(ReferencedJob o1, ReferencedJob o2) { + if (o1.getDistance() <= o2.getDistance()) { + return -1; + } else { + return 1; + } + } + }); + distanceNodeTree.put(i.getId(), treeSet); + for (Job j : vrp.getJobs().values()) { + if(i==j) continue; + double distance = jobDistance.calculateDistance(i, j); + ReferencedJob refNode = new ReferencedJob(j, distance); + if(treeSet.size() < capacity){ + treeSet.add(refNode); + nuOfDistancesStored++; + } + else{ + if(treeSet.last().getDistance() > distance){ + treeSet.pollLast(); + treeSet.add(refNode); + } + } + } + assert treeSet.size() <= capacity : "treeSet.size() is bigger than specified capacity"; + + } + stopWatch.stop(); + logger.info("preprocessing comp-time: " + stopWatch + "; nuOfDistances stored: " + nuOfDistancesStored + "; estimated memory: " + + (distanceNodeTree.keySet().size()*64+nuOfDistancesStored*92) + " bytes"); + } + + @Override + public String toString() { + return "[name=neighborhoodWithCapRestriction][capacity="+capacity+"]"; + } + + } + + static class ReferencedJob { private Job job; private double distance; @@ -72,14 +260,12 @@ final class RuinRadial implements RuinStrategy { private double fractionOfAllNodes2beRuined; - private Map> distanceNodeTree = new HashMap>(); - private Random random = RandomNumberGeneration.getRandom(); - private JobDistance jobDistance; - private RuinListeners ruinListeners; + private JobNeighborhoods jobNeighborhoods; + public void setRandom(Random random) { this.random = random; } @@ -94,42 +280,14 @@ final class RuinRadial implements RuinStrategy { public RuinRadial(VehicleRoutingProblem vrp, double fraction2beRemoved, JobDistance jobDistance) { super(); this.vrp = vrp; - this.jobDistance = jobDistance; this.fractionOfAllNodes2beRuined = fraction2beRemoved; ruinListeners = new RuinListeners(); - calculateDistancesFromJob2Job(); + int nJobsToMemorize = (int) Math.ceil(vrp.getJobs().values().size()*fraction2beRemoved); + JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, nJobsToMemorize); + jobNeighborhoodsImpl.initialise(); + jobNeighborhoods = jobNeighborhoodsImpl; logger.info("intialise " + this); } - - private void calculateDistancesFromJob2Job() { - logger.info("preprocess distances between locations ..."); - StopWatch stopWatch = new StopWatch(); - stopWatch.start(); - int nuOfDistancesStored = 0; - for (Job i : vrp.getJobs().values()) { - TreeSet treeSet = new TreeSet( - new Comparator() { - @Override - public int compare(ReferencedJob o1, ReferencedJob o2) { - if (o1.getDistance() <= o2.getDistance()) { - return 1; - } else { - return -1; - } - } - }); - distanceNodeTree.put(i.getId(), treeSet); - for (Job j : vrp.getJobs().values()) { - double distance = jobDistance.calculateDistance(i, j); - ReferencedJob refNode = new ReferencedJob(j, distance); - treeSet.add(refNode); - nuOfDistancesStored++; - } - } - stopWatch.stop(); - logger.info("preprocessing comp-time: " + stopWatch + "; nuOfDistances stored: " + nuOfDistancesStored + "; estimated memory: " + - (distanceNodeTree.keySet().size()*64+nuOfDistancesStored*92) + " bytes"); - } @Override public String toString() { @@ -143,11 +301,11 @@ final class RuinRadial implements RuinStrategy { @Override public Collection ruin(Collection vehicleRoutes) { if(vehicleRoutes.isEmpty()){ - return Collections.EMPTY_LIST; + return Collections.emptyList(); } int nOfJobs2BeRemoved = getNuOfJobs2BeRemoved(); if (nOfJobs2BeRemoved == 0) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } Job randomJob = pickRandomJob(); Collection unassignedJobs = ruin(vehicleRoutes,randomJob,nOfJobs2BeRemoved); @@ -160,27 +318,30 @@ final class RuinRadial implements RuinStrategy { public Collection ruin(Collection vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){ ruinListeners.ruinStarts(vehicleRoutes); List unassignedJobs = new ArrayList(); - TreeSet tree = distanceNodeTree.get(targetJob.getId()); - Iterator descendingIterator = tree.descendingIterator(); - int counter = 0; - while (descendingIterator.hasNext() && counter < nOfJobs2BeRemoved) { - ReferencedJob refJob = descendingIterator.next(); - Job job = refJob.getJob(); + int nNeighbors = nOfJobs2BeRemoved - 1; + removeJob(targetJob,vehicleRoutes); + unassignedJobs.add(targetJob); + Iterator neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(nNeighbors, targetJob); + while(neighborhoodIterator.hasNext()){ + Job job = neighborhoodIterator.next(); + removeJob(job,vehicleRoutes); unassignedJobs.add(job); - counter++; - boolean removed = false; - for (VehicleRoute route : vehicleRoutes) { - removed = route.getTourActivities().removeJob(job);; - if (removed) { - ruinListeners.removed(job,route); - break; - } - } } ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs); return unassignedJobs; } + private void removeJob(Job job, Collection vehicleRoutes) { + boolean removed = false; + for (VehicleRoute route : vehicleRoutes) { + removed = route.getTourActivities().removeJob(job);; + if (removed) { + ruinListeners.removed(job,route); + break; + } + } + } + private Job pickRandomJob() { int totNuOfJobs = vrp.getJobs().values().size(); int randomIndex = random.nextInt(totNuOfJobs); diff --git a/jsprit-core/src/test/java/algorithms/JobNeighborhoodsImplTest.java b/jsprit-core/src/test/java/algorithms/JobNeighborhoodsImplTest.java new file mode 100644 index 00000000..9ba678b6 --- /dev/null +++ b/jsprit-core/src/test/java/algorithms/JobNeighborhoodsImplTest.java @@ -0,0 +1,110 @@ +package algorithms; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import util.Coordinate; +import algorithms.RuinRadial.JobNeighborhoodsImpl; +import basics.Job; +import basics.Service; +import basics.VehicleRoutingProblem; + +public class JobNeighborhoodsImplTest { + + VehicleRoutingProblem vrp; + + JobDistance jobDistance; + + Service target; + Service s2; + Service s3; + Service s4; + Service s5; + Service s6; + Service s7; + + @Before + public void doBefore(){ + VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance(); + target = Service.Builder.newInstance("s1", 1).setCoord(Coordinate.newInstance(0, 5)).build(); + s2 = Service.Builder.newInstance("s2", 1).setCoord(Coordinate.newInstance(0, 4)).build(); + s3 = Service.Builder.newInstance("s3", 1).setCoord(Coordinate.newInstance(0, 3)).build(); + s4 = Service.Builder.newInstance("s4", 1).setCoord(Coordinate.newInstance(0, 2)).build(); + + s5 = Service.Builder.newInstance("s5", 1).setCoord(Coordinate.newInstance(0, 6)).build(); + s6 = Service.Builder.newInstance("s6", 1).setCoord(Coordinate.newInstance(0, 7)).build(); + s7 = Service.Builder.newInstance("s7", 1).setCoord(Coordinate.newInstance(0, 8)).build(); + + vrp = builder.addJob(target).addJob(s2).addJob(s3).addJob(s4).addJob(s5).addJob(s6).addJob(s7).build(); + + jobDistance = new EuclideanServiceDistance(); + } + + @Test + public void whenRequestingNeighborhoodOfTargetJob_nNeighborsShouldBeTwo(){ + JobNeighborhoodsImpl jn = new JobNeighborhoodsImpl(vrp, jobDistance); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(2, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertEquals(2,services.size()); + } + + @Test + public void whenRequestingNeighborhoodOfTargetJob_s2ShouldBeNeighbor(){ + JobNeighborhoodsImpl jn = new JobNeighborhoodsImpl(vrp, jobDistance); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(2, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertTrue(services.contains(s2)); + } + + @Test + public void whenRequestingNeighborhoodOfTargetJob_s4ShouldBeNeighbor(){ + JobNeighborhoodsImpl jn = new JobNeighborhoodsImpl(vrp, jobDistance); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(2, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertTrue(services.contains(s5)); + } + + @Test + public void whenRequestingNeighborhoodOfTargetJob_sizeShouldBe4(){ + JobNeighborhoodsImpl jn = new JobNeighborhoodsImpl(vrp, jobDistance); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(4, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertEquals(4,services.size()); + } + + @Test + public void whenRequestingMoreNeighborsThanExisting_itShouldReturnMaxNeighbors(){ + JobNeighborhoodsImpl jn = new JobNeighborhoodsImpl(vrp, jobDistance); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(100, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertEquals(6,services.size()); + } + +} diff --git a/jsprit-core/src/test/java/algorithms/JobNeighborhoodsWithCapRestrictionImplTest.java b/jsprit-core/src/test/java/algorithms/JobNeighborhoodsWithCapRestrictionImplTest.java new file mode 100644 index 00000000..8f4bbc28 --- /dev/null +++ b/jsprit-core/src/test/java/algorithms/JobNeighborhoodsWithCapRestrictionImplTest.java @@ -0,0 +1,111 @@ +package algorithms; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import util.Coordinate; +import algorithms.RuinRadial.JobNeighborhoodsImpl; +import algorithms.RuinRadial.JobNeighborhoodsImplWithCapRestriction; +import basics.Job; +import basics.Service; +import basics.VehicleRoutingProblem; + +public class JobNeighborhoodsWithCapRestrictionImplTest { + + VehicleRoutingProblem vrp; + + JobDistance jobDistance; + + Service target; + Service s2; + Service s3; + Service s4; + Service s5; + Service s6; + Service s7; + + @Before + public void doBefore(){ + VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance(); + target = Service.Builder.newInstance("s1", 1).setCoord(Coordinate.newInstance(0, 5)).build(); + s2 = Service.Builder.newInstance("s2", 1).setCoord(Coordinate.newInstance(0, 4)).build(); + s3 = Service.Builder.newInstance("s3", 1).setCoord(Coordinate.newInstance(0, 3)).build(); + s4 = Service.Builder.newInstance("s4", 1).setCoord(Coordinate.newInstance(0, 2)).build(); + + s5 = Service.Builder.newInstance("s5", 1).setCoord(Coordinate.newInstance(0, 6)).build(); + s6 = Service.Builder.newInstance("s6", 1).setCoord(Coordinate.newInstance(0, 7)).build(); + s7 = Service.Builder.newInstance("s7", 1).setCoord(Coordinate.newInstance(0, 8)).build(); + + vrp = builder.addJob(target).addJob(s2).addJob(s3).addJob(s4).addJob(s5).addJob(s6).addJob(s7).build(); + + jobDistance = new EuclideanServiceDistance(); + } + + @Test + public void whenRequestingNeighborhoodOfTargetJob_nNeighborsShouldBeTwo(){ + JobNeighborhoodsImplWithCapRestriction jn = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, 2); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(2, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertEquals(2,services.size()); + } + + @Test + public void whenRequestingNeighborhoodOfTargetJob_s2ShouldBeNeighbor(){ + JobNeighborhoodsImplWithCapRestriction jn = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, 2); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(2, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertTrue(services.contains(s2)); + } + + @Test + public void whenRequestingNeighborhoodOfTargetJob_s4ShouldBeNeighbor(){ + JobNeighborhoodsImplWithCapRestriction jn = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, 2); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(2, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertTrue(services.contains(s5)); + } + + @Test + public void whenRequestingNeighborhoodOfTargetJob_sizeShouldBe4(){ + JobNeighborhoodsImplWithCapRestriction jn = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, 4); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(4, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertEquals(4,services.size()); + } + + @Test + public void whenRequestingMoreNeighborsThanExisting_itShouldReturnMaxNeighbors(){ + JobNeighborhoodsImplWithCapRestriction jn = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, 2); + jn.initialise(); + Iterator iter = jn.getNearestNeighborsIterator(100, target); + List services = new ArrayList(); + while(iter.hasNext()){ + services.add((Service) iter.next()); + } + assertEquals(2,services.size()); + } + +} From 61406bc70ec4042e9841f05650d8b9474e091009 Mon Sep 17 00:00:00 2001 From: Stefan Schroeder <4sschroeder@gmail.com> Date: Tue, 19 Nov 2013 14:56:27 +0100 Subject: [PATCH 5/5] modify license in pom --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3b3c5309..4d8a5078 100644 --- a/pom.xml +++ b/pom.xml @@ -34,8 +34,8 @@ - GNU General Public License, version 2 (GPL-2.0) - http://opensource.org/licenses/GPL-2.0 + GNU Lesser General Public Licence, version 3.0 + http://opensource.org/licenses/LGPL-3.0