diff --git a/jsprit-core/src/main/java/algorithms/EuclideanServiceDistance.java b/jsprit-core/src/main/java/algorithms/EuclideanServiceDistance.java
new file mode 100644
index 00000000..84562fbc
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/EuclideanServiceDistance.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Stefan Schroeder.
+ * eMail: stefan.schroeder@kit.edu
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Public License v2.0
+ * which accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ * Contributors:
+ * Stefan Schroeder - initial API and implementation
+ ******************************************************************************/
+package algorithms;
+
+import util.EuclideanDistanceCalculator;
+import basics.Job;
+import basics.Service;
+
+class EuclideanServiceDistance implements JobDistance {
+
+ public EuclideanServiceDistance() {
+ super();
+ }
+
+ @Override
+ public double calculateDistance(Job i, Job j) {
+ double avgCost = 0.0;
+ if (i instanceof Service && j instanceof Service) {
+ if (i.equals(j)) {
+ avgCost = 0.0;
+ } else {
+ Service s_i = (Service) i;
+ Service s_j = (Service) j;
+ if(s_i.getCoord() == null || s_j.getCoord() == null) throw new IllegalStateException("cannot calculate euclidean distance. since service coords are missing");
+ avgCost = EuclideanDistanceCalculator.calculateDistance(s_i.getCoord(), s_j.getCoord());
+ }
+ } else {
+ throw new UnsupportedOperationException(
+ "currently, this class just works with shipments and services.");
+ }
+ return avgCost;
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/JobDistanceAvgCosts.java b/jsprit-core/src/main/java/algorithms/JobDistanceAvgCosts.java
index 74c742e8..176cb946 100644
--- a/jsprit-core/src/main/java/algorithms/JobDistanceAvgCosts.java
+++ b/jsprit-core/src/main/java/algorithms/JobDistanceAvgCosts.java
@@ -12,14 +12,25 @@
******************************************************************************/
package algorithms;
+import org.apache.log4j.Logger;
+
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
-
+/**
+ * Calculator that calculates average distance between two jobs based on the input-transport costs.
+ *
+ *
If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
+ *
+ * @author stefan schroeder
+ *
+ */
class JobDistanceAvgCosts implements JobDistance {
+ private static Logger log = Logger.getLogger(JobDistanceAvgCosts.class);
+
private VehicleRoutingTransportCosts costs;
public JobDistanceAvgCosts(VehicleRoutingTransportCosts costs) {
@@ -28,29 +39,21 @@ class JobDistanceAvgCosts implements JobDistance {
}
+ /**
+ * Calculates and returns the average distance between two jobs based on the input-transport costs.
+ *
+ *
If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
+ */
@Override
public double calculateDistance(Job i, Job j) {
double avgCost = 0.0;
-// if (i instanceof Shipment && j instanceof Shipment) {
-// if (i.equals(j)) {
-// avgCost = 0.0;
-// } else {
-// Shipment s_i = (Shipment) i;
-// Shipment s_j = (Shipment) j;
-// double cost_i1_j1 = calcDist(s_i.getFromId(), s_j.getFromId());
-// double cost_i1_j2 = calcDist(s_i.getFromId(), s_j.getToId());
-// double cost_i2_j1 = calcDist(s_i.getToId(), s_j.getFromId());
-// double cost_i2_j2 = calcDist(s_i.getToId(), s_j.getToId());
-// avgCost = (cost_i1_j1 + cost_i1_j2 + cost_i2_j1 + cost_i2_j2) / 4;
-// }
-// } else
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {
avgCost = 0.0;
} else {
Service s_i = (Service) i;
Service s_j = (Service) j;
- avgCost = calcDist(s_i.getLocationId(), s_j.getLocationId());
+ avgCost = calcDist(s_i, s_j);
}
} else {
throw new UnsupportedOperationException(
@@ -59,8 +62,18 @@ class JobDistanceAvgCosts implements JobDistance {
return avgCost;
}
- private double calcDist(String from, String to) {
- return costs.getTransportCost(from, to, 0.0, null, null);
+ private double calcDist(Service s_i, Service s_j) {
+ double distance;
+ try{
+ distance = costs.getTransportCost(s_i.getLocationId(), s_j.getLocationId(), 0.0, null, null);
+ return distance;
+ }
+ catch(IllegalStateException e){
+ // now try the euclidean distance between these two services
+ }
+ EuclideanServiceDistance euclidean = new EuclideanServiceDistance();
+ distance = euclidean.calculateDistance(s_i, s_j);
+ return distance;
}
}
diff --git a/jsprit-core/src/main/java/algorithms/JobDistanceBeeline.java b/jsprit-core/src/main/java/algorithms/JobDistanceBeeline.java
index b0fe0f5c..aef489fe 100644
--- a/jsprit-core/src/main/java/algorithms/JobDistanceBeeline.java
+++ b/jsprit-core/src/main/java/algorithms/JobDistanceBeeline.java
@@ -31,19 +31,6 @@ class JobDistanceBeeline implements JobDistance {
@Override
public double calculateDistance(Job i, Job j) {
double avgCost = 0.0;
-// if (i instanceof Shipment && j instanceof Shipment) {
-// if (i.equals(j)) {
-// avgCost = 0.0;
-// } else {
-// Shipment s_i = (Shipment) i;
-// Shipment s_j = (Shipment) j;
-// double cost_i1_j1 = calcDist(s_i.getFromId(), s_j.getFromId());
-// double cost_i1_j2 = calcDist(s_i.getFromId(), s_j.getToId());
-// double cost_i2_j1 = calcDist(s_i.getToId(), s_j.getFromId());
-// double cost_i2_j2 = calcDist(s_i.getToId(), s_j.getToId());
-// avgCost = (cost_i1_j1 + cost_i1_j2 + cost_i2_j1 + cost_i2_j2) / 4;
-// }
-// } else
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {
avgCost = 0.0;
diff --git a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java
index 75236cd3..68d81cc2 100644
--- a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java
+++ b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java
@@ -359,6 +359,13 @@ public class VehicleRoutingAlgorithms {
private VehicleRoutingAlgorithms(){}
+ /**
+ * Creates a {@link VehicleRoutingAlgorithm} from a AlgorithConfig based on the input vrp.
+ *
+ * @param vrp
+ * @param algorithmConfig
+ * @return {@link VehicleRoutingAlgorithm}
+ */
public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){
return createAlgo(vrp,algorithmConfig.getXMLConfiguration());
}
@@ -368,6 +375,13 @@ public class VehicleRoutingAlgorithms {
return createAlgo(vrp,config);
}
+ /**
+ * Read and creates a {@link VehicleRoutingAlgorithm} from an url.
+ *
+ * @param vrp
+ * @param configURL
+ * @return {@link VehicleRoutingProblem}
+ */
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final URL configURL){
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
@@ -375,6 +389,13 @@ public class VehicleRoutingAlgorithms {
return createAlgo(vrp,algorithmConfig.getXMLConfiguration());
}
+ /**
+ * Read and creates {@link VehicleRoutingAlgorithm} from config-file.
+ *
+ * @param vrp
+ * @param configFileName
+ * @return
+ */
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final String configFileName){
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
@@ -572,6 +593,7 @@ public class VehicleRoutingAlgorithms {
StrategyModuleKey strategyModuleKey = new StrategyModuleKey(modKey);
SearchStrategyModule definedModule = definedClasses.get(strategyModuleKey);
if(definedModule != null) return definedModule;
+
if(moduleName.equals("ruin_and_recreate")){
String ruin_name = moduleConfig.getString("ruin[@name]");
if(ruin_name == null) throw new IllegalStateException("module.ruin[@name] is missing.");
@@ -586,7 +608,17 @@ public class VehicleRoutingAlgorithms {
ruin = getRandomRuin(vrp, activityStates, definedClasses, ruinKey, shareToRuin);
}
else if(ruin_name.equals("radialRuin")){
- ruin = getRadialRuin(vrp, activityStates, definedClasses, ruinKey, shareToRuin);
+ String ruin_distance = moduleConfig.getString("ruin.distance");
+ JobDistance jobDistance;
+ if(ruin_distance == null) jobDistance = new JobDistanceAvgCosts(vrp.getTransportCosts());
+ else {
+ if(ruin_distance.equals("euclidean")){
+ jobDistance = new EuclideanServiceDistance();
+ }
+ else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
+ + "default is used or use 'euclidean'");
+ }
+ ruin = getRadialRuin(vrp, activityStates, definedClasses, ruinKey, shareToRuin, jobDistance);
}
else throw new IllegalStateException("ruin[@name] " + ruin_name + " is not known. Use either randomRuin or radialRuin.");
@@ -643,15 +675,16 @@ public class VehicleRoutingAlgorithms {
};
return module;
}
- if(moduleName.equals("bestInsertion") || moduleName.equals("regretInsertion")){
- List prioListeners = new ArrayList();
- AbstractInsertionStrategy insertion = getInsertionStrategy(moduleConfig, vrp, vehicleFleetManager, activityStates,
- definedClasses, modKey, prioListeners);
- SearchStrategyModule module = getModule(moduleName, insertion, vrp);
- definedClasses.put(strategyModuleKey, module);
- algorithmListeners.addAll(prioListeners);
- return module;
- }
+
+// if(moduleName.equals("bestInsertion") || moduleName.equals("regretInsertion")){
+// List prioListeners = new ArrayList();
+// AbstractInsertionStrategy insertion = getInsertionStrategy(moduleConfig, vrp, vehicleFleetManager, activityStates,
+// definedClasses, modKey, prioListeners);
+// SearchStrategyModule module = getModule(moduleName, insertion, vrp);
+// definedClasses.put(strategyModuleKey, module);
+// algorithmListeners.addAll(prioListeners);
+// return module;
+// }
// if(moduleName.equals("regretInsertion")){
// List prioListeners = new ArrayList();
// AbstractInsertionKey insertionKey = new AbstractInsertionKey(modKey);
@@ -664,20 +697,30 @@ public class VehicleRoutingAlgorithms {
// algorithmListeners.addAll(prioListeners);
// return module;
// }
- if(moduleName.equals("randomRuin")){
- double shareToRuin = moduleConfig.getDouble("share");
- RuinStrategy ruin = getRandomRuin(vrp, activityStates,definedClasses, modKey, shareToRuin);
- SearchStrategyModule module = getModule(moduleName, ruin);
- definedClasses.put(strategyModuleKey, module);
- return module;
- }
- if(moduleName.equals("radialRuin")){
- double shareToRuin = moduleConfig.getDouble("share");
- RuinStrategy ruin = getRadialRuin(vrp, activityStates,definedClasses, modKey, shareToRuin);
- SearchStrategyModule module = getModule(moduleName, ruin);
- definedClasses.put(strategyModuleKey, module);
- return module;
- }
+// if(moduleName.equals("randomRuin")){
+// double shareToRuin = moduleConfig.getDouble("share");
+// RuinStrategy ruin = getRandomRuin(vrp, activityStates,definedClasses, modKey, shareToRuin);
+// SearchStrategyModule module = getModule(moduleName, ruin);
+// definedClasses.put(strategyModuleKey, module);
+// return module;
+// }
+// if(moduleName.equals("radialRuin")){
+// double shareToRuin = moduleConfig.getDouble("share");
+// String ruin_distance = moduleConfig.getString("distance");
+// JobDistance jobDistance;
+// if(ruin_distance == null) jobDistance = new JobDistanceAvgCosts(vrp.getTransportCosts());
+// else {
+// if(ruin_distance.equals("euclidean")){
+// jobDistance = new EuclideanServiceDistance();
+// }
+// else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
+// + "default is used or use 'euclidean'");
+// }
+// RuinStrategy ruin = getRadialRuin(vrp, activityStates,definedClasses, modKey, shareToRuin, jobDistance);
+// SearchStrategyModule module = getModule(moduleName, ruin);
+// definedClasses.put(strategyModuleKey, module);
+// return module;
+// }
if(moduleName.equals("gendreauPostOpt")){
int iterations = moduleConfig.getInt("iterations");
double share = moduleConfig.getDouble("share");
@@ -734,13 +777,11 @@ public class VehicleRoutingAlgorithms {
return bestInsertion;
}
- private static RuinStrategy getRadialRuin(VehicleRoutingProblem vrp,
- RouteStates activityStates, TypedMap definedClasses,
- ModKey modKey, double shareToRuin) {
+ private static RuinStrategy getRadialRuin(VehicleRoutingProblem vrp, RouteStates activityStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
- ruin = RuinRadial.newInstance(vrp, shareToRuin, new JobDistanceAvgCosts(vrp.getTransportCosts()), new JobRemoverImpl(), new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
+ ruin = RuinRadial.newInstance(vrp, shareToRuin, jobDistance, new JobRemoverImpl(), new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
definedClasses.put(stratKey, ruin);
}
return ruin;
@@ -778,12 +819,6 @@ public class VehicleRoutingAlgorithms {
double penalty = 0.0;
if(jobsInSolution != vrp.getJobs().values().size()){
throw new IllegalStateException("solution not valid\n" + "#jobsInSolution=" + jobsInSolution + " #jobsInVrp=" + vrp.getJobs().values().size());
-// logger.warn("solution not valid\n" + "#jobsInSolution=" + jobsInSolution + " #jobsInVrp=" + vrp.getJobs().values().size());
-//// throw new IllegalStateException("solution not valid\n" +
-//// "#jobsInSolution=" + jobsInSolution + " #jobsInVrp=" + vrp.getJobs().values().size());
-// logger.warn("a penalty of 1000 is added for each unassigned customer");
-// penalty = (vrp.getJobs().values().size() - jobsInSolution)*1000.0;
-// logger.warn("penalty = " + penalty);
}
double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
vrpSolution.setCost(totalCost + penalty);
@@ -841,37 +876,37 @@ public class VehicleRoutingAlgorithms {
}
- private static SearchStrategyModule getModule(final String moduleName, final RuinStrategy ruin) {
-
-
- return new SearchStrategyModule() {
-
- private Logger logger = Logger.getLogger(SearchStrategyModule.class);
-
- @Override
- public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
- ruin.ruin(vrpSolution.getRoutes());
- return vrpSolution;
- }
-
- @Override
- public String toString() {
- return "[name="+ruin+"]";
- }
-
- @Override
- public String getName() {
- return moduleName;
- }
-
- @Override
- public void addModuleListener(SearchStrategyModuleListener moduleListener) {
- // TODO Auto-generated method stub
-
- }
-
- };
- }
+// private static SearchStrategyModule getModule(final String moduleName, final RuinStrategy ruin) {
+//
+//
+// return new SearchStrategyModule() {
+//
+// private Logger logger = Logger.getLogger(SearchStrategyModule.class);
+//
+// @Override
+// public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
+// ruin.ruin(vrpSolution.getRoutes());
+// return vrpSolution;
+// }
+//
+// @Override
+// public String toString() {
+// return "[name="+ruin+"]";
+// }
+//
+// @Override
+// public String getName() {
+// return moduleName;
+// }
+//
+// @Override
+// public void addModuleListener(SearchStrategyModuleListener moduleListener) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// };
+// }
diff --git a/jsprit-core/src/main/java/basics/VehicleRoutingProblem.java b/jsprit-core/src/main/java/basics/VehicleRoutingProblem.java
index 79695973..2534d1fa 100644
--- a/jsprit-core/src/main/java/basics/VehicleRoutingProblem.java
+++ b/jsprit-core/src/main/java/basics/VehicleRoutingProblem.java
@@ -242,6 +242,12 @@ public class VehicleRoutingProblem {
return this;
}
+ /**
+ * Sets the neighborhood.
+ *
+ * @param neighborhood
+ * @return
+ */
public Builder setNeighborhood(Neighborhood neighborhood){
this.neighborhood = neighborhood;
return this;
@@ -261,6 +267,13 @@ public class VehicleRoutingProblem {
return this;
}
+ /**
+ * Builds the {@link VehicleRoutingProblem}.
+ *
+ * If {@link VehicleRoutingTransportCosts} are not set, {@link CrowFlyCosts} is used.
+ *
+ * @return {@link VehicleRoutingProblem}
+ */
public VehicleRoutingProblem build() {
log.info("build problem ...");
if(transportCosts == null){
@@ -275,6 +288,12 @@ public class VehicleRoutingProblem {
return this;
}
+ /**
+ * Adds a collection of jobs.
+ *
+ * @param jobs
+ * @return
+ */
public Builder addAllJobs(Collection jobs) {
for(Job j : jobs){
addJob(j);
@@ -282,6 +301,12 @@ public class VehicleRoutingProblem {
return this;
}
+ /**
+ * Adds a collection of vehicles.
+ *
+ * @param vehicles
+ * @return
+ */
public Builder addAllVehicles(Collection vehicles) {
for(Vehicle v : vehicles){
addVehicle(v);
@@ -289,11 +314,20 @@ public class VehicleRoutingProblem {
return this;
}
-
+ /**
+ * Gets an unmodifiable collection of already added vehicles.
+ *
+ * @return collection of vehicles
+ */
public Collection getAddedVehicles(){
return Collections.unmodifiableCollection(vehicles);
}
+ /**
+ * Gets an unmodifiable collection of already added services.
+ *
+ * @return collection of services
+ */
public Collection getAddedServices(){
return Collections.unmodifiableCollection(services);
}
diff --git a/jsprit-core/src/main/resources/algorithm_schema.xsd b/jsprit-core/src/main/resources/algorithm_schema.xsd
index 2140340d..348b07a7 100644
--- a/jsprit-core/src/main/resources/algorithm_schema.xsd
+++ b/jsprit-core/src/main/resources/algorithm_schema.xsd
@@ -135,7 +135,7 @@
-
+
@@ -143,6 +143,13 @@
+
+
+
+
+
+
+
diff --git a/jsprit-core/src/test/java/algorithms/TestAlgorithmReader.java b/jsprit-core/src/test/java/algorithms/TestAlgorithmReader.java
index f9288f40..db93a116 100644
--- a/jsprit-core/src/test/java/algorithms/TestAlgorithmReader.java
+++ b/jsprit-core/src/test/java/algorithms/TestAlgorithmReader.java
@@ -230,43 +230,7 @@ public class TestAlgorithmReader {
for(SearchStrategy strat : algo.getSearchStrategyManager().getStrategies()){
nOfModules += strat.getSearchStrategyModules().size();
}
- assertEquals(6, nOfModules);
- }
-
- @Test
- public void whenCreatingAlgorithm_nOfUniqueInstancesOfInsertionModulesIsCorrect(){
- VehicleRoutingAlgorithm algo = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, config);
- int nOfBestInsertions = 0;
- Set uniqueStrategies = new HashSet();
- for(SearchStrategy strat : algo.getSearchStrategyManager().getStrategies()){
- for(SearchStrategyModule module : strat.getSearchStrategyModules()){
- if(module.getName().equals("bestInsertion")){
- nOfBestInsertions++;
- uniqueStrategies.add(module);
- }
- }
-
- }
- assertEquals(3, nOfBestInsertions);
- assertEquals(2, uniqueStrategies.size());
- }
-
- @Test
- public void whenCreatingAlgorithm_nOfUniqueInstancesOfRuinModulesIsCorrect(){
- VehicleRoutingAlgorithm algo = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, config);
- int nOfRuinModules = 0;
- Set uniqueStrategies = new HashSet();
- for(SearchStrategy strat : algo.getSearchStrategyManager().getStrategies()){
- for(SearchStrategyModule module : strat.getSearchStrategyModules()){
- if(module.getName().endsWith("Ruin")){
- nOfRuinModules++;
- uniqueStrategies.add(module);
- }
- }
-
- }
- assertEquals(3, nOfRuinModules);
- assertEquals(2, uniqueStrategies.size());
+ assertEquals(3, nOfModules);
}
@Test
diff --git a/jsprit-core/src/test/resources/testConfig.xml b/jsprit-core/src/test/resources/testConfig.xml
index 149aeb5c..4b5cb4e0 100755
--- a/jsprit-core/src/test/resources/testConfig.xml
+++ b/jsprit-core/src/test/resources/testConfig.xml
@@ -34,11 +34,12 @@
-
- 0.5
+
+
+ 0.5
+
+
-
-
0.4
@@ -47,10 +48,12 @@
-
- 0.1
+
+
+ 0.1
+
+
-
0.4
@@ -59,11 +62,12 @@
-
- 0.3
- euclid
+
+
+ 0.3
+
+
-
0.2