From 4366542df45ca2120cbe7687b78575337610e6f9 Mon Sep 17 00:00:00 2001 From: oblonski Date: Thu, 8 Jan 2015 19:14:08 +0100 Subject: [PATCH] refactor neighborhood creation, i.e. move to new file --- .../core/algorithm/ruin/JobNeighborhoods.java | 14 +++ .../algorithm/ruin/JobNeighborhoodsImpl.java | 75 +++++++++++++++ ...obNeighborhoodsImplWithCapRestriction.java | 93 +++++++++++++++++++ .../ruin/NearestNeighborhoodIterator.java | 50 ++++++++++ .../core/algorithm/ruin/ReferencedJob.java | 25 +++++ 5 files changed, 257 insertions(+) create mode 100644 jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoods.java create mode 100644 jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoodsImpl.java create mode 100644 jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoodsImplWithCapRestriction.java create mode 100644 jsprit-core/src/main/java/jsprit/core/algorithm/ruin/NearestNeighborhoodIterator.java create mode 100644 jsprit-core/src/main/java/jsprit/core/algorithm/ruin/ReferencedJob.java diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoods.java b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoods.java new file mode 100644 index 00000000..6021d9a1 --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoods.java @@ -0,0 +1,14 @@ +package jsprit.core.algorithm.ruin; + +import jsprit.core.problem.job.Job; + +import java.util.Iterator; + +/** +* Created by schroeder on 07/01/15. +*/ +interface JobNeighborhoods { + + public Iterator getNearestNeighborsIterator(int nNeighbors, Job neighborTo); + +} diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoodsImpl.java b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoodsImpl.java new file mode 100644 index 00000000..d37e6b85 --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoodsImpl.java @@ -0,0 +1,75 @@ +package jsprit.core.algorithm.ruin; + +import jsprit.core.algorithm.ruin.distance.JobDistance; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.job.Job; +import jsprit.core.util.StopWatch; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.*; + +/** +* Created by schroeder on 07/01/15. +*/ +class JobNeighborhoodsImpl implements JobNeighborhoods { + + private static Logger logger = LogManager.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 NearestNeighborhoodIterator(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.getDistance(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"); + } + +} diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoodsImplWithCapRestriction.java b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoodsImplWithCapRestriction.java new file mode 100644 index 00000000..e78ae08f --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/JobNeighborhoodsImplWithCapRestriction.java @@ -0,0 +1,93 @@ +package jsprit.core.algorithm.ruin; + +import jsprit.core.algorithm.ruin.distance.JobDistance; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.job.Job; +import jsprit.core.util.StopWatch; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.*; + +/** +* Created by schroeder on 07/01/15. +*/ +class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods { + + private static Logger logger = LogManager.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 NearestNeighborhoodIterator(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."); + if(capacity==0) return; + 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.getDistance(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+"]"; + } + +} diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/NearestNeighborhoodIterator.java b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/NearestNeighborhoodIterator.java new file mode 100644 index 00000000..1542007a --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/NearestNeighborhoodIterator.java @@ -0,0 +1,50 @@ +package jsprit.core.algorithm.ruin; + +import jsprit.core.problem.job.Job; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Iterator; + +/** +* Created by schroeder on 07/01/15. +*/ +class NearestNeighborhoodIterator implements Iterator { + + private static Logger log = LogManager.getLogger(NearestNeighborhoodIterator.class); + + private Iterator jobIter; + + private int nJobs; + + private int jobCount = 0; + + public NearestNeighborhoodIterator(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(); + } + +} diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/ReferencedJob.java b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/ReferencedJob.java new file mode 100644 index 00000000..23a90973 --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/ReferencedJob.java @@ -0,0 +1,25 @@ +package jsprit.core.algorithm.ruin; + +import jsprit.core.problem.job.Job; + +/** +* Created by schroeder on 07/01/15. +*/ +class ReferencedJob { + private Job job; + private double distance; + + public ReferencedJob(Job job, double distance) { + super(); + this.job = job; + this.distance = distance; + } + + public Job getJob() { + return job; + } + + public double getDistance() { + return distance; + } +}