mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
comply with .editorconfig
This commit is contained in:
parent
58afc3590d
commit
33075b479f
416 changed files with 29653 additions and 29979 deletions
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
|
|
@ -35,32 +35,32 @@ import java.util.List;
|
|||
|
||||
public final class InsertionInitialSolutionFactory implements InitialSolutionFactory {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(InsertionInitialSolutionFactory.class);
|
||||
private static final Logger logger = LogManager.getLogger(InsertionInitialSolutionFactory.class);
|
||||
|
||||
private final InsertionStrategy insertion;
|
||||
private final InsertionStrategy insertion;
|
||||
|
||||
private SolutionCostCalculator solutionCostsCalculator;
|
||||
private SolutionCostCalculator solutionCostsCalculator;
|
||||
|
||||
public InsertionInitialSolutionFactory(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) {
|
||||
super();
|
||||
this.insertion = insertionStrategy;
|
||||
this.solutionCostsCalculator = solutionCostCalculator;
|
||||
}
|
||||
public InsertionInitialSolutionFactory(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) {
|
||||
super();
|
||||
this.insertion = insertionStrategy;
|
||||
this.solutionCostsCalculator = solutionCostCalculator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VehicleRoutingProblemSolution createSolution(final VehicleRoutingProblem vrp) {
|
||||
logger.info("create initial solution");
|
||||
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
|
||||
vehicleRoutes.addAll(vrp.getInitialVehicleRoutes());
|
||||
Collection<Job> badJobs = insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
|
||||
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, badJobs, Double.MAX_VALUE);
|
||||
double costs = solutionCostsCalculator.getCosts(solution);
|
||||
solution.setCost(costs);
|
||||
return solution;
|
||||
}
|
||||
@Override
|
||||
public VehicleRoutingProblemSolution createSolution(final VehicleRoutingProblem vrp) {
|
||||
logger.info("create initial solution");
|
||||
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
|
||||
vehicleRoutes.addAll(vrp.getInitialVehicleRoutes());
|
||||
Collection<Job> badJobs = insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
|
||||
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, badJobs, Double.MAX_VALUE);
|
||||
double costs = solutionCostsCalculator.getCosts(solution);
|
||||
solution.setCost(costs);
|
||||
return solution;
|
||||
}
|
||||
|
||||
private List<Job> getUnassignedJobs(VehicleRoutingProblem vrp) {
|
||||
return new ArrayList<Job>(vrp.getJobs().values());
|
||||
}
|
||||
private List<Job> getUnassignedJobs(VehicleRoutingProblem vrp) {
|
||||
return new ArrayList<Job>(vrp.getJobs().values());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ import jsprit.core.util.ActivityTimeTracker;
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 10.12.14.
|
||||
*/
|
||||
* Created by schroeder on 10.12.14.
|
||||
*/
|
||||
public class PrettyAlgorithmBuilder {
|
||||
|
||||
private final VehicleRoutingProblem vrp;
|
||||
|
|
@ -56,11 +56,11 @@ public class PrettyAlgorithmBuilder {
|
|||
|
||||
private boolean coreStuff = false;
|
||||
|
||||
public static PrettyAlgorithmBuilder newInstance(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager){
|
||||
return new PrettyAlgorithmBuilder(vrp,fleetManager,stateManager,constraintManager);
|
||||
public static PrettyAlgorithmBuilder newInstance(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager) {
|
||||
return new PrettyAlgorithmBuilder(vrp, fleetManager, stateManager, constraintManager);
|
||||
}
|
||||
|
||||
PrettyAlgorithmBuilder(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager){
|
||||
PrettyAlgorithmBuilder(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager) {
|
||||
this.vrp = vrp;
|
||||
this.fleetManager = fleetManager;
|
||||
this.stateManager = stateManager;
|
||||
|
|
@ -68,24 +68,24 @@ public class PrettyAlgorithmBuilder {
|
|||
this.searchStrategyManager = new SearchStrategyManager();
|
||||
}
|
||||
|
||||
public PrettyAlgorithmBuilder setRandom(Random random){
|
||||
public PrettyAlgorithmBuilder setRandom(Random random) {
|
||||
searchStrategyManager.setRandom(random);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PrettyAlgorithmBuilder withStrategy(SearchStrategy strategy, double weight){
|
||||
searchStrategyManager.addStrategy(strategy,weight);
|
||||
public PrettyAlgorithmBuilder withStrategy(SearchStrategy strategy, double weight) {
|
||||
searchStrategyManager.addStrategy(strategy, weight);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PrettyAlgorithmBuilder constructInitialSolutionWith(InsertionStrategy insertionStrategy, SolutionCostCalculator objFunction){
|
||||
public PrettyAlgorithmBuilder constructInitialSolutionWith(InsertionStrategy insertionStrategy, SolutionCostCalculator objFunction) {
|
||||
this.iniInsertionStrategy = insertionStrategy;
|
||||
this.iniObjFunction = objFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VehicleRoutingAlgorithm build(){
|
||||
if(coreStuff){
|
||||
public VehicleRoutingAlgorithm build() {
|
||||
if (coreStuff) {
|
||||
constraintManager.addTimeWindowConstraint();
|
||||
constraintManager.addLoadConstraint();
|
||||
constraintManager.addSkillsConstraint();
|
||||
|
|
@ -94,14 +94,14 @@ public class PrettyAlgorithmBuilder {
|
|||
UpdateVehicleDependentPracticalTimeWindows tw_updater = new UpdateVehicleDependentPracticalTimeWindows(stateManager, vrp.getTransportCosts());
|
||||
tw_updater.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() {
|
||||
|
||||
Map<VehicleTypeKey,Vehicle> uniqueTypes = new HashMap<VehicleTypeKey,Vehicle>();
|
||||
Map<VehicleTypeKey, Vehicle> uniqueTypes = new HashMap<VehicleTypeKey, Vehicle>();
|
||||
|
||||
@Override
|
||||
public Collection<Vehicle> get(VehicleRoute vehicleRoute) {
|
||||
if(uniqueTypes.isEmpty()){
|
||||
for( Vehicle v : vrp.getVehicles()){
|
||||
if(!uniqueTypes.containsKey(v.getVehicleTypeIdentifier())){
|
||||
uniqueTypes.put(v.getVehicleTypeIdentifier(),v);
|
||||
if (uniqueTypes.isEmpty()) {
|
||||
for (Vehicle v : vrp.getVehicles()) {
|
||||
if (!uniqueTypes.containsKey(v.getVehicleTypeIdentifier())) {
|
||||
uniqueTypes.put(v.getVehicleTypeIdentifier(), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -116,7 +116,7 @@ public class PrettyAlgorithmBuilder {
|
|||
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS));
|
||||
stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
|
||||
}
|
||||
VehicleRoutingAlgorithm vra = new VehicleRoutingAlgorithm(vrp,searchStrategyManager);
|
||||
VehicleRoutingAlgorithm vra = new VehicleRoutingAlgorithm(vrp, searchStrategyManager);
|
||||
vra.addListener(stateManager);
|
||||
RemoveEmptyVehicles removeEmptyVehicles = new RemoveEmptyVehicles(fleetManager);
|
||||
ResetAndIniFleetManager resetAndIniFleetManager = new ResetAndIniFleetManager(fleetManager);
|
||||
|
|
@ -124,7 +124,7 @@ public class PrettyAlgorithmBuilder {
|
|||
vra.addListener(removeEmptyVehicles);
|
||||
vra.addListener(resetAndIniFleetManager);
|
||||
vra.addListener(vehicleSwitched);
|
||||
if(iniInsertionStrategy != null) {
|
||||
if (iniInsertionStrategy != null) {
|
||||
if (!iniInsertionStrategy.getListeners().contains(removeEmptyVehicles))
|
||||
iniInsertionStrategy.addListener(removeEmptyVehicles);
|
||||
if (!iniInsertionStrategy.getListeners().contains(resetAndIniFleetManager))
|
||||
|
|
@ -150,10 +150,10 @@ public class PrettyAlgorithmBuilder {
|
|||
|
||||
private void searchSchrimpfAndRegister(VehicleRoutingAlgorithm vra) {
|
||||
boolean schrimpfAdded = false;
|
||||
for(SearchStrategy strategy : vra.getSearchStrategyManager().getStrategies()){
|
||||
for (SearchStrategy strategy : vra.getSearchStrategyManager().getStrategies()) {
|
||||
SolutionAcceptor acceptor = strategy.getSolutionAcceptor();
|
||||
if(acceptor instanceof SchrimpfAcceptance){
|
||||
if(!schrimpfAdded) {
|
||||
if (acceptor instanceof SchrimpfAcceptance) {
|
||||
if (!schrimpfAdded) {
|
||||
vra.addListener((SchrimpfAcceptance) acceptor);
|
||||
schrimpfAdded = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm;
|
||||
|
|
@ -25,28 +25,28 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
public class RemoveEmptyVehicles implements InsertionEndsListener{
|
||||
public class RemoveEmptyVehicles implements InsertionEndsListener {
|
||||
|
||||
private VehicleFleetManager fleetManager;
|
||||
|
||||
public RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
|
||||
super();
|
||||
this.fleetManager = fleetManager;
|
||||
}
|
||||
private VehicleFleetManager fleetManager;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=removeEmptyVehicles]";
|
||||
}
|
||||
public RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
|
||||
super();
|
||||
this.fleetManager = fleetManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
||||
List<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
||||
for(VehicleRoute route : routes){
|
||||
if(route.isEmpty()) {
|
||||
fleetManager.unlock(route.getVehicle());
|
||||
vehicleRoutes.remove(route);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=removeEmptyVehicles]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
||||
List<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
||||
for (VehicleRoute route : routes) {
|
||||
if (route.isEmpty()) {
|
||||
fleetManager.unlock(route.getVehicle());
|
||||
vehicleRoutes.remove(route);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm;
|
||||
|
|
@ -25,26 +25,26 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
public class ResetAndIniFleetManager implements InsertionStartsListener{
|
||||
public class ResetAndIniFleetManager implements InsertionStartsListener {
|
||||
|
||||
private VehicleFleetManager vehicleFleetManager;
|
||||
|
||||
public ResetAndIniFleetManager(VehicleFleetManager vehicleFleetManager) {
|
||||
super();
|
||||
this.vehicleFleetManager = vehicleFleetManager;
|
||||
}
|
||||
private VehicleFleetManager vehicleFleetManager;
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
vehicleFleetManager.unlockAll();
|
||||
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
||||
for(VehicleRoute route : routes){
|
||||
vehicleFleetManager.lock(route.getVehicle());
|
||||
}
|
||||
}
|
||||
public ResetAndIniFleetManager(VehicleFleetManager vehicleFleetManager) {
|
||||
super();
|
||||
this.vehicleFleetManager = vehicleFleetManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=resetAndIniFleetManager]";
|
||||
}
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
vehicleFleetManager.unlockAll();
|
||||
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
||||
for (VehicleRoute route : routes) {
|
||||
vehicleFleetManager.lock(route.getVehicle());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=resetAndIniFleetManager]";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm;
|
||||
|
|
@ -31,59 +31,61 @@ import java.util.Collections;
|
|||
|
||||
|
||||
public class SearchStrategy {
|
||||
|
||||
public static class DiscoveredSolution {
|
||||
|
||||
private VehicleRoutingProblemSolution solution;
|
||||
public static class DiscoveredSolution {
|
||||
|
||||
private boolean accepted;
|
||||
private VehicleRoutingProblemSolution solution;
|
||||
|
||||
private String strategyId;
|
||||
|
||||
public DiscoveredSolution(VehicleRoutingProblemSolution solution, boolean accepted, String strategyId) {
|
||||
super();
|
||||
this.solution = solution;
|
||||
this.accepted = accepted;
|
||||
this.strategyId = strategyId;
|
||||
}
|
||||
private boolean accepted;
|
||||
|
||||
public VehicleRoutingProblemSolution getSolution() {
|
||||
return solution;
|
||||
}
|
||||
private String strategyId;
|
||||
|
||||
public boolean isAccepted() {
|
||||
return accepted;
|
||||
}
|
||||
public DiscoveredSolution(VehicleRoutingProblemSolution solution, boolean accepted, String strategyId) {
|
||||
super();
|
||||
this.solution = solution;
|
||||
this.accepted = accepted;
|
||||
this.strategyId = strategyId;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public VehicleRoutingProblemSolution getSolution() {
|
||||
return solution;
|
||||
}
|
||||
|
||||
public boolean isAccepted() {
|
||||
return accepted;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getStrategyName() {
|
||||
return strategyId;
|
||||
}
|
||||
return strategyId;
|
||||
}
|
||||
|
||||
public String getStrategyId() { return strategyId; }
|
||||
public String getStrategyId() {
|
||||
return strategyId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[strategyId="+strategyId+"][solution="+solution+"][accepted="+accepted+"]";
|
||||
}
|
||||
}
|
||||
|
||||
private static Logger logger = LogManager.getLogger(SearchStrategy.class);
|
||||
|
||||
private final Collection<SearchStrategyModule> searchStrategyModules = new ArrayList<SearchStrategyModule>();
|
||||
|
||||
private final SolutionSelector solutionSelector;
|
||||
|
||||
private final SolutionCostCalculator solutionCostCalculator;
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[strategyId=" + strategyId + "][solution=" + solution + "][accepted=" + accepted + "]";
|
||||
}
|
||||
}
|
||||
|
||||
private final SolutionAcceptor solutionAcceptor;
|
||||
private static Logger logger = LogManager.getLogger(SearchStrategy.class);
|
||||
|
||||
private final Collection<SearchStrategyModule> searchStrategyModules = new ArrayList<SearchStrategyModule>();
|
||||
|
||||
private final SolutionSelector solutionSelector;
|
||||
|
||||
private final SolutionCostCalculator solutionCostCalculator;
|
||||
|
||||
private final SolutionAcceptor solutionAcceptor;
|
||||
|
||||
private final String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String name;
|
||||
|
||||
public SearchStrategy(String id, SolutionSelector solutionSelector, SolutionAcceptor solutionAcceptor, SolutionCostCalculator solutionCostCalculator) {
|
||||
if(id == null) throw new IllegalStateException("strategy id cannot be null");
|
||||
if (id == null) throw new IllegalStateException("strategy id cannot be null");
|
||||
this.solutionSelector = solutionSelector;
|
||||
this.solutionAcceptor = solutionAcceptor;
|
||||
this.solutionCostCalculator = solutionCostCalculator;
|
||||
|
|
@ -96,77 +98,77 @@ public class SearchStrategy {
|
|||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Collection<SearchStrategyModule> getSearchStrategyModules() {
|
||||
return Collections.unmodifiableCollection(searchStrategyModules);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public SolutionSelector getSolutionSelector() {
|
||||
return solutionSelector;
|
||||
}
|
||||
public Collection<SearchStrategyModule> getSearchStrategyModules() {
|
||||
return Collections.unmodifiableCollection(searchStrategyModules);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public SolutionAcceptor getSolutionAcceptor() {
|
||||
return solutionAcceptor;
|
||||
}
|
||||
public SolutionSelector getSolutionSelector() {
|
||||
return solutionSelector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "searchStrategy [#modules="+searchStrategyModules.size()+"][selector="+solutionSelector+"][acceptor="+solutionAcceptor+"]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the search-strategy and its according modules, and returns DiscoveredSolution.
|
||||
*
|
||||
* <p>This involves three basic steps: 1) Selecting a solution from solutions (input parameter) according to {@link jsprit.core.algorithm.selector.SolutionSelector}, 2) running the modules
|
||||
* ({@link jsprit.core.algorithm.SearchStrategyModule}) on the selectedSolution and 3) accepting the new solution according to {@link jsprit.core.algorithm.acceptor.SolutionAcceptor}.
|
||||
* <p> Note that after 1) the selected solution is copied, thus the original solution is not modified.
|
||||
* <p> Note also that 3) modifies the input parameter solutions by adding, removing, replacing the existing solutions or whatever is defined in the solutionAcceptor.
|
||||
*
|
||||
* @param vrp the underlying vehicle routing problem
|
||||
* @param solutions which will be modified
|
||||
* @return discoveredSolution
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public SolutionAcceptor getSolutionAcceptor() {
|
||||
return solutionAcceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "searchStrategy [#modules=" + searchStrategyModules.size() + "][selector=" + solutionSelector + "][acceptor=" + solutionAcceptor + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the search-strategy and its according modules, and returns DiscoveredSolution.
|
||||
* <p/>
|
||||
* <p>This involves three basic steps: 1) Selecting a solution from solutions (input parameter) according to {@link jsprit.core.algorithm.selector.SolutionSelector}, 2) running the modules
|
||||
* ({@link jsprit.core.algorithm.SearchStrategyModule}) on the selectedSolution and 3) accepting the new solution according to {@link jsprit.core.algorithm.acceptor.SolutionAcceptor}.
|
||||
* <p> Note that after 1) the selected solution is copied, thus the original solution is not modified.
|
||||
* <p> Note also that 3) modifies the input parameter solutions by adding, removing, replacing the existing solutions or whatever is defined in the solutionAcceptor.
|
||||
*
|
||||
* @param vrp the underlying vehicle routing problem
|
||||
* @param solutions which will be modified
|
||||
* @return discoveredSolution
|
||||
* @throws java.lang.IllegalStateException if selector cannot select any solution
|
||||
*/
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
public DiscoveredSolution run(VehicleRoutingProblem vrp, Collection<VehicleRoutingProblemSolution> solutions){
|
||||
VehicleRoutingProblemSolution solution = solutionSelector.selectSolution(solutions);
|
||||
if(solution == null) throw new IllegalStateException(getErrMsg());
|
||||
VehicleRoutingProblemSolution lastSolution = VehicleRoutingProblemSolution.copyOf(solution);
|
||||
for(SearchStrategyModule module : searchStrategyModules){
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
public DiscoveredSolution run(VehicleRoutingProblem vrp, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
VehicleRoutingProblemSolution solution = solutionSelector.selectSolution(solutions);
|
||||
if (solution == null) throw new IllegalStateException(getErrMsg());
|
||||
VehicleRoutingProblemSolution lastSolution = VehicleRoutingProblemSolution.copyOf(solution);
|
||||
for (SearchStrategyModule module : searchStrategyModules) {
|
||||
lastSolution = module.runAndGetSolution(lastSolution);
|
||||
}
|
||||
double costs = solutionCostCalculator.getCosts(lastSolution);
|
||||
lastSolution.setCost(costs);
|
||||
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
|
||||
return new DiscoveredSolution(lastSolution, solutionAccepted, getId());
|
||||
}
|
||||
}
|
||||
double costs = solutionCostCalculator.getCosts(lastSolution);
|
||||
lastSolution.setCost(costs);
|
||||
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
|
||||
return new DiscoveredSolution(lastSolution, solutionAccepted, getId());
|
||||
}
|
||||
|
||||
private String getErrMsg() {
|
||||
return "solution is null. check solutionSelector to return an appropriate solution. " +
|
||||
"\nfigure out whether you start with an initial solution. either you set it manually by algorithm.addInitialSolution(...)"
|
||||
+ " or let the algorithm create an initial solution for you. then add the <construction>...</construction> xml-snippet to your algorithm's config file.";
|
||||
"\nfigure out whether you start with an initial solution. either you set it manually by algorithm.addInitialSolution(...)"
|
||||
+ " or let the algorithm create an initial solution for you. then add the <construction>...</construction> xml-snippet to your algorithm's config file.";
|
||||
}
|
||||
|
||||
|
||||
public void addModule(SearchStrategyModule module){
|
||||
if(module == null) throw new IllegalStateException("module to be added is null.");
|
||||
searchStrategyModules.add(module);
|
||||
logger.debug("module added [module={}][#modules={}]", module, searchStrategyModules.size());
|
||||
}
|
||||
public void addModule(SearchStrategyModule module) {
|
||||
if (module == null) throw new IllegalStateException("module to be added is null.");
|
||||
searchStrategyModules.add(module);
|
||||
logger.debug("module added [module={}][#modules={}]", module, searchStrategyModules.size());
|
||||
}
|
||||
|
||||
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
|
||||
for(SearchStrategyModule module : searchStrategyModules){
|
||||
module.addModuleListener(moduleListener);
|
||||
}
|
||||
|
||||
}
|
||||
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
|
||||
for (SearchStrategyModule module : searchStrategyModules) {
|
||||
module.addModuleListener(moduleListener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm;
|
||||
|
|
@ -27,71 +27,75 @@ import java.util.*;
|
|||
|
||||
public class SearchStrategyManager {
|
||||
|
||||
private final static Logger logger = LogManager.getLogger();
|
||||
|
||||
private List<SearchStrategyListener> searchStrategyListeners = new ArrayList<SearchStrategyListener>();
|
||||
|
||||
private List<SearchStrategy> strategies = new ArrayList<SearchStrategy>();
|
||||
|
||||
private List<Double> weights = new ArrayList<Double>();
|
||||
private final static Logger logger = LogManager.getLogger();
|
||||
|
||||
private Map<String, Integer> id2index = new HashMap<String,Integer>();
|
||||
|
||||
private Random random = RandomNumberGeneration.getRandom();
|
||||
|
||||
private double sumWeights = 0;
|
||||
private List<SearchStrategyListener> searchStrategyListeners = new ArrayList<SearchStrategyListener>();
|
||||
|
||||
private List<SearchStrategy> strategies = new ArrayList<SearchStrategy>();
|
||||
|
||||
private List<Double> weights = new ArrayList<Double>();
|
||||
|
||||
private Map<String, Integer> id2index = new HashMap<String, Integer>();
|
||||
|
||||
private Random random = RandomNumberGeneration.getRandom();
|
||||
|
||||
private double sumWeights = 0;
|
||||
|
||||
private int strategyIndex = 0;
|
||||
|
||||
public void setRandom(Random random) {
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
public List<SearchStrategy> getStrategies() {
|
||||
return Collections.unmodifiableList(strategies);
|
||||
}
|
||||
|
||||
public void setRandom(Random random) {
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
public List<SearchStrategy> getStrategies() {
|
||||
return Collections.unmodifiableList(strategies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the probabilities.
|
||||
* [schroeder (2014.11.21): Now they are actually no propabilities anymore but weights. The resulting probabilities
|
||||
* are calculated here with the sum of weights]
|
||||
*
|
||||
* @return list of probabilities
|
||||
*/
|
||||
@Deprecated
|
||||
public List<Double> getProbabilities() {
|
||||
return Collections.unmodifiableList(weights);
|
||||
}
|
||||
@Deprecated
|
||||
public List<Double> getProbabilities() {
|
||||
return Collections.unmodifiableList(weights);
|
||||
}
|
||||
|
||||
public List<Double> getWeights(){ return Collections.unmodifiableList(weights); }
|
||||
public List<Double> getWeights() {
|
||||
return Collections.unmodifiableList(weights);
|
||||
}
|
||||
|
||||
public double getWeight(String strategyId){
|
||||
return weights.get(id2index.get(strategyId));
|
||||
}
|
||||
public double getWeight(String strategyId) {
|
||||
return weights.get(id2index.get(strategyId));
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a new search strategy with a certain weight.
|
||||
* @param strategy strategy to be added
|
||||
* @param weight of corresponding strategy to be added
|
||||
/**
|
||||
* adds a new search strategy with a certain weight.
|
||||
*
|
||||
* @param strategy strategy to be added
|
||||
* @param weight of corresponding strategy to be added
|
||||
* @throws java.lang.IllegalStateException if strategy is null OR weight < 0
|
||||
*/
|
||||
public void addStrategy(SearchStrategy strategy, double weight){
|
||||
if(strategy == null){
|
||||
*/
|
||||
public void addStrategy(SearchStrategy strategy, double weight) {
|
||||
if (strategy == null) {
|
||||
throw new IllegalStateException("strategy is null. make sure adding a valid strategy.");
|
||||
}
|
||||
if(id2index.keySet().contains(strategy.getId())){
|
||||
if (id2index.keySet().contains(strategy.getId())) {
|
||||
throw new IllegalStateException("strategyId " + strategy.getId() + " already in use. replace strateId in your config file or code with a unique strategy id");
|
||||
}
|
||||
if(weight < 0.0){
|
||||
throw new IllegalStateException("weight is lower than zero.");
|
||||
}
|
||||
id2index.put(strategy.getId(),strategyIndex);
|
||||
if (weight < 0.0) {
|
||||
throw new IllegalStateException("weight is lower than zero.");
|
||||
}
|
||||
id2index.put(strategy.getId(), strategyIndex);
|
||||
strategyIndex++;
|
||||
strategies.add(strategy);
|
||||
weights.add(weight);
|
||||
sumWeights += weight;
|
||||
}
|
||||
strategies.add(strategy);
|
||||
weights.add(weight);
|
||||
sumWeights += weight;
|
||||
}
|
||||
|
||||
public void informStrategyWeightChanged(String strategyId, double weight){
|
||||
public void informStrategyWeightChanged(String strategyId, double weight) {
|
||||
int strategyIndex = id2index.get(strategyId);
|
||||
weights.set(strategyIndex, weight);
|
||||
updateSumWeights();
|
||||
|
|
@ -99,7 +103,7 @@ public class SearchStrategyManager {
|
|||
|
||||
private void updateSumWeights() {
|
||||
double sum = 0.;
|
||||
for(double w : weights){
|
||||
for (double w : weights) {
|
||||
sum += w;
|
||||
}
|
||||
sumWeights = sum;
|
||||
|
|
@ -111,26 +115,27 @@ public class SearchStrategyManager {
|
|||
* @return selected search strategy
|
||||
* @throws java.lang.IllegalStateException if randomNumberGenerator is null OR no search strategy can be found
|
||||
*/
|
||||
public SearchStrategy getRandomStrategy() {
|
||||
if(random == null) throw new IllegalStateException("randomizer is null. make sure you set random object correctly");
|
||||
double randomFig = random.nextDouble();
|
||||
double sumProbabilities = 0.0;
|
||||
for (int i = 0; i < weights.size(); i++) {
|
||||
sumProbabilities += weights.get(i) / sumWeights;
|
||||
if (randomFig < sumProbabilities) {
|
||||
return strategies.get(i);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("no search-strategy found");
|
||||
}
|
||||
|
||||
public void addSearchStrategyListener(SearchStrategyListener strategyListener){
|
||||
searchStrategyListeners.add(strategyListener);
|
||||
}
|
||||
|
||||
public void addSearchStrategyModuleListener(SearchStrategyModuleListener moduleListener){
|
||||
for(SearchStrategy s : strategies){
|
||||
s.addModuleListener(moduleListener);
|
||||
}
|
||||
}
|
||||
public SearchStrategy getRandomStrategy() {
|
||||
if (random == null)
|
||||
throw new IllegalStateException("randomizer is null. make sure you set random object correctly");
|
||||
double randomFig = random.nextDouble();
|
||||
double sumProbabilities = 0.0;
|
||||
for (int i = 0; i < weights.size(); i++) {
|
||||
sumProbabilities += weights.get(i) / sumWeights;
|
||||
if (randomFig < sumProbabilities) {
|
||||
return strategies.get(i);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("no search-strategy found");
|
||||
}
|
||||
|
||||
public void addSearchStrategyListener(SearchStrategyListener strategyListener) {
|
||||
searchStrategyListeners.add(strategyListener);
|
||||
}
|
||||
|
||||
public void addSearchStrategyModuleListener(SearchStrategyModuleListener moduleListener) {
|
||||
for (SearchStrategy s : strategies) {
|
||||
s.addModuleListener(moduleListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm;
|
||||
|
|
@ -21,11 +21,11 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
|||
|
||||
|
||||
public interface SearchStrategyModule {
|
||||
|
||||
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution);
|
||||
|
||||
public String getName();
|
||||
|
||||
public void addModuleListener(SearchStrategyModuleListener moduleListener);
|
||||
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution);
|
||||
|
||||
public String getName();
|
||||
|
||||
public void addModuleListener(SearchStrategyModuleListener moduleListener);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
|
@ -29,39 +29,38 @@ import jsprit.core.problem.vehicle.Vehicle;
|
|||
* Default objective function which is the sum of all fixed vehicle and variable
|
||||
* transportation costs, i.e. each is generated solution is evaluated according
|
||||
* this objective function.
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public class VariablePlusFixedSolutionCostCalculatorFactory {
|
||||
|
||||
private RouteAndActivityStateGetter stateManager;
|
||||
|
||||
public VariablePlusFixedSolutionCostCalculatorFactory(RouteAndActivityStateGetter stateManager) {
|
||||
super();
|
||||
this.stateManager = stateManager;
|
||||
}
|
||||
|
||||
public SolutionCostCalculator createCalculator(){
|
||||
return new SolutionCostCalculator() {
|
||||
private RouteAndActivityStateGetter stateManager;
|
||||
|
||||
@Override
|
||||
public double getCosts(VehicleRoutingProblemSolution solution) {
|
||||
double c = 0.0;
|
||||
for(VehicleRoute r : solution.getRoutes()){
|
||||
c += stateManager.getRouteState(r, InternalStates.COSTS, Double.class);
|
||||
c += getFixedCosts(r.getVehicle());
|
||||
}
|
||||
public VariablePlusFixedSolutionCostCalculatorFactory(RouteAndActivityStateGetter stateManager) {
|
||||
super();
|
||||
this.stateManager = stateManager;
|
||||
}
|
||||
|
||||
public SolutionCostCalculator createCalculator() {
|
||||
return new SolutionCostCalculator() {
|
||||
|
||||
@Override
|
||||
public double getCosts(VehicleRoutingProblemSolution solution) {
|
||||
double c = 0.0;
|
||||
for (VehicleRoute r : solution.getRoutes()) {
|
||||
c += stateManager.getRouteState(r, InternalStates.COSTS, Double.class);
|
||||
c += getFixedCosts(r.getVehicle());
|
||||
}
|
||||
c += solution.getUnassignedJobs().size() * c * .1;
|
||||
return c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private double getFixedCosts(Vehicle vehicle) {
|
||||
if(vehicle == null) return 0.0;
|
||||
if(vehicle.getType() == null) return 0.0;
|
||||
if (vehicle == null) return 0.0;
|
||||
if (vehicle.getType() == null) return 0.0;
|
||||
return vehicle.getType().getVehicleCostParams().fix;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm;
|
||||
|
|
@ -33,9 +33,8 @@ import java.util.Collection;
|
|||
|
||||
/**
|
||||
* Algorithm that solves a {@link VehicleRoutingProblem}.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*/
|
||||
public class VehicleRoutingAlgorithm {
|
||||
|
||||
|
|
@ -43,14 +42,14 @@ public class VehicleRoutingAlgorithm {
|
|||
|
||||
private Collection<PrematureAlgorithmTermination> terminationCriteria = new ArrayList<PrematureAlgorithmTermination>();
|
||||
|
||||
void addTermination(PrematureAlgorithmTermination termination){
|
||||
void addTermination(PrematureAlgorithmTermination termination) {
|
||||
terminationCriteria.add(termination);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
|
||||
for(PrematureAlgorithmTermination termination : terminationCriteria){
|
||||
if(termination.isPrematureBreak(discoveredSolution)){
|
||||
for (PrematureAlgorithmTermination termination : terminationCriteria) {
|
||||
if (termination.isPrematureBreak(discoveredSolution)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -59,31 +58,31 @@ public class VehicleRoutingAlgorithm {
|
|||
}
|
||||
|
||||
private static class Counter {
|
||||
private final String name;
|
||||
private long counter = 0;
|
||||
private long nextCounter = 1;
|
||||
private static final Logger log = LogManager.getLogger(Counter.class);
|
||||
private final String name;
|
||||
private long counter = 0;
|
||||
private long nextCounter = 1;
|
||||
private static final Logger log = LogManager.getLogger(Counter.class);
|
||||
|
||||
public Counter(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public Counter(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void incCounter() {
|
||||
long i = counter++;
|
||||
long n = nextCounter;
|
||||
if (i >= n) {
|
||||
nextCounter=n*2;
|
||||
public void incCounter() {
|
||||
long i = counter++;
|
||||
long n = nextCounter;
|
||||
if (i >= n) {
|
||||
nextCounter = n * 2;
|
||||
log.info(this.name + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
counter=0;
|
||||
nextCounter=1;
|
||||
}
|
||||
}
|
||||
public void reset() {
|
||||
counter = 0;
|
||||
nextCounter = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private final static Logger logger = LogManager.getLogger();
|
||||
private final static Logger logger = LogManager.getLogger();
|
||||
|
||||
private final Counter counter = new Counter("iterations ");
|
||||
|
||||
|
|
@ -100,63 +99,63 @@ public class VehicleRoutingAlgorithm {
|
|||
private TerminationManager terminationManager = new TerminationManager();
|
||||
|
||||
private VehicleRoutingProblemSolution bestEver = null;
|
||||
|
||||
public VehicleRoutingAlgorithm(VehicleRoutingProblem problem, SearchStrategyManager searchStrategyManager) {
|
||||
super();
|
||||
this.problem = problem;
|
||||
this.searchStrategyManager = searchStrategyManager;
|
||||
initialSolutions = new ArrayList<VehicleRoutingProblemSolution>();
|
||||
}
|
||||
|
||||
public VehicleRoutingAlgorithm(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> initialSolutions, SearchStrategyManager searchStrategyManager) {
|
||||
super();
|
||||
this.problem = problem;
|
||||
this.searchStrategyManager = searchStrategyManager;
|
||||
this.initialSolutions = initialSolutions;
|
||||
}
|
||||
public VehicleRoutingAlgorithm(VehicleRoutingProblem problem, SearchStrategyManager searchStrategyManager) {
|
||||
super();
|
||||
this.problem = problem;
|
||||
this.searchStrategyManager = searchStrategyManager;
|
||||
initialSolutions = new ArrayList<VehicleRoutingProblemSolution>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds solution to the collection of initial solutions.
|
||||
*
|
||||
* @param solution the solution to be added
|
||||
*/
|
||||
public void addInitialSolution(VehicleRoutingProblemSolution solution){
|
||||
public VehicleRoutingAlgorithm(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> initialSolutions, SearchStrategyManager searchStrategyManager) {
|
||||
super();
|
||||
this.problem = problem;
|
||||
this.searchStrategyManager = searchStrategyManager;
|
||||
this.initialSolutions = initialSolutions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds solution to the collection of initial solutions.
|
||||
*
|
||||
* @param solution the solution to be added
|
||||
*/
|
||||
public void addInitialSolution(VehicleRoutingProblemSolution solution) {
|
||||
verify(solution);
|
||||
initialSolutions.add(solution);
|
||||
}
|
||||
}
|
||||
|
||||
private void verify(VehicleRoutingProblemSolution solution) {
|
||||
private void verify(VehicleRoutingProblemSolution solution) {
|
||||
int nuJobs = 0;
|
||||
for(VehicleRoute route : solution.getRoutes()){
|
||||
for (VehicleRoute route : solution.getRoutes()) {
|
||||
nuJobs += route.getTourActivities().getJobs().size();
|
||||
if(route.getVehicle().getIndex() == 0)
|
||||
if (route.getVehicle().getIndex() == 0)
|
||||
throw new IllegalStateException("vehicle used in initial solution has no index. probably a vehicle is used that has not been added to the " +
|
||||
" the VehicleRoutingProblem. only use vehicles that have already been added to the problem.");
|
||||
for(TourActivity act : route.getActivities()) {
|
||||
" the VehicleRoutingProblem. only use vehicles that have already been added to the problem.");
|
||||
for (TourActivity act : route.getActivities()) {
|
||||
if (act.getIndex() == 0) {
|
||||
throw new IllegalStateException("act in initial solution has no index. activities are created and associated to their job in VehicleRoutingProblem\n." +
|
||||
" thus if you build vehicle-routes use the jobActivityFactory from vehicle routing problem like that \n" +
|
||||
" VehicleRoute.Builder.newInstance(knownVehicle).setJobActivityFactory(vrp.getJobActivityFactory).addService(..)....build() \n" +
|
||||
" then the activities that are created to build the route are identical to the ones used in VehicleRoutingProblem");
|
||||
" thus if you build vehicle-routes use the jobActivityFactory from vehicle routing problem like that \n" +
|
||||
" VehicleRoute.Builder.newInstance(knownVehicle).setJobActivityFactory(vrp.getJobActivityFactory).addService(..)....build() \n" +
|
||||
" then the activities that are created to build the route are identical to the ones used in VehicleRoutingProblem");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nuJobs != problem.getJobs().values().size()){
|
||||
if (nuJobs != problem.getJobs().values().size()) {
|
||||
logger.warn("number of jobs in initial solution ({}) is not equal nuJobs in vehicle routing problem ({})" +
|
||||
"\n this might yield unintended effects, e.g. initial solution cannot be improved anymore.", nuJobs, problem.getJobs().values().size() );
|
||||
"\n this might yield unintended effects, e.g. initial solution cannot be improved anymore.", nuJobs, problem.getJobs().values().size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets premature termination and overrides existing termination criteria. If existing ones should not be
|
||||
* Sets premature termination and overrides existing termination criteria. If existing ones should not be
|
||||
* overridden use <code>.addTerminationCriterion(...)</code>.
|
||||
*
|
||||
* @param prematureAlgorithmTermination the termination criterion
|
||||
*/
|
||||
public void setPrematureAlgorithmTermination(PrematureAlgorithmTermination prematureAlgorithmTermination){
|
||||
terminationManager = new TerminationManager();
|
||||
*
|
||||
* @param prematureAlgorithmTermination the termination criterion
|
||||
*/
|
||||
public void setPrematureAlgorithmTermination(PrematureAlgorithmTermination prematureAlgorithmTermination) {
|
||||
terminationManager = new TerminationManager();
|
||||
terminationManager.addTermination(prematureAlgorithmTermination);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a termination criterion to the collection of already specified termination criteria. If one
|
||||
|
|
@ -164,101 +163,104 @@ public class VehicleRoutingAlgorithm {
|
|||
*
|
||||
* @param terminationCriterion the termination criterion
|
||||
*/
|
||||
public void addTerminationCriterion(PrematureAlgorithmTermination terminationCriterion){
|
||||
public void addTerminationCriterion(PrematureAlgorithmTermination terminationCriterion) {
|
||||
terminationManager.addTermination(terminationCriterion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link SearchStrategyManager}.
|
||||
*
|
||||
* @return SearchStrategyManager
|
||||
*/
|
||||
public SearchStrategyManager getSearchStrategyManager() {
|
||||
return searchStrategyManager;
|
||||
}
|
||||
/**
|
||||
* Gets the {@link SearchStrategyManager}.
|
||||
*
|
||||
* @return SearchStrategyManager
|
||||
*/
|
||||
public SearchStrategyManager getSearchStrategyManager() {
|
||||
return searchStrategyManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the vehicle routing algorithm and returns a number of generated solutions.
|
||||
*
|
||||
* <p>The algorithm runs as long as it is specified in nuOfIterations and prematureBreak. In each iteration it selects a searchStrategy according
|
||||
* to searchStrategyManager and runs the strategy to improve solutions.
|
||||
* <p>Note that clients are allowed to observe/listen the algorithm. See {@link VehicleRoutingAlgorithmListener} and its according listeners.
|
||||
*
|
||||
* @return Collection<VehicleRoutingProblemSolution> the solutions
|
||||
* @see {@link SearchStrategyManager}, {@link VehicleRoutingAlgorithmListener}, {@link AlgorithmStartsListener}, {@link AlgorithmEndsListener}, {@link IterationStartsListener}, {@link IterationEndsListener}
|
||||
*/
|
||||
public Collection<VehicleRoutingProblemSolution> searchSolutions(){
|
||||
logger.info("algorithm starts: [maxIterations={}]", maxIterations);
|
||||
double now = System.currentTimeMillis();
|
||||
int noIterationsThisAlgoIsRunning = maxIterations;
|
||||
counter.reset();
|
||||
Collection<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>(initialSolutions);
|
||||
algorithmStarts(problem,solutions);
|
||||
/**
|
||||
* Runs the vehicle routing algorithm and returns a number of generated solutions.
|
||||
* <p/>
|
||||
* <p>The algorithm runs as long as it is specified in nuOfIterations and prematureBreak. In each iteration it selects a searchStrategy according
|
||||
* to searchStrategyManager and runs the strategy to improve solutions.
|
||||
* <p>Note that clients are allowed to observe/listen the algorithm. See {@link VehicleRoutingAlgorithmListener} and its according listeners.
|
||||
*
|
||||
* @return Collection<VehicleRoutingProblemSolution> the solutions
|
||||
* @see {@link SearchStrategyManager}, {@link VehicleRoutingAlgorithmListener}, {@link AlgorithmStartsListener}, {@link AlgorithmEndsListener}, {@link IterationStartsListener}, {@link IterationEndsListener}
|
||||
*/
|
||||
public Collection<VehicleRoutingProblemSolution> searchSolutions() {
|
||||
logger.info("algorithm starts: [maxIterations={}]", maxIterations);
|
||||
double now = System.currentTimeMillis();
|
||||
int noIterationsThisAlgoIsRunning = maxIterations;
|
||||
counter.reset();
|
||||
Collection<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>(initialSolutions);
|
||||
algorithmStarts(problem, solutions);
|
||||
bestEver = Solutions.bestOf(solutions);
|
||||
logger.info("iterations start");
|
||||
for(int i=0;i< maxIterations;i++){
|
||||
iterationStarts(i+1,problem,solutions);
|
||||
logger.debug("start iteration: {}", i);
|
||||
counter.incCounter();
|
||||
SearchStrategy strategy = searchStrategyManager.getRandomStrategy();
|
||||
DiscoveredSolution discoveredSolution = strategy.run(problem, solutions);
|
||||
logger.trace("discovered solution: {}", discoveredSolution);
|
||||
for (int i = 0; i < maxIterations; i++) {
|
||||
iterationStarts(i + 1, problem, solutions);
|
||||
logger.debug("start iteration: {}", i);
|
||||
counter.incCounter();
|
||||
SearchStrategy strategy = searchStrategyManager.getRandomStrategy();
|
||||
DiscoveredSolution discoveredSolution = strategy.run(problem, solutions);
|
||||
logger.trace("discovered solution: {}", discoveredSolution);
|
||||
memorizeIfBestEver(discoveredSolution);
|
||||
selectedStrategy(discoveredSolution,problem,solutions);
|
||||
if(terminationManager.isPrematureBreak(discoveredSolution)){
|
||||
logger.info("premature algorithm termination at iteration {}", (i+1));
|
||||
noIterationsThisAlgoIsRunning = (i+1);
|
||||
break;
|
||||
}
|
||||
iterationEnds(i+1,problem,solutions);
|
||||
}
|
||||
logger.info("iterations end at {} iterations", noIterationsThisAlgoIsRunning);
|
||||
addBestEver(solutions);
|
||||
selectedStrategy(discoveredSolution, problem, solutions);
|
||||
if (terminationManager.isPrematureBreak(discoveredSolution)) {
|
||||
logger.info("premature algorithm termination at iteration {}", (i + 1));
|
||||
noIterationsThisAlgoIsRunning = (i + 1);
|
||||
break;
|
||||
}
|
||||
iterationEnds(i + 1, problem, solutions);
|
||||
}
|
||||
logger.info("iterations end at {} iterations", noIterationsThisAlgoIsRunning);
|
||||
addBestEver(solutions);
|
||||
algorithmEnds(problem, solutions);
|
||||
logger.info("took {} seconds", ((System.currentTimeMillis()-now)/1000.0));
|
||||
return solutions;
|
||||
}
|
||||
logger.info("took {} seconds", ((System.currentTimeMillis() - now) / 1000.0));
|
||||
return solutions;
|
||||
}
|
||||
|
||||
private void addBestEver(Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
if(bestEver != null) solutions.add(bestEver);
|
||||
if (bestEver != null) solutions.add(bestEver);
|
||||
}
|
||||
|
||||
private void memorizeIfBestEver(DiscoveredSolution discoveredSolution) {
|
||||
if(discoveredSolution == null) return;
|
||||
if(bestEver == null) bestEver = discoveredSolution.getSolution();
|
||||
else if(discoveredSolution.getSolution().getCost() < bestEver.getCost()) bestEver = discoveredSolution.getSolution();
|
||||
if (discoveredSolution == null) return;
|
||||
if (bestEver == null) bestEver = discoveredSolution.getSolution();
|
||||
else if (discoveredSolution.getSolution().getCost() < bestEver.getCost())
|
||||
bestEver = discoveredSolution.getSolution();
|
||||
}
|
||||
|
||||
|
||||
private void selectedStrategy(DiscoveredSolution discoveredSolution, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.selectedStrategy(discoveredSolution,problem,solutions);
|
||||
}
|
||||
algoListeners.selectedStrategy(discoveredSolution, problem, solutions);
|
||||
}
|
||||
|
||||
private void algorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.algorithmEnds(problem, solutions);
|
||||
}
|
||||
private void algorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.algorithmEnds(problem, solutions);
|
||||
}
|
||||
|
||||
public VehicleRoutingAlgorithmListeners getAlgorithmListeners() {
|
||||
return algoListeners;
|
||||
}
|
||||
|
||||
public void addListener(VehicleRoutingAlgorithmListener l){
|
||||
algoListeners.addListener(l);
|
||||
if(l instanceof SearchStrategyListener) searchStrategyManager.addSearchStrategyListener((SearchStrategyListener) l);
|
||||
if(l instanceof SearchStrategyModuleListener) searchStrategyManager.addSearchStrategyModuleListener((SearchStrategyModuleListener) l);
|
||||
}
|
||||
public VehicleRoutingAlgorithmListeners getAlgorithmListeners() {
|
||||
return algoListeners;
|
||||
}
|
||||
|
||||
private void iterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.iterationEnds(i,problem, solutions);
|
||||
}
|
||||
public void addListener(VehicleRoutingAlgorithmListener l) {
|
||||
algoListeners.addListener(l);
|
||||
if (l instanceof SearchStrategyListener)
|
||||
searchStrategyManager.addSearchStrategyListener((SearchStrategyListener) l);
|
||||
if (l instanceof SearchStrategyModuleListener)
|
||||
searchStrategyManager.addSearchStrategyModuleListener((SearchStrategyModuleListener) l);
|
||||
}
|
||||
|
||||
private void iterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.iterationStarts(i, problem, solutions);
|
||||
}
|
||||
private void iterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.iterationEnds(i, problem, solutions);
|
||||
}
|
||||
|
||||
private void algorithmStarts(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.algorithmStarts(problem, this, solutions);
|
||||
}
|
||||
private void iterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.iterationStarts(i, problem, solutions);
|
||||
}
|
||||
|
||||
private void algorithmStarts(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
algoListeners.algorithmStarts(problem, this, solutions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets max number of iterations.
|
||||
|
|
|
|||
|
|
@ -27,153 +27,151 @@ import jsprit.core.problem.solution.SolutionCostCalculator;
|
|||
|
||||
/**
|
||||
* Builder that builds a {@link VehicleRoutingAlgorithm}.
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public class VehicleRoutingAlgorithmBuilder {
|
||||
|
||||
private String algorithmConfigFile;
|
||||
|
||||
private AlgorithmConfig algorithmConfig;
|
||||
|
||||
private final VehicleRoutingProblem vrp;
|
||||
private String algorithmConfigFile;
|
||||
|
||||
private SolutionCostCalculator solutionCostCalculator;
|
||||
private AlgorithmConfig algorithmConfig;
|
||||
|
||||
private StateManager stateManager;
|
||||
|
||||
private boolean addCoreConstraints = false;
|
||||
|
||||
private boolean addDefaultCostCalculators = false;
|
||||
private final VehicleRoutingProblem vrp;
|
||||
|
||||
private ConstraintManager constraintManager;
|
||||
private SolutionCostCalculator solutionCostCalculator;
|
||||
|
||||
private int nuOfThreads=0;
|
||||
|
||||
/**
|
||||
* Constructs the builder with the problem and an algorithmConfigFile. Latter is to configure and specify the ruin-and-recreate meta-heuristic.
|
||||
*
|
||||
* @param problem to solve
|
||||
* @param algorithmConfig config file of VehicleRoutingAlgorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithmBuilder(VehicleRoutingProblem problem, String algorithmConfig) {
|
||||
this.vrp=problem;
|
||||
this.algorithmConfigFile=algorithmConfig;
|
||||
this.algorithmConfig=null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the builder with the problem and an algorithmConfig. Latter is to configure and specify the ruin-and-recreate meta-heuristic.
|
||||
*
|
||||
* @param problem to solve
|
||||
private StateManager stateManager;
|
||||
|
||||
private boolean addCoreConstraints = false;
|
||||
|
||||
private boolean addDefaultCostCalculators = false;
|
||||
|
||||
private ConstraintManager constraintManager;
|
||||
|
||||
private int nuOfThreads = 0;
|
||||
|
||||
/**
|
||||
* Constructs the builder with the problem and an algorithmConfigFile. Latter is to configure and specify the ruin-and-recreate meta-heuristic.
|
||||
*
|
||||
* @param problem to solve
|
||||
* @param algorithmConfig config file of VehicleRoutingAlgorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithmBuilder(VehicleRoutingProblem problem, AlgorithmConfig algorithmConfig) {
|
||||
this.vrp=problem;
|
||||
this.algorithmConfigFile=null;
|
||||
this.algorithmConfig=algorithmConfig;
|
||||
}
|
||||
*/
|
||||
public VehicleRoutingAlgorithmBuilder(VehicleRoutingProblem problem, String algorithmConfig) {
|
||||
this.vrp = problem;
|
||||
this.algorithmConfigFile = algorithmConfig;
|
||||
this.algorithmConfig = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets custom objective function.
|
||||
*
|
||||
* <p>If objective function is not set, a default function is applied (which basically minimizes
|
||||
* fixed and variable transportation costs ({@link VariablePlusFixedSolutionCostCalculatorFactory}).
|
||||
*
|
||||
* @param objectiveFunction to be minimized
|
||||
* @see VariablePlusFixedSolutionCostCalculatorFactory
|
||||
*/
|
||||
public void setObjectiveFunction(SolutionCostCalculator objectiveFunction) {
|
||||
this.solutionCostCalculator = objectiveFunction;
|
||||
}
|
||||
/**
|
||||
* Constructs the builder with the problem and an algorithmConfig. Latter is to configure and specify the ruin-and-recreate meta-heuristic.
|
||||
*
|
||||
* @param problem to solve
|
||||
* @param algorithmConfig config file of VehicleRoutingAlgorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithmBuilder(VehicleRoutingProblem problem, AlgorithmConfig algorithmConfig) {
|
||||
this.vrp = problem;
|
||||
this.algorithmConfigFile = null;
|
||||
this.algorithmConfig = algorithmConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets stateManager to memorize states.
|
||||
*
|
||||
* @param stateManager that memorizes your states
|
||||
* @see StateManager
|
||||
*/
|
||||
public void setStateManager(StateManager stateManager) {
|
||||
this.stateManager=stateManager;
|
||||
}
|
||||
/**
|
||||
* Sets custom objective function.
|
||||
* <p/>
|
||||
* <p>If objective function is not set, a default function is applied (which basically minimizes
|
||||
* fixed and variable transportation costs ({@link VariablePlusFixedSolutionCostCalculatorFactory}).
|
||||
*
|
||||
* @param objectiveFunction to be minimized
|
||||
* @see VariablePlusFixedSolutionCostCalculatorFactory
|
||||
*/
|
||||
public void setObjectiveFunction(SolutionCostCalculator objectiveFunction) {
|
||||
this.solutionCostCalculator = objectiveFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds core constraints.
|
||||
*
|
||||
* <p>Thus, it adds vehicle-capacity, time-window and skills constraints and their
|
||||
* required stateUpdater.
|
||||
*
|
||||
*/
|
||||
public void addCoreConstraints() {
|
||||
addCoreConstraints=true;
|
||||
}
|
||||
/**
|
||||
* Sets stateManager to memorize states.
|
||||
*
|
||||
* @param stateManager that memorizes your states
|
||||
* @see StateManager
|
||||
*/
|
||||
public void setStateManager(StateManager stateManager) {
|
||||
this.stateManager = stateManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds default cost calculators used by the insertion heuristic,
|
||||
* to calculate activity insertion costs.
|
||||
* By default, marginal transportation costs are calculated. Thus when inserting
|
||||
* act_k between act_i and act_j, marginal (additional) transportation costs
|
||||
* are basically c(act_i,act_k)+c(act_k,act_j)-c(act_i,act_j).
|
||||
*
|
||||
* <p>Do not use this method, if you plan to control the insertion heuristic
|
||||
* entirely via hard- and soft-constraints.
|
||||
*/
|
||||
public void addDefaultCostCalculators() {
|
||||
addDefaultCostCalculators=true;
|
||||
}
|
||||
/**
|
||||
* Adds core constraints.
|
||||
* <p/>
|
||||
* <p>Thus, it adds vehicle-capacity, time-window and skills constraints and their
|
||||
* required stateUpdater.
|
||||
*/
|
||||
public void addCoreConstraints() {
|
||||
addCoreConstraints = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets state- and constraintManager.
|
||||
*
|
||||
* @param stateManager that memorizes your states
|
||||
* @param constraintManager that manages your constraints
|
||||
* @see StateManager
|
||||
* @see ConstraintManager
|
||||
*/
|
||||
public void setStateAndConstraintManager(StateManager stateManager, ConstraintManager constraintManager) {
|
||||
this.stateManager=stateManager;
|
||||
this.constraintManager=constraintManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets nuOfThreads.
|
||||
*
|
||||
* @param nuOfThreads to be operated
|
||||
*/
|
||||
public void setNuOfThreads(int nuOfThreads){
|
||||
this.nuOfThreads=nuOfThreads;
|
||||
}
|
||||
/**
|
||||
* Adds default cost calculators used by the insertion heuristic,
|
||||
* to calculate activity insertion costs.
|
||||
* By default, marginal transportation costs are calculated. Thus when inserting
|
||||
* act_k between act_i and act_j, marginal (additional) transportation costs
|
||||
* are basically c(act_i,act_k)+c(act_k,act_j)-c(act_i,act_j).
|
||||
* <p/>
|
||||
* <p>Do not use this method, if you plan to control the insertion heuristic
|
||||
* entirely via hard- and soft-constraints.
|
||||
*/
|
||||
public void addDefaultCostCalculators() {
|
||||
addDefaultCostCalculators = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns the algorithm.
|
||||
*
|
||||
* <p>If algorithmConfigFile is set, it reads the configuration.
|
||||
*
|
||||
* @return the algorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithm build() {
|
||||
if(stateManager == null) stateManager = new StateManager(vrp);
|
||||
if(constraintManager == null) constraintManager = new ConstraintManager(vrp,stateManager);
|
||||
//add core updater
|
||||
stateManager.addStateUpdater(new UpdateEndLocationIfRouteIsOpen());
|
||||
/**
|
||||
* Sets state- and constraintManager.
|
||||
*
|
||||
* @param stateManager that memorizes your states
|
||||
* @param constraintManager that manages your constraints
|
||||
* @see StateManager
|
||||
* @see ConstraintManager
|
||||
*/
|
||||
public void setStateAndConstraintManager(StateManager stateManager, ConstraintManager constraintManager) {
|
||||
this.stateManager = stateManager;
|
||||
this.constraintManager = constraintManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets nuOfThreads.
|
||||
*
|
||||
* @param nuOfThreads to be operated
|
||||
*/
|
||||
public void setNuOfThreads(int nuOfThreads) {
|
||||
this.nuOfThreads = nuOfThreads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns the algorithm.
|
||||
* <p/>
|
||||
* <p>If algorithmConfigFile is set, it reads the configuration.
|
||||
*
|
||||
* @return the algorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithm build() {
|
||||
if (stateManager == null) stateManager = new StateManager(vrp);
|
||||
if (constraintManager == null) constraintManager = new ConstraintManager(vrp, stateManager);
|
||||
//add core updater
|
||||
stateManager.addStateUpdater(new UpdateEndLocationIfRouteIsOpen());
|
||||
// stateManager.addStateUpdater(new OpenRouteStateVerifier());
|
||||
|
||||
if(addCoreConstraints){
|
||||
constraintManager.addLoadConstraint();
|
||||
constraintManager.addTimeWindowConstraint();
|
||||
constraintManager.addSkillsConstraint();
|
||||
if (addCoreConstraints) {
|
||||
constraintManager.addLoadConstraint();
|
||||
constraintManager.addTimeWindowConstraint();
|
||||
constraintManager.addSkillsConstraint();
|
||||
stateManager.updateLoadStates();
|
||||
stateManager.updateTimeWindowStates();
|
||||
stateManager.updateTimeWindowStates();
|
||||
stateManager.updateSkillStates();
|
||||
}
|
||||
if(algorithmConfig==null){
|
||||
algorithmConfig = new AlgorithmConfig();
|
||||
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
|
||||
xmlReader.read(algorithmConfigFile);
|
||||
}
|
||||
return VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, algorithmConfig, nuOfThreads, solutionCostCalculator, stateManager, constraintManager, addDefaultCostCalculators);
|
||||
}
|
||||
}
|
||||
if (algorithmConfig == null) {
|
||||
algorithmConfig = new AlgorithmConfig();
|
||||
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
|
||||
xmlReader.read(algorithmConfigFile);
|
||||
}
|
||||
return VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, algorithmConfig, nuOfThreads, solutionCostCalculator, stateManager, constraintManager, addDefaultCostCalculators);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm;
|
||||
|
|
@ -20,7 +20,7 @@ import jsprit.core.problem.VehicleRoutingProblem;
|
|||
|
||||
|
||||
public interface VehicleRoutingAlgorithmFactory {
|
||||
|
||||
public VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vrp);
|
||||
|
||||
public VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vrp);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.acceptor;
|
||||
|
|
@ -24,35 +24,33 @@ import java.util.Collection;
|
|||
* @deprecated use GreedyAcceptance instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class AcceptNewRemoveFirst implements SolutionAcceptor{
|
||||
public class AcceptNewRemoveFirst implements SolutionAcceptor {
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
public AcceptNewRemoveFirst(int solutionMemory){
|
||||
this.solutionMemory = solutionMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts every solution if solution memory allows. If memory occupied, than accepts new solution only if better than the worst in memory.
|
||||
* Consequently, the worst solution is removed from solutions, and the new solution added.
|
||||
*
|
||||
* <p>Note that this modifies Collection<VehicleRoutingProblemSolution> solutions.
|
||||
*/
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
if (solutions.size() >= solutionMemory) {
|
||||
solutions.remove(solutions.iterator().next());
|
||||
}
|
||||
solutions.add(newSolution);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=acceptNewRemoveFirst]";
|
||||
}
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
public AcceptNewRemoveFirst(int solutionMemory) {
|
||||
this.solutionMemory = solutionMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts every solution if solution memory allows. If memory occupied, than accepts new solution only if better than the worst in memory.
|
||||
* Consequently, the worst solution is removed from solutions, and the new solution added.
|
||||
* <p/>
|
||||
* <p>Note that this modifies Collection<VehicleRoutingProblemSolution> solutions.
|
||||
*/
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
if (solutions.size() >= solutionMemory) {
|
||||
solutions.remove(solutions.iterator().next());
|
||||
}
|
||||
solutions.add(newSolution);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=acceptNewRemoveFirst]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.acceptor;
|
||||
|
|
@ -35,122 +35,120 @@ import java.net.URL;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
public class ExperimentalSchrimpfAcceptance implements SolutionAcceptor, IterationStartsListener, AlgorithmStartsListener{
|
||||
public class ExperimentalSchrimpfAcceptance implements SolutionAcceptor, IterationStartsListener, AlgorithmStartsListener {
|
||||
|
||||
final static Logger logger = LogManager.getLogger(ExperimentalSchrimpfAcceptance.class.getName());
|
||||
|
||||
private final double alpha;
|
||||
|
||||
private int nOfTotalIterations = 1000;
|
||||
|
||||
private int currentIteration = 0;
|
||||
|
||||
private double initialThreshold = 0.0;
|
||||
final static Logger logger = LogManager.getLogger(ExperimentalSchrimpfAcceptance.class.getName());
|
||||
|
||||
private final int nOfRandomWalks;
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
|
||||
public ExperimentalSchrimpfAcceptance(int solutionMemory, double alpha, int nOfWarmupIterations) {
|
||||
super();
|
||||
this.alpha = alpha;
|
||||
this.nOfRandomWalks = nOfWarmupIterations;
|
||||
this.solutionMemory = solutionMemory;
|
||||
logger.info("initialise {}", this);
|
||||
}
|
||||
|
||||
private final double alpha;
|
||||
|
||||
private int nOfTotalIterations = 1000;
|
||||
|
||||
private int currentIteration = 0;
|
||||
|
||||
private double initialThreshold = 0.0;
|
||||
|
||||
private final int nOfRandomWalks;
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worst = null;
|
||||
double threshold = getThreshold(currentIteration);
|
||||
for(VehicleRoutingProblemSolution solutionInMemory : solutions){
|
||||
if(worst == null) worst = solutionInMemory;
|
||||
else if(solutionInMemory.getCost() > worst.getCost()) worst = solutionInMemory;
|
||||
}
|
||||
if(newSolution.getRoutes().size() < worst.getRoutes().size()){
|
||||
solutions.remove(worst);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
else if(newSolution.getRoutes().size() == worst.getRoutes().size() && newSolution.getCost() < worst.getCost() + threshold){
|
||||
solutions.remove(worst);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=schrimpfAcceptanceFunction][alpha="+alpha+"][warmup=" + nOfRandomWalks + "]";
|
||||
}
|
||||
|
||||
private double getThreshold(int iteration) {
|
||||
double scheduleVariable = (double) iteration / (double) nOfTotalIterations;
|
||||
public ExperimentalSchrimpfAcceptance(int solutionMemory, double alpha, int nOfWarmupIterations) {
|
||||
super();
|
||||
this.alpha = alpha;
|
||||
this.nOfRandomWalks = nOfWarmupIterations;
|
||||
this.solutionMemory = solutionMemory;
|
||||
logger.info("initialise {}", this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worst = null;
|
||||
double threshold = getThreshold(currentIteration);
|
||||
for (VehicleRoutingProblemSolution solutionInMemory : solutions) {
|
||||
if (worst == null) worst = solutionInMemory;
|
||||
else if (solutionInMemory.getCost() > worst.getCost()) worst = solutionInMemory;
|
||||
}
|
||||
if (newSolution.getRoutes().size() < worst.getRoutes().size()) {
|
||||
solutions.remove(worst);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else if (newSolution.getRoutes().size() == worst.getRoutes().size() && newSolution.getCost() < worst.getCost() + threshold) {
|
||||
solutions.remove(worst);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=schrimpfAcceptanceFunction][alpha=" + alpha + "][warmup=" + nOfRandomWalks + "]";
|
||||
}
|
||||
|
||||
private double getThreshold(int iteration) {
|
||||
double scheduleVariable = (double) iteration / (double) nOfTotalIterations;
|
||||
// logger.debug("iter={} totalIter={} scheduling={}", iteration, nOfTotalIterations, scheduleVariable);
|
||||
double currentThreshold = initialThreshold * Math.exp(-Math.log(2) * scheduleVariable / alpha);
|
||||
return currentThreshold;
|
||||
}
|
||||
double currentThreshold = initialThreshold * Math.exp(-Math.log(2) * scheduleVariable / alpha);
|
||||
return currentThreshold;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
reset();
|
||||
logger.info("---------------------------------------------------------------------");
|
||||
logger.info("prepare schrimpfAcceptanceFunction, i.e. determine initial threshold");
|
||||
logger.info("start random-walk (see randomWalk.xml)");
|
||||
double now = System.currentTimeMillis();
|
||||
this.nOfTotalIterations = algorithm.getMaxIterations();
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
reset();
|
||||
logger.info("---------------------------------------------------------------------");
|
||||
logger.info("prepare schrimpfAcceptanceFunction, i.e. determine initial threshold");
|
||||
logger.info("start random-walk (see randomWalk.xml)");
|
||||
double now = System.currentTimeMillis();
|
||||
this.nOfTotalIterations = algorithm.getMaxIterations();
|
||||
|
||||
/*
|
||||
* randomWalk to determine standardDev
|
||||
*/
|
||||
final double[] results = new double[nOfRandomWalks];
|
||||
|
||||
URL resource = Resource.getAsURL("randomWalk.xml");
|
||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
|
||||
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.createAlgorithm(problem, algorithmConfig);
|
||||
vra.setMaxIterations(nOfRandomWalks);
|
||||
vra.getAlgorithmListeners().addListener(new IterationEndsListener() {
|
||||
|
||||
@Override
|
||||
public void informIterationEnds(int iteration, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
double result = Solutions.bestOf(solutions).getCost();
|
||||
final double[] results = new double[nOfRandomWalks];
|
||||
|
||||
URL resource = Resource.getAsURL("randomWalk.xml");
|
||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
|
||||
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.createAlgorithm(problem, algorithmConfig);
|
||||
vra.setMaxIterations(nOfRandomWalks);
|
||||
vra.getAlgorithmListeners().addListener(new IterationEndsListener() {
|
||||
|
||||
@Override
|
||||
public void informIterationEnds(int iteration, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
double result = Solutions.bestOf(solutions).getCost();
|
||||
// logger.info("result={}", result);
|
||||
results[iteration-1] = result;
|
||||
}
|
||||
|
||||
});
|
||||
vra.searchSolutions();
|
||||
|
||||
StandardDeviation dev = new StandardDeviation();
|
||||
double standardDeviation = dev.evaluate(results);
|
||||
initialThreshold = standardDeviation / 2;
|
||||
|
||||
logger.info("warmup done");
|
||||
logger.info("total time: {}s", ((System.currentTimeMillis()-now)/1000.0));
|
||||
logger.info("initial threshold: {}", initialThreshold);
|
||||
logger.info("---------------------------------------------------------------------");
|
||||
|
||||
}
|
||||
results[iteration - 1] = result;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
currentIteration = 0;
|
||||
}
|
||||
});
|
||||
vra.searchSolutions();
|
||||
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
currentIteration = i;
|
||||
}
|
||||
StandardDeviation dev = new StandardDeviation();
|
||||
double standardDeviation = dev.evaluate(results);
|
||||
initialThreshold = standardDeviation / 2;
|
||||
|
||||
logger.info("warmup done");
|
||||
logger.info("total time: {}s", ((System.currentTimeMillis() - now) / 1000.0));
|
||||
logger.info("initial threshold: {}", initialThreshold);
|
||||
logger.info("---------------------------------------------------------------------");
|
||||
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
currentIteration = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
currentIteration = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.acceptor;
|
||||
|
|
@ -23,51 +23,49 @@ import java.util.Collection;
|
|||
|
||||
/**
|
||||
* Acceptor that accepts solutions to be memorized only better solutions.
|
||||
*
|
||||
* <p/>
|
||||
* <p>If there is enough memory, every solution will be accepted. If there is no memory anymore and the solution
|
||||
* to be evaluated is better than the worst, the worst will be replaced by the new solution.</p>
|
||||
*/
|
||||
public class GreedyAcceptance implements SolutionAcceptor{
|
||||
public class GreedyAcceptance implements SolutionAcceptor {
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
public GreedyAcceptance(int solutionMemory){
|
||||
this.solutionMemory = solutionMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts every solution if solution memory allows. If memory occupied, than accepts new solution only if better than the worst in memory.
|
||||
* Consequently, the worst solution is removed from solutions, and the new solution added.
|
||||
*
|
||||
* <p>Note that this modifies Collection<VehicleRoutingProblemSolution> solutions.
|
||||
*/
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worstSolution = null;
|
||||
for (VehicleRoutingProblemSolution s : solutions) {
|
||||
if (worstSolution == null) worstSolution = s;
|
||||
else if (s.getCost() > worstSolution.getCost()) worstSolution = s;
|
||||
}
|
||||
if(newSolution.getCost() < worstSolution.getCost()){
|
||||
solutions.remove(worstSolution);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=GreedyAcceptance]";
|
||||
}
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
public GreedyAcceptance(int solutionMemory) {
|
||||
this.solutionMemory = solutionMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts every solution if solution memory allows. If memory occupied, than accepts new solution only if better than the worst in memory.
|
||||
* Consequently, the worst solution is removed from solutions, and the new solution added.
|
||||
* <p/>
|
||||
* <p>Note that this modifies Collection<VehicleRoutingProblemSolution> solutions.
|
||||
*/
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worstSolution = null;
|
||||
for (VehicleRoutingProblemSolution s : solutions) {
|
||||
if (worstSolution == null) worstSolution = s;
|
||||
else if (s.getCost() > worstSolution.getCost()) worstSolution = s;
|
||||
}
|
||||
if (newSolution.getCost() < worstSolution.getCost()) {
|
||||
solutions.remove(worstSolution);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=GreedyAcceptance]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.acceptor;
|
||||
|
|
@ -22,52 +22,49 @@ import java.util.Collection;
|
|||
|
||||
|
||||
@Deprecated
|
||||
public class GreedyAcceptance_minVehFirst implements SolutionAcceptor{
|
||||
public class GreedyAcceptance_minVehFirst implements SolutionAcceptor {
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
public GreedyAcceptance_minVehFirst(int solutionMemory){
|
||||
this.solutionMemory = solutionMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts every solution if solution memory allows. If memory occupied, than accepts new solution only if better than the worst in memory.
|
||||
* Consequently, the worst solution is removed from solutions, and the new solution added.
|
||||
*
|
||||
* <p>Note that this modifies Collection<VehicleRoutingProblemSolution> solutions.
|
||||
*/
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worstSolution = null;
|
||||
for (VehicleRoutingProblemSolution s : solutions) {
|
||||
if (worstSolution == null) worstSolution = s;
|
||||
else if (s.getRoutes().size() > worstSolution.getRoutes().size()) worstSolution = s;
|
||||
}
|
||||
if(newSolution.getRoutes().size() < worstSolution.getRoutes().size()){
|
||||
solutions.remove(worstSolution);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
else if(newSolution.getRoutes().size() == worstSolution.getRoutes().size() && newSolution.getCost() < worstSolution.getCost()){
|
||||
solutions.remove(worstSolution);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=greedyAcceptance_minVehFirst]";
|
||||
}
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
public GreedyAcceptance_minVehFirst(int solutionMemory) {
|
||||
this.solutionMemory = solutionMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts every solution if solution memory allows. If memory occupied, than accepts new solution only if better than the worst in memory.
|
||||
* Consequently, the worst solution is removed from solutions, and the new solution added.
|
||||
* <p/>
|
||||
* <p>Note that this modifies Collection<VehicleRoutingProblemSolution> solutions.
|
||||
*/
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worstSolution = null;
|
||||
for (VehicleRoutingProblemSolution s : solutions) {
|
||||
if (worstSolution == null) worstSolution = s;
|
||||
else if (s.getRoutes().size() > worstSolution.getRoutes().size()) worstSolution = s;
|
||||
}
|
||||
if (newSolution.getRoutes().size() < worstSolution.getRoutes().size()) {
|
||||
solutions.remove(worstSolution);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else if (newSolution.getRoutes().size() == worstSolution.getRoutes().size() && newSolution.getCost() < worstSolution.getCost()) {
|
||||
solutions.remove(worstSolution);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=greedyAcceptance_minVehFirst]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.acceptor;
|
||||
|
|
@ -29,24 +29,24 @@ import java.util.Collection;
|
|||
|
||||
/**
|
||||
* ThresholdAcceptance-Function defined by Schrimpf et al. (2000).
|
||||
*
|
||||
* <p>The <b>idea</b> can be described as follows: Most problems do not only have one unique minimum (maximum) but
|
||||
* <p/>
|
||||
* <p>The <b>idea</b> can be described as follows: Most problems do not only have one unique minimum (maximum) but
|
||||
* a number of local minima (maxima). To avoid to get stuck in a local minimum at the beginning of a search
|
||||
* this threshold-acceptance function accepts also worse solution at the beginning (in contrary to a greedy
|
||||
* approach which only accepts better solutions), and converges to a greedy approach at the end. <br>
|
||||
* The difficulty is to define (i) an appropriate initial threshold and (ii) a corresponding function describing
|
||||
* how the threshold converges to zero, i.e. the greedy threshold.
|
||||
*
|
||||
* <p>ad i) The initial threshold is determined by a random walk through the search space.
|
||||
* The random walk currently runs with the following algorithm: src/main/resources/randomWalk.xml. It runs
|
||||
* as long as it is specified in nuOfWarmupIterations. In the first iteration or walk respectively the algorithm generates a solution.
|
||||
* This solution in turn is the basis of the next walk yielding to another solution value ... and so on.
|
||||
* Each solution value is memorized since the initial threshold is essentially a function of the standard deviation of these solution values.
|
||||
* To be more precise: initial threshold = stddev(solution values) / 2.
|
||||
*
|
||||
* <p>ad ii) The threshold of iteration i is determined as follows:
|
||||
* <p/>
|
||||
* <p>ad i) The initial threshold is determined by a random walk through the search space.
|
||||
* The random walk currently runs with the following algorithm: src/main/resources/randomWalk.xml. It runs
|
||||
* as long as it is specified in nuOfWarmupIterations. In the first iteration or walk respectively the algorithm generates a solution.
|
||||
* This solution in turn is the basis of the next walk yielding to another solution value ... and so on.
|
||||
* Each solution value is memorized since the initial threshold is essentially a function of the standard deviation of these solution values.
|
||||
* To be more precise: initial threshold = stddev(solution values) / 2.
|
||||
* <p/>
|
||||
* <p>ad ii) The threshold of iteration i is determined as follows:
|
||||
* threshold(i) = initialThreshold * Math.exp(-Math.log(2) * (i / nuOfTotalIterations) / alpha)
|
||||
* To get a better understanding of the threshold-function go to Wolfram Alpha and plot the following line
|
||||
* To get a better understanding of the threshold-function go to Wolfram Alpha and plot the following line
|
||||
* (just copy and paste it into Wolfram's console: <a href="https://www.wolframalpha.com/">www.wolframalpha.com</a>):
|
||||
* <p>100. * exp(-log(2)* (x/1000) / 0.1) (x from 0 to 1000) (y from 0 to 100)
|
||||
* <p>with <br>
|
||||
|
|
@ -55,102 +55,99 @@ import java.util.Collection;
|
|||
* alpha = 0.1<br>
|
||||
* x corresponds to i iterations and<br>
|
||||
* y to the threshold(i)
|
||||
*
|
||||
* <p>Gerhard Schrimpf, Johannes Schneider, Hermann Stamm- Wilbrandt, and Gunter Dueck (2000).
|
||||
* Record breaking optimization results using the ruin and recreate principle.
|
||||
* Journal of Computational Physics, 159(2):139 – 171, 2000. ISSN 0021-9991. doi: 10.1006/jcph.1999. 6413.
|
||||
* <p/>
|
||||
* <p>Gerhard Schrimpf, Johannes Schneider, Hermann Stamm- Wilbrandt, and Gunter Dueck (2000).
|
||||
* Record breaking optimization results using the ruin and recreate principle.
|
||||
* Journal of Computational Physics, 159(2):139 – 171, 2000. ISSN 0021-9991. doi: 10.1006/jcph.1999. 6413.
|
||||
* URL http://www.sciencedirect.com/science/article/ pii/S0021999199964136
|
||||
*
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
*/
|
||||
public class SchrimpfAcceptance implements SolutionAcceptor, IterationStartsListener, AlgorithmStartsListener{
|
||||
public class SchrimpfAcceptance implements SolutionAcceptor, IterationStartsListener, AlgorithmStartsListener {
|
||||
|
||||
private static Logger logger = LogManager.getLogger(SchrimpfAcceptance.class.getName());
|
||||
|
||||
private final double alpha;
|
||||
|
||||
private int maxIterations = 1000;
|
||||
|
||||
private int currentIteration = 0;
|
||||
|
||||
private double initialThreshold = 0.0;
|
||||
|
||||
private final int solutionMemory;
|
||||
private static Logger logger = LogManager.getLogger(SchrimpfAcceptance.class.getName());
|
||||
|
||||
|
||||
public SchrimpfAcceptance(int solutionMemory, double alpha){
|
||||
this.alpha = alpha;
|
||||
this.solutionMemory = solutionMemory;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
private final double alpha;
|
||||
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worst = null;
|
||||
double threshold = getThreshold(currentIteration);
|
||||
for(VehicleRoutingProblemSolution solutionInMemory : solutions){
|
||||
if(worst == null) worst = solutionInMemory;
|
||||
else if(solutionInMemory.getCost() > worst.getCost()) worst = solutionInMemory;
|
||||
}
|
||||
if(worst == null){
|
||||
private int maxIterations = 1000;
|
||||
|
||||
private int currentIteration = 0;
|
||||
|
||||
private double initialThreshold = 0.0;
|
||||
|
||||
private final int solutionMemory;
|
||||
|
||||
|
||||
public SchrimpfAcceptance(int solutionMemory, double alpha) {
|
||||
this.alpha = alpha;
|
||||
this.solutionMemory = solutionMemory;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
|
||||
boolean solutionAccepted = false;
|
||||
if (solutions.size() < solutionMemory) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else {
|
||||
VehicleRoutingProblemSolution worst = null;
|
||||
double threshold = getThreshold(currentIteration);
|
||||
for (VehicleRoutingProblemSolution solutionInMemory : solutions) {
|
||||
if (worst == null) worst = solutionInMemory;
|
||||
else if (solutionInMemory.getCost() > worst.getCost()) worst = solutionInMemory;
|
||||
}
|
||||
if (worst == null) {
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
} else if (newSolution.getCost() < worst.getCost() + threshold) {
|
||||
solutions.remove(worst);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
else if(newSolution.getCost() < worst.getCost() + threshold){
|
||||
solutions.remove(worst);
|
||||
solutions.add(newSolution);
|
||||
solutionAccepted = true;
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=SchrimpfAcceptance][alpha="+alpha+"]";
|
||||
}
|
||||
|
||||
private double getThreshold(int iteration) {
|
||||
double scheduleVariable = (double) iteration / (double) maxIterations;
|
||||
return initialThreshold * Math.exp(-1. * Math.log(2) * scheduleVariable / alpha);
|
||||
}
|
||||
}
|
||||
return solutionAccepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=SchrimpfAcceptance][alpha=" + alpha + "]";
|
||||
}
|
||||
|
||||
private double getThreshold(int iteration) {
|
||||
double scheduleVariable = (double) iteration / (double) maxIterations;
|
||||
return initialThreshold * Math.exp(-1. * Math.log(2) * scheduleVariable / alpha);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public double getInitialThreshold(){
|
||||
return initialThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets initial threshold.
|
||||
* <p>Note that if initial threshold has been set, automatic generation of initial threshold is disabled.
|
||||
*
|
||||
* @param initialThreshold the initialThreshold to set
|
||||
*/
|
||||
public void setInitialThreshold(double initialThreshold) {
|
||||
this.initialThreshold = initialThreshold;
|
||||
}
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public double getInitialThreshold() {
|
||||
return initialThreshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
/**
|
||||
* Sets initial threshold.
|
||||
* <p>Note that if initial threshold has been set, automatic generation of initial threshold is disabled.
|
||||
*
|
||||
* @param initialThreshold the initialThreshold to set
|
||||
*/
|
||||
public void setInitialThreshold(double initialThreshold) {
|
||||
this.initialThreshold = initialThreshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
reset();
|
||||
this.maxIterations = algorithm.getMaxIterations();
|
||||
}
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
currentIteration = 0;
|
||||
}
|
||||
private void reset() {
|
||||
currentIteration = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
currentIteration = i;
|
||||
}
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
currentIteration = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,55 +34,55 @@ import java.net.URL;
|
|||
import java.util.Collection;
|
||||
|
||||
public class SchrimpfInitialThresholdGenerator implements AlgorithmStartsListener {
|
||||
|
||||
private static Logger logger = LogManager.getLogger(SchrimpfInitialThresholdGenerator.class.getName());
|
||||
|
||||
private SchrimpfAcceptance schrimpfAcceptance;
|
||||
|
||||
private int nOfRandomWalks;
|
||||
|
||||
public SchrimpfInitialThresholdGenerator(SchrimpfAcceptance schrimpfAcceptance, int nOfRandomWalks) {
|
||||
super();
|
||||
this.schrimpfAcceptance = schrimpfAcceptance;
|
||||
this.nOfRandomWalks = nOfRandomWalks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem,VehicleRoutingAlgorithm algorithm,Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
logger.info("prepare schrimpfAcceptanceFunction, i.e. determine initial threshold");
|
||||
double now = System.currentTimeMillis();
|
||||
|
||||
private static Logger logger = LogManager.getLogger(SchrimpfInitialThresholdGenerator.class.getName());
|
||||
|
||||
private SchrimpfAcceptance schrimpfAcceptance;
|
||||
|
||||
private int nOfRandomWalks;
|
||||
|
||||
public SchrimpfInitialThresholdGenerator(SchrimpfAcceptance schrimpfAcceptance, int nOfRandomWalks) {
|
||||
super();
|
||||
this.schrimpfAcceptance = schrimpfAcceptance;
|
||||
this.nOfRandomWalks = nOfRandomWalks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
logger.info("prepare schrimpfAcceptanceFunction, i.e. determine initial threshold");
|
||||
double now = System.currentTimeMillis();
|
||||
|
||||
/*
|
||||
* randomWalk to determine standardDev
|
||||
*/
|
||||
final double[] results = new double[nOfRandomWalks];
|
||||
|
||||
URL resource = Resource.getAsURL("randomWalk.xml");
|
||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
|
||||
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.createAlgorithm(problem, algorithmConfig);
|
||||
vra.setMaxIterations(nOfRandomWalks);
|
||||
vra.getAlgorithmListeners().addListener(new IterationEndsListener() {
|
||||
|
||||
@Override
|
||||
public void informIterationEnds(int iteration, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
double result = Solutions.bestOf(solutions).getCost();
|
||||
// logger.info("result={}", result);
|
||||
results[iteration-1] = result;
|
||||
}
|
||||
|
||||
});
|
||||
vra.searchSolutions();
|
||||
|
||||
StandardDeviation dev = new StandardDeviation();
|
||||
double standardDeviation = dev.evaluate(results);
|
||||
double initialThreshold = standardDeviation / 2;
|
||||
|
||||
schrimpfAcceptance.setInitialThreshold(initialThreshold);
|
||||
final double[] results = new double[nOfRandomWalks];
|
||||
|
||||
logger.info("took {} seconds", ((System.currentTimeMillis()-now)/1000.0) );
|
||||
logger.debug("initial threshold: {}", initialThreshold);
|
||||
logger.info("---------------------------------------------------------------------");
|
||||
}
|
||||
URL resource = Resource.getAsURL("randomWalk.xml");
|
||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
|
||||
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.createAlgorithm(problem, algorithmConfig);
|
||||
vra.setMaxIterations(nOfRandomWalks);
|
||||
vra.getAlgorithmListeners().addListener(new IterationEndsListener() {
|
||||
|
||||
@Override
|
||||
public void informIterationEnds(int iteration, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
double result = Solutions.bestOf(solutions).getCost();
|
||||
// logger.info("result={}", result);
|
||||
results[iteration - 1] = result;
|
||||
}
|
||||
|
||||
});
|
||||
vra.searchSolutions();
|
||||
|
||||
StandardDeviation dev = new StandardDeviation();
|
||||
double standardDeviation = dev.evaluate(results);
|
||||
double initialThreshold = standardDeviation / 2;
|
||||
|
||||
schrimpfAcceptance.setInitialThreshold(initialThreshold);
|
||||
|
||||
logger.info("took {} seconds", ((System.currentTimeMillis() - now) / 1000.0));
|
||||
logger.debug("initial threshold: {}", initialThreshold);
|
||||
logger.info("---------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2014 Stefan Schroeder
|
||||
*
|
||||
|
|
@ -25,22 +24,20 @@ import java.util.Collection;
|
|||
|
||||
/**
|
||||
* Acceptor that decides whether the newSolution is accepted or not.
|
||||
*
|
||||
*
|
||||
* @author stefan
|
||||
*
|
||||
* @author stefan
|
||||
*/
|
||||
public interface SolutionAcceptor {
|
||||
|
||||
/**
|
||||
* Accepts solution or not, and returns true if a new solution has been accepted.
|
||||
*
|
||||
* <p>If the solution is accepted, it is added to solutions, i.e. the solutions-collections is modified.
|
||||
*
|
||||
* @param solutions collection of existing solutions
|
||||
* @param newSolution new solution to be evaluated
|
||||
* @return true if solution accepted
|
||||
*/
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution);
|
||||
|
||||
/**
|
||||
* Accepts solution or not, and returns true if a new solution has been accepted.
|
||||
* <p/>
|
||||
* <p>If the solution is accepted, it is added to solutions, i.e. the solutions-collections is modified.
|
||||
*
|
||||
* @param solutions collection of existing solutions
|
||||
* @param newSolution new solution to be evaluated
|
||||
* @return true if solution accepted
|
||||
*/
|
||||
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.box;
|
||||
|
|
@ -26,41 +26,38 @@ import jsprit.core.util.Resource;
|
|||
import java.net.URL;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Factory that creates the {@link VehicleRoutingAlgorithm} as proposed by Schrimpf et al., 2000 with the following parameters:
|
||||
*
|
||||
* <p>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* R&R_random (prob=0.5, F=0.5);
|
||||
* R&R_radial (prob=0.5, F=0.3);
|
||||
* threshold-accepting with exponentialDecayFunction (alpha=0.1, warmup-iterations=100);
|
||||
* nuOfIterations=2000
|
||||
*
|
||||
* <p>Gerhard Schrimpf, Johannes Schneider, Hermann Stamm- Wilbrandt, and Gunter Dueck.
|
||||
* Record breaking optimization results using the ruin and recreate principle.
|
||||
* Journal of Computational Physics, 159(2):139 – 171, 2000. ISSN 0021-9991. doi: 10.1006/jcph.1999. 6413.
|
||||
* <p/>
|
||||
* <p>Gerhard Schrimpf, Johannes Schneider, Hermann Stamm- Wilbrandt, and Gunter Dueck.
|
||||
* Record breaking optimization results using the ruin and recreate principle.
|
||||
* Journal of Computational Physics, 159(2):139 – 171, 2000. ISSN 0021-9991. doi: 10.1006/jcph.1999. 6413.
|
||||
* URL http://www.sciencedirect.com/science/article/ pii/S0021999199964136
|
||||
*
|
||||
* <p>algorithm-xml-config is available at src/main/resources/schrimpf.xml.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
* <p/>
|
||||
* <p>algorithm-xml-config is available at src/main/resources/schrimpf.xml.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*/
|
||||
public class GreedySchrimpfFactory {
|
||||
|
||||
/**
|
||||
* Creates the {@link VehicleRoutingAlgorithm}.
|
||||
*
|
||||
* @param vrp
|
||||
* @return algorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vrp){
|
||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||
URL resource = Resource.getAsURL("greedySchrimpf.xml");
|
||||
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
|
||||
return VehicleRoutingAlgorithms.createAlgorithm(vrp, algorithmConfig);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates the {@link VehicleRoutingAlgorithm}.
|
||||
*
|
||||
* @param vrp
|
||||
* @return algorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vrp) {
|
||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||
URL resource = Resource.getAsURL("greedySchrimpf.xml");
|
||||
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
|
||||
return VehicleRoutingAlgorithms.createAlgorithm(vrp, algorithmConfig);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ import java.util.List;
|
|||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 16/01/15.
|
||||
*/
|
||||
* Created by schroeder on 16/01/15.
|
||||
*/
|
||||
class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsListener {
|
||||
|
||||
private final double noiseProbability;
|
||||
|
|
@ -44,12 +44,12 @@ class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsList
|
|||
//@ToDo refactor determining max costs to allow skipping this
|
||||
private void determineMaxCosts(VehicleRoutingProblem vrp) {
|
||||
double max = 0.;
|
||||
for(Job i : vrp.getJobs().values()){
|
||||
for (Job i : vrp.getJobs().values()) {
|
||||
List<Location> fromLocations = getLocations(i);
|
||||
for(Job j : vrp.getJobs().values()){
|
||||
for (Job j : vrp.getJobs().values()) {
|
||||
List<Location> toLocations = getLocations(j);
|
||||
for(Location iLoc : fromLocations){
|
||||
for(Location jLoc : toLocations) {
|
||||
for (Location iLoc : fromLocations) {
|
||||
for (Location jLoc : toLocations) {
|
||||
max = Math.max(max, vrp.getTransportCosts().getTransportCost(iLoc, jLoc, 0, null, vrp.getVehicles().iterator().next()));
|
||||
}
|
||||
}
|
||||
|
|
@ -60,10 +60,9 @@ class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsList
|
|||
|
||||
private List<Location> getLocations(Job j) {
|
||||
List<Location> locs = new ArrayList<Location>();
|
||||
if(j instanceof Service) {
|
||||
if (j instanceof Service) {
|
||||
locs.add(((Service) j).getLocation());
|
||||
}
|
||||
else if(j instanceof Shipment){
|
||||
} else if (j instanceof Shipment) {
|
||||
locs.add(((Shipment) j).getPickupLocation());
|
||||
locs.add(((Shipment) j).getDeliveryLocation());
|
||||
}
|
||||
|
|
@ -72,15 +71,14 @@ class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsList
|
|||
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
if(random.nextDouble() < noiseProbability){
|
||||
if (random.nextDouble() < noiseProbability) {
|
||||
makeNoise = true;
|
||||
}
|
||||
else makeNoise = false;
|
||||
} else makeNoise = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
||||
if(makeNoise) {
|
||||
if (makeNoise) {
|
||||
return noiseLevel * maxCosts * random.nextDouble();
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -40,11 +40,11 @@ public class Jsprit {
|
|||
|
||||
String name;
|
||||
|
||||
Construction(String name){
|
||||
Construction(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
|
@ -63,11 +63,11 @@ public class Jsprit {
|
|||
|
||||
String strategyName;
|
||||
|
||||
Strategy(String strategyName){
|
||||
Strategy(String strategyName) {
|
||||
this.strategyName = strategyName;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
public String toString() {
|
||||
return strategyName;
|
||||
}
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ public class Jsprit {
|
|||
public enum Parameter {
|
||||
|
||||
FIXED_COST_PARAM("fixed_cost_param"), VEHICLE_SWITCH("vehicle_switch"), REGRET_TIME_WINDOW_SCORER("regret.tw_scorer"),
|
||||
REGRET_DISTANCE_SCORER("regret.distance_scorer"), INITIAL_THRESHOLD("initial_threshold"), ITERATIONS("iterations"),
|
||||
REGRET_DISTANCE_SCORER("regret.distance_scorer"), INITIAL_THRESHOLD("initial_threshold"), ITERATIONS("iterations"),
|
||||
THREADS("threads"),
|
||||
RANDOM_REGRET_MIN_SHARE("random_regret.min_share"),
|
||||
RANDOM_REGRET_MAX_SHARE("random_regret.max_share"),
|
||||
|
|
@ -97,17 +97,17 @@ public class Jsprit {
|
|||
|
||||
String paraName;
|
||||
|
||||
Parameter(String name){
|
||||
Parameter(String name) {
|
||||
this.paraName = name;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
public String toString() {
|
||||
return paraName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vehicleRoutingProblem){
|
||||
public static VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
return Jsprit.Builder.newInstance(vehicleRoutingProblem).buildAlgorithm();
|
||||
}
|
||||
|
||||
|
|
@ -131,53 +131,53 @@ public class Jsprit {
|
|||
|
||||
private Random random = RandomNumberGeneration.newInstance();
|
||||
|
||||
public static Builder newInstance(VehicleRoutingProblem vrp){
|
||||
public static Builder newInstance(VehicleRoutingProblem vrp) {
|
||||
return new Builder(vrp);
|
||||
}
|
||||
|
||||
private Builder(VehicleRoutingProblem vrp){
|
||||
private Builder(VehicleRoutingProblem vrp) {
|
||||
this.vrp = vrp;
|
||||
properties = new Properties(createDefaultProperties());
|
||||
}
|
||||
|
||||
private Properties createDefaultProperties() {
|
||||
Properties defaults = new Properties();
|
||||
defaults.put(Strategy.RADIAL_BEST.toString(),"0.");
|
||||
defaults.put(Strategy.RADIAL_REGRET.toString(),".5");
|
||||
defaults.put(Strategy.RANDOM_BEST.toString(),".5");
|
||||
defaults.put(Strategy.RANDOM_REGRET.toString(),".5");
|
||||
defaults.put(Strategy.WORST_BEST.toString(),"0.");
|
||||
defaults.put(Strategy.WORST_REGRET.toString(),"1.");
|
||||
defaults.put(Strategy.CLUSTER_BEST.toString(),"0.");
|
||||
defaults.put(Strategy.CLUSTER_REGRET.toString(),"1.");
|
||||
defaults.put(Parameter.FIXED_COST_PARAM.toString(),"0.");
|
||||
defaults.put(Parameter.VEHICLE_SWITCH.toString(),"true");
|
||||
defaults.put(Parameter.ITERATIONS.toString(),"2000");
|
||||
defaults.put(Parameter.REGRET_DISTANCE_SCORER.toString(),".05");
|
||||
defaults.put(Parameter.REGRET_TIME_WINDOW_SCORER.toString(),"-.1");
|
||||
defaults.put(Parameter.THREADS.toString(),"1");
|
||||
int minShare = (int)Math.min(20, Math.max(3,vrp.getJobs().size() * 0.05));
|
||||
int maxShare = (int)Math.min(50, Math.max(5,vrp.getJobs().size() * 0.3));
|
||||
defaults.put(Parameter.RADIAL_MIN_SHARE.toString(),String.valueOf(minShare));
|
||||
defaults.put(Parameter.RADIAL_MAX_SHARE.toString(),String.valueOf(maxShare));
|
||||
defaults.put(Parameter.WORST_MIN_SHARE.toString(),String.valueOf(minShare));
|
||||
defaults.put(Parameter.WORST_MAX_SHARE.toString(),String.valueOf(maxShare));
|
||||
defaults.put(Parameter.CLUSTER_MIN_SHARE.toString(),String.valueOf(minShare));
|
||||
defaults.put(Parameter.CLUSTER_MAX_SHARE.toString(),String.valueOf(maxShare));
|
||||
int minShare_ = (int)Math.min(70, Math.max(5,vrp.getJobs().size() * 0.5));
|
||||
int maxShare_ = (int)Math.min(70, Math.max(5,vrp.getJobs().size() * 0.5));
|
||||
defaults.put(Parameter.RANDOM_REGRET_MIN_SHARE.toString(),String.valueOf(minShare_));
|
||||
defaults.put(Parameter.RANDOM_REGRET_MAX_SHARE.toString(),String.valueOf(maxShare_));
|
||||
defaults.put(Parameter.RANDOM_BEST_MIN_SHARE.toString(),String.valueOf(minShare_));
|
||||
defaults.put(Parameter.RANDOM_BEST_MAX_SHARE.toString(),String.valueOf(maxShare_));
|
||||
defaults.put(Parameter.THRESHOLD_ALPHA.toString(),String.valueOf(0.15));
|
||||
defaults.put(Parameter.THRESHOLD_INI.toString(),String.valueOf(0.03));
|
||||
defaults.put(Parameter.INSERTION_NOISE_LEVEL.toString(),String.valueOf(0.15));
|
||||
defaults.put(Parameter.INSERTION_NOISE_PROB.toString(),String.valueOf(0.2));
|
||||
defaults.put(Parameter.RUIN_WORST_NOISE_LEVEL.toString(),String.valueOf(0.15));
|
||||
defaults.put(Parameter.RUIN_WORST_NOISE_PROB.toString(),String.valueOf(0.2));
|
||||
defaults.put(Parameter.VEHICLE_SWITCH.toString(),String.valueOf(true));
|
||||
defaults.put(Parameter.CONSTRUCTION.toString(),Construction.REGRET_INSERTION.toString());
|
||||
defaults.put(Strategy.RADIAL_BEST.toString(), "0.");
|
||||
defaults.put(Strategy.RADIAL_REGRET.toString(), ".5");
|
||||
defaults.put(Strategy.RANDOM_BEST.toString(), ".5");
|
||||
defaults.put(Strategy.RANDOM_REGRET.toString(), ".5");
|
||||
defaults.put(Strategy.WORST_BEST.toString(), "0.");
|
||||
defaults.put(Strategy.WORST_REGRET.toString(), "1.");
|
||||
defaults.put(Strategy.CLUSTER_BEST.toString(), "0.");
|
||||
defaults.put(Strategy.CLUSTER_REGRET.toString(), "1.");
|
||||
defaults.put(Parameter.FIXED_COST_PARAM.toString(), "0.");
|
||||
defaults.put(Parameter.VEHICLE_SWITCH.toString(), "true");
|
||||
defaults.put(Parameter.ITERATIONS.toString(), "2000");
|
||||
defaults.put(Parameter.REGRET_DISTANCE_SCORER.toString(), ".05");
|
||||
defaults.put(Parameter.REGRET_TIME_WINDOW_SCORER.toString(), "-.1");
|
||||
defaults.put(Parameter.THREADS.toString(), "1");
|
||||
int minShare = (int) Math.min(20, Math.max(3, vrp.getJobs().size() * 0.05));
|
||||
int maxShare = (int) Math.min(50, Math.max(5, vrp.getJobs().size() * 0.3));
|
||||
defaults.put(Parameter.RADIAL_MIN_SHARE.toString(), String.valueOf(minShare));
|
||||
defaults.put(Parameter.RADIAL_MAX_SHARE.toString(), String.valueOf(maxShare));
|
||||
defaults.put(Parameter.WORST_MIN_SHARE.toString(), String.valueOf(minShare));
|
||||
defaults.put(Parameter.WORST_MAX_SHARE.toString(), String.valueOf(maxShare));
|
||||
defaults.put(Parameter.CLUSTER_MIN_SHARE.toString(), String.valueOf(minShare));
|
||||
defaults.put(Parameter.CLUSTER_MAX_SHARE.toString(), String.valueOf(maxShare));
|
||||
int minShare_ = (int) Math.min(70, Math.max(5, vrp.getJobs().size() * 0.5));
|
||||
int maxShare_ = (int) Math.min(70, Math.max(5, vrp.getJobs().size() * 0.5));
|
||||
defaults.put(Parameter.RANDOM_REGRET_MIN_SHARE.toString(), String.valueOf(minShare_));
|
||||
defaults.put(Parameter.RANDOM_REGRET_MAX_SHARE.toString(), String.valueOf(maxShare_));
|
||||
defaults.put(Parameter.RANDOM_BEST_MIN_SHARE.toString(), String.valueOf(minShare_));
|
||||
defaults.put(Parameter.RANDOM_BEST_MAX_SHARE.toString(), String.valueOf(maxShare_));
|
||||
defaults.put(Parameter.THRESHOLD_ALPHA.toString(), String.valueOf(0.15));
|
||||
defaults.put(Parameter.THRESHOLD_INI.toString(), String.valueOf(0.03));
|
||||
defaults.put(Parameter.INSERTION_NOISE_LEVEL.toString(), String.valueOf(0.15));
|
||||
defaults.put(Parameter.INSERTION_NOISE_PROB.toString(), String.valueOf(0.2));
|
||||
defaults.put(Parameter.RUIN_WORST_NOISE_LEVEL.toString(), String.valueOf(0.15));
|
||||
defaults.put(Parameter.RUIN_WORST_NOISE_PROB.toString(), String.valueOf(0.2));
|
||||
defaults.put(Parameter.VEHICLE_SWITCH.toString(), String.valueOf(true));
|
||||
defaults.put(Parameter.CONSTRUCTION.toString(), Construction.REGRET_INSERTION.toString());
|
||||
return defaults;
|
||||
}
|
||||
|
||||
|
|
@ -188,23 +188,23 @@ public class Jsprit {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setRandom(Random random){
|
||||
public Builder setRandom(Random random) {
|
||||
this.random = random;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setProperty(String key, String value){
|
||||
properties.put(key,value);
|
||||
public Builder setProperty(String key, String value) {
|
||||
properties.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setProperty(Parameter parameter, String value){
|
||||
setProperty(parameter.toString(),value);
|
||||
public Builder setProperty(Parameter parameter, String value) {
|
||||
setProperty(parameter.toString(), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setProperty(Strategy strategy, String value){
|
||||
setProperty(strategy.toString(),value);
|
||||
public Builder setProperty(Strategy strategy, String value) {
|
||||
setProperty(strategy.toString(), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ public class Jsprit {
|
|||
return this;
|
||||
}
|
||||
|
||||
public VehicleRoutingAlgorithm buildAlgorithm(){
|
||||
public VehicleRoutingAlgorithm buildAlgorithm() {
|
||||
return new Jsprit(this).create(vrp);
|
||||
}
|
||||
|
||||
|
|
@ -245,13 +245,15 @@ public class Jsprit {
|
|||
}
|
||||
|
||||
public RuinShareFactoryImpl(int minShare, int maxShare) {
|
||||
if(maxShare < minShare) throw new IllegalArgumentException("maxShare must be equal or greater than minShare");
|
||||
if (maxShare < minShare)
|
||||
throw new IllegalArgumentException("maxShare must be equal or greater than minShare");
|
||||
this.minShare = minShare;
|
||||
this.maxShare = maxShare;
|
||||
}
|
||||
|
||||
public RuinShareFactoryImpl(int minShare, int maxShare, Random random) {
|
||||
if(maxShare < minShare) throw new IllegalArgumentException("maxShare must be equal or greater than minShare");
|
||||
if (maxShare < minShare)
|
||||
throw new IllegalArgumentException("maxShare must be equal or greater than minShare");
|
||||
this.minShare = minShare;
|
||||
this.maxShare = maxShare;
|
||||
this.random = random;
|
||||
|
|
@ -293,18 +295,17 @@ public class Jsprit {
|
|||
this.random = builder.random;
|
||||
}
|
||||
|
||||
private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp){
|
||||
private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp) {
|
||||
VehicleFleetManager fm;
|
||||
if(vrp.getFleetSize().equals(VehicleRoutingProblem.FleetSize.INFINITE)){
|
||||
if (vrp.getFleetSize().equals(VehicleRoutingProblem.FleetSize.INFINITE)) {
|
||||
fm = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
|
||||
}
|
||||
else fm = new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
|
||||
} else fm = new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
|
||||
|
||||
if(stateManager == null){
|
||||
if (stateManager == null) {
|
||||
stateManager = new StateManager(vrp);
|
||||
}
|
||||
if(constraintManager == null){
|
||||
constraintManager = new ConstraintManager(vrp,stateManager);
|
||||
if (constraintManager == null) {
|
||||
constraintManager = new ConstraintManager(vrp, stateManager);
|
||||
}
|
||||
|
||||
double noiseLevel = toDouble(getProperty(Parameter.INSERTION_NOISE_LEVEL.toString()));
|
||||
|
|
@ -316,36 +317,36 @@ public class Jsprit {
|
|||
JobNeighborhoods jobNeighborhoods = new JobNeighborhoodsFactory().createNeighborhoods(vrp, new AvgServiceAndShipmentDistance(vrp.getTransportCosts()), (int) (vrp.getJobs().values().size() * 0.5));
|
||||
jobNeighborhoods.initialise();
|
||||
|
||||
RuinRadial radial = new RuinRadial(vrp,vrp.getJobs().size(),jobNeighborhoods);
|
||||
RuinRadial radial = new RuinRadial(vrp, vrp.getJobs().size(), jobNeighborhoods);
|
||||
radial.setRandom(random);
|
||||
radial.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||
toInteger(properties.getProperty(Parameter.RADIAL_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.RADIAL_MAX_SHARE.toString())),
|
||||
random)
|
||||
random)
|
||||
);
|
||||
|
||||
final RuinRandom random_for_regret = new RuinRandom(vrp,0.5);
|
||||
final RuinRandom random_for_regret = new RuinRandom(vrp, 0.5);
|
||||
random_for_regret.setRandom(random);
|
||||
random_for_regret.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||
toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MAX_SHARE.toString())),
|
||||
random)
|
||||
toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MAX_SHARE.toString())),
|
||||
random)
|
||||
);
|
||||
|
||||
final RuinRandom random_for_best = new RuinRandom(vrp,0.5);
|
||||
final RuinRandom random_for_best = new RuinRandom(vrp, 0.5);
|
||||
random_for_best.setRandom(random);
|
||||
random_for_best.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||
toInteger(properties.getProperty(Parameter.RANDOM_BEST_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.RANDOM_BEST_MAX_SHARE.toString())),
|
||||
random)
|
||||
toInteger(properties.getProperty(Parameter.RANDOM_BEST_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.RANDOM_BEST_MAX_SHARE.toString())),
|
||||
random)
|
||||
);
|
||||
|
||||
final RuinWorst worst = new RuinWorst(vrp, (int) (vrp.getJobs().values().size()*0.5));
|
||||
final RuinWorst worst = new RuinWorst(vrp, (int) (vrp.getJobs().values().size() * 0.5));
|
||||
worst.setRandom(random);
|
||||
worst.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||
toInteger(properties.getProperty(Parameter.WORST_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.WORST_MAX_SHARE.toString())),
|
||||
random)
|
||||
toInteger(properties.getProperty(Parameter.WORST_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.WORST_MAX_SHARE.toString())),
|
||||
random)
|
||||
);
|
||||
IterationStartsListener noise = new IterationStartsListener() {
|
||||
@Override
|
||||
|
|
@ -353,52 +354,50 @@ public class Jsprit {
|
|||
worst.setNoiseMaker(new NoiseMaker() {
|
||||
|
||||
public double makeNoise() {
|
||||
if(random.nextDouble() < toDouble(getProperty(Parameter.RUIN_WORST_NOISE_PROB.toString()))) {
|
||||
if (random.nextDouble() < toDouble(getProperty(Parameter.RUIN_WORST_NOISE_PROB.toString()))) {
|
||||
return toDouble(getProperty(Parameter.RUIN_WORST_NOISE_LEVEL.toString()))
|
||||
* noiseMaker.maxCosts * random.nextDouble();
|
||||
}
|
||||
else return 0.;
|
||||
* noiseMaker.maxCosts * random.nextDouble();
|
||||
} else return 0.;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
final RuinClusters clusters = new RuinClusters(vrp,(int) (vrp.getJobs().values().size()*0.5),jobNeighborhoods);
|
||||
final RuinClusters clusters = new RuinClusters(vrp, (int) (vrp.getJobs().values().size() * 0.5), jobNeighborhoods);
|
||||
clusters.setRandom(random);
|
||||
clusters.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||
toInteger(properties.getProperty(Parameter.WORST_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.WORST_MAX_SHARE.toString())),
|
||||
random)
|
||||
toInteger(properties.getProperty(Parameter.WORST_MIN_SHARE.toString())),
|
||||
toInteger(properties.getProperty(Parameter.WORST_MAX_SHARE.toString())),
|
||||
random)
|
||||
);
|
||||
|
||||
AbstractInsertionStrategy regret;
|
||||
final RegretInsertion.DefaultScorer scorer;
|
||||
if(noThreads == null){
|
||||
if (noThreads == null) {
|
||||
noThreads = toInteger(getProperty(Parameter.THREADS.toString()));
|
||||
}
|
||||
if(noThreads > 1){
|
||||
if(es == null){
|
||||
if (noThreads > 1) {
|
||||
if (es == null) {
|
||||
setupExecutorInternally = true;
|
||||
es = Executors.newFixedThreadPool(noThreads);
|
||||
}
|
||||
}
|
||||
if(es != null) {
|
||||
if (es != null) {
|
||||
RegretInsertionConcurrent regretInsertion = (RegretInsertionConcurrent) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||
.setConcurrentMode(es, noThreads)
|
||||
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.build();
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||
.setConcurrentMode(es, noThreads)
|
||||
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.build();
|
||||
scorer = getRegretScorer(vrp);
|
||||
regretInsertion.setScoringFunction(scorer);
|
||||
regret = regretInsertion;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
RegretInsertion regretInsertion = (RegretInsertion) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.build();
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.build();
|
||||
scorer = getRegretScorer(vrp);
|
||||
regretInsertion.setScoringFunction(scorer);
|
||||
regret = regretInsertion;
|
||||
|
|
@ -406,30 +405,29 @@ public class Jsprit {
|
|||
regret.setRandom(random);
|
||||
|
||||
AbstractInsertionStrategy best;
|
||||
if(vrp.getJobs().size() < 250 || es == null) {
|
||||
if (vrp.getJobs().size() < 250 || es == null) {
|
||||
BestInsertion bestInsertion = (BestInsertion) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
|
||||
.considerFixedCosts(Double.valueOf(properties.getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.build();
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
|
||||
.considerFixedCosts(Double.valueOf(properties.getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.build();
|
||||
best = bestInsertion;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
BestInsertionConcurrent bestInsertion = (BestInsertionConcurrent) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
|
||||
.considerFixedCosts(Double.valueOf(properties.getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.setConcurrentMode(es, noThreads)
|
||||
.build();
|
||||
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
|
||||
.considerFixedCosts(Double.valueOf(properties.getProperty(Parameter.FIXED_COST_PARAM.toString())))
|
||||
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
|
||||
.setConcurrentMode(es, noThreads)
|
||||
.build();
|
||||
best = bestInsertion;
|
||||
}
|
||||
best.setRandom(random);
|
||||
|
||||
final SchrimpfAcceptance schrimpfAcceptance = new SchrimpfAcceptance(1,toDouble(getProperty(Parameter.THRESHOLD_ALPHA.toString())));
|
||||
final SchrimpfAcceptance schrimpfAcceptance = new SchrimpfAcceptance(1, toDouble(getProperty(Parameter.THRESHOLD_ALPHA.toString())));
|
||||
IterationStartsListener schrimpfThreshold = new IterationStartsListener() {
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
if(i == 1){
|
||||
if (i == 1) {
|
||||
double initialThreshold = Solutions.bestOf(solutions).getCost() * toDouble(getProperty(Parameter.THRESHOLD_INI.toString()));
|
||||
schrimpfAcceptance.setInitialThreshold(initialThreshold);
|
||||
}
|
||||
|
|
@ -437,48 +435,47 @@ public class Jsprit {
|
|||
};
|
||||
|
||||
SolutionCostCalculator objectiveFunction = getObjectiveFunction(vrp, noiseMaker.maxCosts);
|
||||
SearchStrategy radial_regret = new SearchStrategy(Strategy.RADIAL_REGRET.toString(),new SelectBest(),schrimpfAcceptance, objectiveFunction);
|
||||
SearchStrategy radial_regret = new SearchStrategy(Strategy.RADIAL_REGRET.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||
radial_regret.addModule(new RuinAndRecreateModule(Strategy.RADIAL_REGRET.toString(), regret, radial));
|
||||
|
||||
SearchStrategy radial_best = new SearchStrategy(Strategy.RADIAL_BEST.toString(),new SelectBest(),schrimpfAcceptance,objectiveFunction);
|
||||
radial_best.addModule(new RuinAndRecreateModule(Strategy.RADIAL_BEST.toString(),best,radial));
|
||||
SearchStrategy radial_best = new SearchStrategy(Strategy.RADIAL_BEST.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||
radial_best.addModule(new RuinAndRecreateModule(Strategy.RADIAL_BEST.toString(), best, radial));
|
||||
|
||||
SearchStrategy random_best = new SearchStrategy(Strategy.RANDOM_BEST.toString(),new SelectBest(),schrimpfAcceptance,objectiveFunction);
|
||||
random_best.addModule(new RuinAndRecreateModule(Strategy.RANDOM_BEST.toString(),best,random_for_best));
|
||||
SearchStrategy random_best = new SearchStrategy(Strategy.RANDOM_BEST.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||
random_best.addModule(new RuinAndRecreateModule(Strategy.RANDOM_BEST.toString(), best, random_for_best));
|
||||
|
||||
SearchStrategy random_regret = new SearchStrategy(Strategy.RANDOM_REGRET.toString(),new SelectBest(),schrimpfAcceptance,objectiveFunction);
|
||||
random_regret.addModule(new RuinAndRecreateModule(Strategy.RANDOM_REGRET.toString(),regret,random_for_regret));
|
||||
SearchStrategy random_regret = new SearchStrategy(Strategy.RANDOM_REGRET.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||
random_regret.addModule(new RuinAndRecreateModule(Strategy.RANDOM_REGRET.toString(), regret, random_for_regret));
|
||||
|
||||
SearchStrategy worst_regret = new SearchStrategy(Strategy.WORST_REGRET.toString(),new SelectBest(),schrimpfAcceptance,objectiveFunction);
|
||||
worst_regret.addModule(new RuinAndRecreateModule(Strategy.WORST_REGRET.toString(),regret,worst));
|
||||
SearchStrategy worst_regret = new SearchStrategy(Strategy.WORST_REGRET.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||
worst_regret.addModule(new RuinAndRecreateModule(Strategy.WORST_REGRET.toString(), regret, worst));
|
||||
|
||||
SearchStrategy worst_best = new SearchStrategy(Strategy.WORST_BEST.toString(),new SelectBest(),schrimpfAcceptance,objectiveFunction);
|
||||
worst_best.addModule(new RuinAndRecreateModule(Strategy.WORST_BEST.toString(),best,worst));
|
||||
SearchStrategy worst_best = new SearchStrategy(Strategy.WORST_BEST.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||
worst_best.addModule(new RuinAndRecreateModule(Strategy.WORST_BEST.toString(), best, worst));
|
||||
|
||||
final SearchStrategy clusters_regret = new SearchStrategy(Strategy.CLUSTER_REGRET.toString(),new SelectBest(),schrimpfAcceptance,objectiveFunction);
|
||||
clusters_regret.addModule(new RuinAndRecreateModule(Strategy.CLUSTER_REGRET.toString(),regret,clusters));
|
||||
final SearchStrategy clusters_regret = new SearchStrategy(Strategy.CLUSTER_REGRET.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||
clusters_regret.addModule(new RuinAndRecreateModule(Strategy.CLUSTER_REGRET.toString(), regret, clusters));
|
||||
|
||||
final SearchStrategy clusters_best = new SearchStrategy(Strategy.CLUSTER_BEST.toString(),new SelectBest(),schrimpfAcceptance,objectiveFunction);
|
||||
clusters_best.addModule(new RuinAndRecreateModule(Strategy.CLUSTER_BEST.toString(),best,clusters));
|
||||
final SearchStrategy clusters_best = new SearchStrategy(Strategy.CLUSTER_BEST.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||
clusters_best.addModule(new RuinAndRecreateModule(Strategy.CLUSTER_BEST.toString(), best, clusters));
|
||||
|
||||
|
||||
PrettyAlgorithmBuilder prettyBuilder = PrettyAlgorithmBuilder.newInstance(vrp, fm, stateManager, constraintManager);
|
||||
PrettyAlgorithmBuilder prettyBuilder = PrettyAlgorithmBuilder.newInstance(vrp, fm, stateManager, constraintManager);
|
||||
prettyBuilder.setRandom(random);
|
||||
if(addCoreConstraints){
|
||||
if (addCoreConstraints) {
|
||||
prettyBuilder.addCoreStateAndConstraintStuff();
|
||||
}
|
||||
prettyBuilder.withStrategy(radial_regret, toDouble(getProperty(Strategy.RADIAL_REGRET.toString())))
|
||||
.withStrategy(radial_best, toDouble(getProperty(Strategy.RADIAL_BEST.toString())))
|
||||
.withStrategy(random_best, toDouble(getProperty(Strategy.RANDOM_BEST.toString())))
|
||||
.withStrategy(random_regret, toDouble(getProperty(Strategy.RANDOM_REGRET.toString())))
|
||||
.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())));
|
||||
if (getProperty(Parameter.CONSTRUCTION.toString()).equals(Construction.BEST_INSERTION.toString())){
|
||||
.withStrategy(radial_best, toDouble(getProperty(Strategy.RADIAL_BEST.toString())))
|
||||
.withStrategy(random_best, toDouble(getProperty(Strategy.RANDOM_BEST.toString())))
|
||||
.withStrategy(random_regret, toDouble(getProperty(Strategy.RANDOM_REGRET.toString())))
|
||||
.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())));
|
||||
if (getProperty(Parameter.CONSTRUCTION.toString()).equals(Construction.BEST_INSERTION.toString())) {
|
||||
prettyBuilder.constructInitialSolutionWith(best, objectiveFunction);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
prettyBuilder.constructInitialSolutionWith(regret, objectiveFunction);
|
||||
}
|
||||
|
||||
|
|
@ -504,7 +501,7 @@ public class Jsprit {
|
|||
|
||||
|
||||
private void handleExecutorShutdown(VehicleRoutingAlgorithm vra) {
|
||||
if(setupExecutorInternally){
|
||||
if (setupExecutorInternally) {
|
||||
vra.addListener(new AlgorithmEndsListener() {
|
||||
|
||||
@Override
|
||||
|
|
@ -514,7 +511,7 @@ public class Jsprit {
|
|||
|
||||
});
|
||||
}
|
||||
if(es != null) {
|
||||
if (es != null) {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
public void run() {
|
||||
if (!es.isShutdown()) {
|
||||
|
|
@ -526,7 +523,7 @@ public class Jsprit {
|
|||
}
|
||||
}
|
||||
|
||||
String getProperty(String key){
|
||||
String getProperty(String key) {
|
||||
return properties.getProperty(key);
|
||||
}
|
||||
|
||||
|
|
@ -543,20 +540,20 @@ public class Jsprit {
|
|||
}
|
||||
|
||||
private SolutionCostCalculator getObjectiveFunction(final VehicleRoutingProblem vrp, final double maxCosts) {
|
||||
if(objectiveFunction != null) return objectiveFunction;
|
||||
if (objectiveFunction != null) return objectiveFunction;
|
||||
|
||||
SolutionCostCalculator solutionCostCalculator = new SolutionCostCalculator() {
|
||||
@Override
|
||||
public double getCosts(VehicleRoutingProblemSolution solution) {
|
||||
double costs = 0.;
|
||||
for(VehicleRoute route : solution.getRoutes()){
|
||||
for (VehicleRoute route : solution.getRoutes()) {
|
||||
costs += route.getVehicle().getType().getVehicleCostParams().fix;
|
||||
TourActivity prevAct = route.getStart();
|
||||
for(TourActivity act : route.getActivities()){
|
||||
costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(),act.getLocation(),prevAct.getEndTime(),route.getDriver(),route.getVehicle());
|
||||
for (TourActivity act : route.getActivities()) {
|
||||
costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), act.getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle());
|
||||
prevAct = act;
|
||||
}
|
||||
costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(),route.getEnd().getLocation(),prevAct.getEndTime(),route.getDriver(),route.getVehicle());
|
||||
costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), route.getEnd().getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle());
|
||||
}
|
||||
costs += solution.getUnassignedJobs().size() * maxCosts * 2;
|
||||
return costs;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.box;
|
||||
|
|
@ -26,41 +26,38 @@ import jsprit.core.util.Resource;
|
|||
import java.net.URL;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Factory that creates the {@link VehicleRoutingAlgorithm} as proposed by Schrimpf et al., 2000 with the following parameters:
|
||||
*
|
||||
* <p>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* R&R_random (prob=0.5, F=0.5);
|
||||
* R&R_radial (prob=0.5, F=0.3);
|
||||
* threshold-accepting with exponentialDecayFunction (alpha=0.1, warmup-iterations=100);
|
||||
* nuOfIterations=2000
|
||||
*
|
||||
* <p>Gerhard Schrimpf, Johannes Schneider, Hermann Stamm- Wilbrandt, and Gunter Dueck.
|
||||
* Record breaking optimization results using the ruin and recreate principle.
|
||||
* Journal of Computational Physics, 159(2):139 – 171, 2000. ISSN 0021-9991. doi: 10.1006/jcph.1999. 6413.
|
||||
* <p/>
|
||||
* <p>Gerhard Schrimpf, Johannes Schneider, Hermann Stamm- Wilbrandt, and Gunter Dueck.
|
||||
* Record breaking optimization results using the ruin and recreate principle.
|
||||
* Journal of Computational Physics, 159(2):139 – 171, 2000. ISSN 0021-9991. doi: 10.1006/jcph.1999. 6413.
|
||||
* URL http://www.sciencedirect.com/science/article/ pii/S0021999199964136
|
||||
*
|
||||
* <p>algorithm-xml-config is available at src/main/resources/schrimpf.xml.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
* <p/>
|
||||
* <p>algorithm-xml-config is available at src/main/resources/schrimpf.xml.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*/
|
||||
public class SchrimpfFactory {
|
||||
|
||||
/**
|
||||
* Creates the {@link VehicleRoutingAlgorithm}.
|
||||
*
|
||||
* @param vrp the underlying vehicle routing problem
|
||||
* @return algorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vrp){
|
||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||
URL resource = Resource.getAsURL("schrimpf.xml");
|
||||
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
|
||||
return VehicleRoutingAlgorithms.createAlgorithm(vrp, algorithmConfig);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates the {@link VehicleRoutingAlgorithm}.
|
||||
*
|
||||
* @param vrp the underlying vehicle routing problem
|
||||
* @return algorithm
|
||||
*/
|
||||
public VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vrp) {
|
||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||
URL resource = Resource.getAsURL("schrimpf.xml");
|
||||
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
|
||||
return VehicleRoutingAlgorithms.createAlgorithm(vrp, algorithmConfig);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.io;
|
||||
|
|
@ -19,15 +19,15 @@ package jsprit.core.algorithm.io;
|
|||
import org.apache.commons.configuration.XMLConfiguration;
|
||||
|
||||
public class AlgorithmConfig {
|
||||
|
||||
private XMLConfiguration xmlConfig;
|
||||
|
||||
public AlgorithmConfig(){
|
||||
xmlConfig = new XMLConfiguration();
|
||||
|
||||
}
|
||||
|
||||
public XMLConfiguration getXMLConfiguration(){
|
||||
return xmlConfig;
|
||||
}
|
||||
private XMLConfiguration xmlConfig;
|
||||
|
||||
public AlgorithmConfig() {
|
||||
xmlConfig = new XMLConfiguration();
|
||||
|
||||
}
|
||||
|
||||
public XMLConfiguration getXMLConfiguration() {
|
||||
return xmlConfig;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.io;
|
||||
|
|
@ -30,65 +30,64 @@ import java.net.URL;
|
|||
|
||||
|
||||
public class AlgorithmConfigXmlReader {
|
||||
|
||||
private static Logger log = LogManager.getLogger(AlgorithmConfigXmlReader.class.getName());
|
||||
|
||||
private AlgorithmConfig algorithmConfig;
|
||||
|
||||
private boolean schemaValidation = true;
|
||||
|
||||
/**
|
||||
* @param schemaValidation the schemaValidation to set
|
||||
*/
|
||||
public AlgorithmConfigXmlReader setSchemaValidation(boolean schemaValidation) {
|
||||
this.schemaValidation = schemaValidation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlgorithmConfigXmlReader(AlgorithmConfig algorithmConfig){
|
||||
this.algorithmConfig = algorithmConfig;
|
||||
}
|
||||
|
||||
public void read(URL url){
|
||||
log.debug("read algorithm: " + url);
|
||||
algorithmConfig.getXMLConfiguration().setURL(url);
|
||||
algorithmConfig.getXMLConfiguration().setAttributeSplittingDisabled(true);
|
||||
algorithmConfig.getXMLConfiguration().setDelimiterParsingDisabled(true);
|
||||
|
||||
if(schemaValidation){
|
||||
final InputStream resource = Resource.getAsInputStream("algorithm_schema.xsd");
|
||||
if(resource != null) {
|
||||
EntityResolver resolver = new EntityResolver() {
|
||||
private static Logger log = LogManager.getLogger(AlgorithmConfigXmlReader.class.getName());
|
||||
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
|
||||
{
|
||||
InputSource is = new InputSource(resource);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
};
|
||||
algorithmConfig.getXMLConfiguration().setEntityResolver(resolver);
|
||||
algorithmConfig.getXMLConfiguration().setSchemaValidation(true);
|
||||
}
|
||||
else{
|
||||
log.warn("cannot find schema-xsd file (algorithm_xml_schema.xsd). try to read xml without xml-file-validation.");
|
||||
}
|
||||
}
|
||||
try {
|
||||
algorithmConfig.getXMLConfiguration().load();
|
||||
} catch (ConfigurationException e) {
|
||||
log.error(e);
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void read(String filename){
|
||||
log.debug("read algorithm-config from file " + filename);
|
||||
URL url = Resource.getAsURL(filename);
|
||||
read(url);
|
||||
}
|
||||
private AlgorithmConfig algorithmConfig;
|
||||
|
||||
private boolean schemaValidation = true;
|
||||
|
||||
/**
|
||||
* @param schemaValidation the schemaValidation to set
|
||||
*/
|
||||
public AlgorithmConfigXmlReader setSchemaValidation(boolean schemaValidation) {
|
||||
this.schemaValidation = schemaValidation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlgorithmConfigXmlReader(AlgorithmConfig algorithmConfig) {
|
||||
this.algorithmConfig = algorithmConfig;
|
||||
}
|
||||
|
||||
public void read(URL url) {
|
||||
log.debug("read algorithm: " + url);
|
||||
algorithmConfig.getXMLConfiguration().setURL(url);
|
||||
algorithmConfig.getXMLConfiguration().setAttributeSplittingDisabled(true);
|
||||
algorithmConfig.getXMLConfiguration().setDelimiterParsingDisabled(true);
|
||||
|
||||
if (schemaValidation) {
|
||||
final InputStream resource = Resource.getAsInputStream("algorithm_schema.xsd");
|
||||
if (resource != null) {
|
||||
EntityResolver resolver = new EntityResolver() {
|
||||
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
|
||||
{
|
||||
InputSource is = new InputSource(resource);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
};
|
||||
algorithmConfig.getXMLConfiguration().setEntityResolver(resolver);
|
||||
algorithmConfig.getXMLConfiguration().setSchemaValidation(true);
|
||||
} else {
|
||||
log.warn("cannot find schema-xsd file (algorithm_xml_schema.xsd). try to read xml without xml-file-validation.");
|
||||
}
|
||||
}
|
||||
try {
|
||||
algorithmConfig.getXMLConfiguration().load();
|
||||
} catch (ConfigurationException e) {
|
||||
log.error(e);
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void read(String filename) {
|
||||
log.debug("read algorithm-config from file " + filename);
|
||||
URL url = Resource.getAsURL(filename);
|
||||
read(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.io;
|
||||
|
|
@ -32,85 +32,83 @@ import java.util.concurrent.ExecutorService;
|
|||
|
||||
|
||||
class InsertionFactory {
|
||||
|
||||
private static Logger log = LogManager.getLogger(InsertionFactory.class.getName());
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
||||
VehicleFleetManager vehicleFleetManager, StateManager stateManager, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager, boolean addDefaultCostCalculators){
|
||||
|
||||
if(config.containsKey("[@name]")){
|
||||
String insertionName = config.getString("[@name]");
|
||||
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
||||
throw new IllegalStateException(insertionName + " is not supported. use either \"bestInsertion\" or \"regretInsertion\"");
|
||||
}
|
||||
private static Logger log = LogManager.getLogger(InsertionFactory.class.getName());
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
||||
VehicleFleetManager vehicleFleetManager, StateManager stateManager, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager, boolean addDefaultCostCalculators) {
|
||||
|
||||
if (config.containsKey("[@name]")) {
|
||||
String insertionName = config.getString("[@name]");
|
||||
if (!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")) {
|
||||
throw new IllegalStateException(insertionName + " is not supported. use either \"bestInsertion\" or \"regretInsertion\"");
|
||||
}
|
||||
|
||||
|
||||
InsertionBuilder iBuilder = new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager);
|
||||
|
||||
if(executorService != null){
|
||||
iBuilder.setConcurrentMode(executorService, nuOfThreads);
|
||||
}
|
||||
|
||||
if(config.containsKey("level")){
|
||||
String level = config.getString("level");
|
||||
if(level.equals("local")){
|
||||
iBuilder.setLocalLevel(addDefaultCostCalculators);
|
||||
}
|
||||
else if(level.equals("route")){
|
||||
int forwardLooking = 0;
|
||||
int memory = 1;
|
||||
String forward = config.getString("level[@forwardLooking]");
|
||||
String mem = config.getString("level[@memory]");
|
||||
if(forward != null) forwardLooking = Integer.parseInt(forward);
|
||||
else log.warn("parameter route[@forwardLooking] is missing. by default it is 0 which equals to local level");
|
||||
if(mem != null) memory = Integer.parseInt(mem);
|
||||
else log.warn("parameter route[@memory] is missing. by default it is 1");
|
||||
iBuilder.setRouteLevel(forwardLooking, memory, addDefaultCostCalculators);
|
||||
}
|
||||
else throw new IllegalStateException("level " + level + " is not known. currently it only knows \"local\" or \"route\"");
|
||||
}
|
||||
else iBuilder.setLocalLevel(addDefaultCostCalculators);
|
||||
|
||||
if(config.containsKey("considerFixedCosts") || config.containsKey("considerFixedCost")){
|
||||
if(addDefaultCostCalculators){
|
||||
String val = config.getString("considerFixedCosts");
|
||||
if(val == null) val = config.getString("considerFixedCost");
|
||||
if(val.equals("true")){
|
||||
double fixedCostWeight = 0.5;
|
||||
String weight = config.getString("considerFixedCosts[@weight]");
|
||||
if(weight == null) weight = config.getString("considerFixedCost[@weight]");
|
||||
if(weight != null) fixedCostWeight = Double.parseDouble(weight);
|
||||
else throw new IllegalStateException("fixedCostsParameter 'weight' must be set, e.g. <considerFixedCosts weight=1.0>true</considerFixedCosts>.\n" +
|
||||
"this has to be changed in algorithm-config-xml-file.");
|
||||
iBuilder.considerFixedCosts(fixedCostWeight);
|
||||
}
|
||||
else if(val.equals("false")){
|
||||
if (executorService != null) {
|
||||
iBuilder.setConcurrentMode(executorService, nuOfThreads);
|
||||
}
|
||||
|
||||
}
|
||||
else throw new IllegalStateException("considerFixedCosts must either be true or false, i.e. <considerFixedCosts weight=1.0>true</considerFixedCosts> or \n<considerFixedCosts weight=1.0>false</considerFixedCosts>. " +
|
||||
"if latter, you can also omit the tag. this has to be changed in algorithm-config-xml-file");
|
||||
}
|
||||
}
|
||||
String timeSliceString = config.getString("experimental[@timeSlice]");
|
||||
String neighbors = config.getString("experimental[@neighboringSlices]");
|
||||
if(timeSliceString != null && neighbors != null){
|
||||
iBuilder.experimentalTimeScheduler(Double.parseDouble(timeSliceString),Integer.parseInt(neighbors));
|
||||
}
|
||||
String allowVehicleSwitch = config.getString("allowVehicleSwitch");
|
||||
if(allowVehicleSwitch != null){
|
||||
iBuilder.setAllowVehicleSwitch(Boolean.parseBoolean(allowVehicleSwitch));
|
||||
}
|
||||
if (config.containsKey("level")) {
|
||||
String level = config.getString("level");
|
||||
if (level.equals("local")) {
|
||||
iBuilder.setLocalLevel(addDefaultCostCalculators);
|
||||
} else if (level.equals("route")) {
|
||||
int forwardLooking = 0;
|
||||
int memory = 1;
|
||||
String forward = config.getString("level[@forwardLooking]");
|
||||
String mem = config.getString("level[@memory]");
|
||||
if (forward != null) forwardLooking = Integer.parseInt(forward);
|
||||
else
|
||||
log.warn("parameter route[@forwardLooking] is missing. by default it is 0 which equals to local level");
|
||||
if (mem != null) memory = Integer.parseInt(mem);
|
||||
else log.warn("parameter route[@memory] is missing. by default it is 1");
|
||||
iBuilder.setRouteLevel(forwardLooking, memory, addDefaultCostCalculators);
|
||||
} else
|
||||
throw new IllegalStateException("level " + level + " is not known. currently it only knows \"local\" or \"route\"");
|
||||
} else iBuilder.setLocalLevel(addDefaultCostCalculators);
|
||||
|
||||
if(insertionName.equals("regretInsertion")){
|
||||
if (config.containsKey("considerFixedCosts") || config.containsKey("considerFixedCost")) {
|
||||
if (addDefaultCostCalculators) {
|
||||
String val = config.getString("considerFixedCosts");
|
||||
if (val == null) val = config.getString("considerFixedCost");
|
||||
if (val.equals("true")) {
|
||||
double fixedCostWeight = 0.5;
|
||||
String weight = config.getString("considerFixedCosts[@weight]");
|
||||
if (weight == null) weight = config.getString("considerFixedCost[@weight]");
|
||||
if (weight != null) fixedCostWeight = Double.parseDouble(weight);
|
||||
else
|
||||
throw new IllegalStateException("fixedCostsParameter 'weight' must be set, e.g. <considerFixedCosts weight=1.0>true</considerFixedCosts>.\n" +
|
||||
"this has to be changed in algorithm-config-xml-file.");
|
||||
iBuilder.considerFixedCosts(fixedCostWeight);
|
||||
} else if (val.equals("false")) {
|
||||
|
||||
} else
|
||||
throw new IllegalStateException("considerFixedCosts must either be true or false, i.e. <considerFixedCosts weight=1.0>true</considerFixedCosts> or \n<considerFixedCosts weight=1.0>false</considerFixedCosts>. " +
|
||||
"if latter, you can also omit the tag. this has to be changed in algorithm-config-xml-file");
|
||||
}
|
||||
}
|
||||
String timeSliceString = config.getString("experimental[@timeSlice]");
|
||||
String neighbors = config.getString("experimental[@neighboringSlices]");
|
||||
if (timeSliceString != null && neighbors != null) {
|
||||
iBuilder.experimentalTimeScheduler(Double.parseDouble(timeSliceString), Integer.parseInt(neighbors));
|
||||
}
|
||||
String allowVehicleSwitch = config.getString("allowVehicleSwitch");
|
||||
if (allowVehicleSwitch != null) {
|
||||
iBuilder.setAllowVehicleSwitch(Boolean.parseBoolean(allowVehicleSwitch));
|
||||
}
|
||||
|
||||
if (insertionName.equals("regretInsertion")) {
|
||||
iBuilder.setInsertionStrategy(InsertionBuilder.Strategy.REGRET);
|
||||
}
|
||||
return iBuilder.build();
|
||||
}
|
||||
else throw new IllegalStateException("cannot create insertionStrategy, since it has no name.");
|
||||
}
|
||||
return iBuilder.build();
|
||||
} else throw new IllegalStateException("cannot create insertionStrategy, since it has no name.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
|
@ -22,10 +22,8 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
public interface AlgorithmEndsListener extends VehicleRoutingAlgorithmListener {
|
||||
|
||||
void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
public interface AlgorithmEndsListener extends VehicleRoutingAlgorithmListener{
|
||||
|
||||
void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
|
@ -23,10 +23,8 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
public interface AlgorithmStartsListener extends VehicleRoutingAlgorithmListener {
|
||||
|
||||
void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
public interface AlgorithmStartsListener extends VehicleRoutingAlgorithmListener{
|
||||
|
||||
void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
|
@ -22,12 +22,9 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
public interface IterationEndsListener extends VehicleRoutingAlgorithmListener {
|
||||
|
||||
public void informIterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
|
||||
|
||||
public interface IterationEndsListener extends VehicleRoutingAlgorithmListener{
|
||||
|
||||
public void informIterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
|
@ -22,11 +22,9 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
public interface IterationStartsListener extends VehicleRoutingAlgorithmListener {
|
||||
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
|
||||
public interface IterationStartsListener extends VehicleRoutingAlgorithmListener{
|
||||
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
||||
public interface SearchStrategyListener extends VehicleRoutingAlgorithmListener{
|
||||
public interface SearchStrategyListener extends VehicleRoutingAlgorithmListener {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
||||
public interface SearchStrategyModuleListener extends VehicleRoutingAlgorithmListener{
|
||||
public interface SearchStrategyModuleListener extends VehicleRoutingAlgorithmListener {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
|
@ -23,10 +23,8 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
public interface StrategySelectedListener extends VehicleRoutingAlgorithmListener {
|
||||
|
||||
void informSelectedStrategy(SearchStrategy.DiscoveredSolution discoveredSolution, VehicleRoutingProblem vehicleRoutingProblem, Collection<VehicleRoutingProblemSolution> vehicleRoutingProblemSolutions);
|
||||
|
||||
public interface StrategySelectedListener extends VehicleRoutingAlgorithmListener{
|
||||
|
||||
void informSelectedStrategy(SearchStrategy.DiscoveredSolution discoveredSolution, VehicleRoutingProblem vehicleRoutingProblem, Collection<VehicleRoutingProblemSolution> vehicleRoutingProblemSolutions);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.listener;
|
||||
|
|
@ -24,26 +24,27 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
|||
import java.util.*;
|
||||
|
||||
|
||||
|
||||
|
||||
public class VehicleRoutingAlgorithmListeners {
|
||||
|
||||
public static class PrioritizedVRAListener {
|
||||
|
||||
Priority priority;
|
||||
VehicleRoutingAlgorithmListener l;
|
||||
public PrioritizedVRAListener(Priority priority, VehicleRoutingAlgorithmListener l) {
|
||||
super();
|
||||
this.priority = priority;
|
||||
this.l = l;
|
||||
}
|
||||
public Priority getPriority() {
|
||||
return priority;
|
||||
}
|
||||
public VehicleRoutingAlgorithmListener getListener() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public static class PrioritizedVRAListener {
|
||||
|
||||
Priority priority;
|
||||
VehicleRoutingAlgorithmListener l;
|
||||
|
||||
public PrioritizedVRAListener(Priority priority, VehicleRoutingAlgorithmListener l) {
|
||||
super();
|
||||
this.priority = priority;
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
public Priority getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public VehicleRoutingAlgorithmListener getListener() {
|
||||
return l;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public int hashCode() {
|
||||
// final int prime = 31;
|
||||
|
|
@ -74,109 +75,106 @@ public class VehicleRoutingAlgorithmListeners {
|
|||
// return false;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
public enum Priority {
|
||||
HIGH, MEDIUM, LOW
|
||||
}
|
||||
|
||||
|
||||
private TreeSet<PrioritizedVRAListener> algorithmListeners = new TreeSet<PrioritizedVRAListener>(new Comparator<PrioritizedVRAListener>() {
|
||||
|
||||
@Override
|
||||
public int compare(PrioritizedVRAListener o1, PrioritizedVRAListener o2) {
|
||||
if(o1 == o2) return 0;
|
||||
if(o1.getPriority() == Priority.HIGH && o2.getPriority() != Priority.HIGH){
|
||||
return -1;
|
||||
}
|
||||
else if(o2.getPriority() == Priority.HIGH && o1.getPriority() != Priority.HIGH){
|
||||
return 1;
|
||||
}
|
||||
else if(o1.getPriority() == Priority.MEDIUM && o2.getPriority() != Priority.MEDIUM){
|
||||
return -1;
|
||||
}
|
||||
else if(o2.getPriority() == Priority.MEDIUM && o1.getPriority() != Priority.MEDIUM){
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
public Collection<VehicleRoutingAlgorithmListener> getAlgorithmListeners() {
|
||||
List<VehicleRoutingAlgorithmListener> list = new ArrayList<VehicleRoutingAlgorithmListener>();
|
||||
for(PrioritizedVRAListener l : algorithmListeners){
|
||||
list.add(l.getListener());
|
||||
}
|
||||
return Collections.unmodifiableCollection(list);
|
||||
}
|
||||
|
||||
public void remove(PrioritizedVRAListener listener){
|
||||
boolean removed = algorithmListeners.remove(listener);
|
||||
if(!removed){ throw new IllegalStateException("cannot remove listener"); }
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(VehicleRoutingAlgorithmListener listener, Priority priority){
|
||||
algorithmListeners.add(new PrioritizedVRAListener(priority, listener));
|
||||
}
|
||||
|
||||
public void addListener(VehicleRoutingAlgorithmListener listener){
|
||||
addListener(listener, Priority.LOW);
|
||||
}
|
||||
|
||||
public void algorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for(PrioritizedVRAListener l : algorithmListeners){
|
||||
if(l.getListener() instanceof AlgorithmEndsListener){
|
||||
((AlgorithmEndsListener)l.getListener()).informAlgorithmEnds(problem, solutions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void iterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for(PrioritizedVRAListener l : algorithmListeners){
|
||||
if(l.getListener() instanceof IterationEndsListener){
|
||||
((IterationEndsListener)l.getListener()).informIterationEnds(i,problem, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
public enum Priority {
|
||||
HIGH, MEDIUM, LOW
|
||||
}
|
||||
|
||||
|
||||
private TreeSet<PrioritizedVRAListener> algorithmListeners = new TreeSet<PrioritizedVRAListener>(new Comparator<PrioritizedVRAListener>() {
|
||||
|
||||
public void iterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for(PrioritizedVRAListener l : algorithmListeners){
|
||||
if(l.getListener() instanceof IterationStartsListener){
|
||||
((IterationStartsListener)l.getListener()).informIterationStarts(i,problem, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int compare(PrioritizedVRAListener o1, PrioritizedVRAListener o2) {
|
||||
if (o1 == o2) return 0;
|
||||
if (o1.getPriority() == Priority.HIGH && o2.getPriority() != Priority.HIGH) {
|
||||
return -1;
|
||||
} else if (o2.getPriority() == Priority.HIGH && o1.getPriority() != Priority.HIGH) {
|
||||
return 1;
|
||||
} else if (o1.getPriority() == Priority.MEDIUM && o2.getPriority() != Priority.MEDIUM) {
|
||||
return -1;
|
||||
} else if (o2.getPriority() == Priority.MEDIUM && o1.getPriority() != Priority.MEDIUM) {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
public void algorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for(PrioritizedVRAListener l : algorithmListeners){
|
||||
if(l.getListener() instanceof AlgorithmStartsListener){
|
||||
((AlgorithmStartsListener)l.getListener()).informAlgorithmStarts(problem, algorithm, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Collection<VehicleRoutingAlgorithmListener> getAlgorithmListeners() {
|
||||
List<VehicleRoutingAlgorithmListener> list = new ArrayList<VehicleRoutingAlgorithmListener>();
|
||||
for (PrioritizedVRAListener l : algorithmListeners) {
|
||||
list.add(l.getListener());
|
||||
}
|
||||
return Collections.unmodifiableCollection(list);
|
||||
}
|
||||
|
||||
public void add(PrioritizedVRAListener l){
|
||||
algorithmListeners.add(l);
|
||||
}
|
||||
|
||||
public void addAll(Collection<PrioritizedVRAListener> algorithmListeners) {
|
||||
for(PrioritizedVRAListener l : algorithmListeners){
|
||||
this.algorithmListeners.add(l);
|
||||
}
|
||||
}
|
||||
public void remove(PrioritizedVRAListener listener) {
|
||||
boolean removed = algorithmListeners.remove(listener);
|
||||
if (!removed) {
|
||||
throw new IllegalStateException("cannot remove listener");
|
||||
}
|
||||
}
|
||||
|
||||
public void selectedStrategy(SearchStrategy.DiscoveredSolution discoveredSolution, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for(PrioritizedVRAListener l : algorithmListeners){
|
||||
if(l.getListener() instanceof StrategySelectedListener){
|
||||
((StrategySelectedListener)l.getListener()).informSelectedStrategy(discoveredSolution, problem, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void addListener(VehicleRoutingAlgorithmListener listener, Priority priority) {
|
||||
algorithmListeners.add(new PrioritizedVRAListener(priority, listener));
|
||||
}
|
||||
|
||||
public void addListener(VehicleRoutingAlgorithmListener listener) {
|
||||
addListener(listener, Priority.LOW);
|
||||
}
|
||||
|
||||
public void algorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for (PrioritizedVRAListener l : algorithmListeners) {
|
||||
if (l.getListener() instanceof AlgorithmEndsListener) {
|
||||
((AlgorithmEndsListener) l.getListener()).informAlgorithmEnds(problem, solutions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void iterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for (PrioritizedVRAListener l : algorithmListeners) {
|
||||
if (l.getListener() instanceof IterationEndsListener) {
|
||||
((IterationEndsListener) l.getListener()).informIterationEnds(i, problem, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void iterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for (PrioritizedVRAListener l : algorithmListeners) {
|
||||
if (l.getListener() instanceof IterationStartsListener) {
|
||||
((IterationStartsListener) l.getListener()).informIterationStarts(i, problem, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void algorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for (PrioritizedVRAListener l : algorithmListeners) {
|
||||
if (l.getListener() instanceof AlgorithmStartsListener) {
|
||||
((AlgorithmStartsListener) l.getListener()).informAlgorithmStarts(problem, algorithm, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void add(PrioritizedVRAListener l) {
|
||||
algorithmListeners.add(l);
|
||||
}
|
||||
|
||||
public void addAll(Collection<PrioritizedVRAListener> algorithmListeners) {
|
||||
for (PrioritizedVRAListener l : algorithmListeners) {
|
||||
this.algorithmListeners.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
public void selectedStrategy(SearchStrategy.DiscoveredSolution discoveredSolution, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
for (PrioritizedVRAListener l : algorithmListeners) {
|
||||
if (l.getListener() instanceof StrategySelectedListener) {
|
||||
((StrategySelectedListener) l.getListener()).informSelectedStrategy(discoveredSolution, problem, solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.module;
|
||||
|
|
@ -30,61 +30,61 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
|
||||
|
||||
public class RuinAndRecreateModule implements SearchStrategyModule{
|
||||
public class RuinAndRecreateModule implements SearchStrategyModule {
|
||||
|
||||
private InsertionStrategy insertion;
|
||||
|
||||
private RuinStrategy ruin;
|
||||
|
||||
private String moduleName;
|
||||
|
||||
public RuinAndRecreateModule(String moduleName, InsertionStrategy insertion, RuinStrategy ruin) {
|
||||
super();
|
||||
this.insertion = insertion;
|
||||
this.ruin = ruin;
|
||||
this.moduleName = moduleName;
|
||||
}
|
||||
private InsertionStrategy insertion;
|
||||
|
||||
@Override
|
||||
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
||||
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
|
||||
private RuinStrategy ruin;
|
||||
|
||||
private String moduleName;
|
||||
|
||||
public RuinAndRecreateModule(String moduleName, InsertionStrategy insertion, RuinStrategy ruin) {
|
||||
super();
|
||||
this.insertion = insertion;
|
||||
this.ruin = ruin;
|
||||
this.moduleName = moduleName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
||||
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
|
||||
Set<Job> ruinedJobSet = new HashSet<Job>();
|
||||
ruinedJobSet.addAll(ruinedJobs);
|
||||
ruinedJobSet.addAll(vrpSolution.getUnassignedJobs());
|
||||
Collection<Job> unassignedJobs = insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobSet);
|
||||
Collection<Job> unassignedJobs = insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobSet);
|
||||
vrpSolution.getUnassignedJobs().clear();
|
||||
vrpSolution.getUnassignedJobs().addAll(unassignedJobs);
|
||||
return vrpSolution;
|
||||
return vrpSolution;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return moduleName;
|
||||
}
|
||||
@Override
|
||||
public String getName() {
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
|
||||
if(moduleListener instanceof InsertionListener){
|
||||
InsertionListener iListener = (InsertionListener) moduleListener;
|
||||
if(!insertion.getListeners().contains(iListener)){
|
||||
insertion.addListener(iListener);
|
||||
}
|
||||
}
|
||||
if(moduleListener instanceof RuinListener){
|
||||
RuinListener rListener = (RuinListener) moduleListener;
|
||||
if(!ruin.getListeners().contains(rListener)){
|
||||
ruin.addListener(rListener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
|
||||
if (moduleListener instanceof InsertionListener) {
|
||||
InsertionListener iListener = (InsertionListener) moduleListener;
|
||||
if (!insertion.getListeners().contains(iListener)) {
|
||||
insertion.addListener(iListener);
|
||||
}
|
||||
}
|
||||
if (moduleListener instanceof RuinListener) {
|
||||
RuinListener rListener = (RuinListener) moduleListener;
|
||||
if (!ruin.getListeners().contains(rListener)) {
|
||||
ruin.addListener(rListener);
|
||||
}
|
||||
}
|
||||
|
||||
public InsertionStrategy getInsertion() {
|
||||
return insertion;
|
||||
}
|
||||
}
|
||||
|
||||
public RuinStrategy getRuin() {
|
||||
return ruin;
|
||||
}
|
||||
public InsertionStrategy getInsertion() {
|
||||
return insertion;
|
||||
}
|
||||
|
||||
public RuinStrategy getRuin() {
|
||||
return ruin;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
|
||||
public abstract class AbstractInsertionStrategy implements InsertionStrategy{
|
||||
public abstract class AbstractInsertionStrategy implements InsertionStrategy {
|
||||
|
||||
protected class Insertion {
|
||||
|
||||
|
|
@ -84,9 +84,9 @@ public abstract class AbstractInsertionStrategy implements InsertionStrategy{
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs){
|
||||
public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
insertionsListeners.informInsertionStarts(vehicleRoutes, unassignedJobs);
|
||||
Collection<Job> badJobs = insertUnassignedJobs(vehicleRoutes,unassignedJobs);
|
||||
Collection<Job> badJobs = insertUnassignedJobs(vehicleRoutes, unassignedJobs);
|
||||
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
|
||||
return badJobs;
|
||||
}
|
||||
|
|
@ -109,13 +109,13 @@ public abstract class AbstractInsertionStrategy implements InsertionStrategy{
|
|||
|
||||
}
|
||||
|
||||
protected void insertJob(Job unassignedJob, InsertionData iData, VehicleRoute inRoute){
|
||||
protected void insertJob(Job unassignedJob, InsertionData iData, VehicleRoute inRoute) {
|
||||
logger.trace("insert: [jobId={}]{}", unassignedJob.getId(), iData);
|
||||
insertionsListeners.informBeforeJobInsertion(unassignedJob, iData, inRoute);
|
||||
if(!(inRoute.getVehicle().getId().equals(iData.getSelectedVehicle().getId()))){
|
||||
if (!(inRoute.getVehicle().getId().equals(iData.getSelectedVehicle().getId()))) {
|
||||
insertionsListeners.informVehicleSwitched(inRoute, inRoute.getVehicle(), iData.getSelectedVehicle());
|
||||
}
|
||||
for(Event e : iData.getEvents()){
|
||||
for (Event e : iData.getEvents()) {
|
||||
eventListeners.inform(e);
|
||||
}
|
||||
insertionsListeners.informJobInserted(unassignedJob, inRoute, iData.getInsertionCost(), iData.getAdditionalTime());
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2014 Stefan Schroeder
|
||||
*
|
||||
|
|
@ -22,33 +21,35 @@ import jsprit.core.problem.misc.JobInsertionContext;
|
|||
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
|
||||
public interface ActivityInsertionCostsCalculator {
|
||||
|
||||
public class ActivityInsertionCosts {
|
||||
|
||||
private double additionalCosts;
|
||||
private double additionalTime;
|
||||
public ActivityInsertionCosts(double additionalCosts, double additionalTime) {
|
||||
super();
|
||||
this.additionalCosts = additionalCosts;
|
||||
this.additionalTime = additionalTime;
|
||||
}
|
||||
/**
|
||||
* @return the additionalCosts
|
||||
*/
|
||||
public double getAdditionalCosts() {
|
||||
return additionalCosts;
|
||||
}
|
||||
/**
|
||||
* @return the additionalTime
|
||||
*/
|
||||
public double getAdditionalTime() {
|
||||
return additionalTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public double getCosts(JobInsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
|
||||
public class ActivityInsertionCosts {
|
||||
|
||||
private double additionalCosts;
|
||||
private double additionalTime;
|
||||
|
||||
public ActivityInsertionCosts(double additionalCosts, double additionalTime) {
|
||||
super();
|
||||
this.additionalCosts = additionalCosts;
|
||||
this.additionalTime = additionalTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the additionalCosts
|
||||
*/
|
||||
public double getAdditionalCosts() {
|
||||
return additionalCosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the additionalTime
|
||||
*/
|
||||
public double getAdditionalTime() {
|
||||
return additionalTime;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public double getCosts(JobInsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,52 +25,50 @@ import jsprit.core.problem.vehicle.Vehicle;
|
|||
|
||||
/**
|
||||
* Estimates additional access/egress costs when operating route with a new vehicle that has different start/end-location.
|
||||
*
|
||||
* <p/>
|
||||
* <p>If two vehicles have the same start/end-location and departure-time .getCosts(...) must return zero.
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
class AdditionalAccessEgressCalculator {
|
||||
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
/**
|
||||
* Constructs the estimator that estimates additional access/egress costs when operating route with a new vehicle that has different start/end-location.
|
||||
*
|
||||
* <p>If two vehicles have the same start/end-location and departure-time .getCosts(...) must return zero.
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
*/
|
||||
public AdditionalAccessEgressCalculator(VehicleRoutingTransportCosts routingCosts) {
|
||||
this.routingCosts = routingCosts;
|
||||
}
|
||||
|
||||
public double getCosts(JobInsertionContext insertionContext){
|
||||
double delta_access = 0.0;
|
||||
double delta_egress = 0.0;
|
||||
VehicleRoute currentRoute = insertionContext.getRoute();
|
||||
Vehicle newVehicle = insertionContext.getNewVehicle();
|
||||
Driver newDriver = insertionContext.getNewDriver();
|
||||
double newVehicleDepartureTime = insertionContext.getNewDepTime();
|
||||
if(!currentRoute.isEmpty()){
|
||||
double accessTransportCostNew = routingCosts.getTransportCost(newVehicle.getStartLocation(), currentRoute.getActivities().get(0).getLocation(), newVehicleDepartureTime, newDriver, newVehicle);
|
||||
double accessTransportCostOld = routingCosts.getTransportCost(currentRoute.getStart().getLocation(), currentRoute.getActivities().get(0).getLocation(), currentRoute.getDepartureTime(), currentRoute.getDriver(), currentRoute.getVehicle());
|
||||
|
||||
delta_access = accessTransportCostNew - accessTransportCostOld;
|
||||
|
||||
if(newVehicle.isReturnToDepot()){
|
||||
TourActivity lastActivityBeforeEndOfRoute = currentRoute.getActivities().get(currentRoute.getActivities().size()-1);
|
||||
double lastActivityEndTimeWithOldVehicleAndDepartureTime = lastActivityBeforeEndOfRoute.getEndTime();
|
||||
double lastActivityEndTimeEstimationWithNewVehicleAndNewDepartureTime = Math.max(0.0, lastActivityEndTimeWithOldVehicleAndDepartureTime + (newVehicleDepartureTime - currentRoute.getDepartureTime()));
|
||||
double egressTransportCostNew = routingCosts.getTransportCost(lastActivityBeforeEndOfRoute.getLocation(), newVehicle.getEndLocation() , lastActivityEndTimeEstimationWithNewVehicleAndNewDepartureTime, newDriver, newVehicle);
|
||||
double egressTransportCostOld = routingCosts.getTransportCost(lastActivityBeforeEndOfRoute.getLocation(), currentRoute.getEnd().getLocation(), lastActivityEndTimeWithOldVehicleAndDepartureTime, currentRoute.getDriver(), currentRoute.getVehicle());
|
||||
|
||||
delta_egress = egressTransportCostNew - egressTransportCostOld;
|
||||
}
|
||||
}
|
||||
return delta_access + delta_egress;
|
||||
}
|
||||
|
||||
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
/**
|
||||
* Constructs the estimator that estimates additional access/egress costs when operating route with a new vehicle that has different start/end-location.
|
||||
* <p/>
|
||||
* <p>If two vehicles have the same start/end-location and departure-time .getCosts(...) must return zero.
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public AdditionalAccessEgressCalculator(VehicleRoutingTransportCosts routingCosts) {
|
||||
this.routingCosts = routingCosts;
|
||||
}
|
||||
|
||||
public double getCosts(JobInsertionContext insertionContext) {
|
||||
double delta_access = 0.0;
|
||||
double delta_egress = 0.0;
|
||||
VehicleRoute currentRoute = insertionContext.getRoute();
|
||||
Vehicle newVehicle = insertionContext.getNewVehicle();
|
||||
Driver newDriver = insertionContext.getNewDriver();
|
||||
double newVehicleDepartureTime = insertionContext.getNewDepTime();
|
||||
if (!currentRoute.isEmpty()) {
|
||||
double accessTransportCostNew = routingCosts.getTransportCost(newVehicle.getStartLocation(), currentRoute.getActivities().get(0).getLocation(), newVehicleDepartureTime, newDriver, newVehicle);
|
||||
double accessTransportCostOld = routingCosts.getTransportCost(currentRoute.getStart().getLocation(), currentRoute.getActivities().get(0).getLocation(), currentRoute.getDepartureTime(), currentRoute.getDriver(), currentRoute.getVehicle());
|
||||
|
||||
delta_access = accessTransportCostNew - accessTransportCostOld;
|
||||
|
||||
if (newVehicle.isReturnToDepot()) {
|
||||
TourActivity lastActivityBeforeEndOfRoute = currentRoute.getActivities().get(currentRoute.getActivities().size() - 1);
|
||||
double lastActivityEndTimeWithOldVehicleAndDepartureTime = lastActivityBeforeEndOfRoute.getEndTime();
|
||||
double lastActivityEndTimeEstimationWithNewVehicleAndNewDepartureTime = Math.max(0.0, lastActivityEndTimeWithOldVehicleAndDepartureTime + (newVehicleDepartureTime - currentRoute.getDepartureTime()));
|
||||
double egressTransportCostNew = routingCosts.getTransportCost(lastActivityBeforeEndOfRoute.getLocation(), newVehicle.getEndLocation(), lastActivityEndTimeEstimationWithNewVehicleAndNewDepartureTime, newDriver, newVehicle);
|
||||
double egressTransportCostOld = routingCosts.getTransportCost(lastActivityBeforeEndOfRoute.getLocation(), currentRoute.getEnd().getLocation(), lastActivityEndTimeWithOldVehicleAndDepartureTime, currentRoute.getDriver(), currentRoute.getVehicle());
|
||||
|
||||
delta_egress = egressTransportCostNew - egressTransportCostOld;
|
||||
}
|
||||
}
|
||||
return delta_access + delta_egress;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -27,54 +27,52 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
final class AuxilliaryCostCalculator {
|
||||
|
||||
private final VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
private final VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
public AuxilliaryCostCalculator(final VehicleRoutingTransportCosts routingCosts, final VehicleRoutingActivityCosts actCosts) {
|
||||
super();
|
||||
this.routingCosts = routingCosts;
|
||||
this.activityCosts = actCosts;
|
||||
}
|
||||
private final VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
private final VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
public AuxilliaryCostCalculator(final VehicleRoutingTransportCosts routingCosts, final VehicleRoutingActivityCosts actCosts) {
|
||||
super();
|
||||
this.routingCosts = routingCosts;
|
||||
this.activityCosts = actCosts;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path activity path to get the costs for
|
||||
* @param path activity path to get the costs for
|
||||
* @param depTime departure time at first activity in path
|
||||
* @param driver driver of vehicle
|
||||
* @param driver driver of vehicle
|
||||
* @param vehicle vehicle running the path
|
||||
* @return cost of path
|
||||
*/
|
||||
public double costOfPath(final List<TourActivity> path, final double depTime, final Driver driver, final Vehicle vehicle){
|
||||
if(path.isEmpty()){
|
||||
return 0.0;
|
||||
}
|
||||
double cost = 0.0;
|
||||
Iterator<TourActivity> actIter = path.iterator();
|
||||
TourActivity prevAct = actIter.next();
|
||||
double startCost = 0.0;
|
||||
cost += startCost;
|
||||
double departureTimePrevAct = depTime;
|
||||
while(actIter.hasNext()){
|
||||
TourActivity act = actIter.next();
|
||||
if(act instanceof End){
|
||||
if(!vehicle.isReturnToDepot()){
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
double transportCost = routingCosts.getTransportCost(prevAct.getLocation(), act.getLocation(), departureTimePrevAct, driver, vehicle);
|
||||
double transportTime = routingCosts.getTransportTime(prevAct.getLocation(), act.getLocation(), departureTimePrevAct, driver, vehicle);
|
||||
cost += transportCost;
|
||||
double actStartTime = departureTimePrevAct + transportTime;
|
||||
public double costOfPath(final List<TourActivity> path, final double depTime, final Driver driver, final Vehicle vehicle) {
|
||||
if (path.isEmpty()) {
|
||||
return 0.0;
|
||||
}
|
||||
double cost = 0.0;
|
||||
Iterator<TourActivity> actIter = path.iterator();
|
||||
TourActivity prevAct = actIter.next();
|
||||
double startCost = 0.0;
|
||||
cost += startCost;
|
||||
double departureTimePrevAct = depTime;
|
||||
while (actIter.hasNext()) {
|
||||
TourActivity act = actIter.next();
|
||||
if (act instanceof End) {
|
||||
if (!vehicle.isReturnToDepot()) {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
double transportCost = routingCosts.getTransportCost(prevAct.getLocation(), act.getLocation(), departureTimePrevAct, driver, vehicle);
|
||||
double transportTime = routingCosts.getTransportTime(prevAct.getLocation(), act.getLocation(), departureTimePrevAct, driver, vehicle);
|
||||
cost += transportCost;
|
||||
double actStartTime = departureTimePrevAct + transportTime;
|
||||
departureTimePrevAct = Math.max(actStartTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime();
|
||||
cost += activityCosts.getActivityCost(act, actStartTime, driver, vehicle);
|
||||
prevAct = act;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
||||
cost += activityCosts.getActivityCost(act, actStartTime, driver, vehicle);
|
||||
prevAct = act;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -30,70 +30,67 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Best insertion that insert the job where additional costs are minimal.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
public final class BestInsertion extends AbstractInsertionStrategy{
|
||||
public final class BestInsertion extends AbstractInsertionStrategy {
|
||||
|
||||
private static Logger logger = LogManager.getLogger(BestInsertion.class);
|
||||
private static Logger logger = LogManager.getLogger(BestInsertion.class);
|
||||
|
||||
private JobInsertionCostsCalculator bestInsertionCostCalculator;
|
||||
private JobInsertionCostsCalculator bestInsertionCostCalculator;
|
||||
|
||||
private NoiseMaker noiseMaker = new NoiseMaker() {
|
||||
private NoiseMaker noiseMaker = new NoiseMaker() {
|
||||
|
||||
@Override
|
||||
public double makeNoise() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public double makeNoise() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
public BestInsertion(JobInsertionCostsCalculator jobInsertionCalculator, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
super(vehicleRoutingProblem);
|
||||
bestInsertionCostCalculator = jobInsertionCalculator;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
public BestInsertion(JobInsertionCostsCalculator jobInsertionCalculator, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
super(vehicleRoutingProblem);
|
||||
bestInsertionCostCalculator = jobInsertionCalculator;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=bestInsertion]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=bestInsertion]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
@Override
|
||||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
for(Job unassignedJob : unassignedJobList){
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
for(VehicleRoute vehicleRoute : vehicleRoutes){
|
||||
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if(iData instanceof NoInsertionFound) {
|
||||
continue;
|
||||
}
|
||||
if(iData.getInsertionCost() < bestInsertionCost + noiseMaker.makeNoise()){
|
||||
bestInsertion = new Insertion(vehicleRoute,iData);
|
||||
bestInsertionCost = iData.getInsertionCost();
|
||||
}
|
||||
}
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
for (Job unassignedJob : unassignedJobList) {
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
for (VehicleRoute vehicleRoute : vehicleRoutes) {
|
||||
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if (iData instanceof NoInsertionFound) {
|
||||
continue;
|
||||
}
|
||||
if (iData.getInsertionCost() < bestInsertionCost + noiseMaker.makeNoise()) {
|
||||
bestInsertion = new Insertion(vehicleRoute, iData);
|
||||
bestInsertionCost = iData.getInsertionCost();
|
||||
}
|
||||
}
|
||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if(!(newIData instanceof NoInsertionFound)){
|
||||
if(newIData.getInsertionCost() < bestInsertionCost + noiseMaker.makeNoise()){
|
||||
bestInsertion = new Insertion(newRoute,newIData);
|
||||
if (!(newIData instanceof NoInsertionFound)) {
|
||||
if (newIData.getInsertionCost() < bestInsertionCost + noiseMaker.makeNoise()) {
|
||||
bestInsertion = new Insertion(newRoute, newIData);
|
||||
vehicleRoutes.add(newRoute);
|
||||
}
|
||||
}
|
||||
if(bestInsertion == null) badJobs.add(unassignedJob);
|
||||
if (bestInsertion == null) badJobs.add(unassignedJob);
|
||||
else insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||
}
|
||||
return badJobs;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,150 +30,154 @@ import java.util.concurrent.ExecutorService;
|
|||
|
||||
public class BestInsertionBuilder {
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private StateManager stateManager;
|
||||
|
||||
private boolean local = true;
|
||||
|
||||
private ConstraintManager constraintManager;
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private VehicleFleetManager fleetManager;
|
||||
private StateManager stateManager;
|
||||
|
||||
private double weightOfFixedCosts;
|
||||
private boolean local = true;
|
||||
|
||||
private boolean considerFixedCosts = false;
|
||||
private ConstraintManager constraintManager;
|
||||
|
||||
private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null;
|
||||
private VehicleFleetManager fleetManager;
|
||||
|
||||
private int forwaredLooking;
|
||||
private double weightOfFixedCosts;
|
||||
|
||||
private int memory;
|
||||
private boolean considerFixedCosts = false;
|
||||
|
||||
private ExecutorService executor;
|
||||
private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null;
|
||||
|
||||
private int nuOfThreads;
|
||||
private int forwaredLooking;
|
||||
|
||||
private double timeSlice;
|
||||
private int memory;
|
||||
|
||||
private int nNeighbors;
|
||||
private ExecutorService executor;
|
||||
|
||||
private boolean timeScheduling=false;
|
||||
private int nuOfThreads;
|
||||
|
||||
private boolean allowVehicleSwitch=true;
|
||||
private double timeSlice;
|
||||
|
||||
private boolean addDefaultCostCalc=true;
|
||||
|
||||
public BestInsertionBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.stateManager = stateManager;
|
||||
this.constraintManager = constraintManager;
|
||||
this.fleetManager = vehicleFleetManager;
|
||||
}
|
||||
|
||||
public BestInsertionBuilder setRouteLevel(int forwardLooking, int memory){
|
||||
local = false;
|
||||
this.forwaredLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
return this;
|
||||
};
|
||||
|
||||
public BestInsertionBuilder setRouteLevel(int forwardLooking, int memory, boolean addDefaultMarginalCostCalculation){
|
||||
local = false;
|
||||
this.forwaredLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
this.addDefaultCostCalc = addDefaultMarginalCostCalculation;
|
||||
return this;
|
||||
};
|
||||
|
||||
public BestInsertionBuilder setLocalLevel(){
|
||||
local = true;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* If addDefaulMarginalCostCalculation is false, no calculator is set which implicitly assumes that marginal cost calculation
|
||||
* is controlled by your custom soft constraints.
|
||||
*
|
||||
* @param addDefaultMarginalCostCalculation
|
||||
* @return
|
||||
*/
|
||||
public BestInsertionBuilder setLocalLevel(boolean addDefaultMarginalCostCalculation){
|
||||
local = true;
|
||||
addDefaultCostCalc = addDefaultMarginalCostCalculation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BestInsertionBuilder considerFixedCosts(double weightOfFixedCosts){
|
||||
this.weightOfFixedCosts = weightOfFixedCosts;
|
||||
this.considerFixedCosts = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BestInsertionBuilder setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
|
||||
this.actInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
return this;
|
||||
};
|
||||
|
||||
public BestInsertionBuilder setConcurrentMode(ExecutorService executor, int nuOfThreads){
|
||||
this.executor = executor;
|
||||
this.nuOfThreads = nuOfThreads;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public InsertionStrategy build() {
|
||||
List<InsertionListener> iListeners = new ArrayList<InsertionListener>();
|
||||
List<PrioritizedVRAListener> algorithmListeners = new ArrayList<PrioritizedVRAListener>();
|
||||
JobInsertionCostsCalculatorBuilder calcBuilder = new JobInsertionCostsCalculatorBuilder(iListeners, algorithmListeners);
|
||||
if(local){
|
||||
calcBuilder.setLocalLevel(addDefaultCostCalc);
|
||||
}
|
||||
else {
|
||||
calcBuilder.setRouteLevel(forwaredLooking, memory, addDefaultCostCalc);
|
||||
}
|
||||
calcBuilder.setConstraintManager(constraintManager);
|
||||
calcBuilder.setStateManager(stateManager);
|
||||
calcBuilder.setVehicleRoutingProblem(vrp);
|
||||
calcBuilder.setVehicleFleetManager(fleetManager);
|
||||
calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator);
|
||||
if(considerFixedCosts) {
|
||||
calcBuilder.considerFixedCosts(weightOfFixedCosts);
|
||||
}
|
||||
if(timeScheduling){
|
||||
calcBuilder.experimentalTimeScheduler(timeSlice, nNeighbors);
|
||||
}
|
||||
calcBuilder.setAllowVehicleSwitch(allowVehicleSwitch);
|
||||
JobInsertionCostsCalculator jobInsertions = calcBuilder.build();
|
||||
InsertionStrategy bestInsertion;
|
||||
if(executor == null){
|
||||
bestInsertion = new BestInsertion(jobInsertions,vrp);
|
||||
}
|
||||
else{
|
||||
bestInsertion = new BestInsertionConcurrent(jobInsertions,executor,nuOfThreads,vrp);
|
||||
private int nNeighbors;
|
||||
|
||||
private boolean timeScheduling = false;
|
||||
|
||||
private boolean allowVehicleSwitch = true;
|
||||
|
||||
private boolean addDefaultCostCalc = true;
|
||||
|
||||
public BestInsertionBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.stateManager = stateManager;
|
||||
this.constraintManager = constraintManager;
|
||||
this.fleetManager = vehicleFleetManager;
|
||||
}
|
||||
|
||||
public BestInsertionBuilder setRouteLevel(int forwardLooking, int memory) {
|
||||
local = false;
|
||||
this.forwaredLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
return this;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
public BestInsertionBuilder setRouteLevel(int forwardLooking, int memory, boolean addDefaultMarginalCostCalculation) {
|
||||
local = false;
|
||||
this.forwaredLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
this.addDefaultCostCalc = addDefaultMarginalCostCalculation;
|
||||
return this;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
public BestInsertionBuilder setLocalLevel() {
|
||||
local = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* If addDefaulMarginalCostCalculation is false, no calculator is set which implicitly assumes that marginal cost calculation
|
||||
* is controlled by your custom soft constraints.
|
||||
*
|
||||
* @param addDefaultMarginalCostCalculation
|
||||
* @return
|
||||
*/
|
||||
public BestInsertionBuilder setLocalLevel(boolean addDefaultMarginalCostCalculation) {
|
||||
local = true;
|
||||
addDefaultCostCalc = addDefaultMarginalCostCalculation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BestInsertionBuilder considerFixedCosts(double weightOfFixedCosts) {
|
||||
this.weightOfFixedCosts = weightOfFixedCosts;
|
||||
this.considerFixedCosts = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BestInsertionBuilder setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator) {
|
||||
this.actInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
return this;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
public BestInsertionBuilder setConcurrentMode(ExecutorService executor, int nuOfThreads) {
|
||||
this.executor = executor;
|
||||
this.nuOfThreads = nuOfThreads;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public InsertionStrategy build() {
|
||||
List<InsertionListener> iListeners = new ArrayList<InsertionListener>();
|
||||
List<PrioritizedVRAListener> algorithmListeners = new ArrayList<PrioritizedVRAListener>();
|
||||
JobInsertionCostsCalculatorBuilder calcBuilder = new JobInsertionCostsCalculatorBuilder(iListeners, algorithmListeners);
|
||||
if (local) {
|
||||
calcBuilder.setLocalLevel(addDefaultCostCalc);
|
||||
} else {
|
||||
calcBuilder.setRouteLevel(forwaredLooking, memory, addDefaultCostCalc);
|
||||
}
|
||||
for(InsertionListener l : iListeners) bestInsertion.addListener(l);
|
||||
return bestInsertion;
|
||||
}
|
||||
calcBuilder.setConstraintManager(constraintManager);
|
||||
calcBuilder.setStateManager(stateManager);
|
||||
calcBuilder.setVehicleRoutingProblem(vrp);
|
||||
calcBuilder.setVehicleFleetManager(fleetManager);
|
||||
calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator);
|
||||
if (considerFixedCosts) {
|
||||
calcBuilder.considerFixedCosts(weightOfFixedCosts);
|
||||
}
|
||||
if (timeScheduling) {
|
||||
calcBuilder.experimentalTimeScheduler(timeSlice, nNeighbors);
|
||||
}
|
||||
calcBuilder.setAllowVehicleSwitch(allowVehicleSwitch);
|
||||
JobInsertionCostsCalculator jobInsertions = calcBuilder.build();
|
||||
InsertionStrategy bestInsertion;
|
||||
if (executor == null) {
|
||||
bestInsertion = new BestInsertion(jobInsertions, vrp);
|
||||
} else {
|
||||
bestInsertion = new BestInsertionConcurrent(jobInsertions, executor, nuOfThreads, vrp);
|
||||
}
|
||||
for (InsertionListener l : iListeners) bestInsertion.addListener(l);
|
||||
return bestInsertion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this is experimental and can disappear.
|
||||
* @param timeSlice the time slice
|
||||
* @param nNeighbors number of neighbors
|
||||
*/
|
||||
@Deprecated
|
||||
public void experimentalTimeScheduler(double timeSlice, int nNeighbors) {
|
||||
this.timeSlice=timeSlice;
|
||||
this.nNeighbors=nNeighbors;
|
||||
timeScheduling=true;
|
||||
}
|
||||
/**
|
||||
* @param timeSlice the time slice
|
||||
* @param nNeighbors number of neighbors
|
||||
* @deprecated this is experimental and can disappear.
|
||||
*/
|
||||
@Deprecated
|
||||
public void experimentalTimeScheduler(double timeSlice, int nNeighbors) {
|
||||
this.timeSlice = timeSlice;
|
||||
this.nNeighbors = nNeighbors;
|
||||
timeScheduling = true;
|
||||
}
|
||||
|
||||
public void setAllowVehicleSwitch(boolean allowVehicleSwitch) {
|
||||
this.allowVehicleSwitch = allowVehicleSwitch;
|
||||
}
|
||||
|
||||
|
||||
public void setAllowVehicleSwitch(boolean allowVehicleSwitch) {
|
||||
this.allowVehicleSwitch = allowVehicleSwitch;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -30,171 +30,165 @@ import java.util.*;
|
|||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
|
||||
public final class BestInsertionConcurrent extends AbstractInsertionStrategy{
|
||||
|
||||
static class Batch {
|
||||
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
||||
|
||||
}
|
||||
|
||||
class Insertion {
|
||||
|
||||
private final VehicleRoute route;
|
||||
|
||||
private final InsertionData insertionData;
|
||||
public final class BestInsertionConcurrent extends AbstractInsertionStrategy {
|
||||
|
||||
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
|
||||
super();
|
||||
this.route = vehicleRoute;
|
||||
this.insertionData = insertionData;
|
||||
}
|
||||
static class Batch {
|
||||
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
||||
|
||||
public VehicleRoute getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public InsertionData getInsertionData() {
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Logger logger = LogManager.getLogger(BestInsertionConcurrent.class);
|
||||
|
||||
private final static double NO_NEW_DEPARTURE_TIME_YET = -12345.12345;
|
||||
|
||||
private final static Vehicle NO_NEW_VEHICLE_YET = null;
|
||||
|
||||
private final static Driver NO_NEW_DRIVER_YET = null;
|
||||
|
||||
private InsertionListeners insertionsListeners;
|
||||
|
||||
private JobInsertionCostsCalculator bestInsertionCostCalculator;
|
||||
}
|
||||
|
||||
private int nuOfBatches;
|
||||
class Insertion {
|
||||
|
||||
private ExecutorCompletionService<Insertion> completionService;
|
||||
private final VehicleRoute route;
|
||||
|
||||
@Deprecated
|
||||
public void setRandom(Random random) {
|
||||
super.random = random;
|
||||
}
|
||||
|
||||
public BestInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
super(vehicleRoutingProblem);
|
||||
this.insertionsListeners = new InsertionListeners();
|
||||
this.nuOfBatches = nuOfBatches;
|
||||
bestInsertionCostCalculator = jobInsertionCalculator;
|
||||
completionService = new ExecutorCompletionService<Insertion>(executorService);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
private final InsertionData insertionData;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=bestInsertion]";
|
||||
}
|
||||
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
|
||||
super();
|
||||
this.route = vehicleRoute;
|
||||
this.insertionData = insertionData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
|
||||
for(final Job unassignedJob : unassignedJobList){
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
for(final Batch batch : batches){
|
||||
completionService.submit(new Callable<Insertion>() {
|
||||
public VehicleRoute getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insertion call() throws Exception {
|
||||
return getBestInsertion(batch,unassignedJob);
|
||||
}
|
||||
public InsertionData getInsertionData() {
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
try {
|
||||
for (int i = 0; i < batches.size(); i++) {
|
||||
Future<Insertion> futureIData = completionService.take();
|
||||
Insertion insertion = futureIData.get();
|
||||
if (insertion == null) continue;
|
||||
if (insertion.getInsertionData().getInsertionCost() < bestInsertionCost) {
|
||||
bestInsertion = insertion;
|
||||
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
|
||||
}
|
||||
}
|
||||
} catch(InterruptedException e){
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Exception", e);
|
||||
System.exit(1);
|
||||
}
|
||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if(newIData.getInsertionCost() < bestInsertionCost){
|
||||
bestInsertion = new Insertion(newRoute,newIData);
|
||||
vehicleRoutes.add(newRoute);
|
||||
batches.get(random.nextInt(batches.size())).routes.add(newRoute);
|
||||
}
|
||||
if(bestInsertion == null) badJobs.add(unassignedJob);
|
||||
else insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||
}
|
||||
return badJobs;
|
||||
}
|
||||
|
||||
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
for(VehicleRoute vehicleRoute : batch.routes){
|
||||
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if(iData instanceof NoInsertionFound) {
|
||||
continue;
|
||||
}
|
||||
if(iData.getInsertionCost() < bestInsertionCost){
|
||||
bestInsertion = new Insertion(vehicleRoute,iData);
|
||||
bestInsertionCost = iData.getInsertionCost();
|
||||
}
|
||||
}
|
||||
return bestInsertion;
|
||||
}
|
||||
|
||||
private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
|
||||
List<Batch> batches = new ArrayList<Batch>();
|
||||
for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
|
||||
/*
|
||||
}
|
||||
|
||||
private static Logger logger = LogManager.getLogger(BestInsertionConcurrent.class);
|
||||
|
||||
private final static double NO_NEW_DEPARTURE_TIME_YET = -12345.12345;
|
||||
|
||||
private final static Vehicle NO_NEW_VEHICLE_YET = null;
|
||||
|
||||
private final static Driver NO_NEW_DRIVER_YET = null;
|
||||
|
||||
private InsertionListeners insertionsListeners;
|
||||
|
||||
private JobInsertionCostsCalculator bestInsertionCostCalculator;
|
||||
|
||||
private int nuOfBatches;
|
||||
|
||||
private ExecutorCompletionService<Insertion> completionService;
|
||||
|
||||
@Deprecated
|
||||
public void setRandom(Random random) {
|
||||
super.random = random;
|
||||
}
|
||||
|
||||
public BestInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
super(vehicleRoutingProblem);
|
||||
this.insertionsListeners = new InsertionListeners();
|
||||
this.nuOfBatches = nuOfBatches;
|
||||
bestInsertionCostCalculator = jobInsertionCalculator;
|
||||
completionService = new ExecutorCompletionService<Insertion>(executorService);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=bestInsertion]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
List<Batch> batches = distributeRoutes(vehicleRoutes, nuOfBatches);
|
||||
for (final Job unassignedJob : unassignedJobList) {
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
for (final Batch batch : batches) {
|
||||
completionService.submit(new Callable<Insertion>() {
|
||||
|
||||
@Override
|
||||
public Insertion call() throws Exception {
|
||||
return getBestInsertion(batch, unassignedJob);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
try {
|
||||
for (int i = 0; i < batches.size(); i++) {
|
||||
Future<Insertion> futureIData = completionService.take();
|
||||
Insertion insertion = futureIData.get();
|
||||
if (insertion == null) continue;
|
||||
if (insertion.getInsertionData().getInsertionCost() < bestInsertionCost) {
|
||||
bestInsertion = insertion;
|
||||
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Exception", e);
|
||||
System.exit(1);
|
||||
}
|
||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if (newIData.getInsertionCost() < bestInsertionCost) {
|
||||
bestInsertion = new Insertion(newRoute, newIData);
|
||||
vehicleRoutes.add(newRoute);
|
||||
batches.get(random.nextInt(batches.size())).routes.add(newRoute);
|
||||
}
|
||||
if (bestInsertion == null) badJobs.add(unassignedJob);
|
||||
else insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||
}
|
||||
return badJobs;
|
||||
}
|
||||
|
||||
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
for (VehicleRoute vehicleRoute : batch.routes) {
|
||||
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||
if (iData instanceof NoInsertionFound) {
|
||||
continue;
|
||||
}
|
||||
if (iData.getInsertionCost() < bestInsertionCost) {
|
||||
bestInsertion = new Insertion(vehicleRoute, iData);
|
||||
bestInsertionCost = iData.getInsertionCost();
|
||||
}
|
||||
}
|
||||
return bestInsertion;
|
||||
}
|
||||
|
||||
private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
|
||||
List<Batch> batches = new ArrayList<Batch>();
|
||||
for (int i = 0; i < nuOfBatches; i++) batches.add(new Batch());
|
||||
/*
|
||||
* if route.size < nuOfBatches add as much routes as empty batches are available
|
||||
* else add one empty route anyway
|
||||
*/
|
||||
if(vehicleRoutes.size()<nuOfBatches){
|
||||
int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
|
||||
for(int i=0;i<nOfNewRoutes;i++){
|
||||
vehicleRoutes.add(VehicleRoute.emptyRoute());
|
||||
}
|
||||
}
|
||||
else{
|
||||
vehicleRoutes.add(VehicleRoute.emptyRoute());
|
||||
}
|
||||
if (vehicleRoutes.size() < nuOfBatches) {
|
||||
int nOfNewRoutes = nuOfBatches - vehicleRoutes.size();
|
||||
for (int i = 0; i < nOfNewRoutes; i++) {
|
||||
vehicleRoutes.add(VehicleRoute.emptyRoute());
|
||||
}
|
||||
} else {
|
||||
vehicleRoutes.add(VehicleRoute.emptyRoute());
|
||||
}
|
||||
/*
|
||||
* distribute routes to batches equally
|
||||
*/
|
||||
int count = 0;
|
||||
for(VehicleRoute route : vehicleRoutes){
|
||||
if(count == nuOfBatches) count=0;
|
||||
batches.get(count).routes.add(route);
|
||||
count++;
|
||||
}
|
||||
return batches;
|
||||
}
|
||||
int count = 0;
|
||||
for (VehicleRoute route : vehicleRoutes) {
|
||||
if (count == nuOfBatches) count = 0;
|
||||
batches.get(count).routes.add(route);
|
||||
count++;
|
||||
}
|
||||
return batches;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,22 +15,24 @@ import java.util.List;
|
|||
import java.util.Random;
|
||||
|
||||
|
||||
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{
|
||||
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator {
|
||||
|
||||
|
||||
public static class KnowledgeInjection implements InsertionStartsListener {
|
||||
private CalculatesServiceInsertionWithTimeScheduling c;
|
||||
|
||||
public KnowledgeInjection(CalculatesServiceInsertionWithTimeScheduling c) {
|
||||
super();
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
List<Double> knowledge = new ArrayList<Double>();
|
||||
if(vehicleRoutes.isEmpty()){
|
||||
if (vehicleRoutes.isEmpty()) {
|
||||
// System.out.println("hmm");
|
||||
}
|
||||
for(VehicleRoute route : vehicleRoutes){
|
||||
for (VehicleRoute route : vehicleRoutes) {
|
||||
// if(route.getDepartureTime() == 21600.){
|
||||
// System.out.println("hu");
|
||||
// }
|
||||
|
|
@ -60,18 +62,17 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsC
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name="+this.getClass().toString()+"]";
|
||||
return "[name=" + this.getClass().toString() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
|
||||
double departureTime = newVehicleDepartureTime;
|
||||
if(currentRoute.isEmpty()){
|
||||
if(!departureTimeKnowledge.isEmpty()){
|
||||
if (currentRoute.isEmpty()) {
|
||||
if (!departureTimeKnowledge.isEmpty()) {
|
||||
departureTime = departureTimeKnowledge.get(random.nextInt(departureTimeKnowledge.size()));
|
||||
}
|
||||
}
|
||||
else if(!currentRoute.getVehicle().getId().equals(newVehicle.getId())){
|
||||
} else if (!currentRoute.getVehicle().getId().equals(newVehicle.getId())) {
|
||||
departureTime = currentRoute.getDepartureTime();
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +83,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsC
|
|||
return insertionData;
|
||||
}
|
||||
|
||||
public void setDepartureTimeKnowledge(List<Double> departureTimes){
|
||||
departureTimeKnowledge=departureTimes;
|
||||
public void setDepartureTimeKnowledge(List<Double> departureTimes) {
|
||||
departureTimeKnowledge = departureTimes;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -27,65 +27,64 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
class CalculatesServiceInsertionWithTimeSchedulingInSlices implements JobInsertionCostsCalculator{
|
||||
class CalculatesServiceInsertionWithTimeSchedulingInSlices implements JobInsertionCostsCalculator {
|
||||
|
||||
|
||||
private static Logger log = LogManager.getLogger(CalculatesServiceInsertionWithTimeSchedulingInSlices.class);
|
||||
|
||||
private JobInsertionCostsCalculator jic;
|
||||
private static Logger log = LogManager.getLogger(CalculatesServiceInsertionWithTimeSchedulingInSlices.class);
|
||||
|
||||
private int nOfDepartureTimes = 3;
|
||||
|
||||
private double timeSlice = 900.0;
|
||||
|
||||
public CalculatesServiceInsertionWithTimeSchedulingInSlices(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) {
|
||||
super();
|
||||
this.jic = jic;
|
||||
this.timeSlice = timeSlice;
|
||||
this.nOfDepartureTimes = neighbors;
|
||||
log.debug("initialise " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name="+this.getClass().toString()+"][timeSlice="+timeSlice+"][#timeSlice="+nOfDepartureTimes+"]";
|
||||
}
|
||||
private JobInsertionCostsCalculator jic;
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
|
||||
List<Double> vehicleDepartureTimes = new ArrayList<Double>();
|
||||
double currentStart;
|
||||
if(currentRoute.getStart() == null){
|
||||
currentStart = newVehicleDepartureTime;
|
||||
}
|
||||
else currentStart = currentRoute.getStart().getEndTime();
|
||||
|
||||
vehicleDepartureTimes.add(currentStart);
|
||||
private int nOfDepartureTimes = 3;
|
||||
|
||||
private double timeSlice = 900.0;
|
||||
|
||||
public CalculatesServiceInsertionWithTimeSchedulingInSlices(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) {
|
||||
super();
|
||||
this.jic = jic;
|
||||
this.timeSlice = timeSlice;
|
||||
this.nOfDepartureTimes = neighbors;
|
||||
log.debug("initialise " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=" + this.getClass().toString() + "][timeSlice=" + timeSlice + "][#timeSlice=" + nOfDepartureTimes + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
|
||||
List<Double> vehicleDepartureTimes = new ArrayList<Double>();
|
||||
double currentStart;
|
||||
if (currentRoute.getStart() == null) {
|
||||
currentStart = newVehicleDepartureTime;
|
||||
} else currentStart = currentRoute.getStart().getEndTime();
|
||||
|
||||
vehicleDepartureTimes.add(currentStart);
|
||||
// double earliestDeparture = newVehicle.getEarliestDeparture();
|
||||
// double latestEnd = newVehicle.getLatestArrival();
|
||||
|
||||
for(int i=0;i<nOfDepartureTimes;i++){
|
||||
double neighborStartTime_earlier = currentStart - (i+1)*timeSlice;
|
||||
|
||||
for (int i = 0; i < nOfDepartureTimes; i++) {
|
||||
double neighborStartTime_earlier = currentStart - (i + 1) * timeSlice;
|
||||
// if(neighborStartTime_earlier > earliestDeparture) {
|
||||
vehicleDepartureTimes.add(neighborStartTime_earlier);
|
||||
vehicleDepartureTimes.add(neighborStartTime_earlier);
|
||||
// }
|
||||
double neighborStartTime_later = currentStart + (i+1)*timeSlice;
|
||||
double neighborStartTime_later = currentStart + (i + 1) * timeSlice;
|
||||
// if(neighborStartTime_later < latestEnd) {
|
||||
vehicleDepartureTimes.add(neighborStartTime_later);
|
||||
vehicleDepartureTimes.add(neighborStartTime_later);
|
||||
// }
|
||||
}
|
||||
|
||||
InsertionData bestIData = null;
|
||||
for(Double departureTime : vehicleDepartureTimes){
|
||||
InsertionData iData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
|
||||
if(bestIData == null) bestIData = iData;
|
||||
else if(iData.getInsertionCost() < bestIData.getInsertionCost()){
|
||||
iData.setVehicleDepartureTime(departureTime);
|
||||
bestIData = iData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InsertionData bestIData = null;
|
||||
for (Double departureTime : vehicleDepartureTimes) {
|
||||
InsertionData iData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
|
||||
if (bestIData == null) bestIData = iData;
|
||||
else if (iData.getInsertionCost() < bestIData.getInsertionCost()) {
|
||||
iData.setVehicleDepartureTime(departureTime);
|
||||
bestIData = iData;
|
||||
}
|
||||
}
|
||||
// log.info(bestIData);
|
||||
return bestIData;
|
||||
}
|
||||
return bestIData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -26,38 +26,38 @@ import jsprit.core.problem.solution.route.VehicleRoute;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
final class ConfigureFixCostCalculator implements InsertionStartsListener, JobInsertedListener{
|
||||
final class ConfigureFixCostCalculator implements InsertionStartsListener, JobInsertedListener {
|
||||
|
||||
VehicleRoutingProblem vrp;
|
||||
|
||||
JobInsertionConsideringFixCostsCalculator calcConsideringFix;
|
||||
|
||||
private int nuOfJobsToRecreate;
|
||||
VehicleRoutingProblem vrp;
|
||||
|
||||
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.calcConsideringFix = calcConsideringFix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=configureFixCostCalculator]";
|
||||
}
|
||||
JobInsertionConsideringFixCostsCalculator calcConsideringFix;
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
this.nuOfJobsToRecreate = unassignedJobs.size();
|
||||
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
|
||||
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
||||
private int nuOfJobsToRecreate;
|
||||
|
||||
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.calcConsideringFix = calcConsideringFix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=configureFixCostCalculator]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
this.nuOfJobsToRecreate = unassignedJobs.size();
|
||||
double completenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) vrp.getJobs().values().size()));
|
||||
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
||||
// log.debug("initialise completenessRatio to " + completenessRatio);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||
nuOfJobsToRecreate--;
|
||||
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
|
||||
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
||||
@Override
|
||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||
nuOfJobsToRecreate--;
|
||||
double completenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) vrp.getJobs().values().size()));
|
||||
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
||||
// log.debug("set completenessRatio to " + completenessRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
|
@ -28,38 +28,38 @@ import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
public class DellAmicoFixCostCalculator implements SoftRouteConstraint, InsertionStartsListener, JobInsertedListener{
|
||||
public class DellAmicoFixCostCalculator implements SoftRouteConstraint, InsertionStartsListener, JobInsertedListener {
|
||||
|
||||
private int nuOfJobsToRecreate;
|
||||
|
||||
private final JobInsertionConsideringFixCostsCalculator calculator;
|
||||
|
||||
private final int nuOfJobs;
|
||||
|
||||
public DellAmicoFixCostCalculator(final int nuOfJobs, final RouteAndActivityStateGetter stateGetter) {
|
||||
super();
|
||||
this.nuOfJobs=nuOfJobs;
|
||||
calculator = new JobInsertionConsideringFixCostsCalculator(null, stateGetter);
|
||||
}
|
||||
private int nuOfJobsToRecreate;
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext insertionContext) {
|
||||
return calculator.getCosts(insertionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
this.nuOfJobsToRecreate = unassignedJobs.size();
|
||||
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)nuOfJobs));
|
||||
calculator.setSolutionCompletenessRatio(completenessRatio);
|
||||
}
|
||||
private final JobInsertionConsideringFixCostsCalculator calculator;
|
||||
|
||||
@Override
|
||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||
nuOfJobsToRecreate--;
|
||||
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)nuOfJobs));
|
||||
calculator.setSolutionCompletenessRatio(completenessRatio);
|
||||
System.out.println(completenessRatio);
|
||||
}
|
||||
private final int nuOfJobs;
|
||||
|
||||
public DellAmicoFixCostCalculator(final int nuOfJobs, final RouteAndActivityStateGetter stateGetter) {
|
||||
super();
|
||||
this.nuOfJobs = nuOfJobs;
|
||||
calculator = new JobInsertionConsideringFixCostsCalculator(null, stateGetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext insertionContext) {
|
||||
return calculator.getCosts(insertionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
this.nuOfJobsToRecreate = unassignedJobs.size();
|
||||
double completenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) nuOfJobs));
|
||||
calculator.setSolutionCompletenessRatio(completenessRatio);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||
nuOfJobsToRecreate--;
|
||||
double completenessRatio = (1 - ((double) nuOfJobsToRecreate / (double) nuOfJobs));
|
||||
calculator.setSolutionCompletenessRatio(completenessRatio);
|
||||
System.out.println(completenessRatio);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ class EventListeners {
|
|||
listeners.add(new SwitchVehicleListener());
|
||||
}
|
||||
|
||||
public void inform(Event event){
|
||||
for(EventListener l : listeners){
|
||||
public void inform(Event event) {
|
||||
for (EventListener l : listeners) {
|
||||
l.inform(event);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ class InsertActivityListener implements EventListener {
|
|||
|
||||
@Override
|
||||
public void inform(Event event) {
|
||||
if(event instanceof InsertActivity){
|
||||
if (event instanceof InsertActivity) {
|
||||
InsertActivity insertActivity = (InsertActivity) event;
|
||||
if(!insertActivity.getNewVehicle().isReturnToDepot()){
|
||||
if(insertActivity.getIndex()>=insertActivity.getVehicleRoute().getActivities().size()){
|
||||
if (!insertActivity.getNewVehicle().isReturnToDepot()) {
|
||||
if (insertActivity.getIndex() >= insertActivity.getVehicleRoute().getActivities().size()) {
|
||||
insertActivity.getVehicleRoute().getEnd().setLocation(insertActivity.getActivity().getLocation());
|
||||
}
|
||||
}
|
||||
insertActivity.getVehicleRoute().getTourActivities().addActivity(insertActivity.getIndex(),((InsertActivity) event).getActivity());
|
||||
insertActivity.getVehicleRoute().getTourActivities().addActivity(insertActivity.getIndex(), ((InsertActivity) event).getActivity());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -29,34 +29,34 @@ import jsprit.core.problem.solution.route.activity.*;
|
|||
import java.util.List;
|
||||
|
||||
class Inserter {
|
||||
|
||||
interface JobInsertionHandler {
|
||||
|
||||
void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route);
|
||||
|
||||
void setNextHandler(JobInsertionHandler handler);
|
||||
interface JobInsertionHandler {
|
||||
|
||||
}
|
||||
|
||||
class JobExceptionHandler implements JobInsertionHandler{
|
||||
void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route);
|
||||
|
||||
@Override
|
||||
public void handleJobInsertion(Job job, InsertionData iData,VehicleRoute route) {
|
||||
throw new IllegalStateException("job insertion is not supported. Do not know job type.");
|
||||
}
|
||||
void setNextHandler(JobInsertionHandler handler);
|
||||
|
||||
@Override
|
||||
public void setNextHandler(JobInsertionHandler handler) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ServiceInsertionHandler implements JobInsertionHandler{
|
||||
class JobExceptionHandler implements JobInsertionHandler {
|
||||
|
||||
private TourActivityFactory activityFactory = new DefaultTourActivityFactory();
|
||||
|
||||
private JobInsertionHandler delegator = new JobExceptionHandler();
|
||||
@Override
|
||||
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
|
||||
throw new IllegalStateException("job insertion is not supported. Do not know job type.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextHandler(JobInsertionHandler handler) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ServiceInsertionHandler implements JobInsertionHandler {
|
||||
|
||||
private TourActivityFactory activityFactory = new DefaultTourActivityFactory();
|
||||
|
||||
private JobInsertionHandler delegator = new JobExceptionHandler();
|
||||
|
||||
private VehicleRoutingProblem vehicleRoutingProblem;
|
||||
|
||||
|
|
@ -65,94 +65,93 @@ class Inserter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
|
||||
if(job instanceof Service){
|
||||
route.setVehicleAndDepartureTime(iData.getSelectedVehicle(),iData.getVehicleDepartureTime());
|
||||
if(!iData.getSelectedVehicle().isReturnToDepot()){
|
||||
if(iData.getDeliveryInsertionIndex()>=route.getTourActivities().getActivities().size()){
|
||||
setEndLocation(route,(Service)job);
|
||||
}
|
||||
}
|
||||
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
|
||||
if (job instanceof Service) {
|
||||
route.setVehicleAndDepartureTime(iData.getSelectedVehicle(), iData.getVehicleDepartureTime());
|
||||
if (!iData.getSelectedVehicle().isReturnToDepot()) {
|
||||
if (iData.getDeliveryInsertionIndex() >= route.getTourActivities().getActivities().size()) {
|
||||
setEndLocation(route, (Service) job);
|
||||
}
|
||||
}
|
||||
TourActivity activity = vehicleRoutingProblem.copyAndGetActivities(job).get(0);
|
||||
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), activity);
|
||||
}
|
||||
else delegator.handleJobInsertion(job, iData, route);
|
||||
}
|
||||
|
||||
private void setEndLocation(VehicleRoute route, Service service) {
|
||||
route.getEnd().setLocation(service.getLocation());
|
||||
}
|
||||
|
||||
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
|
||||
this.delegator = jobInsertionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ShipmentInsertionHandler implements JobInsertionHandler {
|
||||
} else delegator.handleJobInsertion(job, iData, route);
|
||||
}
|
||||
|
||||
private void setEndLocation(VehicleRoute route, Service service) {
|
||||
route.getEnd().setLocation(service.getLocation());
|
||||
}
|
||||
|
||||
public void setNextHandler(JobInsertionHandler jobInsertionHandler) {
|
||||
this.delegator = jobInsertionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ShipmentInsertionHandler implements JobInsertionHandler {
|
||||
|
||||
private final VehicleRoutingProblem vehicleRoutingProblem;
|
||||
|
||||
private TourShipmentActivityFactory activityFactory = new DefaultShipmentActivityFactory();
|
||||
|
||||
private JobInsertionHandler delegator = new JobExceptionHandler();
|
||||
|
||||
private JobInsertionHandler delegator = new JobExceptionHandler();
|
||||
|
||||
public ShipmentInsertionHandler(VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
this.vehicleRoutingProblem = vehicleRoutingProblem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
|
||||
if(job instanceof Shipment){
|
||||
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
|
||||
if (job instanceof Shipment) {
|
||||
List<AbstractActivity> acts = vehicleRoutingProblem.copyAndGetActivities(job);
|
||||
TourActivity pickupShipment = acts.get(0);
|
||||
TourActivity deliverShipment = acts.get(1);
|
||||
route.setVehicleAndDepartureTime(iData.getSelectedVehicle(),iData.getVehicleDepartureTime());
|
||||
if(!iData.getSelectedVehicle().isReturnToDepot()){
|
||||
if(iData.getDeliveryInsertionIndex()>=route.getActivities().size()){
|
||||
setEndLocation(route,(Shipment)job);
|
||||
}
|
||||
}
|
||||
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), deliverShipment);
|
||||
route.getTourActivities().addActivity(iData.getPickupInsertionIndex(), pickupShipment);
|
||||
}
|
||||
else delegator.handleJobInsertion(job, iData, route);
|
||||
}
|
||||
|
||||
private void setEndLocation(VehicleRoute route, Shipment shipment) {
|
||||
route.getEnd().setLocation(shipment.getDeliveryLocation());
|
||||
}
|
||||
TourActivity pickupShipment = acts.get(0);
|
||||
TourActivity deliverShipment = acts.get(1);
|
||||
route.setVehicleAndDepartureTime(iData.getSelectedVehicle(), iData.getVehicleDepartureTime());
|
||||
if (!iData.getSelectedVehicle().isReturnToDepot()) {
|
||||
if (iData.getDeliveryInsertionIndex() >= route.getActivities().size()) {
|
||||
setEndLocation(route, (Shipment) job);
|
||||
}
|
||||
}
|
||||
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), deliverShipment);
|
||||
route.getTourActivities().addActivity(iData.getPickupInsertionIndex(), pickupShipment);
|
||||
} else delegator.handleJobInsertion(job, iData, route);
|
||||
}
|
||||
|
||||
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
|
||||
this.delegator = jobInsertionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
private void setEndLocation(VehicleRoute route, Shipment shipment) {
|
||||
route.getEnd().setLocation(shipment.getDeliveryLocation());
|
||||
}
|
||||
|
||||
private InsertionListeners insertionListeners;
|
||||
|
||||
private JobInsertionHandler jobInsertionHandler;
|
||||
public void setNextHandler(JobInsertionHandler jobInsertionHandler) {
|
||||
this.delegator = jobInsertionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private InsertionListeners insertionListeners;
|
||||
|
||||
private JobInsertionHandler jobInsertionHandler;
|
||||
|
||||
private VehicleRoutingProblem vehicleRoutingProblem;
|
||||
|
||||
public Inserter(InsertionListeners insertionListeners, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
this.insertionListeners = insertionListeners;
|
||||
new DefaultTourActivityFactory();
|
||||
jobInsertionHandler = new ServiceInsertionHandler(vehicleRoutingProblem);
|
||||
jobInsertionHandler.setNextHandler(new ShipmentInsertionHandler(vehicleRoutingProblem));
|
||||
}
|
||||
|
||||
public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
|
||||
insertionListeners.informBeforeJobInsertion(job, insertionData, vehicleRoute);
|
||||
|
||||
if(insertionData == null || (insertionData instanceof NoInsertionFound)) throw new IllegalStateException("insertionData null. cannot insert job.");
|
||||
if(job == null) throw new IllegalStateException("cannot insert null-job");
|
||||
if(!(vehicleRoute.getVehicle().getId().equals(insertionData.getSelectedVehicle().getId()))){
|
||||
insertionListeners.informVehicleSwitched(vehicleRoute, vehicleRoute.getVehicle(), insertionData.getSelectedVehicle());
|
||||
vehicleRoute.setVehicleAndDepartureTime(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
|
||||
}
|
||||
jobInsertionHandler.handleJobInsertion(job, insertionData, vehicleRoute);
|
||||
public Inserter(InsertionListeners insertionListeners, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
this.insertionListeners = insertionListeners;
|
||||
new DefaultTourActivityFactory();
|
||||
jobInsertionHandler = new ServiceInsertionHandler(vehicleRoutingProblem);
|
||||
jobInsertionHandler.setNextHandler(new ShipmentInsertionHandler(vehicleRoutingProblem));
|
||||
}
|
||||
|
||||
insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
|
||||
}
|
||||
public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute) {
|
||||
insertionListeners.informBeforeJobInsertion(job, insertionData, vehicleRoute);
|
||||
|
||||
if (insertionData == null || (insertionData instanceof NoInsertionFound))
|
||||
throw new IllegalStateException("insertionData null. cannot insert job.");
|
||||
if (job == null) throw new IllegalStateException("cannot insert null-job");
|
||||
if (!(vehicleRoute.getVehicle().getId().equals(insertionData.getSelectedVehicle().getId()))) {
|
||||
insertionListeners.informVehicleSwitched(vehicleRoute, vehicleRoute.getVehicle(), insertionData.getSelectedVehicle());
|
||||
vehicleRoute.setVehicleAndDepartureTime(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
|
||||
}
|
||||
jobInsertionHandler.handleJobInsertion(job, insertionData, vehicleRoute);
|
||||
|
||||
insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,169 +34,163 @@ public class InsertionBuilder {
|
|||
REGRET, BEST
|
||||
}
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private StateManager stateManager;
|
||||
private StateManager stateManager;
|
||||
|
||||
private boolean local = true;
|
||||
private boolean local = true;
|
||||
|
||||
private ConstraintManager constraintManager;
|
||||
private ConstraintManager constraintManager;
|
||||
|
||||
private VehicleFleetManager fleetManager;
|
||||
private VehicleFleetManager fleetManager;
|
||||
|
||||
private double weightOfFixedCosts;
|
||||
private double weightOfFixedCosts;
|
||||
|
||||
private boolean considerFixedCosts = false;
|
||||
private boolean considerFixedCosts = false;
|
||||
|
||||
private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null;
|
||||
private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null;
|
||||
|
||||
private int forwaredLooking;
|
||||
private int forwaredLooking;
|
||||
|
||||
private int memory;
|
||||
private int memory;
|
||||
|
||||
private ExecutorService executor;
|
||||
private ExecutorService executor;
|
||||
|
||||
private int nuOfThreads;
|
||||
private int nuOfThreads;
|
||||
|
||||
private double timeSlice;
|
||||
private double timeSlice;
|
||||
|
||||
private int nNeighbors;
|
||||
private int nNeighbors;
|
||||
|
||||
private boolean timeScheduling=false;
|
||||
private boolean timeScheduling = false;
|
||||
|
||||
private boolean allowVehicleSwitch=true;
|
||||
private boolean allowVehicleSwitch = true;
|
||||
|
||||
private boolean addDefaultCostCalc=true;
|
||||
private boolean addDefaultCostCalc = true;
|
||||
|
||||
private Strategy strategy = Strategy.BEST;
|
||||
|
||||
public InsertionBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.stateManager = stateManager;
|
||||
this.constraintManager = constraintManager;
|
||||
this.fleetManager = vehicleFleetManager;
|
||||
}
|
||||
public InsertionBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
this.stateManager = stateManager;
|
||||
this.constraintManager = constraintManager;
|
||||
this.fleetManager = vehicleFleetManager;
|
||||
}
|
||||
|
||||
public InsertionBuilder setInsertionStrategy(Strategy strategy){
|
||||
public InsertionBuilder setInsertionStrategy(Strategy strategy) {
|
||||
this.strategy = strategy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setRouteLevel(int forwardLooking, int memory){
|
||||
local = false;
|
||||
this.forwaredLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setRouteLevel(int forwardLooking, int memory, boolean addDefaultMarginalCostCalculation){
|
||||
local = false;
|
||||
this.forwaredLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
this.addDefaultCostCalc = addDefaultMarginalCostCalculation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setLocalLevel(){
|
||||
local = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If addDefaulMarginalCostCalculation is false, no calculator is set which implicitly assumes that marginal cost calculation
|
||||
* is controlled by your custom soft constraints.
|
||||
*
|
||||
* @param addDefaultMarginalCostCalculation
|
||||
* @return
|
||||
*/
|
||||
public InsertionBuilder setLocalLevel(boolean addDefaultMarginalCostCalculation){
|
||||
local = true;
|
||||
addDefaultCostCalc = addDefaultMarginalCostCalculation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder considerFixedCosts(double weightOfFixedCosts){
|
||||
this.weightOfFixedCosts = weightOfFixedCosts;
|
||||
this.considerFixedCosts = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
|
||||
this.actInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setConcurrentMode(ExecutorService executor, int nuOfThreads){
|
||||
this.executor = executor;
|
||||
this.nuOfThreads = nuOfThreads;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public InsertionStrategy build() {
|
||||
List<InsertionListener> iListeners = new ArrayList<InsertionListener>();
|
||||
List<PrioritizedVRAListener> algorithmListeners = new ArrayList<PrioritizedVRAListener>();
|
||||
JobInsertionCostsCalculatorBuilder calcBuilder = new JobInsertionCostsCalculatorBuilder(iListeners, algorithmListeners);
|
||||
if(local){
|
||||
calcBuilder.setLocalLevel(addDefaultCostCalc);
|
||||
}
|
||||
else {
|
||||
calcBuilder.setRouteLevel(forwaredLooking, memory, addDefaultCostCalc);
|
||||
}
|
||||
calcBuilder.setConstraintManager(constraintManager);
|
||||
calcBuilder.setStateManager(stateManager);
|
||||
calcBuilder.setVehicleRoutingProblem(vrp);
|
||||
calcBuilder.setVehicleFleetManager(fleetManager);
|
||||
calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator);
|
||||
if(considerFixedCosts) {
|
||||
calcBuilder.considerFixedCosts(weightOfFixedCosts);
|
||||
}
|
||||
if(timeScheduling){
|
||||
calcBuilder.experimentalTimeScheduler(timeSlice, nNeighbors);
|
||||
}
|
||||
calcBuilder.setAllowVehicleSwitch(allowVehicleSwitch);
|
||||
JobInsertionCostsCalculator costCalculator = calcBuilder.build();
|
||||
|
||||
public InsertionBuilder setRouteLevel(int forwardLooking, int memory) {
|
||||
local = false;
|
||||
this.forwaredLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setRouteLevel(int forwardLooking, int memory, boolean addDefaultMarginalCostCalculation) {
|
||||
local = false;
|
||||
this.forwaredLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
this.addDefaultCostCalc = addDefaultMarginalCostCalculation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setLocalLevel() {
|
||||
local = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If addDefaulMarginalCostCalculation is false, no calculator is set which implicitly assumes that marginal cost calculation
|
||||
* is controlled by your custom soft constraints.
|
||||
*
|
||||
* @param addDefaultMarginalCostCalculation
|
||||
* @return
|
||||
*/
|
||||
public InsertionBuilder setLocalLevel(boolean addDefaultMarginalCostCalculation) {
|
||||
local = true;
|
||||
addDefaultCostCalc = addDefaultMarginalCostCalculation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder considerFixedCosts(double weightOfFixedCosts) {
|
||||
this.weightOfFixedCosts = weightOfFixedCosts;
|
||||
this.considerFixedCosts = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator) {
|
||||
this.actInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InsertionBuilder setConcurrentMode(ExecutorService executor, int nuOfThreads) {
|
||||
this.executor = executor;
|
||||
this.nuOfThreads = nuOfThreads;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public InsertionStrategy build() {
|
||||
List<InsertionListener> iListeners = new ArrayList<InsertionListener>();
|
||||
List<PrioritizedVRAListener> algorithmListeners = new ArrayList<PrioritizedVRAListener>();
|
||||
JobInsertionCostsCalculatorBuilder calcBuilder = new JobInsertionCostsCalculatorBuilder(iListeners, algorithmListeners);
|
||||
if (local) {
|
||||
calcBuilder.setLocalLevel(addDefaultCostCalc);
|
||||
} else {
|
||||
calcBuilder.setRouteLevel(forwaredLooking, memory, addDefaultCostCalc);
|
||||
}
|
||||
calcBuilder.setConstraintManager(constraintManager);
|
||||
calcBuilder.setStateManager(stateManager);
|
||||
calcBuilder.setVehicleRoutingProblem(vrp);
|
||||
calcBuilder.setVehicleFleetManager(fleetManager);
|
||||
calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator);
|
||||
if (considerFixedCosts) {
|
||||
calcBuilder.considerFixedCosts(weightOfFixedCosts);
|
||||
}
|
||||
if (timeScheduling) {
|
||||
calcBuilder.experimentalTimeScheduler(timeSlice, nNeighbors);
|
||||
}
|
||||
calcBuilder.setAllowVehicleSwitch(allowVehicleSwitch);
|
||||
JobInsertionCostsCalculator costCalculator = calcBuilder.build();
|
||||
|
||||
InsertionStrategy insertion;
|
||||
if(strategy.equals(Strategy.BEST)) {
|
||||
if (strategy.equals(Strategy.BEST)) {
|
||||
if (executor == null) {
|
||||
insertion = new BestInsertion(costCalculator, vrp);
|
||||
} else {
|
||||
insertion = new BestInsertionConcurrent(costCalculator, executor, nuOfThreads, vrp);
|
||||
}
|
||||
}
|
||||
else if(strategy.equals(Strategy.REGRET)){
|
||||
} else if (strategy.equals(Strategy.REGRET)) {
|
||||
if (executor == null) {
|
||||
insertion = new RegretInsertion(costCalculator, vrp);
|
||||
} else {
|
||||
insertion = new RegretInsertionConcurrent(costCalculator, vrp, executor);
|
||||
}
|
||||
else {
|
||||
insertion = new RegretInsertionConcurrent(costCalculator,vrp,executor);
|
||||
}
|
||||
}
|
||||
else throw new IllegalStateException("you should never get here");
|
||||
for(InsertionListener l : iListeners) insertion.addListener(l);
|
||||
return insertion;
|
||||
}
|
||||
} else throw new IllegalStateException("you should never get here");
|
||||
for (InsertionListener l : iListeners) insertion.addListener(l);
|
||||
return insertion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this is experimental and can disappear.
|
||||
* @param timeSlice the time slice
|
||||
* @param nNeighbors number of neighbors
|
||||
*/
|
||||
@Deprecated
|
||||
public void experimentalTimeScheduler(double timeSlice, int nNeighbors) {
|
||||
this.timeSlice=timeSlice;
|
||||
this.nNeighbors=nNeighbors;
|
||||
timeScheduling=true;
|
||||
}
|
||||
/**
|
||||
* @param timeSlice the time slice
|
||||
* @param nNeighbors number of neighbors
|
||||
* @deprecated this is experimental and can disappear.
|
||||
*/
|
||||
@Deprecated
|
||||
public void experimentalTimeScheduler(double timeSlice, int nNeighbors) {
|
||||
this.timeSlice = timeSlice;
|
||||
this.nNeighbors = nNeighbors;
|
||||
timeScheduling = true;
|
||||
}
|
||||
|
||||
public InsertionBuilder setAllowVehicleSwitch(boolean allowVehicleSwitch) {
|
||||
this.allowVehicleSwitch = allowVehicleSwitch;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public InsertionBuilder setAllowVehicleSwitch(boolean allowVehicleSwitch) {
|
||||
this.allowVehicleSwitch = allowVehicleSwitch;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -25,142 +25,140 @@ import java.util.List;
|
|||
/**
|
||||
* Data object that collects insertion information. It collects insertionCosts, insertionIndeces, vehicle and driver to be employed
|
||||
* and departureTime of vehicle at vehicle's start location (e.g. depot).
|
||||
*
|
||||
* @author stefan
|
||||
*
|
||||
* @author stefan
|
||||
*/
|
||||
public class InsertionData {
|
||||
|
||||
public static class NoInsertionFound extends InsertionData{
|
||||
|
||||
public NoInsertionFound() {
|
||||
super(Double.MAX_VALUE, NO_INDEX, NO_INDEX, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static InsertionData noInsertion = new NoInsertionFound();
|
||||
|
||||
/**
|
||||
* Returns an instance of InsertionData that represents an EmptyInsertionData (which might indicate
|
||||
* that no insertion has been found). It is internally instantiated as follows:<br>
|
||||
* <code>new InsertionData(Double.MAX_VALUE, NO_INDEX, NO_INDEX, null, null);</code><br>
|
||||
* where NO_INDEX=-1.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static InsertionData createEmptyInsertionData(){
|
||||
return noInsertion;
|
||||
}
|
||||
|
||||
static int NO_INDEX = -1;
|
||||
public static class NoInsertionFound extends InsertionData {
|
||||
|
||||
private final double insertionCost;
|
||||
|
||||
private final int pickupInsertionIndex;
|
||||
|
||||
private final int deliveryInsertionIndex;
|
||||
|
||||
private final Vehicle selectedVehicle;
|
||||
|
||||
private final Driver selectedDriver;
|
||||
|
||||
private double departureTime;
|
||||
|
||||
private double additionalTime;
|
||||
public NoInsertionFound() {
|
||||
super(Double.MAX_VALUE, NO_INDEX, NO_INDEX, null, null);
|
||||
}
|
||||
|
||||
private List<Event> events = new ArrayList<Event>();
|
||||
}
|
||||
|
||||
List<Event> getEvents(){
|
||||
return events;
|
||||
}
|
||||
private static InsertionData noInsertion = new NoInsertionFound();
|
||||
|
||||
/**
|
||||
* @return the additionalTime
|
||||
*/
|
||||
public double getAdditionalTime() {
|
||||
return additionalTime;
|
||||
}
|
||||
/**
|
||||
* Returns an instance of InsertionData that represents an EmptyInsertionData (which might indicate
|
||||
* that no insertion has been found). It is internally instantiated as follows:<br>
|
||||
* <code>new InsertionData(Double.MAX_VALUE, NO_INDEX, NO_INDEX, null, null);</code><br>
|
||||
* where NO_INDEX=-1.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static InsertionData createEmptyInsertionData() {
|
||||
return noInsertion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param additionalTime the additionalTime to set
|
||||
*/
|
||||
public void setAdditionalTime(double additionalTime) {
|
||||
this.additionalTime = additionalTime;
|
||||
}
|
||||
static int NO_INDEX = -1;
|
||||
|
||||
public InsertionData(double insertionCost, int pickupInsertionIndex, int deliveryInsertionIndex, Vehicle vehicle, Driver driver){
|
||||
this.insertionCost = insertionCost;
|
||||
this.pickupInsertionIndex = pickupInsertionIndex;
|
||||
this.deliveryInsertionIndex = deliveryInsertionIndex;
|
||||
this.selectedVehicle = vehicle;
|
||||
this.selectedDriver = driver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[iCost="+insertionCost+"][pickupIndex="+pickupInsertionIndex+"][deliveryIndex="+deliveryInsertionIndex+"][depTime="+departureTime+"][vehicle="+selectedVehicle+"][driver="+selectedDriver+"]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns insertionIndex of deliveryActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getDeliveryInsertionIndex(){
|
||||
return deliveryInsertionIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns insertionIndex of pickkupActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getPickupInsertionIndex(){
|
||||
return pickupInsertionIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns insertion costs (which might be the additional costs of inserting the corresponding job).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public double getInsertionCost() {
|
||||
return insertionCost;
|
||||
}
|
||||
private final double insertionCost;
|
||||
|
||||
/**
|
||||
* Returns the vehicle to be employed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Vehicle getSelectedVehicle() {
|
||||
return selectedVehicle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vehicle to be employed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Driver getSelectedDriver(){
|
||||
return selectedDriver;
|
||||
}
|
||||
private final int pickupInsertionIndex;
|
||||
|
||||
private final int deliveryInsertionIndex;
|
||||
|
||||
private final Vehicle selectedVehicle;
|
||||
|
||||
private final Driver selectedDriver;
|
||||
|
||||
private double departureTime;
|
||||
|
||||
private double additionalTime;
|
||||
|
||||
private List<Event> events = new ArrayList<Event>();
|
||||
|
||||
List<Event> getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the additionalTime
|
||||
*/
|
||||
public double getAdditionalTime() {
|
||||
return additionalTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param additionalTime the additionalTime to set
|
||||
*/
|
||||
public void setAdditionalTime(double additionalTime) {
|
||||
this.additionalTime = additionalTime;
|
||||
}
|
||||
|
||||
public InsertionData(double insertionCost, int pickupInsertionIndex, int deliveryInsertionIndex, Vehicle vehicle, Driver driver) {
|
||||
this.insertionCost = insertionCost;
|
||||
this.pickupInsertionIndex = pickupInsertionIndex;
|
||||
this.deliveryInsertionIndex = deliveryInsertionIndex;
|
||||
this.selectedVehicle = vehicle;
|
||||
this.selectedDriver = driver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[iCost=" + insertionCost + "][pickupIndex=" + pickupInsertionIndex + "][deliveryIndex=" + deliveryInsertionIndex + "][depTime=" + departureTime + "][vehicle=" + selectedVehicle + "][driver=" + selectedDriver + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns insertionIndex of deliveryActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getDeliveryInsertionIndex() {
|
||||
return deliveryInsertionIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns insertionIndex of pickkupActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getPickupInsertionIndex() {
|
||||
return pickupInsertionIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns insertion costs (which might be the additional costs of inserting the corresponding job).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public double getInsertionCost() {
|
||||
return insertionCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vehicle to be employed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Vehicle getSelectedVehicle() {
|
||||
return selectedVehicle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vehicle to be employed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Driver getSelectedDriver() {
|
||||
return selectedDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the departureTime
|
||||
*/
|
||||
public double getVehicleDepartureTime() {
|
||||
return departureTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param departureTime the departureTime to set
|
||||
*/
|
||||
public void setVehicleDepartureTime(double departureTime) {
|
||||
this.departureTime = departureTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the departureTime
|
||||
*/
|
||||
public double getVehicleDepartureTime() {
|
||||
return departureTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param departureTime the departureTime to set
|
||||
*/
|
||||
public void setVehicleDepartureTime(double departureTime) {
|
||||
this.departureTime = departureTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -23,27 +23,26 @@ import jsprit.core.problem.solution.route.VehicleRoute;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Basic interface for insertion strategies
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
|
||||
public interface InsertionStrategy {
|
||||
|
||||
/**
|
||||
* Inserts unassigned jobs into vehicle routes.
|
||||
* @param vehicleRoutes existing vehicle routes
|
||||
* @param unassignedJobs jobs to be inserted
|
||||
/**
|
||||
* Inserts unassigned jobs into vehicle routes.
|
||||
*
|
||||
* @param vehicleRoutes existing vehicle routes
|
||||
* @param unassignedJobs jobs to be inserted
|
||||
*/
|
||||
public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||
public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||
|
||||
public void addListener(InsertionListener insertionListener);
|
||||
|
||||
public void removeListener(InsertionListener insertionListener);
|
||||
|
||||
public Collection<InsertionListener> getListeners();
|
||||
|
||||
public void removeListener(InsertionListener insertionListener);
|
||||
|
||||
public Collection<InsertionListener> getListeners();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -20,6 +20,6 @@ import jsprit.core.problem.VehicleRoutingProblem;
|
|||
|
||||
public interface InsertionStrategyFactory {
|
||||
|
||||
public InsertionStrategy createStrategy(VehicleRoutingProblem vrp);
|
||||
|
||||
public InsertionStrategy createStrategy(VehicleRoutingProblem vrp);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
|
@ -27,18 +27,18 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
|
||||
class JobCalculatorSwitcher implements JobInsertionCostsCalculator{
|
||||
class JobCalculatorSwitcher implements JobInsertionCostsCalculator {
|
||||
|
||||
private Map<Class<? extends Job>, JobInsertionCostsCalculator> calcMap = new HashMap<Class<? extends Job>, JobInsertionCostsCalculator>();
|
||||
|
||||
void put(Class<? extends Job> jobClass, JobInsertionCostsCalculator jic) {
|
||||
calcMap.put(jobClass, jic);
|
||||
}
|
||||
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
|
||||
JobInsertionCostsCalculator jic = calcMap.get(jobToInsert.getClass());
|
||||
if (jic == null) throw new IllegalStateException("cannot find calculator for " + jobToInsert.getClass());
|
||||
return jic.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownScore);
|
||||
}
|
||||
|
||||
private Map<Class<? extends Job>,JobInsertionCostsCalculator> calcMap = new HashMap<Class<? extends Job>, JobInsertionCostsCalculator>();
|
||||
|
||||
void put(Class<? extends Job> jobClass, JobInsertionCostsCalculator jic){
|
||||
calcMap.put(jobClass, jic);
|
||||
}
|
||||
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore){
|
||||
JobInsertionCostsCalculator jic = calcMap.get(jobToInsert.getClass());
|
||||
if(jic==null) throw new IllegalStateException("cannot find calculator for " + jobToInsert.getClass());
|
||||
return jic.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownScore);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -30,107 +30,107 @@ import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCostsCalculator, SoftRouteConstraint{
|
||||
final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCostsCalculator, SoftRouteConstraint {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(JobInsertionConsideringFixCostsCalculator.class);
|
||||
|
||||
private final JobInsertionCostsCalculator standardServiceInsertion;
|
||||
|
||||
private double weight_deltaFixCost = 0.5;
|
||||
|
||||
private double solution_completeness_ratio = 0.5;
|
||||
|
||||
private RouteAndActivityStateGetter stateGetter;
|
||||
private static final Logger logger = LogManager.getLogger(JobInsertionConsideringFixCostsCalculator.class);
|
||||
|
||||
public JobInsertionConsideringFixCostsCalculator(final JobInsertionCostsCalculator standardInsertionCalculator, RouteAndActivityStateGetter stateGetter) {
|
||||
super();
|
||||
this.standardServiceInsertion = standardInsertionCalculator;
|
||||
this.stateGetter = stateGetter;
|
||||
logger.debug("inialise {}", this);
|
||||
}
|
||||
private final JobInsertionCostsCalculator standardServiceInsertion;
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
|
||||
double fixcost_contribution = getFixCostContribution(currentRoute,jobToInsert, newVehicle);
|
||||
if(fixcost_contribution > bestKnownPrice){
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData iData = standardServiceInsertion.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
|
||||
if(iData instanceof NoInsertionFound){
|
||||
return iData;
|
||||
}
|
||||
double totalInsertionCost = iData.getInsertionCost() + fixcost_contribution;
|
||||
InsertionData insertionData = new InsertionData(totalInsertionCost, iData.getPickupInsertionIndex(), iData.getDeliveryInsertionIndex(), newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
insertionData.getEvents().addAll(iData.getEvents());
|
||||
return insertionData;
|
||||
}
|
||||
private double weight_deltaFixCost = 0.5;
|
||||
|
||||
private double getFixCostContribution(final VehicleRoute currentRoute,
|
||||
final Job jobToInsert, final Vehicle newVehicle) {
|
||||
double relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert);
|
||||
double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert);
|
||||
double deltaFixCost = (1-solution_completeness_ratio)*relFixCost + solution_completeness_ratio*absFixCost;
|
||||
double fixcost_contribution = weight_deltaFixCost*solution_completeness_ratio*deltaFixCost;
|
||||
return fixcost_contribution;
|
||||
}
|
||||
|
||||
public void setWeightOfFixCost(double weight){
|
||||
weight_deltaFixCost = weight;
|
||||
logger.debug("set weightOfFixCostSaving to {}", weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertionConsideringFixCost][weightOfFixedCostSavings="+weight_deltaFixCost+"]";
|
||||
}
|
||||
private double solution_completeness_ratio = 0.5;
|
||||
|
||||
public void setSolutionCompletenessRatio(double ratio){
|
||||
solution_completeness_ratio = ratio;
|
||||
}
|
||||
private RouteAndActivityStateGetter stateGetter;
|
||||
|
||||
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
||||
Capacity load = Capacity.addup(getCurrentMaxLoadInRoute(route), job.getSize());
|
||||
public JobInsertionConsideringFixCostsCalculator(final JobInsertionCostsCalculator standardInsertionCalculator, RouteAndActivityStateGetter stateGetter) {
|
||||
super();
|
||||
this.standardServiceInsertion = standardInsertionCalculator;
|
||||
this.stateGetter = stateGetter;
|
||||
logger.debug("inialise {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
|
||||
double fixcost_contribution = getFixCostContribution(currentRoute, jobToInsert, newVehicle);
|
||||
if (fixcost_contribution > bestKnownPrice) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData iData = standardServiceInsertion.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
|
||||
if (iData instanceof NoInsertionFound) {
|
||||
return iData;
|
||||
}
|
||||
double totalInsertionCost = iData.getInsertionCost() + fixcost_contribution;
|
||||
InsertionData insertionData = new InsertionData(totalInsertionCost, iData.getPickupInsertionIndex(), iData.getDeliveryInsertionIndex(), newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
insertionData.getEvents().addAll(iData.getEvents());
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
private double getFixCostContribution(final VehicleRoute currentRoute,
|
||||
final Job jobToInsert, final Vehicle newVehicle) {
|
||||
double relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert);
|
||||
double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert);
|
||||
double deltaFixCost = (1 - solution_completeness_ratio) * relFixCost + solution_completeness_ratio * absFixCost;
|
||||
double fixcost_contribution = weight_deltaFixCost * solution_completeness_ratio * deltaFixCost;
|
||||
return fixcost_contribution;
|
||||
}
|
||||
|
||||
public void setWeightOfFixCost(double weight) {
|
||||
weight_deltaFixCost = weight;
|
||||
logger.debug("set weightOfFixCostSaving to {}", weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertionConsideringFixCost][weightOfFixedCostSavings=" + weight_deltaFixCost + "]";
|
||||
}
|
||||
|
||||
public void setSolutionCompletenessRatio(double ratio) {
|
||||
solution_completeness_ratio = ratio;
|
||||
}
|
||||
|
||||
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
||||
Capacity load = Capacity.addup(getCurrentMaxLoadInRoute(route), job.getSize());
|
||||
// double load = getCurrentMaxLoadInRoute(route) + job.getCapacityDemand();
|
||||
double currentFix = 0.0;
|
||||
if(route.getVehicle() != null){
|
||||
if(!(route.getVehicle() instanceof NoVehicle)){
|
||||
currentFix += route.getVehicle().getType().getVehicleCostParams().fix;
|
||||
}
|
||||
}
|
||||
if(!newVehicle.getType().getCapacityDimensions().isGreaterOrEqual(load)){
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
return newVehicle.getType().getVehicleCostParams().fix - currentFix;
|
||||
}
|
||||
double currentFix = 0.0;
|
||||
if (route.getVehicle() != null) {
|
||||
if (!(route.getVehicle() instanceof NoVehicle)) {
|
||||
currentFix += route.getVehicle().getType().getVehicleCostParams().fix;
|
||||
}
|
||||
}
|
||||
if (!newVehicle.getType().getCapacityDimensions().isGreaterOrEqual(load)) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
return newVehicle.getType().getVehicleCostParams().fix - currentFix;
|
||||
}
|
||||
|
||||
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
||||
Capacity currentLoad = getCurrentMaxLoadInRoute(route);
|
||||
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
||||
Capacity currentLoad = getCurrentMaxLoadInRoute(route);
|
||||
// int currentLoad = getCurrentMaxLoadInRoute(route);
|
||||
Capacity load = Capacity.addup(currentLoad, job.getSize());
|
||||
Capacity load = Capacity.addup(currentLoad, job.getSize());
|
||||
// double load = currentLoad + job.getCapacityDemand();
|
||||
double currentRelFix = 0.0;
|
||||
if(route.getVehicle() != null){
|
||||
if(!(route.getVehicle() instanceof NoVehicle)){
|
||||
currentRelFix += route.getVehicle().getType().getVehicleCostParams().fix * Capacity.divide(currentLoad, route.getVehicle().getType().getCapacityDimensions());
|
||||
}
|
||||
}
|
||||
if(!newVehicle.getType().getCapacityDimensions().isGreaterOrEqual(load)){
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
double relativeFixCost = newVehicle.getType().getVehicleCostParams().fix* (Capacity.divide(load, newVehicle.getType().getCapacityDimensions())) - currentRelFix;
|
||||
return relativeFixCost;
|
||||
}
|
||||
double currentRelFix = 0.0;
|
||||
if (route.getVehicle() != null) {
|
||||
if (!(route.getVehicle() instanceof NoVehicle)) {
|
||||
currentRelFix += route.getVehicle().getType().getVehicleCostParams().fix * Capacity.divide(currentLoad, route.getVehicle().getType().getCapacityDimensions());
|
||||
}
|
||||
}
|
||||
if (!newVehicle.getType().getCapacityDimensions().isGreaterOrEqual(load)) {
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
double relativeFixCost = newVehicle.getType().getVehicleCostParams().fix * (Capacity.divide(load, newVehicle.getType().getCapacityDimensions())) - currentRelFix;
|
||||
return relativeFixCost;
|
||||
}
|
||||
|
||||
private Capacity getCurrentMaxLoadInRoute(VehicleRoute route) {
|
||||
private Capacity getCurrentMaxLoadInRoute(VehicleRoute route) {
|
||||
Capacity maxLoad = stateGetter.getRouteState(route, InternalStates.MAXLOAD, Capacity.class);
|
||||
if(maxLoad == null) maxLoad = Capacity.Builder.newInstance().build();
|
||||
return maxLoad;
|
||||
}
|
||||
if (maxLoad == null) maxLoad = Capacity.Builder.newInstance().build();
|
||||
return maxLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext insertionContext) {
|
||||
return getFixCostContribution(insertionContext.getRoute(), insertionContext.getJob(), insertionContext.getNewVehicle());
|
||||
}
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext insertionContext) {
|
||||
return getFixCostContribution(insertionContext.getRoute(), insertionContext.getJob(), insertionContext.getNewVehicle());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -22,8 +22,8 @@ import jsprit.core.problem.solution.route.VehicleRoute;
|
|||
import jsprit.core.problem.vehicle.Vehicle;
|
||||
|
||||
|
||||
public interface JobInsertionCostsCalculator {
|
||||
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts);
|
||||
public interface JobInsertionCostsCalculator {
|
||||
|
||||
public InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -32,250 +32,249 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
|
||||
public class JobInsertionCostsCalculatorBuilder {
|
||||
|
||||
private static class CalculatorPlusListeners {
|
||||
private static class CalculatorPlusListeners {
|
||||
|
||||
private JobInsertionCostsCalculator calculator;
|
||||
private JobInsertionCostsCalculator calculator;
|
||||
|
||||
public JobInsertionCostsCalculator getCalculator() {
|
||||
return calculator;
|
||||
}
|
||||
public JobInsertionCostsCalculator getCalculator() {
|
||||
return calculator;
|
||||
}
|
||||
|
||||
private List<PrioritizedVRAListener> algorithmListener = new ArrayList<PrioritizedVRAListener>();
|
||||
private List<InsertionListener> insertionListener = new ArrayList<InsertionListener>();
|
||||
private List<PrioritizedVRAListener> algorithmListener = new ArrayList<PrioritizedVRAListener>();
|
||||
private List<InsertionListener> insertionListener = new ArrayList<InsertionListener>();
|
||||
|
||||
public CalculatorPlusListeners(JobInsertionCostsCalculator calculator) {
|
||||
super();
|
||||
this.calculator = calculator;
|
||||
}
|
||||
public CalculatorPlusListeners(JobInsertionCostsCalculator calculator) {
|
||||
super();
|
||||
this.calculator = calculator;
|
||||
}
|
||||
|
||||
public List<PrioritizedVRAListener> getAlgorithmListener() {
|
||||
return algorithmListener;
|
||||
}
|
||||
public List<PrioritizedVRAListener> getAlgorithmListener() {
|
||||
return algorithmListener;
|
||||
}
|
||||
|
||||
public List<InsertionListener> getInsertionListener() {
|
||||
return insertionListener;
|
||||
}
|
||||
}
|
||||
public List<InsertionListener> getInsertionListener() {
|
||||
return insertionListener;
|
||||
}
|
||||
}
|
||||
|
||||
private List<InsertionListener> insertionListeners;
|
||||
private List<InsertionListener> insertionListeners;
|
||||
|
||||
private List<PrioritizedVRAListener> algorithmListeners;
|
||||
private List<PrioritizedVRAListener> algorithmListeners;
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private RouteAndActivityStateGetter states;
|
||||
private RouteAndActivityStateGetter states;
|
||||
|
||||
private boolean local = true;
|
||||
private boolean local = true;
|
||||
|
||||
private int forwardLooking = 0;
|
||||
private int forwardLooking = 0;
|
||||
|
||||
private int memory = 1;
|
||||
private int memory = 1;
|
||||
|
||||
private boolean considerFixedCost = false;
|
||||
private boolean considerFixedCost = false;
|
||||
|
||||
private double weightOfFixedCost = 0;
|
||||
private double weightOfFixedCost = 0;
|
||||
|
||||
private VehicleFleetManager fleetManager;
|
||||
private VehicleFleetManager fleetManager;
|
||||
|
||||
private boolean timeScheduling = false;
|
||||
private boolean timeScheduling = false;
|
||||
|
||||
private double timeSlice;
|
||||
private double timeSlice;
|
||||
|
||||
private int neighbors;
|
||||
|
||||
private ConstraintManager constraintManager;
|
||||
|
||||
private ActivityInsertionCostsCalculator activityInsertionCostCalculator = null;
|
||||
private int neighbors;
|
||||
|
||||
private boolean allowVehicleSwitch = true;
|
||||
private ConstraintManager constraintManager;
|
||||
|
||||
private boolean addDefaultCostCalc = true;
|
||||
private ActivityInsertionCostsCalculator activityInsertionCostCalculator = null;
|
||||
|
||||
/**
|
||||
* Constructs the builder.
|
||||
*
|
||||
* <p>Some calculators require information from the overall algorithm or the higher-level insertion procedure. Thus listeners inform them.
|
||||
* These listeners are cached in the according list and can thus be added when its time to add them.
|
||||
*
|
||||
* @param insertionListeners
|
||||
* @param algorithmListeners
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder(List<InsertionListener> insertionListeners, List<PrioritizedVRAListener> algorithmListeners) {
|
||||
super();
|
||||
this.insertionListeners = insertionListeners;
|
||||
this.algorithmListeners = algorithmListeners;
|
||||
}
|
||||
private boolean allowVehicleSwitch = true;
|
||||
|
||||
/**
|
||||
* Sets activityStates. MUST be set.
|
||||
* @param stateManager
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setStateManager(RouteAndActivityStateGetter stateManager){
|
||||
this.states = stateManager;
|
||||
return this;
|
||||
}
|
||||
private boolean addDefaultCostCalc = true;
|
||||
|
||||
/**
|
||||
* Sets routingProblem. MUST be set.
|
||||
*
|
||||
* @param vehicleRoutingProblem
|
||||
* @return
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setVehicleRoutingProblem(VehicleRoutingProblem vehicleRoutingProblem){
|
||||
this.vrp = vehicleRoutingProblem;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Constructs the builder.
|
||||
* <p/>
|
||||
* <p>Some calculators require information from the overall algorithm or the higher-level insertion procedure. Thus listeners inform them.
|
||||
* These listeners are cached in the according list and can thus be added when its time to add them.
|
||||
*
|
||||
* @param insertionListeners
|
||||
* @param algorithmListeners
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder(List<InsertionListener> insertionListeners, List<PrioritizedVRAListener> algorithmListeners) {
|
||||
super();
|
||||
this.insertionListeners = insertionListeners;
|
||||
this.algorithmListeners = algorithmListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets fleetManager. MUST be set.
|
||||
*
|
||||
* @param fleetManager
|
||||
* @return
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setVehicleFleetManager(VehicleFleetManager fleetManager){
|
||||
this.fleetManager = fleetManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a flag to build a calculator based on local calculations.
|
||||
*
|
||||
* <p>Insertion of a job and job-activity is evaluated based on the previous and next activity.
|
||||
* @param addDefaultCostCalc
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setLocalLevel(boolean addDefaultCostCalc){
|
||||
local = true;
|
||||
this.addDefaultCostCalc = addDefaultCostCalc;
|
||||
/**
|
||||
* Sets activityStates. MUST be set.
|
||||
*
|
||||
* @param stateManager
|
||||
* @return
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setStateManager(RouteAndActivityStateGetter stateManager) {
|
||||
this.states = stateManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JobInsertionCostsCalculatorBuilder setActivityInsertionCostsCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
|
||||
this.activityInsertionCostCalculator = activityInsertionCostsCalculator;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a flag to build a calculator that evaluates job insertion on route-level.
|
||||
*
|
||||
* @param forwardLooking
|
||||
* @param memory
|
||||
* @param addDefaultMarginalCostCalc
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setRouteLevel(int forwardLooking, int memory, boolean addDefaultMarginalCostCalc){
|
||||
local = false;
|
||||
this.forwardLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
/**
|
||||
* Sets routingProblem. MUST be set.
|
||||
*
|
||||
* @param vehicleRoutingProblem
|
||||
* @return
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setVehicleRoutingProblem(VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
this.vrp = vehicleRoutingProblem;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a flag to consider also fixed-cost when evaluating the insertion of a job. The weight of the fixed-cost can be determined by setting
|
||||
* weightofFixedCosts.
|
||||
*
|
||||
* @param weightOfFixedCosts
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder considerFixedCosts(double weightOfFixedCosts){
|
||||
considerFixedCost = true;
|
||||
this.weightOfFixedCost = weightOfFixedCosts;
|
||||
/**
|
||||
* Sets fleetManager. MUST be set.
|
||||
*
|
||||
* @param fleetManager
|
||||
* @return
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setVehicleFleetManager(VehicleFleetManager fleetManager) {
|
||||
this.fleetManager = fleetManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JobInsertionCostsCalculatorBuilder experimentalTimeScheduler(double timeSlice, int neighbors){
|
||||
timeScheduling = true;
|
||||
this.timeSlice = timeSlice;
|
||||
this.neighbors = neighbors;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the jobInsertionCalculator.
|
||||
*
|
||||
* @return jobInsertionCalculator.
|
||||
* @throws IllegalStateException if vrp == null or activityStates == null or fleetManager == null.
|
||||
*/
|
||||
public JobInsertionCostsCalculator build(){
|
||||
if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))");
|
||||
if(states == null) throw new IllegalStateException("states is null, but is must be set (this.setStateManager(states))");
|
||||
if(fleetManager == null) throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))");
|
||||
JobInsertionCostsCalculator baseCalculator = null;
|
||||
CalculatorPlusListeners standardLocal = null;
|
||||
if(local){
|
||||
standardLocal = createStandardLocal(vrp, states);
|
||||
}
|
||||
else{
|
||||
checkServicesOnly();
|
||||
standardLocal = createStandardRoute(vrp, states,forwardLooking,memory);
|
||||
}
|
||||
baseCalculator = standardLocal.getCalculator();
|
||||
addAlgorithmListeners(standardLocal.getAlgorithmListener());
|
||||
addInsertionListeners(standardLocal.getInsertionListener());
|
||||
if(considerFixedCost){
|
||||
CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost);
|
||||
baseCalculator = withFixed.getCalculator();
|
||||
addAlgorithmListeners(withFixed.getAlgorithmListener());
|
||||
addInsertionListeners(withFixed.getInsertionListener());
|
||||
}
|
||||
if(timeScheduling){
|
||||
/**
|
||||
* Sets a flag to build a calculator based on local calculations.
|
||||
* <p/>
|
||||
* <p>Insertion of a job and job-activity is evaluated based on the previous and next activity.
|
||||
*
|
||||
* @param addDefaultCostCalc
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setLocalLevel(boolean addDefaultCostCalc) {
|
||||
local = true;
|
||||
this.addDefaultCostCalc = addDefaultCostCalc;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JobInsertionCostsCalculatorBuilder setActivityInsertionCostsCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator) {
|
||||
this.activityInsertionCostCalculator = activityInsertionCostsCalculator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a flag to build a calculator that evaluates job insertion on route-level.
|
||||
*
|
||||
* @param forwardLooking
|
||||
* @param memory
|
||||
* @param addDefaultMarginalCostCalc
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder setRouteLevel(int forwardLooking, int memory, boolean addDefaultMarginalCostCalc) {
|
||||
local = false;
|
||||
this.forwardLooking = forwardLooking;
|
||||
this.memory = memory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a flag to consider also fixed-cost when evaluating the insertion of a job. The weight of the fixed-cost can be determined by setting
|
||||
* weightofFixedCosts.
|
||||
*
|
||||
* @param weightOfFixedCosts
|
||||
*/
|
||||
public JobInsertionCostsCalculatorBuilder considerFixedCosts(double weightOfFixedCosts) {
|
||||
considerFixedCost = true;
|
||||
this.weightOfFixedCost = weightOfFixedCosts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JobInsertionCostsCalculatorBuilder experimentalTimeScheduler(double timeSlice, int neighbors) {
|
||||
timeScheduling = true;
|
||||
this.timeSlice = timeSlice;
|
||||
this.neighbors = neighbors;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the jobInsertionCalculator.
|
||||
*
|
||||
* @return jobInsertionCalculator.
|
||||
* @throws IllegalStateException if vrp == null or activityStates == null or fleetManager == null.
|
||||
*/
|
||||
public JobInsertionCostsCalculator build() {
|
||||
if (vrp == null)
|
||||
throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))");
|
||||
if (states == null)
|
||||
throw new IllegalStateException("states is null, but is must be set (this.setStateManager(states))");
|
||||
if (fleetManager == null)
|
||||
throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))");
|
||||
JobInsertionCostsCalculator baseCalculator = null;
|
||||
CalculatorPlusListeners standardLocal = null;
|
||||
if (local) {
|
||||
standardLocal = createStandardLocal(vrp, states);
|
||||
} else {
|
||||
checkServicesOnly();
|
||||
standardLocal = createStandardRoute(vrp, states, forwardLooking, memory);
|
||||
}
|
||||
baseCalculator = standardLocal.getCalculator();
|
||||
addAlgorithmListeners(standardLocal.getAlgorithmListener());
|
||||
addInsertionListeners(standardLocal.getInsertionListener());
|
||||
if (considerFixedCost) {
|
||||
CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost);
|
||||
baseCalculator = withFixed.getCalculator();
|
||||
addAlgorithmListeners(withFixed.getAlgorithmListener());
|
||||
addInsertionListeners(withFixed.getInsertionListener());
|
||||
}
|
||||
if (timeScheduling) {
|
||||
// baseCalculator = new CalculatesServiceInsertionWithTimeSchedulingInSlices(baseCalculator,timeSlice,neighbors);
|
||||
CalculatesServiceInsertionWithTimeScheduling wts = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator,timeSlice,neighbors);
|
||||
CalculatesServiceInsertionWithTimeScheduling wts = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator, timeSlice, neighbors);
|
||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(wts);
|
||||
calcPlusListeners.getInsertionListener().add(new CalculatesServiceInsertionWithTimeScheduling.KnowledgeInjection(wts));
|
||||
addInsertionListeners(calcPlusListeners.getInsertionListener());
|
||||
baseCalculator = calcPlusListeners.getCalculator();
|
||||
}
|
||||
return createFinalInsertion(fleetManager, baseCalculator, states);
|
||||
}
|
||||
}
|
||||
return createFinalInsertion(fleetManager, baseCalculator, states);
|
||||
}
|
||||
|
||||
private void checkServicesOnly() {
|
||||
for(Job j : vrp.getJobs().values()){
|
||||
if(j instanceof Shipment){
|
||||
throw new UnsupportedOperationException("currently the 'insert-on-route-level' option is only available for services (i.e. service, pickup, delivery), \n" +
|
||||
"if you want to deal with shipments switch to option 'local-level' by either setting bestInsertionBuilder.setLocalLevel() or \n"
|
||||
+ "by omitting the xml-tag '<level forwardLooking=2 memory=1>route</level>' when defining your insertionStrategy in algo-config.xml file");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private void checkServicesOnly() {
|
||||
for (Job j : vrp.getJobs().values()) {
|
||||
if (j instanceof Shipment) {
|
||||
throw new UnsupportedOperationException("currently the 'insert-on-route-level' option is only available for services (i.e. service, pickup, delivery), \n" +
|
||||
"if you want to deal with shipments switch to option 'local-level' by either setting bestInsertionBuilder.setLocalLevel() or \n"
|
||||
+ "by omitting the xml-tag '<level forwardLooking=2 memory=1>route</level>' when defining your insertionStrategy in algo-config.xml file");
|
||||
}
|
||||
}
|
||||
|
||||
private void addInsertionListeners(List<InsertionListener> list) {
|
||||
for(InsertionListener iL : list){
|
||||
insertionListeners.add(iL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addAlgorithmListeners(List<PrioritizedVRAListener> list) {
|
||||
for(PrioritizedVRAListener aL : list){
|
||||
algorithmListeners.add(aL);
|
||||
}
|
||||
}
|
||||
private void addInsertionListeners(List<InsertionListener> list) {
|
||||
for (InsertionListener iL : list) {
|
||||
insertionListeners.add(iL);
|
||||
}
|
||||
}
|
||||
|
||||
private CalculatorPlusListeners createStandardLocal(final VehicleRoutingProblem vrp, RouteAndActivityStateGetter statesManager){
|
||||
if(constraintManager == null) throw new IllegalStateException("constraint-manager is null");
|
||||
private void addAlgorithmListeners(List<PrioritizedVRAListener> list) {
|
||||
for (PrioritizedVRAListener aL : list) {
|
||||
algorithmListeners.add(aL);
|
||||
}
|
||||
}
|
||||
|
||||
ActivityInsertionCostsCalculator actInsertionCalc;
|
||||
if(activityInsertionCostCalculator == null && addDefaultCostCalc){
|
||||
actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||
}
|
||||
else if(activityInsertionCostCalculator == null && !addDefaultCostCalc){
|
||||
actInsertionCalc = new ActivityInsertionCostsCalculator(){
|
||||
private CalculatorPlusListeners createStandardLocal(final VehicleRoutingProblem vrp, RouteAndActivityStateGetter statesManager) {
|
||||
if (constraintManager == null) throw new IllegalStateException("constraint-manager is null");
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct,
|
||||
ActivityInsertionCostsCalculator actInsertionCalc;
|
||||
if (activityInsertionCostCalculator == null && addDefaultCostCalc) {
|
||||
actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||
} else if (activityInsertionCostCalculator == null && !addDefaultCostCalc) {
|
||||
actInsertionCalc = new ActivityInsertionCostsCalculator() {
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct,
|
||||
double depTimeAtPrevAct) {
|
||||
return 0.;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
else{
|
||||
actInsertionCalc = activityInsertionCostCalculator;
|
||||
}
|
||||
return 0.;
|
||||
}
|
||||
|
||||
};
|
||||
} else {
|
||||
actInsertionCalc = activityInsertionCostCalculator;
|
||||
}
|
||||
|
||||
JobActivityFactory activityFactory = new JobActivityFactory() {
|
||||
|
||||
|
|
@ -285,55 +284,53 @@ public class JobInsertionCostsCalculatorBuilder {
|
|||
}
|
||||
|
||||
};
|
||||
ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager);
|
||||
ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager);
|
||||
shipmentInsertion.setJobActivityFactory(activityFactory);
|
||||
ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager);
|
||||
ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager);
|
||||
serviceInsertion.setJobActivityFactory(activityFactory);
|
||||
|
||||
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
|
||||
switcher.put(Shipment.class, shipmentInsertion);
|
||||
switcher.put(Service.class, serviceInsertion);
|
||||
switcher.put(Pickup.class, serviceInsertion);
|
||||
switcher.put(Delivery.class, serviceInsertion);
|
||||
switcher.put(Shipment.class, shipmentInsertion);
|
||||
switcher.put(Service.class, serviceInsertion);
|
||||
switcher.put(Pickup.class, serviceInsertion);
|
||||
switcher.put(Delivery.class, serviceInsertion);
|
||||
|
||||
return new CalculatorPlusListeners(switcher);
|
||||
}
|
||||
return new CalculatorPlusListeners(switcher);
|
||||
}
|
||||
|
||||
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, RouteAndActivityStateGetter activityStates2, double weightOfFixedCosts){
|
||||
final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2);
|
||||
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
|
||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
|
||||
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
|
||||
return calcPlusListeners;
|
||||
}
|
||||
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, RouteAndActivityStateGetter activityStates2, double weightOfFixedCosts) {
|
||||
final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2);
|
||||
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
|
||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
|
||||
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
|
||||
return calcPlusListeners;
|
||||
}
|
||||
|
||||
private CalculatorPlusListeners createStandardRoute(final VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory){
|
||||
ActivityInsertionCostsCalculator routeLevelCostEstimator;
|
||||
if(activityInsertionCostCalculator == null && addDefaultCostCalc){
|
||||
private CalculatorPlusListeners createStandardRoute(final VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory) {
|
||||
ActivityInsertionCostsCalculator routeLevelCostEstimator;
|
||||
if (activityInsertionCostCalculator == null && addDefaultCostCalc) {
|
||||
RouteLevelActivityInsertionCostsEstimator routeLevelActivityInsertionCostsEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityStates2);
|
||||
routeLevelActivityInsertionCostsEstimator.setForwardLooking(forwardLooking);
|
||||
routeLevelCostEstimator = routeLevelActivityInsertionCostsEstimator;
|
||||
}
|
||||
else if(activityInsertionCostCalculator == null && !addDefaultCostCalc){
|
||||
routeLevelCostEstimator = new ActivityInsertionCostsCalculator(){
|
||||
} else if (activityInsertionCostCalculator == null && !addDefaultCostCalc) {
|
||||
routeLevelCostEstimator = new ActivityInsertionCostsCalculator() {
|
||||
|
||||
final ActivityInsertionCosts noInsertionCosts = new ActivityInsertionCosts(0.,0.);
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct,
|
||||
final ActivityInsertionCosts noInsertionCosts = new ActivityInsertionCosts(0., 0.);
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct,
|
||||
double depTimeAtPrevAct) {
|
||||
return 0.;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
else{
|
||||
routeLevelCostEstimator = activityInsertionCostCalculator;
|
||||
}
|
||||
return 0.;
|
||||
}
|
||||
|
||||
};
|
||||
} else {
|
||||
routeLevelCostEstimator = activityInsertionCostCalculator;
|
||||
}
|
||||
ServiceInsertionOnRouteLevelCalculator jobInsertionCalculator = new ServiceInsertionOnRouteLevelCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), routeLevelCostEstimator, constraintManager, constraintManager);
|
||||
jobInsertionCalculator.setNuOfActsForwardLooking(forwardLooking);
|
||||
jobInsertionCalculator.setMemorySize(solutionMemory);
|
||||
jobInsertionCalculator.setStates(activityStates2);
|
||||
jobInsertionCalculator.setNuOfActsForwardLooking(forwardLooking);
|
||||
jobInsertionCalculator.setMemorySize(solutionMemory);
|
||||
jobInsertionCalculator.setStates(activityStates2);
|
||||
jobInsertionCalculator.setJobActivityFactory(new JobActivityFactory() {
|
||||
@Override
|
||||
public List<AbstractActivity> createActivities(Job job) {
|
||||
|
|
@ -341,23 +338,23 @@ public class JobInsertionCostsCalculatorBuilder {
|
|||
}
|
||||
});
|
||||
return new CalculatorPlusListeners(jobInsertionCalculator);
|
||||
}
|
||||
}
|
||||
|
||||
private JobInsertionCostsCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCostsCalculator baseCalc, RouteAndActivityStateGetter activityStates2){
|
||||
VehicleTypeDependentJobInsertionCalculator vehicleTypeDependentJobInsertionCalculator = new VehicleTypeDependentJobInsertionCalculator(vrp, fleetManager, baseCalc);
|
||||
vehicleTypeDependentJobInsertionCalculator.setVehicleSwitchAllowed(allowVehicleSwitch);
|
||||
return vehicleTypeDependentJobInsertionCalculator;
|
||||
}
|
||||
private JobInsertionCostsCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCostsCalculator baseCalc, RouteAndActivityStateGetter activityStates2) {
|
||||
VehicleTypeDependentJobInsertionCalculator vehicleTypeDependentJobInsertionCalculator = new VehicleTypeDependentJobInsertionCalculator(vrp, fleetManager, baseCalc);
|
||||
vehicleTypeDependentJobInsertionCalculator.setVehicleSwitchAllowed(allowVehicleSwitch);
|
||||
return vehicleTypeDependentJobInsertionCalculator;
|
||||
}
|
||||
|
||||
public JobInsertionCostsCalculatorBuilder setConstraintManager(ConstraintManager constraintManager) {
|
||||
this.constraintManager = constraintManager;
|
||||
public JobInsertionCostsCalculatorBuilder setConstraintManager(ConstraintManager constraintManager) {
|
||||
this.constraintManager = constraintManager;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public JobInsertionCostsCalculatorBuilder setAllowVehicleSwitch(boolean allowVehicleSwitch) {
|
||||
public JobInsertionCostsCalculatorBuilder setAllowVehicleSwitch(boolean allowVehicleSwitch) {
|
||||
this.allowVehicleSwitch = allowVehicleSwitch;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -22,6 +22,6 @@ import jsprit.core.problem.solution.route.VehicleRoute;
|
|||
|
||||
public interface JobInsertionCostsCalculatorLight {
|
||||
|
||||
public InsertionData getInsertionData(Job unassignedJob, VehicleRoute route, double bestKnownCosts);
|
||||
public InsertionData getInsertionData(Job unassignedJob, VehicleRoute route, double bestKnownCosts);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,23 +38,23 @@ public class JobInsertionCostsCalculatorLightFactory {
|
|||
* Returns standard insertion calculator, i.e. the calculator that identifies best insertion positions for the
|
||||
* jobs to be inserted. The position basically consists of the route and the according indices.
|
||||
*
|
||||
* @param vrp vehicle routing problem
|
||||
* @param fleetManager fleet manager
|
||||
* @param stateManager state manager
|
||||
* @param vrp vehicle routing problem
|
||||
* @param fleetManager fleet manager
|
||||
* @param stateManager state manager
|
||||
* @param constraintManager constraint manager
|
||||
* @return insertion calculator
|
||||
*/
|
||||
public static JobInsertionCostsCalculatorLight createStandardCalculator(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager){
|
||||
public static JobInsertionCostsCalculatorLight createStandardCalculator(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager) {
|
||||
List<VehicleRoutingAlgorithmListeners.PrioritizedVRAListener> al = new ArrayList<VehicleRoutingAlgorithmListeners.PrioritizedVRAListener>();
|
||||
List<InsertionListener> il = new ArrayList<InsertionListener>();
|
||||
JobInsertionCostsCalculatorBuilder builder = new JobInsertionCostsCalculatorBuilder(il,al);
|
||||
JobInsertionCostsCalculatorBuilder builder = new JobInsertionCostsCalculatorBuilder(il, al);
|
||||
builder.setVehicleRoutingProblem(vrp).setConstraintManager(constraintManager).setStateManager(stateManager).setVehicleFleetManager(fleetManager);
|
||||
final JobInsertionCostsCalculator calculator = builder.build();
|
||||
return new JobInsertionCostsCalculatorLight() {
|
||||
|
||||
@Override
|
||||
public InsertionData getInsertionData(Job unassignedJob, VehicleRoute route, double bestKnownCosts) {
|
||||
return calculator.getInsertionData(route,unassignedJob,AbstractInsertionStrategy.NO_NEW_VEHICLE_YET,AbstractInsertionStrategy.NO_NEW_DEPARTURE_TIME_YET,AbstractInsertionStrategy.NO_NEW_DRIVER_YET,bestKnownCosts);
|
||||
return calculator.getInsertionData(route, unassignedJob, AbstractInsertionStrategy.NO_NEW_VEHICLE_YET, AbstractInsertionStrategy.NO_NEW_DEPARTURE_TIME_YET, AbstractInsertionStrategy.NO_NEW_DRIVER_YET, bestKnownCosts);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2014 Stefan Schroeder
|
||||
*
|
||||
|
|
@ -29,61 +28,59 @@ import jsprit.core.util.CalculationUtils;
|
|||
* Calculates activity insertion costs locally, i.e. by comparing the additional costs of insertion the new activity k between
|
||||
* activity i (prevAct) and j (nextAct).
|
||||
* Additional costs are then basically calculated as delta c = c_ik + c_kj - c_ij.
|
||||
*
|
||||
* <p/>
|
||||
* <p>Note once time has an effect on costs this class requires activity endTimes.
|
||||
*
|
||||
* @author stefan
|
||||
*
|
||||
* @author stefan
|
||||
*/
|
||||
class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator{
|
||||
class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator {
|
||||
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
private VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
|
||||
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts) {
|
||||
super();
|
||||
this.routingCosts = routingCosts;
|
||||
this.activityCosts = actCosts;
|
||||
}
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
|
||||
|
||||
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocation(), newAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocation(), newAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
|
||||
double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
|
||||
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
|
||||
//open routes
|
||||
if(nextAct instanceof End){
|
||||
if(!iFacts.getNewVehicle().isReturnToDepot()){
|
||||
return tp_costs_prevAct_newAct;
|
||||
}
|
||||
}
|
||||
|
||||
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocation(), nextAct.getLocation(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocation(), nextAct.getLocation(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
|
||||
double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
|
||||
|
||||
double oldCosts;
|
||||
if(iFacts.getRoute().isEmpty()){
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
|
||||
}
|
||||
else{
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
|
||||
}
|
||||
return totalCosts - oldCosts;
|
||||
}
|
||||
private VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
|
||||
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts) {
|
||||
super();
|
||||
this.routingCosts = routingCosts;
|
||||
this.activityCosts = actCosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
|
||||
|
||||
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocation(), newAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocation(), newAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
|
||||
double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
|
||||
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
|
||||
//open routes
|
||||
if (nextAct instanceof End) {
|
||||
if (!iFacts.getNewVehicle().isReturnToDepot()) {
|
||||
return tp_costs_prevAct_newAct;
|
||||
}
|
||||
}
|
||||
|
||||
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocation(), nextAct.getLocation(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocation(), nextAct.getLocation(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
|
||||
double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
|
||||
|
||||
double oldCosts;
|
||||
if (iFacts.getRoute().isEmpty()) {
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
|
||||
} else {
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
|
||||
}
|
||||
return totalCosts - oldCosts;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +1,32 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
||||
public class NoSolutionFoundException extends IllegalStateException{
|
||||
public class NoSolutionFoundException extends IllegalStateException {
|
||||
|
||||
public NoSolutionFoundException(String errorMsg) {
|
||||
super(errorMsg);
|
||||
}
|
||||
public NoSolutionFoundException(String errorMsg) {
|
||||
super(errorMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,16 +31,15 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Insertion based on regret approach.
|
||||
*
|
||||
* <p>Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference
|
||||
* between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction.
|
||||
* The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this
|
||||
* customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
* Insertion based on regret approach.
|
||||
* <p/>
|
||||
* <p>Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference
|
||||
* between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction.
|
||||
* The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this
|
||||
* customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*/
|
||||
public class RegretInsertion extends AbstractInsertionStrategy {
|
||||
|
||||
static class ScoredJob {
|
||||
|
|
@ -92,134 +91,133 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scorer to include other impacts on score such as time-window length or distance to depot.
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
*/
|
||||
static interface ScoringFunction {
|
||||
/**
|
||||
* Scorer to include other impacts on score such as time-window length or distance to depot.
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
static interface ScoringFunction {
|
||||
|
||||
public double score(InsertionData best, Job job);
|
||||
public double score(InsertionData best, Job job);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scorer that includes the length of the time-window when scoring a job. The wider the time-window, the lower the score.
|
||||
*
|
||||
* <p>This is the default scorer, i.e.: score = (secondBest - firstBest) + this.TimeWindowScorer.score(job)
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
*/
|
||||
public static class DefaultScorer implements ScoringFunction {
|
||||
/**
|
||||
* Scorer that includes the length of the time-window when scoring a job. The wider the time-window, the lower the score.
|
||||
* <p/>
|
||||
* <p>This is the default scorer, i.e.: score = (secondBest - firstBest) + this.TimeWindowScorer.score(job)
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public static class DefaultScorer implements ScoringFunction {
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private double tw_param = - 0.5;
|
||||
private double tw_param = -0.5;
|
||||
|
||||
private double depotDistance_param = + 0.1;
|
||||
private double depotDistance_param = +0.1;
|
||||
|
||||
private double minTimeWindowScore = - 100000;
|
||||
private double minTimeWindowScore = -100000;
|
||||
|
||||
public DefaultScorer(VehicleRoutingProblem vrp) {
|
||||
this.vrp = vrp;
|
||||
}
|
||||
|
||||
public void setTimeWindowParam(double tw_param){ this.tw_param = tw_param; }
|
||||
public void setTimeWindowParam(double tw_param) {
|
||||
this.tw_param = tw_param;
|
||||
}
|
||||
|
||||
public void setDepotDistanceParam(double depotDistance_param){ this.depotDistance_param = depotDistance_param; }
|
||||
public void setDepotDistanceParam(double depotDistance_param) {
|
||||
this.depotDistance_param = depotDistance_param;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double score(InsertionData best, Job job) {
|
||||
double score;
|
||||
if(job instanceof Service){
|
||||
if (job instanceof Service) {
|
||||
score = scoreService(best, job);
|
||||
}
|
||||
else if(job instanceof Shipment){
|
||||
score = scoreShipment(best,job);
|
||||
}
|
||||
else throw new IllegalStateException("not supported");
|
||||
} else if (job instanceof Shipment) {
|
||||
score = scoreShipment(best, job);
|
||||
} else throw new IllegalStateException("not supported");
|
||||
return score;
|
||||
}
|
||||
|
||||
private double scoreShipment(InsertionData best, Job job) {
|
||||
Shipment shipment = (Shipment)job;
|
||||
Shipment shipment = (Shipment) job;
|
||||
double maxDepotDistance_1 = Math.max(
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(),shipment.getPickupLocation()),
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(),shipment.getDeliveryLocation())
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(), shipment.getPickupLocation()),
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(), shipment.getDeliveryLocation())
|
||||
);
|
||||
double maxDepotDistance_2 = Math.max(
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(),shipment.getPickupLocation()),
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(),shipment.getDeliveryLocation())
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(), shipment.getPickupLocation()),
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(), shipment.getDeliveryLocation())
|
||||
);
|
||||
double maxDepotDistance = Math.max(maxDepotDistance_1,maxDepotDistance_2);
|
||||
double minTimeToOperate = Math.min(shipment.getPickupTimeWindow().getEnd()-shipment.getPickupTimeWindow().getStart(),
|
||||
shipment.getDeliveryTimeWindow().getEnd()-shipment.getDeliveryTimeWindow().getStart());
|
||||
return Math.max(tw_param * minTimeToOperate,minTimeWindowScore) + depotDistance_param * maxDepotDistance;
|
||||
double maxDepotDistance = Math.max(maxDepotDistance_1, maxDepotDistance_2);
|
||||
double minTimeToOperate = Math.min(shipment.getPickupTimeWindow().getEnd() - shipment.getPickupTimeWindow().getStart(),
|
||||
shipment.getDeliveryTimeWindow().getEnd() - shipment.getDeliveryTimeWindow().getStart());
|
||||
return Math.max(tw_param * minTimeToOperate, minTimeWindowScore) + depotDistance_param * maxDepotDistance;
|
||||
}
|
||||
|
||||
private double scoreService(InsertionData best, Job job) {
|
||||
double maxDepotDistance = Math.max(
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(), ((Service) job).getLocation()),
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(), ((Service) job).getLocation())
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(), ((Service) job).getLocation()),
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(), ((Service) job).getLocation())
|
||||
);
|
||||
return Math.max(tw_param * (((Service)job).getTimeWindow().getEnd() - ((Service)job).getTimeWindow().getStart()),minTimeWindowScore) +
|
||||
depotDistance_param * maxDepotDistance;
|
||||
return Math.max(tw_param * (((Service) job).getTimeWindow().getEnd() - ((Service) job).getTimeWindow().getStart()), minTimeWindowScore) +
|
||||
depotDistance_param * maxDepotDistance;
|
||||
}
|
||||
|
||||
|
||||
private double getDistance(Location loc1, Location loc2) {
|
||||
return vrp.getTransportCosts().getTransportCost(loc1,loc2,0.,null,null);
|
||||
return vrp.getTransportCosts().getTransportCost(loc1, loc2, 0., null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=defaultScorer][twParam="+tw_param+"][depotDistanceParam=" + depotDistance_param + "]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=defaultScorer][twParam=" + tw_param + "][depotDistanceParam=" + depotDistance_param + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static Logger logger = LogManager.getLogger(RegretInsertion.class);
|
||||
|
||||
private ScoringFunction scoringFunction;
|
||||
private ScoringFunction scoringFunction;
|
||||
|
||||
private JobInsertionCostsCalculator insertionCostsCalculator;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the scoring function.
|
||||
*
|
||||
* <p>By default, the this.TimeWindowScorer is used.
|
||||
*
|
||||
* @param scoringFunction to score
|
||||
*/
|
||||
public void setScoringFunction(ScoringFunction scoringFunction) {
|
||||
this.scoringFunction = scoringFunction;
|
||||
}
|
||||
* Sets the scoring function.
|
||||
* <p/>
|
||||
* <p>By default, the this.TimeWindowScorer is used.
|
||||
*
|
||||
* @param scoringFunction to score
|
||||
*/
|
||||
public void setScoringFunction(ScoringFunction scoringFunction) {
|
||||
this.scoringFunction = scoringFunction;
|
||||
}
|
||||
|
||||
public RegretInsertion(JobInsertionCostsCalculator jobInsertionCalculator, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
super(vehicleRoutingProblem);
|
||||
public RegretInsertion(JobInsertionCostsCalculator jobInsertionCalculator, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
super(vehicleRoutingProblem);
|
||||
this.scoringFunction = new DefaultScorer(vehicleRoutingProblem);
|
||||
this.insertionCostsCalculator = jobInsertionCalculator;
|
||||
this.insertionCostsCalculator = jobInsertionCalculator;
|
||||
this.vrp = vehicleRoutingProblem;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=regretInsertion][additionalScorer="+scoringFunction+"]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=regretInsertion][additionalScorer=" + scoringFunction + "]";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs insertion.
|
||||
*
|
||||
* <p>Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
/**
|
||||
* Runs insertion.
|
||||
* <p/>
|
||||
* <p>Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> jobs = new ArrayList<Job>(unassignedJobs);
|
||||
|
||||
|
|
@ -227,14 +225,14 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||
List<Job> badJobList = new ArrayList<Job>();
|
||||
ScoredJob bestScoredJob = nextJob(routes, unassignedJobList, badJobList);
|
||||
if(bestScoredJob != null){
|
||||
if(bestScoredJob.isNewRoute()){
|
||||
if (bestScoredJob != null) {
|
||||
if (bestScoredJob.isNewRoute()) {
|
||||
routes.add(bestScoredJob.getRoute());
|
||||
}
|
||||
insertJob(bestScoredJob.getJob(),bestScoredJob.getInsertionData(),bestScoredJob.getRoute());
|
||||
insertJob(bestScoredJob.getJob(), bestScoredJob.getInsertionData(), bestScoredJob.getRoute());
|
||||
jobs.remove(bestScoredJob.getJob());
|
||||
}
|
||||
for(Job bad : badJobList) {
|
||||
for (Job bad : badJobList) {
|
||||
jobs.remove(bad);
|
||||
badJobs.add(bad);
|
||||
}
|
||||
|
|
@ -245,14 +243,14 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
private ScoredJob nextJob(Collection<VehicleRoute> routes, List<Job> unassignedJobList, List<Job> badJobs) {
|
||||
ScoredJob bestScoredJob = null;
|
||||
for (Job unassignedJob : unassignedJobList) {
|
||||
ScoredJob scoredJob = getScoredJob(routes,unassignedJob,insertionCostsCalculator,scoringFunction);
|
||||
if(scoredJob instanceof BadJob){
|
||||
ScoredJob scoredJob = getScoredJob(routes, unassignedJob, insertionCostsCalculator, scoringFunction);
|
||||
if (scoredJob instanceof BadJob) {
|
||||
badJobs.add(unassignedJob);
|
||||
continue;
|
||||
}
|
||||
if(bestScoredJob == null) bestScoredJob = scoredJob;
|
||||
else{
|
||||
if(scoredJob.getScore() > bestScoredJob.getScore()){
|
||||
if (bestScoredJob == null) bestScoredJob = scoredJob;
|
||||
else {
|
||||
if (scoredJob.getScore() > bestScoredJob.getScore()) {
|
||||
bestScoredJob = scoredJob;
|
||||
}
|
||||
}
|
||||
|
|
@ -298,31 +296,29 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
secondBest = iData;
|
||||
}
|
||||
}
|
||||
if(best == null){
|
||||
if (best == null) {
|
||||
return new RegretInsertion.BadJob(unassignedJob);
|
||||
}
|
||||
double score = score(unassignedJob, best, secondBest, scoringFunction);
|
||||
ScoredJob scoredJob;
|
||||
if(bestRoute == emptyRoute){
|
||||
if (bestRoute == emptyRoute) {
|
||||
scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, true);
|
||||
}
|
||||
else scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false);
|
||||
} else scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false);
|
||||
return scoredJob;
|
||||
}
|
||||
|
||||
|
||||
static double score(Job unassignedJob, InsertionData best, InsertionData secondBest, ScoringFunction scoringFunction) {
|
||||
if(best == null){
|
||||
throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
|
||||
if (best == null) {
|
||||
throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
|
||||
}
|
||||
double score;
|
||||
if(secondBest == null){ //either there is only one vehicle or there are more vehicles, but they cannot load unassignedJob
|
||||
if (secondBest == null) { //either there is only one vehicle or there are more vehicles, but they cannot load unassignedJob
|
||||
//if only one vehicle, I want the job to be inserted with min iCosts
|
||||
//if there are more vehicles, I want this job to be prioritized since there are no alternatives
|
||||
score = Integer.MAX_VALUE - best.getInsertionCost() + scoringFunction.score(best, unassignedJob);
|
||||
}
|
||||
else{
|
||||
score = (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
} else {
|
||||
score = (secondBest.getInsertionCost() - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,61 +32,59 @@ import java.util.List;
|
|||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Insertion based on regret approach.
|
||||
*
|
||||
* <p>Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference
|
||||
* between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction.
|
||||
* The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this
|
||||
* customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
* Insertion based on regret approach.
|
||||
* <p/>
|
||||
* <p>Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference
|
||||
* between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction.
|
||||
* The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this
|
||||
* customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*/
|
||||
public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
|
||||
|
||||
|
||||
private static Logger logger = LogManager.getLogger(RegretInsertionConcurrent.class);
|
||||
|
||||
private ScoringFunction scoringFunction;
|
||||
private ScoringFunction scoringFunction;
|
||||
|
||||
private final JobInsertionCostsCalculator insertionCostsCalculator;
|
||||
|
||||
private final ExecutorCompletionService<ScoredJob> completionService;
|
||||
|
||||
/**
|
||||
* Sets the scoring function.
|
||||
*
|
||||
* <p>By default, the this.TimeWindowScorer is used.
|
||||
*
|
||||
* @param scoringFunction to score
|
||||
*/
|
||||
public void setScoringFunction(ScoringFunction scoringFunction) {
|
||||
this.scoringFunction = scoringFunction;
|
||||
}
|
||||
* Sets the scoring function.
|
||||
* <p/>
|
||||
* <p>By default, the this.TimeWindowScorer is used.
|
||||
*
|
||||
* @param scoringFunction to score
|
||||
*/
|
||||
public void setScoringFunction(ScoringFunction scoringFunction) {
|
||||
this.scoringFunction = scoringFunction;
|
||||
}
|
||||
|
||||
public RegretInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, VehicleRoutingProblem vehicleRoutingProblem, ExecutorService executorService) {
|
||||
super(vehicleRoutingProblem);
|
||||
public RegretInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, VehicleRoutingProblem vehicleRoutingProblem, ExecutorService executorService) {
|
||||
super(vehicleRoutingProblem);
|
||||
this.scoringFunction = new DefaultScorer(vehicleRoutingProblem);
|
||||
this.insertionCostsCalculator = jobInsertionCalculator;
|
||||
this.insertionCostsCalculator = jobInsertionCalculator;
|
||||
this.vrp = vehicleRoutingProblem;
|
||||
completionService = new ExecutorCompletionService<ScoredJob>(executorService);
|
||||
logger.debug("initialise " + this);
|
||||
}
|
||||
logger.debug("initialise " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=regretInsertion][additionalScorer="+scoringFunction+"]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=regretInsertion][additionalScorer=" + scoringFunction + "]";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs insertion.
|
||||
*
|
||||
* <p>Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
/**
|
||||
* Runs insertion.
|
||||
* <p/>
|
||||
* <p>Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> jobs = new ArrayList<Job>(unassignedJobs);
|
||||
|
||||
|
|
@ -94,14 +92,14 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||
List<Job> badJobList = new ArrayList<Job>();
|
||||
ScoredJob bestScoredJob = nextJob(routes, unassignedJobList, badJobList);
|
||||
if(bestScoredJob != null){
|
||||
if(bestScoredJob.isNewRoute()){
|
||||
if (bestScoredJob != null) {
|
||||
if (bestScoredJob.isNewRoute()) {
|
||||
routes.add(bestScoredJob.getRoute());
|
||||
}
|
||||
insertJob(bestScoredJob.getJob(),bestScoredJob.getInsertionData(),bestScoredJob.getRoute());
|
||||
insertJob(bestScoredJob.getJob(), bestScoredJob.getInsertionData(), bestScoredJob.getRoute());
|
||||
jobs.remove(bestScoredJob.getJob());
|
||||
}
|
||||
for(Job j : badJobList) {
|
||||
for (Job j : badJobList) {
|
||||
jobs.remove(j);
|
||||
badJobs.add(j);
|
||||
}
|
||||
|
|
@ -123,26 +121,23 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
});
|
||||
}
|
||||
|
||||
try{
|
||||
for(int i=0; i < unassignedJobList.size(); i++){
|
||||
try {
|
||||
for (int i = 0; i < unassignedJobList.size(); i++) {
|
||||
Future<ScoredJob> fsj = completionService.take();
|
||||
ScoredJob sJob = fsj.get();
|
||||
if(sJob instanceof RegretInsertion.BadJob){
|
||||
if (sJob instanceof RegretInsertion.BadJob) {
|
||||
badJobList.add(sJob.getJob());
|
||||
continue;
|
||||
}
|
||||
if(bestScoredJob == null){
|
||||
if (bestScoredJob == null) {
|
||||
bestScoredJob = sJob;
|
||||
}
|
||||
else if(sJob.getScore() > bestScoredJob.getScore()){
|
||||
} else if (sJob.getScore() > bestScoredJob.getScore()) {
|
||||
bestScoredJob = sJob;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(InterruptedException e){
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Exception", e);
|
||||
System.exit(1);
|
||||
|
|
@ -152,9 +147,4 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2014 Stefan Schroeder
|
||||
*
|
||||
|
|
@ -32,65 +31,68 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCostsCalculator{
|
||||
class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCostsCalculator {
|
||||
|
||||
private VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
||||
|
||||
private RouteAndActivityStateGetter stateManager;
|
||||
|
||||
private int nuOfActivities2LookForward = 0;
|
||||
|
||||
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, RouteAndActivityStateGetter stateManager) {
|
||||
super();
|
||||
this.activityCosts = actCosts;
|
||||
this.stateManager = stateManager;
|
||||
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
|
||||
}
|
||||
private VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
|
||||
List<TourActivity> path = new ArrayList<TourActivity>();
|
||||
path.add(prevAct); path.add(newAct); path.add(nextAct);
|
||||
int actIndex;
|
||||
if(prevAct instanceof Start) actIndex = 0;
|
||||
else actIndex = iFacts.getRoute().getTourActivities().getActivities().indexOf(nextAct);
|
||||
if(nuOfActivities2LookForward > 0 && !(nextAct instanceof End)){ path.addAll(getForwardLookingPath(iFacts.getRoute(),actIndex)); }
|
||||
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
||||
|
||||
private RouteAndActivityStateGetter stateManager;
|
||||
|
||||
private int nuOfActivities2LookForward = 0;
|
||||
|
||||
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, RouteAndActivityStateGetter stateManager) {
|
||||
super();
|
||||
this.activityCosts = actCosts;
|
||||
this.stateManager = stateManager;
|
||||
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
|
||||
List<TourActivity> path = new ArrayList<TourActivity>();
|
||||
path.add(prevAct);
|
||||
path.add(newAct);
|
||||
path.add(nextAct);
|
||||
int actIndex;
|
||||
if (prevAct instanceof Start) actIndex = 0;
|
||||
else actIndex = iFacts.getRoute().getTourActivities().getActivities().indexOf(nextAct);
|
||||
if (nuOfActivities2LookForward > 0 && !(nextAct instanceof End)) {
|
||||
path.addAll(getForwardLookingPath(iFacts.getRoute(), actIndex));
|
||||
}
|
||||
|
||||
/*
|
||||
* calculates the path costs with new vehicle, c(forwardPath,newVehicle).
|
||||
* calculates the path costs with new vehicle, c(forwardPath,newVehicle).
|
||||
*/
|
||||
double forwardPathCost_newVehicle = auxilliaryPathCostCalculator.costOfPath(path, depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
return forwardPathCost_newVehicle - (actCostsOld(iFacts.getRoute(), path.get(path.size()-1)) - actCostsOld(iFacts.getRoute(), prevAct));
|
||||
}
|
||||
|
||||
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
|
||||
double forwardPathCost_newVehicle = auxilliaryPathCostCalculator.costOfPath(path, depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
return forwardPathCost_newVehicle - (actCostsOld(iFacts.getRoute(), path.get(path.size() - 1)) - actCostsOld(iFacts.getRoute(), prevAct));
|
||||
}
|
||||
|
||||
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
|
||||
Double cost_at_act;
|
||||
if(act instanceof End){
|
||||
if (act instanceof End) {
|
||||
cost_at_act = stateManager.getRouteState(vehicleRoute, InternalStates.COSTS, Double.class);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
cost_at_act = stateManager.getActivityState(act, InternalStates.COSTS, Double.class);
|
||||
}
|
||||
if(cost_at_act == null) cost_at_act = 0.;
|
||||
if (cost_at_act == null) cost_at_act = 0.;
|
||||
return cost_at_act;
|
||||
}
|
||||
|
||||
private List<TourActivity> getForwardLookingPath(VehicleRoute route, int actIndex) {
|
||||
List<TourActivity> forwardLookingPath = new ArrayList<TourActivity>();
|
||||
int nuOfActsInPath = 0;
|
||||
int index = actIndex + 1;
|
||||
while(index < route.getTourActivities().getActivities().size() && nuOfActsInPath < nuOfActivities2LookForward){
|
||||
forwardLookingPath.add(route.getTourActivities().getActivities().get(index));
|
||||
index++;
|
||||
nuOfActsInPath++;
|
||||
}
|
||||
if(nuOfActsInPath < nuOfActivities2LookForward){
|
||||
forwardLookingPath.add(route.getEnd());
|
||||
}
|
||||
return forwardLookingPath;
|
||||
}
|
||||
}
|
||||
|
||||
private List<TourActivity> getForwardLookingPath(VehicleRoute route, int actIndex) {
|
||||
List<TourActivity> forwardLookingPath = new ArrayList<TourActivity>();
|
||||
int nuOfActsInPath = 0;
|
||||
int index = actIndex + 1;
|
||||
while (index < route.getTourActivities().getActivities().size() && nuOfActsInPath < nuOfActivities2LookForward) {
|
||||
forwardLookingPath.add(route.getTourActivities().getActivities().get(index));
|
||||
index++;
|
||||
nuOfActsInPath++;
|
||||
}
|
||||
if (nuOfActsInPath < nuOfActivities2LookForward) {
|
||||
forwardLookingPath.add(route.getEnd());
|
||||
}
|
||||
return forwardLookingPath;
|
||||
}
|
||||
|
||||
public void setForwardLooking(int nActivities) {
|
||||
this.nuOfActivities2LookForward = nActivities;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -37,125 +37,122 @@ import java.util.Iterator;
|
|||
|
||||
/**
|
||||
* Calculator that calculates the best insertion position for a {@link Service}.
|
||||
*
|
||||
* @author schroeder
|
||||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(ServiceInsertionCalculator.class);
|
||||
final class ServiceInsertionCalculator implements JobInsertionCostsCalculator {
|
||||
|
||||
private HardRouteConstraint hardRouteLevelConstraint;
|
||||
|
||||
private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private SoftRouteConstraint softRouteConstraint;
|
||||
|
||||
private SoftActivityConstraint softActivityConstraint;
|
||||
|
||||
private VehicleRoutingTransportCosts transportCosts;
|
||||
|
||||
private ActivityInsertionCostsCalculator additionalTransportCostsCalculator;
|
||||
|
||||
private JobActivityFactory activityFactory;
|
||||
|
||||
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
|
||||
private static final Logger logger = LogManager.getLogger(ServiceInsertionCalculator.class);
|
||||
|
||||
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.transportCosts = routingCosts;
|
||||
hardRouteLevelConstraint = constraintManager;
|
||||
hardActivityLevelConstraint = constraintManager;
|
||||
softActivityConstraint = constraintManager;
|
||||
softRouteConstraint = constraintManager;
|
||||
this.additionalTransportCostsCalculator = additionalTransportCostsCalculator;
|
||||
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
private HardRouteConstraint hardRouteLevelConstraint;
|
||||
|
||||
public void setJobActivityFactory(JobActivityFactory jobActivityFactory){
|
||||
private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private SoftRouteConstraint softRouteConstraint;
|
||||
|
||||
private SoftActivityConstraint softActivityConstraint;
|
||||
|
||||
private VehicleRoutingTransportCosts transportCosts;
|
||||
|
||||
private ActivityInsertionCostsCalculator additionalTransportCostsCalculator;
|
||||
|
||||
private JobActivityFactory activityFactory;
|
||||
|
||||
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
|
||||
|
||||
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.transportCosts = routingCosts;
|
||||
hardRouteLevelConstraint = constraintManager;
|
||||
hardActivityLevelConstraint = constraintManager;
|
||||
softActivityConstraint = constraintManager;
|
||||
softRouteConstraint = constraintManager;
|
||||
this.additionalTransportCostsCalculator = additionalTransportCostsCalculator;
|
||||
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
public void setJobActivityFactory(JobActivityFactory jobActivityFactory) {
|
||||
this.activityFactory = jobActivityFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertion]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the marginal cost of inserting job i locally. This is based on the
|
||||
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
|
||||
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
|
||||
Service service = (Service)jobToInsert;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertion]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the marginal cost of inserting job i locally. This is based on the
|
||||
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
|
||||
*/
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
|
||||
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
|
||||
Service service = (Service) jobToInsert;
|
||||
int insertionIndex = InsertionData.NO_INDEX;
|
||||
|
||||
TourActivity deliveryAct2Insert = activityFactory.createActivities(service).get(0);
|
||||
TourActivity deliveryAct2Insert = activityFactory.createActivities(service).get(0);
|
||||
insertionContext.getAssociatedActivities().add(deliveryAct2Insert);
|
||||
|
||||
/*
|
||||
check hard constraints at route level
|
||||
*/
|
||||
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
if (!hardRouteLevelConstraint.fulfilled(insertionContext)) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
|
||||
/*
|
||||
check soft constraints at route level
|
||||
*/
|
||||
double additionalICostsAtRouteLevel = softRouteConstraint.getCosts(insertionContext);
|
||||
|
||||
double bestCost = bestKnownCosts;
|
||||
double bestCost = bestKnownCosts;
|
||||
additionalICostsAtRouteLevel += additionalAccessEgressCalculator.getCosts(insertionContext);
|
||||
|
||||
/*
|
||||
generate new start and end for new vehicle
|
||||
*/
|
||||
Start start = new Start(newVehicle.getStartLocation(), newVehicle.getEarliestDeparture(), Double.MAX_VALUE);
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
End end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
|
||||
|
||||
TourActivity prevAct = start;
|
||||
double prevActStartTime = newVehicleDepartureTime;
|
||||
int actIndex = 0;
|
||||
Iterator<TourActivity> activityIterator = currentRoute.getActivities().iterator();
|
||||
boolean tourEnd = false;
|
||||
while(!tourEnd){
|
||||
TourActivity nextAct;
|
||||
if(activityIterator.hasNext()) nextAct = activityIterator.next();
|
||||
else{
|
||||
nextAct = end;
|
||||
tourEnd = true;
|
||||
}
|
||||
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
|
||||
if(status.equals(ConstraintsStatus.FULFILLED)){
|
||||
//from job2insert induced costs at activity level
|
||||
double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
|
||||
double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
|
||||
if(additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts < bestCost){
|
||||
bestCost = additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts;
|
||||
insertionIndex = actIndex;
|
||||
}
|
||||
}
|
||||
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
|
||||
break;
|
||||
}
|
||||
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActStartTime, newDriver, newVehicle);
|
||||
prevActStartTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
|
||||
prevAct = nextAct;
|
||||
actIndex++;
|
||||
}
|
||||
if(insertionIndex == InsertionData.NO_INDEX) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
||||
insertionData.getEvents().add(new InsertActivity(currentRoute,newVehicle,deliveryAct2Insert,insertionIndex));
|
||||
insertionData.getEvents().add(new SwitchVehicle(currentRoute,newVehicle,newVehicleDepartureTime));
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
return insertionData;
|
||||
}
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
End end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
|
||||
|
||||
TourActivity prevAct = start;
|
||||
double prevActStartTime = newVehicleDepartureTime;
|
||||
int actIndex = 0;
|
||||
Iterator<TourActivity> activityIterator = currentRoute.getActivities().iterator();
|
||||
boolean tourEnd = false;
|
||||
while (!tourEnd) {
|
||||
TourActivity nextAct;
|
||||
if (activityIterator.hasNext()) nextAct = activityIterator.next();
|
||||
else {
|
||||
nextAct = end;
|
||||
tourEnd = true;
|
||||
}
|
||||
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
|
||||
if (status.equals(ConstraintsStatus.FULFILLED)) {
|
||||
//from job2insert induced costs at activity level
|
||||
double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
|
||||
double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
|
||||
if (additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts < bestCost) {
|
||||
bestCost = additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts;
|
||||
insertionIndex = actIndex;
|
||||
}
|
||||
} else if (status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
|
||||
break;
|
||||
}
|
||||
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActStartTime, newDriver, newVehicle);
|
||||
prevActStartTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
|
||||
prevAct = nextAct;
|
||||
actIndex++;
|
||||
}
|
||||
if (insertionIndex == InsertionData.NO_INDEX) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
||||
insertionData.getEvents().add(new InsertActivity(currentRoute, newVehicle, deliveryAct2Insert, insertionIndex));
|
||||
insertionData.getEvents().add(new SwitchVehicle(currentRoute, newVehicle, newVehicleDepartureTime));
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -45,127 +45,125 @@ import java.util.List;
|
|||
import java.util.PriorityQueue;
|
||||
|
||||
|
||||
final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsCalculator {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(ServiceInsertionOnRouteLevelCalculator.class);
|
||||
|
||||
private final VehicleRoutingTransportCosts transportCosts;
|
||||
|
||||
private final VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
||||
|
||||
private JobActivityFactory activityFactory;
|
||||
|
||||
private RouteAndActivityStateGetter stateManager;
|
||||
|
||||
private HardRouteConstraint hardRouteLevelConstraint;
|
||||
|
||||
private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
||||
|
||||
private int nuOfActsForwardLooking = 0;
|
||||
//
|
||||
private int memorySize = 2;
|
||||
|
||||
private Start start;
|
||||
|
||||
private End end;
|
||||
|
||||
public void setJobActivityFactory(JobActivityFactory jobActivityFactory) {
|
||||
this.activityFactory = jobActivityFactory;
|
||||
}
|
||||
|
||||
public void setMemorySize(int memorySize) {
|
||||
this.memorySize = memorySize;
|
||||
logger.debug("set [solutionMemory={}]", memorySize);
|
||||
}
|
||||
|
||||
public ServiceInsertionOnRouteLevelCalculator(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteConstraint hardRouteLevelConstraint, HardActivityConstraint hardActivityLevelConstraint) {
|
||||
super();
|
||||
this.transportCosts = vehicleRoutingCosts;
|
||||
this.activityCosts = costFunc;
|
||||
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
||||
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
|
||||
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
|
||||
final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsCalculator{
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(ServiceInsertionOnRouteLevelCalculator.class);
|
||||
|
||||
private final VehicleRoutingTransportCosts transportCosts;
|
||||
|
||||
private final VehicleRoutingActivityCosts activityCosts;
|
||||
public void setStates(RouteAndActivityStateGetter stateManager) {
|
||||
this.stateManager = stateManager;
|
||||
}
|
||||
|
||||
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
||||
|
||||
private JobActivityFactory activityFactory;
|
||||
|
||||
private RouteAndActivityStateGetter stateManager;
|
||||
|
||||
private HardRouteConstraint hardRouteLevelConstraint;
|
||||
|
||||
private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
||||
|
||||
private int nuOfActsForwardLooking = 0;
|
||||
//
|
||||
private int memorySize = 2;
|
||||
|
||||
private Start start;
|
||||
|
||||
private End end;
|
||||
void setNuOfActsForwardLooking(int nOfActsForwardLooking) {
|
||||
this.nuOfActsForwardLooking = nOfActsForwardLooking;
|
||||
logger.debug("set [forwardLooking={}]", nOfActsForwardLooking);
|
||||
}
|
||||
|
||||
public void setJobActivityFactory(JobActivityFactory jobActivityFactory){
|
||||
this.activityFactory=jobActivityFactory;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertionOnRouteLevel][solutionMemory=" + memorySize + "][forwardLooking=" + nuOfActsForwardLooking + "]";
|
||||
}
|
||||
|
||||
public void setMemorySize(int memorySize) {
|
||||
this.memorySize = memorySize;
|
||||
logger.debug("set [solutionMemory={}]", memorySize);
|
||||
}
|
||||
/**
|
||||
* Calculates the insertion costs of job i on route level (which is based on the assumption that inserting job i does not only
|
||||
* have local effects but affects the entire route).
|
||||
* Calculation is conducted by two steps. In the first step, promising insertion positions are identified by appromiximating their
|
||||
* marginal insertion cost. In the second step, marginal cost of the best M positions are calculated exactly.
|
||||
*/
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) {
|
||||
if (jobToInsert == null)
|
||||
throw new IllegalStateException("job is null. cannot calculate the insertion of a null-job.");
|
||||
if (newVehicle == null || newVehicle instanceof NoVehicle)
|
||||
throw new IllegalStateException("no vehicle given. set para vehicle!");
|
||||
|
||||
public ServiceInsertionOnRouteLevelCalculator(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteConstraint hardRouteLevelConstraint, HardActivityConstraint hardActivityLevelConstraint) {
|
||||
super();
|
||||
this.transportCosts = vehicleRoutingCosts;
|
||||
this.activityCosts = costFunc;
|
||||
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
||||
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
|
||||
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
|
||||
if (!hardRouteLevelConstraint.fulfilled(insertionContext)) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
|
||||
|
||||
public void setStates(RouteAndActivityStateGetter stateManager){
|
||||
this.stateManager = stateManager;
|
||||
}
|
||||
|
||||
void setNuOfActsForwardLooking(int nOfActsForwardLooking) {
|
||||
this.nuOfActsForwardLooking = nOfActsForwardLooking;
|
||||
logger.debug("set [forwardLooking={}]", nOfActsForwardLooking);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertionOnRouteLevel][solutionMemory="+memorySize+"][forwardLooking="+nuOfActsForwardLooking+"]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the insertion costs of job i on route level (which is based on the assumption that inserting job i does not only
|
||||
* have local effects but affects the entire route).
|
||||
* Calculation is conducted by two steps. In the first step, promising insertion positions are identified by appromiximating their
|
||||
* marginal insertion cost. In the second step, marginal cost of the best M positions are calculated exactly.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) {
|
||||
if(jobToInsert == null) throw new IllegalStateException("job is null. cannot calculate the insertion of a null-job.");
|
||||
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("no vehicle given. set para vehicle!");
|
||||
|
||||
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
|
||||
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
|
||||
/**
|
||||
* map that memorizes the costs with newVehicle, which is a cost-snapshot at tour-activities.
|
||||
*/
|
||||
/**
|
||||
* map that memorizes the costs with newVehicle, which is a cost-snapshot at tour-activities.
|
||||
*/
|
||||
// Map<TourActivity,Double> activity2costWithNewVehicle = new HashMap<TourActivity,Double>();
|
||||
|
||||
/**
|
||||
* priority queue that stores insertion-data by insertion-costs in ascending order.
|
||||
*/
|
||||
PriorityQueue<InsertionData> bestInsertionsQueue = new PriorityQueue<InsertionData>(Math.max(2, currentRoute.getTourActivities().getActivities().size()), getComparator());
|
||||
|
||||
TourActivities tour = currentRoute.getTourActivities();
|
||||
double best_insertion_costs = best_known_insertion_costs;
|
||||
Service service = (Service)jobToInsert;
|
||||
|
||||
|
||||
/**
|
||||
* some inis
|
||||
*/
|
||||
TourActivity serviceAct2Insert = activityFactory.createActivities(service).get(0);
|
||||
int best_insertion_index = InsertionData.NO_INDEX;
|
||||
|
||||
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
|
||||
|
||||
TourActivity prevAct = start;
|
||||
int actIndex = 0;
|
||||
double sumOf_prevCosts_newVehicle = 0.0;
|
||||
double prevActDepTime_newVehicle = start.getEndTime();
|
||||
/**
|
||||
* priority queue that stores insertion-data by insertion-costs in ascending order.
|
||||
*/
|
||||
PriorityQueue<InsertionData> bestInsertionsQueue = new PriorityQueue<InsertionData>(Math.max(2, currentRoute.getTourActivities().getActivities().size()), getComparator());
|
||||
|
||||
TourActivities tour = currentRoute.getTourActivities();
|
||||
double best_insertion_costs = best_known_insertion_costs;
|
||||
Service service = (Service) jobToInsert;
|
||||
|
||||
|
||||
/**
|
||||
* some inis
|
||||
*/
|
||||
TourActivity serviceAct2Insert = activityFactory.createActivities(service).get(0);
|
||||
int best_insertion_index = InsertionData.NO_INDEX;
|
||||
|
||||
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
|
||||
|
||||
TourActivity prevAct = start;
|
||||
int actIndex = 0;
|
||||
double sumOf_prevCosts_newVehicle = 0.0;
|
||||
double prevActDepTime_newVehicle = start.getEndTime();
|
||||
|
||||
boolean loopBroken = false;
|
||||
/**
|
||||
* inserting serviceAct2Insert in route r={0,1,...,i-1,i,j,j+1,...,n(r),n(r)+1}
|
||||
* i=prevAct
|
||||
* j=nextAct
|
||||
* k=serviceAct2Insert
|
||||
*/
|
||||
for(TourActivity nextAct : tour.getActivities()){
|
||||
/**
|
||||
* inserting serviceAct2Insert in route r={0,1,...,i-1,i,j,j+1,...,n(r),n(r)+1}
|
||||
* i=prevAct
|
||||
* j=nextAct
|
||||
* k=serviceAct2Insert
|
||||
*/
|
||||
for (TourActivity nextAct : tour.getActivities()) {
|
||||
ConstraintsStatus hardActivityConstraintsStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||
if(hardActivityConstraintsStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||
if (hardActivityConstraintsStatus.equals(ConstraintsStatus.FULFILLED)) {
|
||||
/**
|
||||
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
|
||||
*/
|
||||
|
|
@ -174,16 +172,15 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
|||
/**
|
||||
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
|
||||
*/
|
||||
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts;
|
||||
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute, prevAct) + actInsertionCosts;
|
||||
|
||||
/**
|
||||
* memorize it in insertion-queue
|
||||
*/
|
||||
if(insertion_cost_approximation < best_known_insertion_costs){
|
||||
if (insertion_cost_approximation < best_known_insertion_costs) {
|
||||
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
||||
}
|
||||
}
|
||||
else if(hardActivityConstraintsStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
|
||||
} else if (hardActivityConstraintsStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
|
||||
loopBroken = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -192,148 +189,143 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
|||
/**
|
||||
* calculate transport and activity costs with new vehicle (without inserting k)
|
||||
*/
|
||||
double transportCost_prevAct_nextAct_newVehicle = transportCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), prevActDepTime_newVehicle, newDriver, newVehicle);
|
||||
double transportTime_prevAct_nextAct_newVehicle = transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActDepTime_newVehicle, newDriver, newVehicle);
|
||||
double arrTime_nextAct_newVehicle = prevActDepTime_newVehicle + transportTime_prevAct_nextAct_newVehicle;
|
||||
double activityCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct_newVehicle, newDriver, newVehicle);
|
||||
double transportCost_prevAct_nextAct_newVehicle = transportCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), prevActDepTime_newVehicle, newDriver, newVehicle);
|
||||
double transportTime_prevAct_nextAct_newVehicle = transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActDepTime_newVehicle, newDriver, newVehicle);
|
||||
double arrTime_nextAct_newVehicle = prevActDepTime_newVehicle + transportTime_prevAct_nextAct_newVehicle;
|
||||
double activityCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct_newVehicle, newDriver, newVehicle);
|
||||
|
||||
/**
|
||||
* memorize transport and activity costs with new vehicle without inserting k
|
||||
*/
|
||||
sumOf_prevCosts_newVehicle += transportCost_prevAct_nextAct_newVehicle + activityCost_nextAct;
|
||||
/**
|
||||
* memorize transport and activity costs with new vehicle without inserting k
|
||||
*/
|
||||
sumOf_prevCosts_newVehicle += transportCost_prevAct_nextAct_newVehicle + activityCost_nextAct;
|
||||
// activity2costWithNewVehicle.put(nextAct, sumOf_prevCosts_newVehicle);
|
||||
|
||||
/**
|
||||
* departure time at nextAct with new vehicle
|
||||
*/
|
||||
double depTime_nextAct_newVehicle = Math.max(arrTime_nextAct_newVehicle, nextAct.getTheoreticalEarliestOperationStartTime()) + nextAct.getOperationTime();
|
||||
/**
|
||||
* departure time at nextAct with new vehicle
|
||||
*/
|
||||
double depTime_nextAct_newVehicle = Math.max(arrTime_nextAct_newVehicle, nextAct.getTheoreticalEarliestOperationStartTime()) + nextAct.getOperationTime();
|
||||
|
||||
/**
|
||||
* set previous to next
|
||||
*/
|
||||
prevAct = nextAct;
|
||||
prevActDepTime_newVehicle = depTime_nextAct_newVehicle;
|
||||
/**
|
||||
* set previous to next
|
||||
*/
|
||||
prevAct = nextAct;
|
||||
prevActDepTime_newVehicle = depTime_nextAct_newVehicle;
|
||||
|
||||
actIndex++;
|
||||
}
|
||||
if(!loopBroken){
|
||||
End nextAct = end;
|
||||
actIndex++;
|
||||
}
|
||||
if (!loopBroken) {
|
||||
End nextAct = end;
|
||||
ConstraintsStatus hardActivityConstraintsStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||
if(hardActivityConstraintsStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||
if (hardActivityConstraintsStatus.equals(ConstraintsStatus.FULFILLED)) {
|
||||
double actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||
|
||||
/**
|
||||
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
|
||||
*/
|
||||
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts;
|
||||
/**
|
||||
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
|
||||
*/
|
||||
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute, prevAct) + actInsertionCosts;
|
||||
|
||||
/**
|
||||
* memorize it in insertion-queue
|
||||
*/
|
||||
if(insertion_cost_approximation < best_known_insertion_costs){
|
||||
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
||||
}
|
||||
/**
|
||||
* memorize it in insertion-queue
|
||||
*/
|
||||
if (insertion_cost_approximation < best_known_insertion_costs) {
|
||||
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* the above calculations approximate insertion costs. now calculate the exact insertion costs for the most promising (according to the approximation)
|
||||
* insertion positions.
|
||||
*
|
||||
*/
|
||||
|
||||
if(memorySize==0){ // return bestInsertion
|
||||
InsertionData insertion = bestInsertionsQueue.poll();
|
||||
if(insertion != null){
|
||||
best_insertion_index = insertion.getDeliveryInsertionIndex();
|
||||
best_insertion_costs = insertion.getInsertionCost();
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
for(int i=0;i<memorySize;i++){
|
||||
InsertionData data = bestInsertionsQueue.poll();
|
||||
if(data == null){
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* build tour with new activity.
|
||||
*/
|
||||
List<TourActivity> wholeTour = new ArrayList<TourActivity>();
|
||||
wholeTour.add(start);
|
||||
wholeTour.addAll(currentRoute.getTourActivities().getActivities());
|
||||
wholeTour.add(end);
|
||||
wholeTour.add(data.getDeliveryInsertionIndex()+1, serviceAct2Insert);
|
||||
|
||||
/**
|
||||
* compute cost-diff of tour with and without new activity --> insertion_costs
|
||||
*/
|
||||
/**
|
||||
* the above calculations approximate insertion costs. now calculate the exact insertion costs for the most promising (according to the approximation)
|
||||
* insertion positions.
|
||||
*
|
||||
*/
|
||||
|
||||
if (memorySize == 0) { // return bestInsertion
|
||||
InsertionData insertion = bestInsertionsQueue.poll();
|
||||
if (insertion != null) {
|
||||
best_insertion_index = insertion.getDeliveryInsertionIndex();
|
||||
best_insertion_costs = insertion.getInsertionCost();
|
||||
}
|
||||
} else {
|
||||
|
||||
for (int i = 0; i < memorySize; i++) {
|
||||
InsertionData data = bestInsertionsQueue.poll();
|
||||
if (data == null) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* build tour with new activity.
|
||||
*/
|
||||
List<TourActivity> wholeTour = new ArrayList<TourActivity>();
|
||||
wholeTour.add(start);
|
||||
wholeTour.addAll(currentRoute.getTourActivities().getActivities());
|
||||
wholeTour.add(end);
|
||||
wholeTour.add(data.getDeliveryInsertionIndex() + 1, serviceAct2Insert);
|
||||
|
||||
/**
|
||||
* compute cost-diff of tour with and without new activity --> insertion_costs
|
||||
*/
|
||||
Double currentRouteCosts = stateManager.getRouteState(currentRoute, InternalStates.COSTS, Double.class);
|
||||
if(currentRouteCosts == null) currentRouteCosts = 0.;
|
||||
if (currentRouteCosts == null) currentRouteCosts = 0.;
|
||||
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - currentRouteCosts;
|
||||
|
||||
/**
|
||||
* if better than best known, make it the best known
|
||||
*/
|
||||
if(insertion_costs < best_insertion_costs){
|
||||
best_insertion_index = data.getDeliveryInsertionIndex();
|
||||
best_insertion_costs = insertion_costs;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.createEmptyInsertionData();
|
||||
InsertionData insertionData = new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(start.getEndTime());
|
||||
return insertionData;
|
||||
}
|
||||
/**
|
||||
* if better than best known, make it the best known
|
||||
*/
|
||||
if (insertion_costs < best_insertion_costs) {
|
||||
best_insertion_index = data.getDeliveryInsertionIndex();
|
||||
best_insertion_costs = insertion_costs;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_insertion_index == InsertionData.NO_INDEX) return InsertionData.createEmptyInsertionData();
|
||||
InsertionData insertionData = new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(start.getEndTime());
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
private void initialiseStartAndEnd(final Vehicle newVehicle, double newVehicleDepartureTime) {
|
||||
if(start == null){
|
||||
start = new Start(newVehicle.getStartLocation(), newVehicle.getEarliestDeparture(), Double.MAX_VALUE);
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
}
|
||||
else{
|
||||
start.setLocation(Location.newInstance(newVehicle.getStartLocation().getId()));
|
||||
start.setTheoreticalEarliestOperationStartTime(newVehicle.getEarliestDeparture());
|
||||
start.setTheoreticalLatestOperationStartTime(Double.MAX_VALUE);
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
}
|
||||
|
||||
if(end == null){
|
||||
end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
|
||||
}
|
||||
else{
|
||||
end.setLocation(Location.newInstance(newVehicle.getEndLocation().getId()));
|
||||
end.setTheoreticalEarliestOperationStartTime(0.0);
|
||||
end.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
|
||||
}
|
||||
}
|
||||
private void initialiseStartAndEnd(final Vehicle newVehicle, double newVehicleDepartureTime) {
|
||||
if (start == null) {
|
||||
start = new Start(newVehicle.getStartLocation(), newVehicle.getEarliestDeparture(), Double.MAX_VALUE);
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
} else {
|
||||
start.setLocation(Location.newInstance(newVehicle.getStartLocation().getId()));
|
||||
start.setTheoreticalEarliestOperationStartTime(newVehicle.getEarliestDeparture());
|
||||
start.setTheoreticalLatestOperationStartTime(Double.MAX_VALUE);
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
}
|
||||
|
||||
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
|
||||
Double prevCost;
|
||||
if(act instanceof End){
|
||||
prevCost = stateManager.getRouteState(vehicleRoute, InternalStates.COSTS,Double.class);
|
||||
}
|
||||
else prevCost = stateManager.getActivityState(act, InternalStates.COSTS,Double.class);
|
||||
if(prevCost == null) prevCost = 0.;
|
||||
return prevCost;
|
||||
}
|
||||
if (end == null) {
|
||||
end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
|
||||
} else {
|
||||
end.setLocation(Location.newInstance(newVehicle.getEndLocation().getId()));
|
||||
end.setTheoreticalEarliestOperationStartTime(0.0);
|
||||
end.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
|
||||
}
|
||||
}
|
||||
|
||||
private Comparator<InsertionData> getComparator() {
|
||||
return new Comparator<InsertionData>() {
|
||||
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
|
||||
Double prevCost;
|
||||
if (act instanceof End) {
|
||||
prevCost = stateManager.getRouteState(vehicleRoute, InternalStates.COSTS, Double.class);
|
||||
} else prevCost = stateManager.getActivityState(act, InternalStates.COSTS, Double.class);
|
||||
if (prevCost == null) prevCost = 0.;
|
||||
return prevCost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(InsertionData o1, InsertionData o2) {
|
||||
if(o1.getInsertionCost() < o2.getInsertionCost()){
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
private Comparator<InsertionData> getComparator() {
|
||||
return new Comparator<InsertionData>() {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public int compare(InsertionData o1, InsertionData o2) {
|
||||
if (o1.getInsertionCost() < o2.getInsertionCost()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -37,58 +37,55 @@ import org.apache.logging.log4j.Logger;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(ShipmentInsertionCalculator.class);
|
||||
|
||||
final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
|
||||
private HardRouteConstraint hardRouteLevelConstraint;
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(ShipmentInsertionCalculator.class);
|
||||
private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private HardRouteConstraint hardRouteLevelConstraint;
|
||||
|
||||
private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private SoftRouteConstraint softRouteConstraint;
|
||||
|
||||
private SoftActivityConstraint softActivityConstraint;
|
||||
|
||||
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
||||
|
||||
private VehicleRoutingTransportCosts transportCosts;
|
||||
|
||||
private JobActivityFactory activityFactory;
|
||||
|
||||
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
|
||||
|
||||
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
this.hardRouteLevelConstraint = constraintManager;
|
||||
this.hardActivityLevelConstraint = constraintManager;
|
||||
this.softActivityConstraint = constraintManager;
|
||||
this.softRouteConstraint = constraintManager;
|
||||
this.transportCosts = routingCosts;
|
||||
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
private SoftRouteConstraint softRouteConstraint;
|
||||
|
||||
public void setJobActivityFactory(JobActivityFactory activityFactory){
|
||||
private SoftActivityConstraint softActivityConstraint;
|
||||
|
||||
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
||||
|
||||
private VehicleRoutingTransportCosts transportCosts;
|
||||
|
||||
private JobActivityFactory activityFactory;
|
||||
|
||||
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
|
||||
|
||||
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, ConstraintManager constraintManager) {
|
||||
super();
|
||||
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||
this.hardRouteLevelConstraint = constraintManager;
|
||||
this.hardActivityLevelConstraint = constraintManager;
|
||||
this.softActivityConstraint = constraintManager;
|
||||
this.softRouteConstraint = constraintManager;
|
||||
this.transportCosts = routingCosts;
|
||||
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
public void setJobActivityFactory(JobActivityFactory activityFactory) {
|
||||
this.activityFactory = activityFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertion]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the marginal cost of inserting job i locally. This is based on the
|
||||
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertion]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the marginal cost of inserting job i locally. This is based on the
|
||||
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
|
||||
*/
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
|
||||
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
|
||||
Shipment shipment = (Shipment)jobToInsert;
|
||||
Shipment shipment = (Shipment) jobToInsert;
|
||||
TourActivity pickupShipment = activityFactory.createActivities(shipment).get(0);
|
||||
TourActivity deliverShipment = activityFactory.createActivities(shipment).get(1);
|
||||
insertionContext.getAssociatedActivities().add(pickupShipment);
|
||||
|
|
@ -97,9 +94,9 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
|
|||
/*
|
||||
check hard route constraints
|
||||
*/
|
||||
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
if (!hardRouteLevelConstraint.fulfilled(insertionContext)) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
/*
|
||||
check soft route constraints
|
||||
*/
|
||||
|
|
@ -109,51 +106,49 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
|
|||
additionalICostsAtRouteLevel += additionalAccessEgressCalculator.getCosts(insertionContext);
|
||||
|
||||
int pickupInsertionIndex = InsertionData.NO_INDEX;
|
||||
int deliveryInsertionIndex = InsertionData.NO_INDEX;
|
||||
|
||||
Start start = new Start(newVehicle.getStartLocation(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
|
||||
End end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
|
||||
int deliveryInsertionIndex = InsertionData.NO_INDEX;
|
||||
|
||||
Start start = new Start(newVehicle.getStartLocation(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
|
||||
End end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
|
||||
|
||||
ActivityContext pickupContext = new ActivityContext();
|
||||
|
||||
TourActivity prevAct = start;
|
||||
double prevActEndTime = newVehicleDepartureTime;
|
||||
TourActivity prevAct = start;
|
||||
double prevActEndTime = newVehicleDepartureTime;
|
||||
|
||||
//loops
|
||||
int i = 0;
|
||||
boolean tourEnd = false;
|
||||
//pickupShipmentLoop
|
||||
List<TourActivity> activities = currentRoute.getTourActivities().getActivities();
|
||||
//loops
|
||||
int i = 0;
|
||||
boolean tourEnd = false;
|
||||
//pickupShipmentLoop
|
||||
List<TourActivity> activities = currentRoute.getTourActivities().getActivities();
|
||||
|
||||
while(!tourEnd){
|
||||
TourActivity nextAct;
|
||||
if(i < activities.size()){
|
||||
nextAct = activities.get(i);
|
||||
}
|
||||
else{
|
||||
nextAct = end;
|
||||
tourEnd = true;
|
||||
}
|
||||
while (!tourEnd) {
|
||||
TourActivity nextAct;
|
||||
if (i < activities.size()) {
|
||||
nextAct = activities.get(i);
|
||||
} else {
|
||||
nextAct = end;
|
||||
tourEnd = true;
|
||||
}
|
||||
// logger.info("activity: {}, act-size: {}", i, activities.size());
|
||||
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime);
|
||||
if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)){
|
||||
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActEndTime, newDriver, newVehicle);
|
||||
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
|
||||
prevAct = nextAct;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
|
||||
break;
|
||||
}
|
||||
double additionalPickupICosts = softActivityConstraint.getCosts(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime);
|
||||
double pickupAIC = calculate(insertionContext,prevAct,pickupShipment, nextAct,prevActEndTime);
|
||||
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime);
|
||||
if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)) {
|
||||
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActEndTime, newDriver, newVehicle);
|
||||
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
|
||||
prevAct = nextAct;
|
||||
i++;
|
||||
continue;
|
||||
} else if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
|
||||
break;
|
||||
}
|
||||
double additionalPickupICosts = softActivityConstraint.getCosts(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime);
|
||||
double pickupAIC = calculate(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime);
|
||||
|
||||
TourActivity prevAct_deliveryLoop = pickupShipment;
|
||||
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), pickupShipment.getLocation(), prevActEndTime, newDriver, newVehicle);
|
||||
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
|
||||
TourActivity prevAct_deliveryLoop = pickupShipment;
|
||||
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), pickupShipment.getLocation(), prevActEndTime, newDriver, newVehicle);
|
||||
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
|
||||
|
||||
pickupContext.setArrivalTime(shipmentPickupArrTime);
|
||||
pickupContext.setEndTime(shipmentPickupEndTime);
|
||||
|
|
@ -163,63 +158,61 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
|
|||
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
|
||||
|
||||
/*
|
||||
--------------------------------
|
||||
--------------------------------
|
||||
*/
|
||||
//deliverShipmentLoop
|
||||
int j = i;
|
||||
boolean tourEnd_deliveryLoop = false;
|
||||
while(!tourEnd_deliveryLoop){
|
||||
//deliverShipmentLoop
|
||||
int j = i;
|
||||
boolean tourEnd_deliveryLoop = false;
|
||||
while (!tourEnd_deliveryLoop) {
|
||||
|
||||
// for(int j=i;j<activities.size();j++){
|
||||
TourActivity nextAct_deliveryLoop;
|
||||
if(j < activities.size()) {
|
||||
nextAct_deliveryLoop = activities.get(j);
|
||||
}
|
||||
else{
|
||||
nextAct_deliveryLoop = end;
|
||||
tourEnd_deliveryLoop = true;
|
||||
}
|
||||
TourActivity nextAct_deliveryLoop;
|
||||
if (j < activities.size()) {
|
||||
nextAct_deliveryLoop = activities.get(j);
|
||||
} else {
|
||||
nextAct_deliveryLoop = end;
|
||||
tourEnd_deliveryLoop = true;
|
||||
}
|
||||
|
||||
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
|
||||
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||
double additionalDeliveryICosts = softActivityConstraint.getCosts(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
|
||||
double deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment, nextAct_deliveryLoop,prevActEndTime_deliveryLoop);
|
||||
double totalActivityInsertionCosts = pickupAIC + deliveryAIC
|
||||
+ additionalICostsAtRouteLevel + additionalPickupICosts + additionalDeliveryICosts;
|
||||
if(totalActivityInsertionCosts < bestCost){
|
||||
bestCost = totalActivityInsertionCosts;
|
||||
pickupInsertionIndex = i;
|
||||
deliveryInsertionIndex = j;
|
||||
}
|
||||
}
|
||||
else if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
|
||||
break;
|
||||
}
|
||||
//update prevAct and endTime
|
||||
double nextActArrTime = prevActEndTime_deliveryLoop + transportCosts.getTransportTime(prevAct_deliveryLoop.getLocation(), nextAct_deliveryLoop.getLocation(), prevActEndTime_deliveryLoop, newDriver, newVehicle);
|
||||
prevActEndTime_deliveryLoop = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct_deliveryLoop);
|
||||
prevAct_deliveryLoop = nextAct_deliveryLoop;
|
||||
j++;
|
||||
}
|
||||
//update prevAct and endTime
|
||||
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActEndTime, newDriver, newVehicle);
|
||||
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
|
||||
prevAct = nextAct;
|
||||
i++;
|
||||
}
|
||||
if(pickupInsertionIndex == InsertionData.NO_INDEX) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
insertionData.getEvents().add(new InsertActivity(currentRoute,newVehicle,deliverShipment,deliveryInsertionIndex));
|
||||
insertionData.getEvents().add(new InsertActivity(currentRoute,newVehicle,pickupShipment,pickupInsertionIndex));
|
||||
insertionData.getEvents().add(new SwitchVehicle(currentRoute,newVehicle,newVehicleDepartureTime));
|
||||
return insertionData;
|
||||
}
|
||||
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
|
||||
if (deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)) {
|
||||
double additionalDeliveryICosts = softActivityConstraint.getCosts(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
|
||||
double deliveryAIC = calculate(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
|
||||
double totalActivityInsertionCosts = pickupAIC + deliveryAIC
|
||||
+ additionalICostsAtRouteLevel + additionalPickupICosts + additionalDeliveryICosts;
|
||||
if (totalActivityInsertionCosts < bestCost) {
|
||||
bestCost = totalActivityInsertionCosts;
|
||||
pickupInsertionIndex = i;
|
||||
deliveryInsertionIndex = j;
|
||||
}
|
||||
} else if (deliverShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
|
||||
break;
|
||||
}
|
||||
//update prevAct and endTime
|
||||
double nextActArrTime = prevActEndTime_deliveryLoop + transportCosts.getTransportTime(prevAct_deliveryLoop.getLocation(), nextAct_deliveryLoop.getLocation(), prevActEndTime_deliveryLoop, newDriver, newVehicle);
|
||||
prevActEndTime_deliveryLoop = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct_deliveryLoop);
|
||||
prevAct_deliveryLoop = nextAct_deliveryLoop;
|
||||
j++;
|
||||
}
|
||||
//update prevAct and endTime
|
||||
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActEndTime, newDriver, newVehicle);
|
||||
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
|
||||
prevAct = nextAct;
|
||||
i++;
|
||||
}
|
||||
if (pickupInsertionIndex == InsertionData.NO_INDEX) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
insertionData.getEvents().add(new InsertActivity(currentRoute, newVehicle, deliverShipment, deliveryInsertionIndex));
|
||||
insertionData.getEvents().add(new InsertActivity(currentRoute, newVehicle, pickupShipment, pickupInsertionIndex));
|
||||
insertionData.getEvents().add(new SwitchVehicle(currentRoute, newVehicle, newVehicleDepartureTime));
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
private double calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) {
|
||||
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
|
||||
|
||||
}
|
||||
private double calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) {
|
||||
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ package jsprit.core.algorithm.recreate;
|
|||
/**
|
||||
* Created by schroeder on 19/05/15.
|
||||
*/
|
||||
class SwitchVehicleListener implements EventListener{
|
||||
class SwitchVehicleListener implements EventListener {
|
||||
|
||||
@Override
|
||||
public void inform(Event event) {
|
||||
if(event instanceof SwitchVehicle){
|
||||
if (event instanceof SwitchVehicle) {
|
||||
SwitchVehicle switchVehicle = (SwitchVehicle) event;
|
||||
switchVehicle.getRoute().setVehicleAndDepartureTime(switchVehicle.getVehicle(),((SwitchVehicle) event).getDepartureTime());
|
||||
switchVehicle.getRoute().setVehicleAndDepartureTime(switchVehicle.getVehicle(), ((SwitchVehicle) event).getDepartureTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,43 +23,42 @@ import jsprit.core.problem.solution.route.activity.End;
|
|||
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import jsprit.core.util.CalculationUtils;
|
||||
|
||||
public class VariableTransportCostCalculator implements SoftActivityConstraint{
|
||||
public class VariableTransportCostCalculator implements SoftActivityConstraint {
|
||||
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
public VariableTransportCostCalculator(VehicleRoutingTransportCosts routingCosts) {
|
||||
super();
|
||||
this.routingCosts = routingCosts;
|
||||
}
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double depTimeAtPrevAct) {
|
||||
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocation(), newAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocation(), newAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
|
||||
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
|
||||
double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
|
||||
|
||||
//open routes
|
||||
if(nextAct instanceof End){
|
||||
if(!iFacts.getNewVehicle().isReturnToDepot()){
|
||||
return tp_costs_prevAct_newAct;
|
||||
}
|
||||
}
|
||||
|
||||
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocation(), nextAct.getLocation(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct;
|
||||
|
||||
double oldCosts;
|
||||
if(iFacts.getRoute().isEmpty()){
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct;
|
||||
}
|
||||
else{
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct;
|
||||
}
|
||||
return totalCosts - oldCosts;
|
||||
}
|
||||
public VariableTransportCostCalculator(VehicleRoutingTransportCosts routingCosts) {
|
||||
super();
|
||||
this.routingCosts = routingCosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double depTimeAtPrevAct) {
|
||||
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocation(), newAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocation(), newAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
|
||||
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
|
||||
double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
|
||||
|
||||
//open routes
|
||||
if (nextAct instanceof End) {
|
||||
if (!iFacts.getNewVehicle().isReturnToDepot()) {
|
||||
return tp_costs_prevAct_newAct;
|
||||
}
|
||||
}
|
||||
|
||||
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocation(), nextAct.getLocation(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct;
|
||||
|
||||
double oldCosts;
|
||||
if (iFacts.getRoute().isEmpty()) {
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct;
|
||||
} else {
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct;
|
||||
}
|
||||
return totalCosts - oldCosts;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -22,18 +22,18 @@ import jsprit.core.problem.vehicle.Vehicle;
|
|||
import jsprit.core.problem.vehicle.VehicleFleetManager;
|
||||
|
||||
|
||||
public class VehicleSwitched implements VehicleSwitchedListener{
|
||||
public class VehicleSwitched implements VehicleSwitchedListener {
|
||||
|
||||
private VehicleFleetManager fleetManager;
|
||||
|
||||
public VehicleSwitched(VehicleFleetManager fleetManager){
|
||||
this.fleetManager = fleetManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle) {
|
||||
fleetManager.unlock(oldVehicle);
|
||||
fleetManager.lock(newVehicle);
|
||||
}
|
||||
private VehicleFleetManager fleetManager;
|
||||
|
||||
public VehicleSwitched(VehicleFleetManager fleetManager) {
|
||||
this.fleetManager = fleetManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle) {
|
||||
fleetManager.unlock(oldVehicle);
|
||||
fleetManager.lock(newVehicle);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate;
|
||||
|
|
@ -33,99 +33,97 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
|
||||
|
||||
final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCostsCalculator{
|
||||
final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCostsCalculator {
|
||||
|
||||
private Logger logger = LogManager.getLogger(VehicleTypeDependentJobInsertionCalculator.class);
|
||||
|
||||
private final VehicleFleetManager fleetManager;
|
||||
|
||||
private final JobInsertionCostsCalculator insertionCalculator;
|
||||
|
||||
private final VehicleRoutingProblem vrp;
|
||||
|
||||
private Set<String> initialVehicleIds = new HashSet<String>();
|
||||
|
||||
/**
|
||||
* true if a vehicle(-type) is allowed to take over the whole route that was previously served by another vehicle
|
||||
*
|
||||
* <p>vehicleSwitch allowed makes sense if fleet consists of vehicles with different capacities such that one
|
||||
* can start with a small vehicle, but as the number of customers grows bigger vehicles can be operated, i.e.
|
||||
* bigger vehicles can take over the route that was previously served by a small vehicle.
|
||||
*
|
||||
*/
|
||||
private boolean vehicleSwitchAllowed = false;
|
||||
private Logger logger = LogManager.getLogger(VehicleTypeDependentJobInsertionCalculator.class);
|
||||
|
||||
public VehicleTypeDependentJobInsertionCalculator(final VehicleRoutingProblem vrp, final VehicleFleetManager fleetManager, final JobInsertionCostsCalculator jobInsertionCalc) {
|
||||
this.fleetManager = fleetManager;
|
||||
this.insertionCalculator = jobInsertionCalc;
|
||||
this.vrp = vrp;
|
||||
getInitialVehicleIds();
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
private final VehicleFleetManager fleetManager;
|
||||
|
||||
private void getInitialVehicleIds() {
|
||||
private final JobInsertionCostsCalculator insertionCalculator;
|
||||
|
||||
private final VehicleRoutingProblem vrp;
|
||||
|
||||
private Set<String> initialVehicleIds = new HashSet<String>();
|
||||
|
||||
/**
|
||||
* true if a vehicle(-type) is allowed to take over the whole route that was previously served by another vehicle
|
||||
* <p/>
|
||||
* <p>vehicleSwitch allowed makes sense if fleet consists of vehicles with different capacities such that one
|
||||
* can start with a small vehicle, but as the number of customers grows bigger vehicles can be operated, i.e.
|
||||
* bigger vehicles can take over the route that was previously served by a small vehicle.
|
||||
*/
|
||||
private boolean vehicleSwitchAllowed = false;
|
||||
|
||||
public VehicleTypeDependentJobInsertionCalculator(final VehicleRoutingProblem vrp, final VehicleFleetManager fleetManager, final JobInsertionCostsCalculator jobInsertionCalc) {
|
||||
this.fleetManager = fleetManager;
|
||||
this.insertionCalculator = jobInsertionCalc;
|
||||
this.vrp = vrp;
|
||||
getInitialVehicleIds();
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
private void getInitialVehicleIds() {
|
||||
Collection<VehicleRoute> initialVehicleRoutes = vrp.getInitialVehicleRoutes();
|
||||
for(VehicleRoute initialRoute : initialVehicleRoutes){
|
||||
initialVehicleIds.add(initialRoute.getVehicle().getId());
|
||||
}
|
||||
}
|
||||
for (VehicleRoute initialRoute : initialVehicleRoutes) {
|
||||
initialVehicleIds.add(initialRoute.getVehicle().getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=vehicleTypeDependentServiceInsertion]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vehicleSwitchAllowed
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=vehicleTypeDependentServiceInsertion]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vehicleSwitchAllowed
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public boolean isVehicleSwitchAllowed() {
|
||||
return vehicleSwitchAllowed;
|
||||
}
|
||||
return vehicleSwitchAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* default is true
|
||||
*
|
||||
* @param vehicleSwitchAllowed the vehicleSwitchAllowed to set
|
||||
*/
|
||||
public void setVehicleSwitchAllowed(boolean vehicleSwitchAllowed) {
|
||||
logger.debug("set vehicleSwitchAllowed to {}", vehicleSwitchAllowed);
|
||||
this.vehicleSwitchAllowed = vehicleSwitchAllowed;
|
||||
}
|
||||
/**
|
||||
* default is true
|
||||
*
|
||||
* @param vehicleSwitchAllowed the vehicleSwitchAllowed to set
|
||||
*/
|
||||
public void setVehicleSwitchAllowed(boolean vehicleSwitchAllowed) {
|
||||
logger.debug("set vehicleSwitchAllowed to {}", vehicleSwitchAllowed);
|
||||
this.vehicleSwitchAllowed = vehicleSwitchAllowed;
|
||||
}
|
||||
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
|
||||
Vehicle selectedVehicle = currentRoute.getVehicle();
|
||||
Driver selectedDriver = currentRoute.getDriver();
|
||||
InsertionData bestIData = InsertionData.createEmptyInsertionData();
|
||||
double bestKnownCost_ = bestKnownCost;
|
||||
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
|
||||
if(!(selectedVehicle instanceof NoVehicle)) {
|
||||
relevantVehicles.add(selectedVehicle);
|
||||
if(vehicleSwitchAllowed && !isVehicleWithInitialRoute(selectedVehicle)){
|
||||
relevantVehicles.addAll(fleetManager.getAvailableVehicles(selectedVehicle));
|
||||
}
|
||||
}
|
||||
else{ //if no vehicle has been assigned, i.e. it is an empty route
|
||||
relevantVehicles.addAll(fleetManager.getAvailableVehicles());
|
||||
}
|
||||
for(Vehicle v : relevantVehicles){
|
||||
double depTime;
|
||||
if(v == selectedVehicle) depTime = currentRoute.getDepartureTime();
|
||||
else depTime = v.getEarliestDeparture();
|
||||
InsertionData iData = insertionCalculator.getInsertionData(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
|
||||
if(iData instanceof NoInsertionFound) {
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
|
||||
Vehicle selectedVehicle = currentRoute.getVehicle();
|
||||
Driver selectedDriver = currentRoute.getDriver();
|
||||
InsertionData bestIData = InsertionData.createEmptyInsertionData();
|
||||
double bestKnownCost_ = bestKnownCost;
|
||||
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
|
||||
if (!(selectedVehicle instanceof NoVehicle)) {
|
||||
relevantVehicles.add(selectedVehicle);
|
||||
if (vehicleSwitchAllowed && !isVehicleWithInitialRoute(selectedVehicle)) {
|
||||
relevantVehicles.addAll(fleetManager.getAvailableVehicles(selectedVehicle));
|
||||
}
|
||||
} else { //if no vehicle has been assigned, i.e. it is an empty route
|
||||
relevantVehicles.addAll(fleetManager.getAvailableVehicles());
|
||||
}
|
||||
for (Vehicle v : relevantVehicles) {
|
||||
double depTime;
|
||||
if (v == selectedVehicle) depTime = currentRoute.getDepartureTime();
|
||||
else depTime = v.getEarliestDeparture();
|
||||
InsertionData iData = insertionCalculator.getInsertionData(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
|
||||
if (iData instanceof NoInsertionFound) {
|
||||
continue;
|
||||
}
|
||||
if(iData.getInsertionCost() < bestKnownCost_){
|
||||
bestIData = iData;
|
||||
bestKnownCost_ = iData.getInsertionCost();
|
||||
}
|
||||
}
|
||||
return bestIData;
|
||||
}
|
||||
}
|
||||
if (iData.getInsertionCost() < bestKnownCost_) {
|
||||
bestIData = iData;
|
||||
bestKnownCost_ = iData.getInsertionCost();
|
||||
}
|
||||
}
|
||||
return bestIData;
|
||||
}
|
||||
|
||||
private boolean isVehicleWithInitialRoute(Vehicle selectedVehicle) {
|
||||
return initialVehicleIds.contains(selectedVehicle.getId());
|
||||
}
|
||||
private boolean isVehicleWithInitialRoute(Vehicle selectedVehicle) {
|
||||
return initialVehicleIds.contains(selectedVehicle.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate.listener;
|
||||
|
|
@ -20,8 +20,8 @@ import jsprit.core.algorithm.recreate.InsertionData;
|
|||
import jsprit.core.problem.job.Job;
|
||||
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||
|
||||
public interface BeforeJobInsertionListener extends InsertionListener{
|
||||
public interface BeforeJobInsertionListener extends InsertionListener {
|
||||
|
||||
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route);
|
||||
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate.listener;
|
||||
|
|
@ -21,8 +21,7 @@ import jsprit.core.problem.solution.route.VehicleRoute;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
|
||||
public interface InsertionEndsListener extends InsertionListener {
|
||||
|
||||
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes);
|
||||
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate.listener;
|
||||
|
|
@ -19,11 +19,7 @@ package jsprit.core.algorithm.recreate.listener;
|
|||
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
|
||||
|
||||
|
||||
public interface InsertionListener extends SearchStrategyModuleListener {
|
||||
|
||||
|
||||
|
||||
public interface InsertionListener extends SearchStrategyModuleListener{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate.listener;
|
||||
|
|
@ -26,63 +26,63 @@ import java.util.Collection;
|
|||
|
||||
|
||||
public class InsertionListeners {
|
||||
|
||||
private Collection<InsertionListener> listeners = new ArrayList<InsertionListener>();
|
||||
|
||||
public Collection<InsertionListener> getListeners(){
|
||||
return listeners;
|
||||
}
|
||||
|
||||
public void informJobInserted(Job insertedJob, VehicleRoute inRoute, double additionalCosts, double additionalTime){
|
||||
for(InsertionListener l : listeners){
|
||||
if(l instanceof JobInsertedListener){
|
||||
((JobInsertedListener)l).informJobInserted(insertedJob, inRoute, additionalCosts, additionalTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void informVehicleSwitched(VehicleRoute route, Vehicle oldVehicle, Vehicle newVehicle){
|
||||
for(InsertionListener l : listeners){
|
||||
if(l instanceof VehicleSwitchedListener){
|
||||
((VehicleSwitchedListener) l).vehicleSwitched(route, oldVehicle, newVehicle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route){
|
||||
for(InsertionListener l : listeners){
|
||||
if(l instanceof BeforeJobInsertionListener){
|
||||
((BeforeJobInsertionListener)l).informBeforeJobInsertion(job, data, route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs){
|
||||
for(InsertionListener l : listeners){
|
||||
if(l instanceof InsertionStartsListener){
|
||||
((InsertionStartsListener)l).informInsertionStarts(vehicleRoutes, unassignedJobs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void informInsertionEndsListeners(Collection<VehicleRoute> vehicleRoutes) {
|
||||
for(InsertionListener l : listeners){
|
||||
if(l instanceof InsertionEndsListener){
|
||||
((InsertionEndsListener)l).informInsertionEnds(vehicleRoutes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(InsertionListener insertionListener){
|
||||
listeners.add(insertionListener);
|
||||
}
|
||||
|
||||
public void removeListener(InsertionListener insertionListener){
|
||||
listeners.remove(insertionListener);
|
||||
}
|
||||
|
||||
public void addAllListeners(Collection<InsertionListener> listeners) {
|
||||
for(InsertionListener l : listeners) addListener(l);
|
||||
}
|
||||
private Collection<InsertionListener> listeners = new ArrayList<InsertionListener>();
|
||||
|
||||
public Collection<InsertionListener> getListeners() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
public void informJobInserted(Job insertedJob, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||
for (InsertionListener l : listeners) {
|
||||
if (l instanceof JobInsertedListener) {
|
||||
((JobInsertedListener) l).informJobInserted(insertedJob, inRoute, additionalCosts, additionalTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void informVehicleSwitched(VehicleRoute route, Vehicle oldVehicle, Vehicle newVehicle) {
|
||||
for (InsertionListener l : listeners) {
|
||||
if (l instanceof VehicleSwitchedListener) {
|
||||
((VehicleSwitchedListener) l).vehicleSwitched(route, oldVehicle, newVehicle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route) {
|
||||
for (InsertionListener l : listeners) {
|
||||
if (l instanceof BeforeJobInsertionListener) {
|
||||
((BeforeJobInsertionListener) l).informBeforeJobInsertion(job, data, route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
for (InsertionListener l : listeners) {
|
||||
if (l instanceof InsertionStartsListener) {
|
||||
((InsertionStartsListener) l).informInsertionStarts(vehicleRoutes, unassignedJobs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void informInsertionEndsListeners(Collection<VehicleRoute> vehicleRoutes) {
|
||||
for (InsertionListener l : listeners) {
|
||||
if (l instanceof InsertionEndsListener) {
|
||||
((InsertionEndsListener) l).informInsertionEnds(vehicleRoutes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(InsertionListener insertionListener) {
|
||||
listeners.add(insertionListener);
|
||||
}
|
||||
|
||||
public void removeListener(InsertionListener insertionListener) {
|
||||
listeners.remove(insertionListener);
|
||||
}
|
||||
|
||||
public void addAllListeners(Collection<InsertionListener> listeners) {
|
||||
for (InsertionListener l : listeners) addListener(l);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate.listener;
|
||||
|
|
@ -22,9 +22,8 @@ import jsprit.core.problem.solution.route.VehicleRoute;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
|
||||
public interface InsertionStartsListener extends InsertionListener {
|
||||
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate.listener;
|
||||
|
|
@ -20,11 +20,7 @@ import jsprit.core.problem.job.Job;
|
|||
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||
|
||||
|
||||
public interface JobInsertedListener extends InsertionListener {
|
||||
|
||||
|
||||
|
||||
|
||||
public interface JobInsertedListener extends InsertionListener{
|
||||
|
||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime);
|
||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.recreate.listener;
|
||||
|
|
@ -19,8 +19,8 @@ package jsprit.core.algorithm.recreate.listener;
|
|||
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import jsprit.core.problem.vehicle.Vehicle;
|
||||
|
||||
public interface VehicleSwitchedListener extends InsertionListener{
|
||||
|
||||
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle);
|
||||
public interface VehicleSwitchedListener extends InsertionListener {
|
||||
|
||||
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import org.apache.logging.log4j.Logger;
|
|||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
|
||||
public abstract class AbstractRuinStrategy implements RuinStrategy{
|
||||
public abstract class AbstractRuinStrategy implements RuinStrategy {
|
||||
|
||||
private final static Logger logger = LogManager.getLogger();
|
||||
|
||||
|
|
@ -46,11 +46,11 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
|
|||
|
||||
protected RuinShareFactory ruinShareFactory;
|
||||
|
||||
public void setRuinShareFactory(RuinShareFactory ruinShareFactory){
|
||||
public void setRuinShareFactory(RuinShareFactory ruinShareFactory) {
|
||||
this.ruinShareFactory = ruinShareFactory;
|
||||
}
|
||||
|
||||
public RuinShareFactory getRuinShareFactory(){
|
||||
public RuinShareFactory getRuinShareFactory() {
|
||||
return ruinShareFactory;
|
||||
}
|
||||
|
||||
|
|
@ -60,11 +60,11 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes){
|
||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes) {
|
||||
ruinListeners.ruinStarts(vehicleRoutes);
|
||||
Collection<Job> unassigned = ruinRoutes(vehicleRoutes);
|
||||
logger.trace("ruin: [ruined={}]", unassigned.size());
|
||||
ruinListeners.ruinEnds(vehicleRoutes,unassigned);
|
||||
ruinListeners.ruinEnds(vehicleRoutes, unassigned);
|
||||
return unassigned;
|
||||
}
|
||||
|
||||
|
|
@ -73,10 +73,10 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
|
|||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
|
||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
ruinListeners.ruinStarts(vehicleRoutes);
|
||||
Collection<Job> unassigned = ruinRoutes(vehicleRoutes, targetJob, nOfJobs2BeRemoved);
|
||||
ruinListeners.ruinEnds(vehicleRoutes,unassigned);
|
||||
ruinListeners.ruinEnds(vehicleRoutes, unassigned);
|
||||
return unassigned;
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
|
|||
}
|
||||
|
||||
protected boolean removeJob(Job job, Collection<VehicleRoute> vehicleRoutes) {
|
||||
if(jobIsInitial(job)) return false;
|
||||
if (jobIsInitial(job)) return false;
|
||||
for (VehicleRoute route : vehicleRoutes) {
|
||||
if (removeJob(job, route)) {
|
||||
return true;
|
||||
|
|
@ -108,16 +108,16 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
|
|||
return false;
|
||||
}
|
||||
|
||||
private boolean jobIsInitial(Job job){
|
||||
private boolean jobIsInitial(Job job) {
|
||||
return !vrp.getJobs().containsKey(job.getId()); //for initial jobs (being not contained in problem
|
||||
}
|
||||
|
||||
protected boolean removeJob(Job job, VehicleRoute route) {
|
||||
if(jobIsInitial(job)) return false;
|
||||
if (jobIsInitial(job)) return false;
|
||||
boolean removed = route.getTourActivities().removeJob(job);
|
||||
if (removed) {
|
||||
logger.trace("ruin: {}", job.getId());
|
||||
ruinListeners.removed(job,route);
|
||||
ruinListeners.removed(job, route);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ import org.apache.commons.math3.ml.distance.DistanceMeasure;
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 04/02/15.
|
||||
*/
|
||||
* Created by schroeder on 04/02/15.
|
||||
*/
|
||||
public class DBSCANClusterer {
|
||||
|
||||
private static class LocationWrapper implements Clusterable {
|
||||
|
|
@ -37,12 +37,11 @@ public class DBSCANClusterer {
|
|||
this.id = objCounter;
|
||||
}
|
||||
|
||||
private List<Location> getLocations(Job job){
|
||||
private List<Location> getLocations(Job job) {
|
||||
List<Location> locs = new ArrayList<Location>();
|
||||
if(job instanceof Service) {
|
||||
if (job instanceof Service) {
|
||||
locs.add(((Service) job).getLocation());
|
||||
}
|
||||
else if(job instanceof Shipment){
|
||||
} else if (job instanceof Shipment) {
|
||||
locs.add(((Shipment) job).getPickupLocation());
|
||||
locs.add(((Shipment) job).getDeliveryLocation());
|
||||
}
|
||||
|
|
@ -55,7 +54,7 @@ public class DBSCANClusterer {
|
|||
|
||||
@Override
|
||||
public double[] getPoint() {
|
||||
return new double[]{ id };
|
||||
return new double[]{id};
|
||||
}
|
||||
|
||||
public Job getJob() {
|
||||
|
|
@ -65,31 +64,31 @@ public class DBSCANClusterer {
|
|||
|
||||
private static class MyDistance implements DistanceMeasure {
|
||||
|
||||
private Map<Integer,LocationWrapper> locations;
|
||||
private Map<Integer, LocationWrapper> locations;
|
||||
|
||||
private VehicleRoutingTransportCosts costs;
|
||||
|
||||
public MyDistance(List<LocationWrapper> locations, VehicleRoutingTransportCosts costs) {
|
||||
this.locations = new HashMap<Integer, LocationWrapper>();
|
||||
for(LocationWrapper lw : locations){
|
||||
this.locations.put((int)lw.getPoint()[0],lw);
|
||||
for (LocationWrapper lw : locations) {
|
||||
this.locations.put((int) lw.getPoint()[0], lw);
|
||||
}
|
||||
this.costs = costs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double compute(double[] doubles, double[] doubles1) {
|
||||
LocationWrapper l1 = locations.get((int)doubles[0]);
|
||||
LocationWrapper l2 = locations.get((int)doubles1[0]);
|
||||
LocationWrapper l1 = locations.get((int) doubles[0]);
|
||||
LocationWrapper l2 = locations.get((int) doubles1[0]);
|
||||
int count = 0;
|
||||
double sum = 0;
|
||||
for(Location loc_1 : l1.getLocations()){
|
||||
for(Location loc_2 : l2.getLocations()){
|
||||
sum += costs.getTransportCost(loc_1,loc_2,0,null,null);
|
||||
for (Location loc_1 : l1.getLocations()) {
|
||||
for (Location loc_2 : l2.getLocations()) {
|
||||
sum += costs.getTransportCost(loc_1, loc_2, 0, null, null);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return sum / (double)count;
|
||||
return sum / (double) count;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,21 +112,21 @@ public class DBSCANClusterer {
|
|||
this.costs = costs;
|
||||
}
|
||||
|
||||
public void setMinPts(int pts){
|
||||
public void setMinPts(int pts) {
|
||||
this.minNoOfJobsInCluster = pts;
|
||||
}
|
||||
|
||||
public void setEpsFactor(double epsFactor){
|
||||
public void setEpsFactor(double epsFactor) {
|
||||
this.epsFactor = epsFactor;
|
||||
}
|
||||
|
||||
public void setEpsDistance(double epsDistance){
|
||||
public void setEpsDistance(double epsDistance) {
|
||||
this.epsDistance = epsDistance;
|
||||
}
|
||||
|
||||
public List<List<Job>> getClusters(VehicleRoute route){
|
||||
public List<List<Job>> getClusters(VehicleRoute route) {
|
||||
List<LocationWrapper> locations = new ArrayList<LocationWrapper>(route.getTourActivities().getJobs().size());
|
||||
for(Job j : route.getTourActivities().getJobs()){
|
||||
for (Job j : route.getTourActivities().getJobs()) {
|
||||
locations.add(new LocationWrapper(j));
|
||||
}
|
||||
List<Cluster<LocationWrapper>> clusterResults = getClusters(route, locations);
|
||||
|
|
@ -136,15 +135,15 @@ public class DBSCANClusterer {
|
|||
|
||||
private List<Cluster<LocationWrapper>> getClusters(VehicleRoute route, List<LocationWrapper> locations) {
|
||||
double sampledDistance;
|
||||
if(epsDistance != null) sampledDistance = epsDistance;
|
||||
if (epsDistance != null) sampledDistance = epsDistance;
|
||||
else sampledDistance = Math.max(0, sample(costs, route));
|
||||
org.apache.commons.math3.ml.clustering.DBSCANClusterer<LocationWrapper> clusterer = new org.apache.commons.math3.ml.clustering.DBSCANClusterer<LocationWrapper>(sampledDistance, minNoOfJobsInCluster, new MyDistance(locations,costs));
|
||||
org.apache.commons.math3.ml.clustering.DBSCANClusterer<LocationWrapper> clusterer = new org.apache.commons.math3.ml.clustering.DBSCANClusterer<LocationWrapper>(sampledDistance, minNoOfJobsInCluster, new MyDistance(locations, costs));
|
||||
return clusterer.cluster(locations);
|
||||
}
|
||||
|
||||
private List<List<Job>> makeList(List<Cluster<LocationWrapper>> clusterResults) {
|
||||
List<List<Job>> l = new ArrayList<List<Job>>();
|
||||
for(Cluster<LocationWrapper> c : clusterResults){
|
||||
for (Cluster<LocationWrapper> c : clusterResults) {
|
||||
List<Job> l_ = getJobList(c);
|
||||
l.add(l_);
|
||||
}
|
||||
|
|
@ -153,21 +152,21 @@ public class DBSCANClusterer {
|
|||
|
||||
private List<Job> getJobList(Cluster<LocationWrapper> c) {
|
||||
List<Job> l_ = new ArrayList<Job>();
|
||||
if(c == null) return l_;
|
||||
for(LocationWrapper lw : c.getPoints()){
|
||||
if (c == null) return l_;
|
||||
for (LocationWrapper lw : c.getPoints()) {
|
||||
l_.add(lw.getJob());
|
||||
}
|
||||
return l_;
|
||||
}
|
||||
|
||||
public List<Job> getRandomCluster(VehicleRoute route){
|
||||
if(route.isEmpty()) return Collections.emptyList();
|
||||
public List<Job> getRandomCluster(VehicleRoute route) {
|
||||
if (route.isEmpty()) return Collections.emptyList();
|
||||
List<LocationWrapper> locations = new ArrayList<LocationWrapper>(route.getTourActivities().getJobs().size());
|
||||
for(Job j : route.getTourActivities().getJobs()){
|
||||
for (Job j : route.getTourActivities().getJobs()) {
|
||||
locations.add(new LocationWrapper(j));
|
||||
}
|
||||
List<Cluster<LocationWrapper>> clusterResults = getClusters(route,locations);
|
||||
if(clusterResults.isEmpty()) return Collections.emptyList();
|
||||
List<Cluster<LocationWrapper>> clusterResults = getClusters(route, locations);
|
||||
if (clusterResults.isEmpty()) return Collections.emptyList();
|
||||
Cluster<LocationWrapper> randomCluster = RandomUtils.nextItem(clusterResults, random);
|
||||
return getJobList(randomCluster);
|
||||
}
|
||||
|
|
@ -175,15 +174,15 @@ public class DBSCANClusterer {
|
|||
private double sample(VehicleRoutingTransportCosts costs, VehicleRoute r) {
|
||||
double min = Double.MAX_VALUE;
|
||||
double sum = 0;
|
||||
for(int i=0;i<noDistanceSamples;i++){
|
||||
for (int i = 0; i < noDistanceSamples; i++) {
|
||||
TourActivity act1 = RandomUtils.nextItem(r.getActivities(), random);
|
||||
TourActivity act2 = RandomUtils.nextItem(r.getActivities(), random);
|
||||
double dist = costs.getTransportCost(act1.getLocation(), act2.getLocation(),
|
||||
0., null, r.getVehicle());
|
||||
if(dist < min) min = dist;
|
||||
0., null, r.getVehicle());
|
||||
if (dist < min) min = dist;
|
||||
sum += dist;
|
||||
}
|
||||
double avg = sum / ((double)noDistanceSamples);
|
||||
double avg = sum / ((double) noDistanceSamples);
|
||||
return (avg - min) * epsFactor;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import jsprit.core.problem.job.Job;
|
|||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
public interface JobNeighborhoods {
|
||||
|
||||
public Iterator<Job> getNearestNeighborsIterator(int nNeighbors, Job neighborTo);
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import jsprit.core.problem.VehicleRoutingProblem;
|
|||
*/
|
||||
public class JobNeighborhoodsFactory {
|
||||
|
||||
public JobNeighborhoods createNeighborhoods(VehicleRoutingProblem vrp, JobDistance jobDistance){
|
||||
return new JobNeighborhoodsImpl(vrp,jobDistance);
|
||||
public JobNeighborhoods createNeighborhoods(VehicleRoutingProblem vrp, JobDistance jobDistance) {
|
||||
return new JobNeighborhoodsImpl(vrp, jobDistance);
|
||||
}
|
||||
|
||||
public JobNeighborhoods createNeighborhoods(VehicleRoutingProblem vrp, JobDistance jobDistance, int capacity){
|
||||
return new JobNeighborhoodsImplWithCapRestriction(vrp,jobDistance,capacity);
|
||||
public JobNeighborhoods createNeighborhoods(VehicleRoutingProblem vrp, JobDistance jobDistance, int capacity) {
|
||||
return new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, capacity);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import org.apache.logging.log4j.Logger;
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
class JobNeighborhoodsImpl implements JobNeighborhoods {
|
||||
|
||||
private static Logger logger = LogManager.getLogger(JobNeighborhoodsImpl.class);
|
||||
|
|
@ -30,9 +30,9 @@ class JobNeighborhoodsImpl implements JobNeighborhoods {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Job> getNearestNeighborsIterator(int nNeighbors, Job neighborTo){
|
||||
public Iterator<Job> getNearestNeighborsIterator(int nNeighbors, Job neighborTo) {
|
||||
TreeSet<ReferencedJob> tree = distanceNodeTree.get(neighborTo.getId());
|
||||
if(tree == null) return new Iterator<Job>() {
|
||||
if (tree == null) return new Iterator<Job>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
|
|
@ -53,7 +53,7 @@ class JobNeighborhoodsImpl implements JobNeighborhoods {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
public void initialise() {
|
||||
logger.debug("calculates and memorizes distances from EACH job to EACH job --> n^2 calculations");
|
||||
calculateDistancesFromJob2Job();
|
||||
}
|
||||
|
|
@ -65,19 +65,19 @@ class JobNeighborhoodsImpl implements JobNeighborhoods {
|
|||
int nuOfDistancesStored = 0;
|
||||
for (Job i : vrp.getJobs().values()) {
|
||||
TreeSet<ReferencedJob> treeSet = new TreeSet<ReferencedJob>(
|
||||
new Comparator<ReferencedJob>() {
|
||||
@Override
|
||||
public int compare(ReferencedJob o1, ReferencedJob o2) {
|
||||
if (o1.getDistance() <= o2.getDistance()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
new Comparator<ReferencedJob>() {
|
||||
@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;
|
||||
if (i == j) continue;
|
||||
double distance = jobDistance.getDistance(i, j);
|
||||
ReferencedJob refNode = new ReferencedJob(j, distance);
|
||||
treeSet.add(refNode);
|
||||
|
|
@ -87,7 +87,7 @@ class JobNeighborhoodsImpl implements JobNeighborhoods {
|
|||
}
|
||||
stopWatch.stop();
|
||||
logger.debug("preprocessing comp-time: {}; nuOfDistances stored: {}; estimated memory: {}" +
|
||||
" bytes", stopWatch, nuOfDistancesStored, (distanceNodeTree.keySet().size()*64+nuOfDistancesStored*92) );
|
||||
" bytes", stopWatch, nuOfDistancesStored, (distanceNodeTree.keySet().size() * 64 + nuOfDistancesStored * 92));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import org.apache.logging.log4j.Logger;
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods {
|
||||
|
||||
private static Logger logger = LogManager.getLogger(JobNeighborhoodsImpl.class);
|
||||
|
|
@ -33,9 +33,9 @@ class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Job> getNearestNeighborsIterator(int nNeighbors, Job neighborTo){
|
||||
public Iterator<Job> getNearestNeighborsIterator(int nNeighbors, Job neighborTo) {
|
||||
TreeSet<ReferencedJob> tree = distanceNodeTree.get(neighborTo.getId());
|
||||
if(tree == null) return new Iterator<Job>() {
|
||||
if (tree == null) return new Iterator<Job>() {
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
|
|
@ -58,9 +58,9 @@ class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void initialise(){
|
||||
logger.debug("calculates distances from EACH job to EACH job --> n^2={} calculations, but 'only' {} are cached.", Math.pow(vrp.getJobs().values().size(), 2), (vrp.getJobs().values().size()*capacity));
|
||||
if(capacity==0) return;
|
||||
public void initialise() {
|
||||
logger.debug("calculates distances from EACH job to EACH job --> n^2={} calculations, but 'only' {} are cached.", Math.pow(vrp.getJobs().values().size(), 2), (vrp.getJobs().values().size() * capacity));
|
||||
if (capacity == 0) return;
|
||||
calculateDistancesFromJob2Job();
|
||||
}
|
||||
|
||||
|
|
@ -71,27 +71,26 @@ class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods {
|
|||
int nuOfDistancesStored = 0;
|
||||
for (Job i : vrp.getJobs().values()) {
|
||||
TreeSet<ReferencedJob> treeSet = new TreeSet<ReferencedJob>(
|
||||
new Comparator<ReferencedJob>() {
|
||||
@Override
|
||||
public int compare(ReferencedJob o1, ReferencedJob o2) {
|
||||
if (o1.getDistance() <= o2.getDistance()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
new Comparator<ReferencedJob>() {
|
||||
@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;
|
||||
if (i == j) continue;
|
||||
double distance = jobDistance.getDistance(i, j);
|
||||
ReferencedJob refNode = new ReferencedJob(j, distance);
|
||||
if(treeSet.size() < capacity){
|
||||
if (treeSet.size() < capacity) {
|
||||
treeSet.add(refNode);
|
||||
nuOfDistancesStored++;
|
||||
}
|
||||
else{
|
||||
if(treeSet.last().getDistance() > distance){
|
||||
} else {
|
||||
if (treeSet.last().getDistance() > distance) {
|
||||
treeSet.pollLast();
|
||||
treeSet.add(refNode);
|
||||
}
|
||||
|
|
@ -102,12 +101,12 @@ class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods {
|
|||
}
|
||||
stopWatch.stop();
|
||||
logger.debug("preprocessing comp-time: {}; nuOfDistances stored: {}; estimated memory: {}" +
|
||||
" bytes", stopWatch, nuOfDistancesStored, (distanceNodeTree.keySet().size()*64+nuOfDistancesStored*92));
|
||||
" bytes", stopWatch, nuOfDistancesStored, (distanceNodeTree.keySet().size() * 64 + nuOfDistancesStored * 92));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=neighborhoodWithCapRestriction][capacity="+capacity+"]";
|
||||
return "[name=neighborhoodWithCapRestriction][capacity=" + capacity + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import org.apache.logging.log4j.Logger;
|
|||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
class NearestNeighborhoodIterator implements Iterator<Job> {
|
||||
|
||||
private static Logger log = LogManager.getLogger(NearestNeighborhoodIterator.class);
|
||||
|
|
@ -27,9 +27,10 @@ class NearestNeighborhoodIterator implements Iterator<Job> {
|
|||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if(jobCount < nJobs){
|
||||
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");
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
|
@ -21,21 +21,21 @@ package jsprit.core.algorithm.ruin;
|
|||
import jsprit.core.algorithm.ruin.distance.JobDistance;
|
||||
import jsprit.core.problem.VehicleRoutingProblem;
|
||||
|
||||
public class RadialRuinStrategyFactory implements RuinStrategyFactory{
|
||||
public class RadialRuinStrategyFactory implements RuinStrategyFactory {
|
||||
|
||||
private double fraction;
|
||||
|
||||
private JobDistance jobDistance;
|
||||
|
||||
public RadialRuinStrategyFactory(double fraction, JobDistance jobDistance) {
|
||||
super();
|
||||
this.fraction = fraction;
|
||||
this.jobDistance = jobDistance;
|
||||
}
|
||||
private double fraction;
|
||||
|
||||
@Override
|
||||
public RuinStrategy createStrategy(VehicleRoutingProblem vrp) {
|
||||
return new RuinRadial(vrp,fraction,jobDistance);
|
||||
}
|
||||
private JobDistance jobDistance;
|
||||
|
||||
public RadialRuinStrategyFactory(double fraction, JobDistance jobDistance) {
|
||||
super();
|
||||
this.fraction = fraction;
|
||||
this.jobDistance = jobDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuinStrategy createStrategy(VehicleRoutingProblem vrp) {
|
||||
return new RuinRadial(vrp, fraction, jobDistance);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
|
|
@ -20,18 +20,18 @@ package jsprit.core.algorithm.ruin;
|
|||
|
||||
import jsprit.core.problem.VehicleRoutingProblem;
|
||||
|
||||
public class RandomRuinStrategyFactory implements RuinStrategyFactory{
|
||||
public class RandomRuinStrategyFactory implements RuinStrategyFactory {
|
||||
|
||||
private double fraction;
|
||||
|
||||
public RandomRuinStrategyFactory(double fraction) {
|
||||
super();
|
||||
this.fraction = fraction;
|
||||
}
|
||||
private double fraction;
|
||||
|
||||
@Override
|
||||
public RuinStrategy createStrategy(VehicleRoutingProblem vrp) {
|
||||
return new RuinRandom(vrp, fraction);
|
||||
}
|
||||
public RandomRuinStrategyFactory(double fraction) {
|
||||
super();
|
||||
this.fraction = fraction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuinStrategy createStrategy(VehicleRoutingProblem vrp) {
|
||||
return new RuinRandom(vrp, fraction);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package jsprit.core.algorithm.ruin;
|
|||
import jsprit.core.problem.job.Job;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
* Created by schroeder on 07/01/15.
|
||||
*/
|
||||
class ReferencedJob {
|
||||
private Job job;
|
||||
private double distance;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin;
|
||||
|
|
@ -33,159 +33,157 @@ import java.util.*;
|
|||
/**
|
||||
* Ruin strategy that ruins current solution randomly. I.e.
|
||||
* customer are removed randomly from current solution.
|
||||
*
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
|
||||
public final class RuinClusters extends AbstractRuinStrategy implements IterationStartsListener {
|
||||
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
minPts = 1 + random.nextInt(2);
|
||||
epsFactor = 0.5 + random.nextDouble();
|
||||
}
|
||||
@Override
|
||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||
minPts = 1 + random.nextInt(2);
|
||||
epsFactor = 0.5 + random.nextDouble();
|
||||
}
|
||||
|
||||
public static class JobActivityWrapper implements Clusterable {
|
||||
public static class JobActivityWrapper implements Clusterable {
|
||||
|
||||
private TourActivity.JobActivity jobActivity;
|
||||
private TourActivity.JobActivity jobActivity;
|
||||
|
||||
public JobActivityWrapper(TourActivity.JobActivity jobActivity) {
|
||||
this.jobActivity = jobActivity;
|
||||
}
|
||||
public JobActivityWrapper(TourActivity.JobActivity jobActivity) {
|
||||
this.jobActivity = jobActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] getPoint() {
|
||||
return new double[]{ jobActivity.getLocation().getCoordinate().getX(), jobActivity.getLocation().getCoordinate().getY() };
|
||||
}
|
||||
@Override
|
||||
public double[] getPoint() {
|
||||
return new double[]{jobActivity.getLocation().getCoordinate().getX(), jobActivity.getLocation().getCoordinate().getY()};
|
||||
}
|
||||
|
||||
public TourActivity.JobActivity getActivity(){
|
||||
return jobActivity;
|
||||
}
|
||||
}
|
||||
public TourActivity.JobActivity getActivity() {
|
||||
return jobActivity;
|
||||
}
|
||||
}
|
||||
|
||||
private Logger logger = LogManager.getLogger(RuinClusters.class);
|
||||
private Logger logger = LogManager.getLogger(RuinClusters.class);
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
|
||||
private JobNeighborhoods jobNeighborhoods;
|
||||
private JobNeighborhoods jobNeighborhoods;
|
||||
|
||||
private int noClusters = 2;
|
||||
private int noClusters = 2;
|
||||
|
||||
private int minPts = 1;
|
||||
private int minPts = 1;
|
||||
|
||||
private double epsFactor = 0.8;
|
||||
private double epsFactor = 0.8;
|
||||
|
||||
public RuinClusters(VehicleRoutingProblem vrp, final int initialNumberJobsToRemove, JobNeighborhoods jobNeighborhoods) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
setRuinShareFactory(new RuinShareFactory() {
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return initialNumberJobsToRemove;
|
||||
}
|
||||
});
|
||||
this.jobNeighborhoods = jobNeighborhoods;
|
||||
public RuinClusters(VehicleRoutingProblem vrp, final int initialNumberJobsToRemove, JobNeighborhoods jobNeighborhoods) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
setRuinShareFactory(new RuinShareFactory() {
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return initialNumberJobsToRemove;
|
||||
}
|
||||
});
|
||||
this.jobNeighborhoods = jobNeighborhoods;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
}
|
||||
|
||||
public void setNoClusters(int noClusters) {
|
||||
this.noClusters = noClusters;
|
||||
}
|
||||
public void setNoClusters(int noClusters) {
|
||||
this.noClusters = noClusters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a fraction of jobs from vehicleRoutes.
|
||||
*
|
||||
* <p>The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined).
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
/**
|
||||
* Removes a fraction of jobs from vehicleRoutes.
|
||||
* <p/>
|
||||
* <p>The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined).
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||
int nOfJobs2BeRemoved = getRuinShareFactory().createNumberToBeRemoved();
|
||||
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
||||
int nOfJobs2BeRemoved = getRuinShareFactory().createNumberToBeRemoved();
|
||||
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
||||
return unassignedJobs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes nOfJobs2BeRemoved from vehicleRoutes, including targetJob.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
/**
|
||||
* Removes nOfJobs2BeRemoved from vehicleRoutes, including targetJob.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
throw new IllegalStateException("not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private void ruin(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2BeRemoved, List<Job> unassignedJobs) {
|
||||
Map<Job,VehicleRoute> mappedRoutes = map(vehicleRoutes);
|
||||
int toRemove = nOfJobs2BeRemoved;
|
||||
private void ruin(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2BeRemoved, List<Job> unassignedJobs) {
|
||||
Map<Job, VehicleRoute> mappedRoutes = map(vehicleRoutes);
|
||||
int toRemove = nOfJobs2BeRemoved;
|
||||
|
||||
Collection<Job> lastRemoved = new ArrayList<Job>();
|
||||
Set<VehicleRoute> ruined = new HashSet<VehicleRoute>();
|
||||
Set<Job> removed = new HashSet<Job>();
|
||||
Set<VehicleRoute> cycleCandidates = new HashSet<VehicleRoute>();
|
||||
while(toRemove > 0) {
|
||||
Job target;
|
||||
VehicleRoute targetRoute = null;
|
||||
if(lastRemoved.isEmpty()){
|
||||
target = RandomUtils.nextJob(vrp.getJobs().values(), random);
|
||||
targetRoute = mappedRoutes.get(target);
|
||||
}
|
||||
else{
|
||||
target = RandomUtils.nextJob(lastRemoved, random);
|
||||
Iterator<Job> neighborIterator = jobNeighborhoods.getNearestNeighborsIterator(nOfJobs2BeRemoved,target);
|
||||
while(neighborIterator.hasNext()){
|
||||
Job j = neighborIterator.next();
|
||||
if(!removed.contains(j) && !ruined.contains(mappedRoutes.get(j))){
|
||||
targetRoute = mappedRoutes.get(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastRemoved.clear();
|
||||
}
|
||||
if(targetRoute == null) break;
|
||||
if(cycleCandidates.contains(targetRoute)) break;
|
||||
if(ruined.contains(targetRoute)) {
|
||||
cycleCandidates.add(targetRoute);
|
||||
break;
|
||||
}
|
||||
DBSCANClusterer dbscan = new DBSCANClusterer(vrp.getTransportCosts());
|
||||
dbscan.setRandom(random);
|
||||
dbscan.setMinPts(minPts);
|
||||
dbscan.setEpsFactor(epsFactor);
|
||||
List<Job> cluster = dbscan.getRandomCluster(targetRoute);
|
||||
for(Job j : cluster){
|
||||
if(toRemove == 0) break;
|
||||
if(removeJob(j, vehicleRoutes)) {
|
||||
lastRemoved.add(j);
|
||||
unassignedJobs.add(j);
|
||||
}
|
||||
toRemove--;
|
||||
}
|
||||
ruined.add(targetRoute);
|
||||
}
|
||||
}
|
||||
Collection<Job> lastRemoved = new ArrayList<Job>();
|
||||
Set<VehicleRoute> ruined = new HashSet<VehicleRoute>();
|
||||
Set<Job> removed = new HashSet<Job>();
|
||||
Set<VehicleRoute> cycleCandidates = new HashSet<VehicleRoute>();
|
||||
while (toRemove > 0) {
|
||||
Job target;
|
||||
VehicleRoute targetRoute = null;
|
||||
if (lastRemoved.isEmpty()) {
|
||||
target = RandomUtils.nextJob(vrp.getJobs().values(), random);
|
||||
targetRoute = mappedRoutes.get(target);
|
||||
} else {
|
||||
target = RandomUtils.nextJob(lastRemoved, random);
|
||||
Iterator<Job> neighborIterator = jobNeighborhoods.getNearestNeighborsIterator(nOfJobs2BeRemoved, target);
|
||||
while (neighborIterator.hasNext()) {
|
||||
Job j = neighborIterator.next();
|
||||
if (!removed.contains(j) && !ruined.contains(mappedRoutes.get(j))) {
|
||||
targetRoute = mappedRoutes.get(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastRemoved.clear();
|
||||
}
|
||||
if (targetRoute == null) break;
|
||||
if (cycleCandidates.contains(targetRoute)) break;
|
||||
if (ruined.contains(targetRoute)) {
|
||||
cycleCandidates.add(targetRoute);
|
||||
break;
|
||||
}
|
||||
DBSCANClusterer dbscan = new DBSCANClusterer(vrp.getTransportCosts());
|
||||
dbscan.setRandom(random);
|
||||
dbscan.setMinPts(minPts);
|
||||
dbscan.setEpsFactor(epsFactor);
|
||||
List<Job> cluster = dbscan.getRandomCluster(targetRoute);
|
||||
for (Job j : cluster) {
|
||||
if (toRemove == 0) break;
|
||||
if (removeJob(j, vehicleRoutes)) {
|
||||
lastRemoved.add(j);
|
||||
unassignedJobs.add(j);
|
||||
}
|
||||
toRemove--;
|
||||
}
|
||||
ruined.add(targetRoute);
|
||||
}
|
||||
}
|
||||
|
||||
private List<JobActivityWrapper> wrap(List<TourActivity> activities) {
|
||||
List<JobActivityWrapper> wl = new ArrayList<JobActivityWrapper>();
|
||||
for(TourActivity act : activities){
|
||||
wl.add(new JobActivityWrapper((TourActivity.JobActivity) act));
|
||||
}
|
||||
return wl;
|
||||
}
|
||||
private List<JobActivityWrapper> wrap(List<TourActivity> activities) {
|
||||
List<JobActivityWrapper> wl = new ArrayList<JobActivityWrapper>();
|
||||
for (TourActivity act : activities) {
|
||||
wl.add(new JobActivityWrapper((TourActivity.JobActivity) act));
|
||||
}
|
||||
return wl;
|
||||
}
|
||||
|
||||
private Map<Job, VehicleRoute> map(Collection<VehicleRoute> vehicleRoutes) {
|
||||
Map<Job,VehicleRoute> map = new HashMap<Job, VehicleRoute>(vrp.getJobs().size());
|
||||
for(VehicleRoute r : vehicleRoutes){
|
||||
for(Job j : r.getTourActivities().getJobs()){
|
||||
map.put(j,r);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
private Map<Job, VehicleRoute> map(Collection<VehicleRoute> vehicleRoutes) {
|
||||
Map<Job, VehicleRoute> map = new HashMap<Job, VehicleRoute>(vrp.getJobs().size());
|
||||
for (VehicleRoute r : vehicleRoutes) {
|
||||
for (Job j : r.getTourActivities().getJobs()) {
|
||||
map.put(j, r);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=clusterRuin]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=clusterRuin]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin;
|
||||
|
|
@ -28,124 +28,123 @@ 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
|
||||
* 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
|
||||
*
|
||||
* @author stefan
|
||||
*/
|
||||
public final class RuinRadial extends AbstractRuinStrategy {
|
||||
|
||||
private Logger logger = LogManager.getLogger(RuinRadial.class);
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
private Logger logger = LogManager.getLogger(RuinRadial.class);
|
||||
|
||||
private JobNeighborhoods jobNeighborhoods;
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private final int noJobsToMemorize;
|
||||
private JobNeighborhoods jobNeighborhoods;
|
||||
|
||||
/**
|
||||
* Constructs RuinRadial.
|
||||
*
|
||||
* @param vrp
|
||||
* @param fraction2beRemoved i.e. the share of jobs to be removed (relative to the total number of jobs in vrp)
|
||||
* @param jobDistance i.e. a measure to define the distance between two jobs and whether they are located close or distant to eachother
|
||||
*/
|
||||
public RuinRadial(VehicleRoutingProblem vrp, double fraction2beRemoved, JobDistance jobDistance) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
noJobsToMemorize = (int) Math.ceil(vrp.getJobs().values().size()*fraction2beRemoved);
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
private final int noJobsToMemorize;
|
||||
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
/**
|
||||
* Constructs RuinRadial.
|
||||
*
|
||||
* @param vrp
|
||||
* @param fraction2beRemoved i.e. the share of jobs to be removed (relative to the total number of jobs in vrp)
|
||||
* @param jobDistance i.e. a measure to define the distance between two jobs and whether they are located close or distant to eachother
|
||||
*/
|
||||
public RuinRadial(VehicleRoutingProblem vrp, double fraction2beRemoved, JobDistance jobDistance) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
noJobsToMemorize = (int) Math.ceil(vrp.getJobs().values().size() * fraction2beRemoved);
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
|
||||
};
|
||||
JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, noJobsToMemorize);
|
||||
jobNeighborhoodsImpl.initialise();
|
||||
jobNeighborhoods = jobNeighborhoodsImpl;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
|
||||
public RuinRadial(VehicleRoutingProblem vrp, int noJobs2beRemoved, JobDistance jobDistance) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
};
|
||||
JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, noJobsToMemorize);
|
||||
jobNeighborhoodsImpl.initialise();
|
||||
jobNeighborhoods = jobNeighborhoodsImpl;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
public RuinRadial(VehicleRoutingProblem vrp, int noJobs2beRemoved, JobDistance jobDistance) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
// this.fractionOfAllNodes2beRuined = fraction2beRemoved;
|
||||
noJobsToMemorize = noJobs2beRemoved;
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
noJobsToMemorize = noJobs2beRemoved;
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
|
||||
};
|
||||
JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, noJobsToMemorize);
|
||||
jobNeighborhoodsImpl.initialise();
|
||||
jobNeighborhoods = jobNeighborhoodsImpl;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
};
|
||||
JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, noJobsToMemorize);
|
||||
jobNeighborhoodsImpl.initialise();
|
||||
jobNeighborhoods = jobNeighborhoodsImpl;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
public RuinRadial(VehicleRoutingProblem vrp, int noJobs2beRemoved, JobNeighborhoods neighborhoods) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
noJobsToMemorize = noJobs2beRemoved;
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
public RuinRadial(VehicleRoutingProblem vrp, int noJobs2beRemoved, JobNeighborhoods neighborhoods) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
noJobsToMemorize = noJobs2beRemoved;
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
|
||||
};
|
||||
jobNeighborhoods = neighborhoods;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=radialRuin][noJobsToBeRemoved="+noJobsToMemorize+"]";
|
||||
}
|
||||
};
|
||||
jobNeighborhoods = neighborhoods;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
if(vehicleRoutes.isEmpty()){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
int nOfJobs2BeRemoved = Math.min(ruinShareFactory.createNumberToBeRemoved(), noJobsToMemorize);
|
||||
if (nOfJobs2BeRemoved == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Job randomJob = RandomUtils.nextJob(vrp.getJobs().values(),random);
|
||||
return ruinRoutes(vehicleRoutes, randomJob, nOfJobs2BeRemoved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes targetJob and its neighborhood and returns the removed jobs.
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=radialRuin][noJobsToBeRemoved=" + noJobsToMemorize + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
if (vehicleRoutes.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
int nOfJobs2BeRemoved = Math.min(ruinShareFactory.createNumberToBeRemoved(), noJobsToMemorize);
|
||||
if (nOfJobs2BeRemoved == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Job randomJob = RandomUtils.nextJob(vrp.getJobs().values(), random);
|
||||
return ruinRoutes(vehicleRoutes, randomJob, nOfJobs2BeRemoved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes targetJob and its neighborhood and returns the removed jobs.
|
||||
*
|
||||
* @deprecated will be private
|
||||
*/
|
||||
*/
|
||||
@Deprecated
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||
int nNeighbors = nOfJobs2BeRemoved - 1;
|
||||
removeJob(targetJob,vehicleRoutes);
|
||||
unassignedJobs.add(targetJob);
|
||||
Iterator<Job> neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(nNeighbors, targetJob);
|
||||
while(neighborhoodIterator.hasNext()){
|
||||
Job job = neighborhoodIterator.next();
|
||||
if(removeJob(job,vehicleRoutes)){
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
}
|
||||
int nNeighbors = nOfJobs2BeRemoved - 1;
|
||||
removeJob(targetJob, vehicleRoutes);
|
||||
unassignedJobs.add(targetJob);
|
||||
Iterator<Job> neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(nNeighbors, targetJob);
|
||||
while (neighborhoodIterator.hasNext()) {
|
||||
Job job = neighborhoodIterator.next();
|
||||
if (removeJob(job, vehicleRoutes)) {
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
}
|
||||
return unassignedJobs;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin;
|
||||
|
|
@ -27,112 +27,110 @@ 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
|
||||
* 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
|
||||
*
|
||||
* @author stefan
|
||||
*/
|
||||
public final class RuinRadialMultipleCenters extends AbstractRuinStrategy {
|
||||
|
||||
private Logger logger = LogManager.getLogger(RuinRadialMultipleCenters.class);
|
||||
private Logger logger = LogManager.getLogger(RuinRadialMultipleCenters.class);
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private JobNeighborhoods jobNeighborhoods;
|
||||
private JobNeighborhoods jobNeighborhoods;
|
||||
|
||||
private final int noJobsToMemorize;
|
||||
private final int noJobsToMemorize;
|
||||
|
||||
private int noCenters = 1;
|
||||
private int noCenters = 1;
|
||||
|
||||
public RuinRadialMultipleCenters(VehicleRoutingProblem vrp, int neighborhoodSize, JobDistance jobDistance) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
noJobsToMemorize = neighborhoodSize;
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
public RuinRadialMultipleCenters(VehicleRoutingProblem vrp, int neighborhoodSize, JobDistance jobDistance) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
noJobsToMemorize = neighborhoodSize;
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
|
||||
};
|
||||
JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, noJobsToMemorize);
|
||||
jobNeighborhoodsImpl.initialise();
|
||||
jobNeighborhoods = jobNeighborhoodsImpl;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
};
|
||||
JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, noJobsToMemorize);
|
||||
jobNeighborhoodsImpl.initialise();
|
||||
jobNeighborhoods = jobNeighborhoodsImpl;
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
|
||||
public void setNumberOfRuinCenters(int noCenters){
|
||||
this.noCenters = noCenters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=radialRuin][noJobsToBeRemoved="+noJobsToMemorize+"]";
|
||||
}
|
||||
public void setNumberOfRuinCenters(int noCenters) {
|
||||
this.noCenters = noCenters;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
if(vehicleRoutes.isEmpty()){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<Job> available = new HashSet<Job>(vrp.getJobs().values());
|
||||
Collection<Job> ruined = new ArrayList<Job>();
|
||||
for(int center=0;center<noCenters;center++) {
|
||||
int nOfJobs2BeRemoved = ruinShareFactory.createNumberToBeRemoved();
|
||||
if (nOfJobs2BeRemoved == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Job randomJob = pickRandomJob(available);
|
||||
if(randomJob != null) {
|
||||
ruined.addAll(ruinRoutes_(vehicleRoutes, randomJob, nOfJobs2BeRemoved, available));
|
||||
}
|
||||
}
|
||||
return ruined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes targetJob and its neighborhood and returns the removed jobs.
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=radialRuin][noJobsToBeRemoved=" + noJobsToMemorize + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
if (vehicleRoutes.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<Job> available = new HashSet<Job>(vrp.getJobs().values());
|
||||
Collection<Job> ruined = new ArrayList<Job>();
|
||||
for (int center = 0; center < noCenters; center++) {
|
||||
int nOfJobs2BeRemoved = ruinShareFactory.createNumberToBeRemoved();
|
||||
if (nOfJobs2BeRemoved == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Job randomJob = pickRandomJob(available);
|
||||
if (randomJob != null) {
|
||||
ruined.addAll(ruinRoutes_(vehicleRoutes, randomJob, nOfJobs2BeRemoved, available));
|
||||
}
|
||||
}
|
||||
return ruined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes targetJob and its neighborhood and returns the removed jobs.
|
||||
*
|
||||
* @deprecated will be private
|
||||
*/
|
||||
*/
|
||||
@Deprecated
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
|
||||
return ruinRoutes_(vehicleRoutes,targetJob,nOfJobs2BeRemoved,null);
|
||||
}
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
return ruinRoutes_(vehicleRoutes, targetJob, nOfJobs2BeRemoved, null);
|
||||
}
|
||||
|
||||
private Collection<Job> ruinRoutes_(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved, Set<Job> available){
|
||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||
int nNeighbors = nOfJobs2BeRemoved - 1;
|
||||
removeJob(targetJob,vehicleRoutes);
|
||||
unassignedJobs.add(targetJob);
|
||||
Iterator<Job> neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(nNeighbors, targetJob);
|
||||
while(neighborhoodIterator.hasNext()){
|
||||
Job job = neighborhoodIterator.next();
|
||||
if(available!=null) available.remove(job);
|
||||
if(removeJob(job,vehicleRoutes)) {
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
}
|
||||
return unassignedJobs;
|
||||
}
|
||||
private Collection<Job> ruinRoutes_(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved, Set<Job> available) {
|
||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||
int nNeighbors = nOfJobs2BeRemoved - 1;
|
||||
removeJob(targetJob, vehicleRoutes);
|
||||
unassignedJobs.add(targetJob);
|
||||
Iterator<Job> neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(nNeighbors, targetJob);
|
||||
while (neighborhoodIterator.hasNext()) {
|
||||
Job job = neighborhoodIterator.next();
|
||||
if (available != null) available.remove(job);
|
||||
if (removeJob(job, vehicleRoutes)) {
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
}
|
||||
return unassignedJobs;
|
||||
}
|
||||
|
||||
private Job pickRandomJob(Set<Job> available) {
|
||||
int randomIndex = random.nextInt(available.size());
|
||||
int i=0;
|
||||
for(Job j : available){
|
||||
if(i>=randomIndex) {
|
||||
return j;
|
||||
}
|
||||
else i++;
|
||||
}
|
||||
return null;
|
||||
private Job pickRandomJob(Set<Job> available) {
|
||||
int randomIndex = random.nextInt(available.size());
|
||||
int i = 0;
|
||||
for (Job j : available) {
|
||||
if (i >= randomIndex) {
|
||||
return j;
|
||||
} else i++;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin;
|
||||
|
|
@ -31,80 +31,79 @@ import java.util.List;
|
|||
/**
|
||||
* Ruin strategy that ruins current solution randomly. I.e.
|
||||
* customer are removed randomly from current solution.
|
||||
*
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
|
||||
public final class RuinRandom extends AbstractRuinStrategy {
|
||||
|
||||
private Logger logger = LogManager.getLogger(RuinRandom.class);
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
private Logger logger = LogManager.getLogger(RuinRandom.class);
|
||||
|
||||
private double fractionOfAllNodes2beRuined;
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
/**
|
||||
* Constructs ruinRandom.
|
||||
*
|
||||
* @param vrp
|
||||
* @param fraction which is the fraction of total c
|
||||
*/
|
||||
public RuinRandom(VehicleRoutingProblem vrp, double fraction) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
this.fractionOfAllNodes2beRuined = fraction;
|
||||
setRuinShareFactory(new RuinShareFactory() {
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return selectNuOfJobs2BeRemoved();
|
||||
}
|
||||
});
|
||||
private double fractionOfAllNodes2beRuined;
|
||||
|
||||
/**
|
||||
* Constructs ruinRandom.
|
||||
*
|
||||
* @param vrp
|
||||
* @param fraction which is the fraction of total c
|
||||
*/
|
||||
public RuinRandom(VehicleRoutingProblem vrp, double fraction) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
this.fractionOfAllNodes2beRuined = fraction;
|
||||
setRuinShareFactory(new RuinShareFactory() {
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return selectNuOfJobs2BeRemoved();
|
||||
}
|
||||
});
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a fraction of jobs from vehicleRoutes.
|
||||
*
|
||||
* <p>The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined).
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
/**
|
||||
* Removes a fraction of jobs from vehicleRoutes.
|
||||
* <p/>
|
||||
* <p>The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined).
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||
int nOfJobs2BeRemoved = getRuinShareFactory().createNumberToBeRemoved();
|
||||
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
||||
int nOfJobs2BeRemoved = getRuinShareFactory().createNumberToBeRemoved();
|
||||
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
||||
return unassignedJobs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes nOfJobs2BeRemoved from vehicleRoutes, including targetJob.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
/**
|
||||
* Removes nOfJobs2BeRemoved from vehicleRoutes, including targetJob.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
throw new IllegalStateException("not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private void ruin(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2BeRemoved, List<Job> unassignedJobs) {
|
||||
ArrayList<Job> availableJobs = new ArrayList<Job>(vrp.getJobs().values());
|
||||
Collections.shuffle(availableJobs,random);
|
||||
int removed = 0;
|
||||
for (Job job : availableJobs) {
|
||||
if(removed == nOfJobs2BeRemoved) break;
|
||||
if(removeJob(job,vehicleRoutes)) {
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
private void ruin(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2BeRemoved, List<Job> unassignedJobs) {
|
||||
ArrayList<Job> availableJobs = new ArrayList<Job>(vrp.getJobs().values());
|
||||
Collections.shuffle(availableJobs, random);
|
||||
int removed = 0;
|
||||
for (Job job : availableJobs) {
|
||||
if (removed == nOfJobs2BeRemoved) break;
|
||||
if (removeJob(job, vehicleRoutes)) {
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=randomRuin][noJobsToBeRemoved="+selectNuOfJobs2BeRemoved()+"]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=randomRuin][noJobsToBeRemoved=" + selectNuOfJobs2BeRemoved() + "]";
|
||||
}
|
||||
|
||||
private int selectNuOfJobs2BeRemoved() {
|
||||
return (int) Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined);
|
||||
}
|
||||
private int selectNuOfJobs2BeRemoved() {
|
||||
return (int) Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin;
|
||||
|
|
@ -23,41 +23,36 @@ import jsprit.core.problem.solution.route.VehicleRoute;
|
|||
import java.util.Collection;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
|
||||
public interface RuinStrategy {
|
||||
|
||||
/**
|
||||
* Ruins a current solution, i.e. a collection of vehicle-routes and
|
||||
* returns a collection of removed and thus unassigned jobs.
|
||||
*
|
||||
* @param {@link VehicleRoute}
|
||||
* @return Collection of {@link Job}
|
||||
*/
|
||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes);
|
||||
|
||||
/**
|
||||
* Removes targetJob as well as its neighbors with a size of (nOfJobs2BeRemoved-1).
|
||||
*/
|
||||
/**
|
||||
* Ruins a current solution, i.e. a collection of vehicle-routes and
|
||||
* returns a collection of removed and thus unassigned jobs.
|
||||
*
|
||||
* @param {@link VehicleRoute}
|
||||
* @return Collection of {@link Job}
|
||||
*/
|
||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes);
|
||||
|
||||
/**
|
||||
* Removes targetJob as well as its neighbors with a size of (nOfJobs2BeRemoved-1).
|
||||
*/
|
||||
@Deprecated
|
||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved);
|
||||
|
||||
/**
|
||||
* Adds a ruin-listener.
|
||||
*
|
||||
* @param {@link RuinListener}
|
||||
*/
|
||||
public void addListener(RuinListener ruinListener);
|
||||
|
||||
public void removeListener(RuinListener ruinListener);
|
||||
|
||||
public Collection<RuinListener> getListeners();
|
||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved);
|
||||
|
||||
/**
|
||||
* Adds a ruin-listener.
|
||||
*
|
||||
* @param {@link RuinListener}
|
||||
*/
|
||||
public void addListener(RuinListener ruinListener);
|
||||
|
||||
public void removeListener(RuinListener ruinListener);
|
||||
|
||||
public Collection<RuinListener> getListeners();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin;
|
||||
|
|
@ -19,7 +19,7 @@ package jsprit.core.algorithm.ruin;
|
|||
import jsprit.core.problem.VehicleRoutingProblem;
|
||||
|
||||
public interface RuinStrategyFactory {
|
||||
|
||||
public RuinStrategy createStrategy(VehicleRoutingProblem vrp);
|
||||
|
||||
public RuinStrategy createStrategy(VehicleRoutingProblem vrp);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin;
|
||||
|
|
@ -32,134 +32,131 @@ import java.util.*;
|
|||
/**
|
||||
* Ruin strategy that ruins current solution randomly. I.e.
|
||||
* customer are removed randomly from current solution.
|
||||
*
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
*/
|
||||
|
||||
public final class RuinWorst extends AbstractRuinStrategy {
|
||||
|
||||
private Logger logger = LogManager.getLogger(RuinWorst.class);
|
||||
private Logger logger = LogManager.getLogger(RuinWorst.class);
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private NoiseMaker noiseMaker = new NoiseMaker(){
|
||||
private NoiseMaker noiseMaker = new NoiseMaker() {
|
||||
|
||||
@Override
|
||||
public double makeNoise() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public double makeNoise() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public void setNoiseMaker(NoiseMaker noiseMaker) {
|
||||
this.noiseMaker = noiseMaker;
|
||||
}
|
||||
public void setNoiseMaker(NoiseMaker noiseMaker) {
|
||||
this.noiseMaker = noiseMaker;
|
||||
}
|
||||
|
||||
public RuinWorst(VehicleRoutingProblem vrp, final int initialNumberJobsToRemove) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
setRuinShareFactory(new RuinShareFactory() {
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return initialNumberJobsToRemove;
|
||||
}
|
||||
});
|
||||
public RuinWorst(VehicleRoutingProblem vrp, final int initialNumberJobsToRemove) {
|
||||
super(vrp);
|
||||
this.vrp = vrp;
|
||||
setRuinShareFactory(new RuinShareFactory() {
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return initialNumberJobsToRemove;
|
||||
}
|
||||
});
|
||||
logger.debug("initialise {}", this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a fraction of jobs from vehicleRoutes.
|
||||
*
|
||||
* <p>The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined).
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
/**
|
||||
* Removes a fraction of jobs from vehicleRoutes.
|
||||
* <p/>
|
||||
* <p>The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined).
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||
int nOfJobs2BeRemoved = getRuinShareFactory().createNumberToBeRemoved();
|
||||
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
||||
int nOfJobs2BeRemoved = getRuinShareFactory().createNumberToBeRemoved();
|
||||
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
||||
return unassignedJobs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes nOfJobs2BeRemoved from vehicleRoutes, including targetJob.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
/**
|
||||
* Removes nOfJobs2BeRemoved from vehicleRoutes, including targetJob.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||
throw new UnsupportedOperationException("ruinRoutes not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private void ruin(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2BeRemoved, List<Job> unassignedJobs) {
|
||||
LinkedList<Job> availableJobs = new LinkedList<Job>(vrp.getJobs().values());
|
||||
int toRemove = nOfJobs2BeRemoved;
|
||||
while(toRemove > 0){
|
||||
Job worst = getWorst(vehicleRoutes);
|
||||
if(worst == null) break;
|
||||
if(removeJob(worst,vehicleRoutes)) {
|
||||
availableJobs.remove(worst);
|
||||
unassignedJobs.add(worst);
|
||||
}
|
||||
toRemove--;
|
||||
}
|
||||
}
|
||||
private void ruin(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2BeRemoved, List<Job> unassignedJobs) {
|
||||
LinkedList<Job> availableJobs = new LinkedList<Job>(vrp.getJobs().values());
|
||||
int toRemove = nOfJobs2BeRemoved;
|
||||
while (toRemove > 0) {
|
||||
Job worst = getWorst(vehicleRoutes);
|
||||
if (worst == null) break;
|
||||
if (removeJob(worst, vehicleRoutes)) {
|
||||
availableJobs.remove(worst);
|
||||
unassignedJobs.add(worst);
|
||||
}
|
||||
toRemove--;
|
||||
}
|
||||
}
|
||||
|
||||
private Job getWorst(Collection<VehicleRoute> copied) {
|
||||
Job worst = null;
|
||||
double bestSavings = Double.MIN_VALUE;
|
||||
private Job getWorst(Collection<VehicleRoute> copied) {
|
||||
Job worst = null;
|
||||
double bestSavings = Double.MIN_VALUE;
|
||||
|
||||
for(VehicleRoute route : copied) {
|
||||
if(route.isEmpty()) continue;
|
||||
Map<Job,Double> savingsMap = new HashMap<Job,Double>();
|
||||
TourActivity actBefore = route.getStart();
|
||||
TourActivity actToEval = null;
|
||||
for (TourActivity act : route.getActivities()) {
|
||||
if (actToEval == null) {
|
||||
actToEval = act;
|
||||
continue;
|
||||
}
|
||||
double savings = savings(route, actBefore, actToEval, act);
|
||||
Job job = ((TourActivity.JobActivity) actToEval).getJob();
|
||||
if(!savingsMap.containsKey(job)){
|
||||
savingsMap.put(job,savings);
|
||||
}
|
||||
else {
|
||||
double s = savingsMap.get(job);
|
||||
savingsMap.put(job,s+savings);
|
||||
}
|
||||
actBefore = actToEval;
|
||||
actToEval = act;
|
||||
}
|
||||
double savings = savings(route, actBefore, actToEval, route.getEnd());
|
||||
Job job = ((TourActivity.JobActivity) actToEval).getJob();
|
||||
if(!savingsMap.containsKey(job)){
|
||||
savingsMap.put(job,savings);
|
||||
}
|
||||
else {
|
||||
double s = savingsMap.get(job);
|
||||
savingsMap.put(job,s+savings);
|
||||
}
|
||||
//getCounts best
|
||||
for(Job j : savingsMap.keySet()){
|
||||
if(savingsMap.get(j) > bestSavings){
|
||||
bestSavings = savingsMap.get(j);
|
||||
worst = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
return worst;
|
||||
}
|
||||
for (VehicleRoute route : copied) {
|
||||
if (route.isEmpty()) continue;
|
||||
Map<Job, Double> savingsMap = new HashMap<Job, Double>();
|
||||
TourActivity actBefore = route.getStart();
|
||||
TourActivity actToEval = null;
|
||||
for (TourActivity act : route.getActivities()) {
|
||||
if (actToEval == null) {
|
||||
actToEval = act;
|
||||
continue;
|
||||
}
|
||||
double savings = savings(route, actBefore, actToEval, act);
|
||||
Job job = ((TourActivity.JobActivity) actToEval).getJob();
|
||||
if (!savingsMap.containsKey(job)) {
|
||||
savingsMap.put(job, savings);
|
||||
} else {
|
||||
double s = savingsMap.get(job);
|
||||
savingsMap.put(job, s + savings);
|
||||
}
|
||||
actBefore = actToEval;
|
||||
actToEval = act;
|
||||
}
|
||||
double savings = savings(route, actBefore, actToEval, route.getEnd());
|
||||
Job job = ((TourActivity.JobActivity) actToEval).getJob();
|
||||
if (!savingsMap.containsKey(job)) {
|
||||
savingsMap.put(job, savings);
|
||||
} else {
|
||||
double s = savingsMap.get(job);
|
||||
savingsMap.put(job, s + savings);
|
||||
}
|
||||
//getCounts best
|
||||
for (Job j : savingsMap.keySet()) {
|
||||
if (savingsMap.get(j) > bestSavings) {
|
||||
bestSavings = savingsMap.get(j);
|
||||
worst = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
return worst;
|
||||
}
|
||||
|
||||
private double savings(VehicleRoute route, TourActivity actBefore, TourActivity actToEval, TourActivity act) {
|
||||
double savings = c(actBefore, actToEval, route.getVehicle()) + c(actToEval, act, route.getVehicle()) - c(actBefore, act, route.getVehicle());
|
||||
return Math.max(0,savings + noiseMaker.makeNoise());
|
||||
}
|
||||
private double savings(VehicleRoute route, TourActivity actBefore, TourActivity actToEval, TourActivity act) {
|
||||
double savings = c(actBefore, actToEval, route.getVehicle()) + c(actToEval, act, route.getVehicle()) - c(actBefore, act, route.getVehicle());
|
||||
return Math.max(0, savings + noiseMaker.makeNoise());
|
||||
}
|
||||
|
||||
private double c(TourActivity from, TourActivity to, Vehicle vehicle) {
|
||||
return vrp.getTransportCosts().getTransportCost(from.getLocation(),to.getLocation(),from.getEndTime(), DriverImpl.noDriver(), vehicle);
|
||||
}
|
||||
private double c(TourActivity from, TourActivity to, Vehicle vehicle) {
|
||||
return vrp.getTransportCosts().getTransportCost(from.getLocation(), to.getLocation(), from.getEndTime(), DriverImpl.noDriver(), vehicle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=worstRuin]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=worstRuin]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin.distance;
|
||||
|
|
@ -24,76 +24,69 @@ import jsprit.core.problem.job.Shipment;
|
|||
import jsprit.core.util.EuclideanDistanceCalculator;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calculator that calculates average distance between two jobs based on the input-transport costs.
|
||||
*
|
||||
* <p/>
|
||||
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*/
|
||||
public class AvgServiceAndShipmentDistance implements JobDistance {
|
||||
|
||||
private VehicleRoutingTransportCosts costs;
|
||||
private VehicleRoutingTransportCosts costs;
|
||||
|
||||
public AvgServiceAndShipmentDistance(VehicleRoutingTransportCosts costs) {
|
||||
super();
|
||||
this.costs = costs;
|
||||
public AvgServiceAndShipmentDistance(VehicleRoutingTransportCosts costs) {
|
||||
super();
|
||||
this.costs = costs;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and returns the average distance between two jobs based on the input-transport costs.
|
||||
*
|
||||
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
|
||||
*/
|
||||
@Override
|
||||
public double getDistance(Job i, Job j) {
|
||||
if (i.equals(j)) return 0.0;
|
||||
/**
|
||||
* Calculates and returns the average distance between two jobs based on the input-transport costs.
|
||||
* <p/>
|
||||
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
|
||||
*/
|
||||
@Override
|
||||
public double getDistance(Job i, Job j) {
|
||||
if (i.equals(j)) return 0.0;
|
||||
|
||||
if (i instanceof Service && j instanceof Service) {
|
||||
return calcDist((Service)i, (Service)j);
|
||||
}
|
||||
else if(i instanceof Service && j instanceof Shipment){
|
||||
return calcDist((Service)i,(Shipment)j);
|
||||
}
|
||||
else if(i instanceof Shipment && j instanceof Service){
|
||||
return calcDist((Service)j,(Shipment)i);
|
||||
}
|
||||
else if(i instanceof Shipment && j instanceof Shipment){
|
||||
return calcDist((Shipment)i,(Shipment)j);
|
||||
}
|
||||
else{
|
||||
throw new IllegalStateException("this supports only shipments or services");
|
||||
}
|
||||
}
|
||||
|
||||
private double calcDist(Service i, Service j) {
|
||||
return calcDist(i.getLocation(),j.getLocation());
|
||||
}
|
||||
|
||||
private double calcDist(Service i, Shipment j) {
|
||||
double c_ij1 = calcDist(i.getLocation(),j.getPickupLocation());
|
||||
double c_ij2 = calcDist(i.getLocation(),j.getDeliveryLocation());
|
||||
return (c_ij1 + c_ij2)/2.0;
|
||||
}
|
||||
|
||||
private double calcDist(Shipment i, Shipment j) {
|
||||
double c_i1j1 = calcDist(i.getPickupLocation(),j.getPickupLocation());
|
||||
double c_i1j2 = calcDist(i.getPickupLocation(),j.getDeliveryLocation());
|
||||
double c_i2j1 = calcDist(i.getDeliveryLocation(),j.getPickupLocation());
|
||||
double c_i2j2 = calcDist(i.getDeliveryLocation(),j.getDeliveryLocation());
|
||||
return (c_i1j1 + c_i1j2 + c_i2j1 + c_i2j2)/4.0;
|
||||
}
|
||||
|
||||
private double calcDist(Location location_i, Location location_j){
|
||||
try{
|
||||
return costs.getTransportCost(location_i, location_j, 0.0, null, null);
|
||||
if (i instanceof Service && j instanceof Service) {
|
||||
return calcDist((Service) i, (Service) j);
|
||||
} else if (i instanceof Service && j instanceof Shipment) {
|
||||
return calcDist((Service) i, (Shipment) j);
|
||||
} else if (i instanceof Shipment && j instanceof Service) {
|
||||
return calcDist((Service) j, (Shipment) i);
|
||||
} else if (i instanceof Shipment && j instanceof Shipment) {
|
||||
return calcDist((Shipment) i, (Shipment) j);
|
||||
} else {
|
||||
throw new IllegalStateException("this supports only shipments or services");
|
||||
}
|
||||
catch(IllegalStateException e){
|
||||
// now try the euclidean distance between these two services
|
||||
}
|
||||
return EuclideanDistanceCalculator.calculateDistance(location_i.getCoordinate(), location_j.getCoordinate());
|
||||
}
|
||||
}
|
||||
|
||||
private double calcDist(Service i, Service j) {
|
||||
return calcDist(i.getLocation(), j.getLocation());
|
||||
}
|
||||
|
||||
private double calcDist(Service i, Shipment j) {
|
||||
double c_ij1 = calcDist(i.getLocation(), j.getPickupLocation());
|
||||
double c_ij2 = calcDist(i.getLocation(), j.getDeliveryLocation());
|
||||
return (c_ij1 + c_ij2) / 2.0;
|
||||
}
|
||||
|
||||
private double calcDist(Shipment i, Shipment j) {
|
||||
double c_i1j1 = calcDist(i.getPickupLocation(), j.getPickupLocation());
|
||||
double c_i1j2 = calcDist(i.getPickupLocation(), j.getDeliveryLocation());
|
||||
double c_i2j1 = calcDist(i.getDeliveryLocation(), j.getPickupLocation());
|
||||
double c_i2j2 = calcDist(i.getDeliveryLocation(), j.getDeliveryLocation());
|
||||
return (c_i1j1 + c_i1j2 + c_i2j1 + c_i2j2) / 4.0;
|
||||
}
|
||||
|
||||
private double calcDist(Location location_i, Location location_j) {
|
||||
try {
|
||||
return costs.getTransportCost(location_i, location_j, 0.0, null, null);
|
||||
} catch (IllegalStateException e) {
|
||||
// now try the euclidean distance between these two services
|
||||
}
|
||||
return EuclideanDistanceCalculator.calculateDistance(location_i.getCoordinate(), location_j.getCoordinate());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin.distance;
|
||||
|
|
@ -21,60 +21,57 @@ import jsprit.core.problem.job.Job;
|
|||
import jsprit.core.problem.job.Service;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calculator that calculates average distance between two jobs based on the input-transport costs.
|
||||
*
|
||||
* <p/>
|
||||
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*
|
||||
* @author stefan schroeder
|
||||
*/
|
||||
public class AvgServiceDistance implements JobDistance {
|
||||
|
||||
private VehicleRoutingTransportCosts costs;
|
||||
private VehicleRoutingTransportCosts costs;
|
||||
|
||||
public AvgServiceDistance(VehicleRoutingTransportCosts costs) {
|
||||
super();
|
||||
this.costs = costs;
|
||||
public AvgServiceDistance(VehicleRoutingTransportCosts costs) {
|
||||
super();
|
||||
this.costs = costs;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and returns the average distance between two jobs based on the input-transport costs.
|
||||
*
|
||||
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
|
||||
*/
|
||||
@Override
|
||||
public double getDistance(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;
|
||||
avgCost = calcDist(s_i, s_j);
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedOperationException(
|
||||
"currently, this class just works services.");
|
||||
}
|
||||
return avgCost;
|
||||
}
|
||||
/**
|
||||
* Calculates and returns the average distance between two jobs based on the input-transport costs.
|
||||
* <p/>
|
||||
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
|
||||
*/
|
||||
@Override
|
||||
public double getDistance(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;
|
||||
avgCost = calcDist(s_i, s_j);
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedOperationException(
|
||||
"currently, this class just works services.");
|
||||
}
|
||||
return avgCost;
|
||||
}
|
||||
|
||||
private double calcDist(Service s_i, Service s_j) {
|
||||
double distance;
|
||||
try{
|
||||
distance = costs.getTransportCost(s_i.getLocation(), s_j.getLocation(), 0.0, null, null);
|
||||
return distance;
|
||||
}
|
||||
catch(IllegalStateException e){
|
||||
// now try the euclidean distance between these two services
|
||||
}
|
||||
EuclideanServiceDistance euclidean = new EuclideanServiceDistance();
|
||||
distance = euclidean.getDistance(s_i, s_j);
|
||||
return distance;
|
||||
}
|
||||
private double calcDist(Service s_i, Service s_j) {
|
||||
double distance;
|
||||
try {
|
||||
distance = costs.getTransportCost(s_i.getLocation(), s_j.getLocation(), 0.0, null, null);
|
||||
return distance;
|
||||
} catch (IllegalStateException e) {
|
||||
// now try the euclidean distance between these two services
|
||||
}
|
||||
EuclideanServiceDistance euclidean = new EuclideanServiceDistance();
|
||||
distance = euclidean.getDistance(s_i, s_j);
|
||||
return distance;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
* 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
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin.distance;
|
||||
|
|
@ -22,27 +22,28 @@ import jsprit.core.util.EuclideanDistanceCalculator;
|
|||
|
||||
public class EuclideanServiceDistance implements JobDistance {
|
||||
|
||||
public EuclideanServiceDistance() {
|
||||
super();
|
||||
}
|
||||
public EuclideanServiceDistance() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDistance(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.getLocation().getCoordinate() == null || s_j.getLocation().getCoordinate() == null) throw new IllegalStateException("cannot calculate euclidean distance. since service coords are missing");
|
||||
avgCost = EuclideanDistanceCalculator.calculateDistance(s_i.getLocation().getCoordinate(), s_j.getLocation().getCoordinate());
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedOperationException(
|
||||
"currently, this class just works with shipments and services.");
|
||||
}
|
||||
return avgCost;
|
||||
}
|
||||
@Override
|
||||
public double getDistance(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.getLocation().getCoordinate() == null || s_j.getLocation().getCoordinate() == null)
|
||||
throw new IllegalStateException("cannot calculate euclidean distance. since service coords are missing");
|
||||
avgCost = EuclideanDistanceCalculator.calculateDistance(s_i.getLocation().getCoordinate(), s_j.getLocation().getCoordinate());
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedOperationException(
|
||||
"currently, this class just works with shipments and services.");
|
||||
}
|
||||
return avgCost;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin.distance;
|
||||
|
|
@ -19,9 +19,8 @@ package jsprit.core.algorithm.ruin.distance;
|
|||
import jsprit.core.problem.job.Job;
|
||||
|
||||
|
||||
|
||||
public interface JobDistance {
|
||||
|
||||
public double getDistance(Job i, Job j);
|
||||
public double getDistance(Job i, Job j);
|
||||
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue