Package jsprit.core.algorithm.io

Source Code of jsprit.core.algorithm.io.VehicleRoutingAlgorithms$TypedMap$StrategyModuleKey

/*******************************************************************************
* 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
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.io;


import jsprit.core.algorithm.*;
import jsprit.core.algorithm.acceptor.*;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.*;
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority;
import jsprit.core.algorithm.module.RuinAndRecreateModule;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.recreate.VehicleSwitched;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RuinStrategy;
import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance;
import jsprit.core.algorithm.ruin.distance.JobDistance;
import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.algorithm.selector.SelectRandomly;
import jsprit.core.algorithm.selector.SolutionSelector;
import jsprit.core.algorithm.state.*;
import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination;
import jsprit.core.algorithm.termination.PrematureAlgorithmTermination;
import jsprit.core.algorithm.termination.TimeTermination;
import jsprit.core.algorithm.termination.VariationCoefficientTermination;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.FleetSize;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.FiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import jsprit.core.util.ActivityTimeTracker;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.Thread.UncaughtExceptionHandler;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class VehicleRoutingAlgorithms {
 
  static class TypedMap {
   
    static interface AbstractKey<K> {
     
        Class<K> getType();
    }
   
    static class AcceptorKey implements AbstractKey<SolutionAcceptor>{

      private ModKey modKey;
     
      public AcceptorKey(ModKey modKey) {
        super();
        this.modKey = modKey;
      }

     
      @Override
      public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
            + ((modKey == null) ? 0 : modKey.hashCode());
        return result;
      }


      @Override
      public boolean equals(Object obj) {
        if (this == obj)
          return true;
        if (obj == null)
          return false;
        if (!(obj instanceof AcceptorKey))
          return false;
        AcceptorKey other = (AcceptorKey) obj;
        if (modKey == null) {
          if (other.modKey != null)
            return false;
        } else if (!modKey.equals(other.modKey))
          return false;
        return true;
      }


      @Override
      public Class<SolutionAcceptor> getType() {
        return SolutionAcceptor.class;
      }
     
    }
   
    static class SelectorKey implements AbstractKey<SolutionSelector>{

      private ModKey modKey;
     
      public SelectorKey(ModKey modKey) {
        super();
        this.modKey = modKey;
      }
     
      @Override
      public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
            + ((modKey == null) ? 0 : modKey.hashCode());
        return result;
      }

      @Override
      public boolean equals(Object obj) {
        if (this == obj)
          return true;
        if (obj == null)
          return false;
        if (getClass() != obj.getClass())
          return false;
        SelectorKey other = (SelectorKey) obj;
        if (modKey == null) {
          if (other.modKey != null)
            return false;
        } else if (!modKey.equals(other.modKey))
          return false;
        return true;
      }



      @Override
      public Class<SolutionSelector> getType() {
        return SolutionSelector.class;
      }
     
    }
   
    static class StrategyModuleKey implements AbstractKey<SearchStrategyModule>{

      private ModKey modKey;
     
      public StrategyModuleKey(ModKey modKey) {
        super();
        this.modKey = modKey;
      }
     
      @Override
      public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
            + ((modKey == null) ? 0 : modKey.hashCode());
        return result;
      }

      @Override
      public boolean equals(Object obj) {
        if (this == obj)
          return true;
        if (obj == null)
          return false;
        if (getClass() != obj.getClass())
          return false;
        StrategyModuleKey other = (StrategyModuleKey) obj;
        if (modKey == null) {
          if (other.modKey != null)
            return false;
        } else if (!modKey.equals(other.modKey))
          return false;
        return true;
      }



      @Override
      public Class<SearchStrategyModule> getType() {
        return SearchStrategyModule.class;
      }
     
    }
   
    static class RuinStrategyKey implements AbstractKey<RuinStrategy>{

      private ModKey modKey;
     
      public RuinStrategyKey(ModKey modKey) {
        super();
        this.modKey = modKey;
      }
     
      @Override
      public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
            + ((modKey == null) ? 0 : modKey.hashCode());
        return result;
      }

      @Override
      public boolean equals(Object obj) {
        if (this == obj)
          return true;
        if (obj == null)
          return false;
        if (getClass() != obj.getClass())
          return false;
        RuinStrategyKey other = (RuinStrategyKey) obj;
        if (modKey == null) {
          if (other.modKey != null)
            return false;
        } else if (!modKey.equals(other.modKey))
          return false;
        return true;
      }



      @Override
      public Class<RuinStrategy> getType() {
        return RuinStrategy.class;
      }
     
    }

    static class InsertionStrategyKey implements AbstractKey<InsertionStrategy>{

      private ModKey modKey;
     
      public InsertionStrategyKey(ModKey modKey) {
        super();
        this.modKey = modKey;
      }
     
      @Override
      public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
            + ((modKey == null) ? 0 : modKey.hashCode());
        return result;
      }

      @Override
      public boolean equals(Object obj) {
        if (this == obj)
          return true;
        if (obj == null)
          return false;
        if (getClass() != obj.getClass())
          return false;
        InsertionStrategyKey other = (InsertionStrategyKey) obj;
        if (modKey == null) {
          if (other.modKey != null)
            return false;
        } else if (!modKey.equals(other.modKey))
          return false;
        return true;
      }



      @Override
      public Class<InsertionStrategy> getType() {
        return InsertionStrategy.class;
      }
     
    }
       
    private Map<AbstractKey<?>, Object> map = new HashMap<AbstractKey<?>, Object>();

    public <T> T get(AbstractKey<T> key) {
      if(map.get(key) == null) return null;
          return key.getType().cast(map.get(key));
      }

      public <T> T put(AbstractKey<T> key, T value) {
          return key.getType().cast(map.put(key, key.getType().cast(value)));
      }
     
      public Set<AbstractKey<?>> keySet(){
        return map.keySet();
      }
  }
 
  static class ModKey {
    private String name;
    private String id;
   
    public ModKey(String name, String id) {
      super();
      this.name = name;
      this.id = id;
    }
   
    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((id == null) ? 0 : id.hashCode());
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      return result;
    }
    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      ModKey other = (ModKey) obj;
      if (id == null) {
        if (other.id != null)
          return false;
      } else if (!id.equals(other.id))
        return false;
      if (name == null) {
        if (other.name != null)
          return false;
      } else if (!name.equals(other.name))
        return false;
      return true;
    }
   
  }
 
  private static Logger log = LogManager.getLogger(VehicleRoutingAlgorithms.class.getName());
 
  private VehicleRoutingAlgorithms(){}
 
  /**
   * Creates a {@link jsprit.core.algorithm.VehicleRoutingAlgorithm} from a AlgorithConfig based on the input vrp.
   *
   * @param vrp the routing problem
   * @param algorithmConfig the algorithm config
   * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm}
   */
  public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){
    return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0, null);
  }
  public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, int nThreads, final AlgorithmConfig algorithmConfig){
    return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),nThreads, null);
  }
 
  /**
   * Read and creates a {@link VehicleRoutingAlgorithm} from an url.
   *
   * @param vrp the routing problem
   * @param configURL config url
   * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm}
   */
  public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final URL configURL){
    AlgorithmConfig algorithmConfig = new AlgorithmConfig();
    AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
    xmlReader.read(configURL);
    return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0, null);
  }
  public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, int nThreads, final URL configURL){
    AlgorithmConfig algorithmConfig = new AlgorithmConfig();
    AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
    xmlReader.read(configURL);
    return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),nThreads, null);
  }
 
  /**
   * Read and creates {@link jsprit.core.problem.VehicleRoutingProblem} from config-file.
   *
   * @param vrp the routing problem
   * @param configFileName the config filename (and location)
   * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm}
   */
  public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final String configFileName){
    AlgorithmConfig algorithmConfig = new AlgorithmConfig();
    AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
    xmlReader.read(configFileName);
    return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0, null);
  }

  public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final String configFileName, StateManager stateManager){
    AlgorithmConfig algorithmConfig = new AlgorithmConfig();
    AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
    xmlReader.read(configFileName);
    return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0, stateManager);
  }
 
  public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, int nThreads, final String configFileName, StateManager stateManager){
    AlgorithmConfig algorithmConfig = new AlgorithmConfig();
    AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
    xmlReader.read(configFileName);
    return createAlgo(vrp,algorithmConfig.getXMLConfiguration(), nThreads, stateManager);
  }
 
  public static VehicleRoutingAlgorithm readAndCreateAlgorithm(VehicleRoutingProblem vrp, int nThreads, String configFileName) {
    AlgorithmConfig algorithmConfig = new AlgorithmConfig();
    AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
    xmlReader.read(configFileName);
    return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),nThreads, null);
  }
 
  private static class OpenRouteStateVerifier implements StateUpdater, ReverseActivityVisitor{

    private End end;
   
    private boolean firstAct = true;
   
    private Vehicle vehicle;
   
    @Override
    public void begin(VehicleRoute route) {
      end = route.getEnd();
      vehicle = route.getVehicle();
    }

    @Override
    public void visit(TourActivity activity) {
      if(firstAct){
        firstAct=false;
        if(!vehicle.isReturnToDepot()){
          assert activity.getLocationId().equals(end.getLocationId()) : "route end and last activity are not equal even route is open. this should not be.";
        }
      }
     
    }

    @Override
    public void finish() {
      firstAct = true;
    }
   
  }

  private static VehicleRoutingAlgorithm createAlgo(final VehicleRoutingProblem vrp, XMLConfiguration config, int nuOfThreads, StateManager stateMan){
    //create state-manager
    final StateManager stateManager;
    if(stateMan!=null) {
      stateManager = stateMan;
    }
    else{
      stateManager =   new StateManager(vrp);
    }
    stateManager.updateLoadStates();
    stateManager.updateTimeWindowStates();
        stateManager.updateSkillStates();
    stateManager.addStateUpdater(new UpdateEndLocationIfRouteIsOpen());
    stateManager.addStateUpdater(new OpenRouteStateVerifier());
    stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts()));
    stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));

    /*
     * define constraints
     */
    //constraint manager
    ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
    constraintManager.addTimeWindowConstraint();
    constraintManager.addLoadConstraint();
        constraintManager.addSkillsConstraint();
   
    return readAndCreateAlgorithm(vrp, config, nuOfThreads, null, stateManager, constraintManager, true)
  }

  public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, AlgorithmConfig config,
      int nuOfThreads, SolutionCostCalculator solutionCostCalculator, final StateManager stateManager, ConstraintManager constraintManager, boolean addDefaultCostCalculators) {
    return readAndCreateAlgorithm(vrp, config.getXMLConfiguration(),nuOfThreads, solutionCostCalculator, stateManager, constraintManager, addDefaultCostCalculators);
  }
 
  private static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, XMLConfiguration config,
      int nuOfThreads, SolutionCostCalculator solutionCostCalculator, final StateManager stateManager, ConstraintManager constraintManager, boolean addDefaultCostCalculators) {
    // map to store constructed modules
    TypedMap definedClasses = new TypedMap();
   
    // algorithm listeners
    Set<PrioritizedVRAListener> algorithmListeners = new HashSet<PrioritizedVRAListener>();
   
    // insertion listeners
    List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();


    //threading
    final ExecutorService executorService;
    if(nuOfThreads > 0){
      log.info("setup executor-service with " + nuOfThreads + " threads");
      executorService = Executors.newFixedThreadPool(nuOfThreads);
      algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new AlgorithmEndsListener() {

        @Override
        public void informAlgorithmEnds(VehicleRoutingProblem problem,Collection<VehicleRoutingProblemSolution> solutions) {
          log.info("shutdown executor-service");
          executorService.shutdown();
        }
      }));
      Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {

        @Override
        public void uncaughtException(Thread arg0, Throwable arg1) {
          System.err.println(arg1.toString());
          System.exit(0);
        }
      });
      Runtime.getRuntime().addShutdownHook(new Thread(){
        public void run(){
          if(!executorService.isShutdown()){
            System.err.println("shutdowHook shuts down executorService");
            executorService.shutdown();
          }
        }
      });
    }
    else executorService = null;


    //create fleetmanager
    final VehicleFleetManager vehicleFleetManager = createFleetManager(vrp);

        String switchString = config.getString("construction.insertion.allowVehicleSwitch");
        final boolean switchAllowed;
        if(switchString != null){
            switchAllowed = Boolean.parseBoolean(switchString);
        }
        else switchAllowed = true;
        ActivityTimeTracker.ActivityPolicy activityPolicy;
        if(stateManager.timeWindowUpdateIsActivated()){
            UpdateVehicleDependentPracticalTimeWindows timeWindowUpdater = new UpdateVehicleDependentPracticalTimeWindows(stateManager,vrp.getTransportCosts());
            timeWindowUpdater.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() {

                @Override
                public Collection<Vehicle> get(VehicleRoute route) {
                    Collection<Vehicle> vehicles = new ArrayList<Vehicle>();
                    vehicles.add(route.getVehicle());
                    if(switchAllowed) {
                        vehicles.addAll(vehicleFleetManager.getAvailableVehicles(route.getVehicle()));
                    }
                    return vehicles;
                }

            });
            stateManager.addStateUpdater(timeWindowUpdater);
            activityPolicy = ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS;
        }
        else{
            activityPolicy = ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_ARRIVED;
        }
        stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(),activityPolicy));
        stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager, activityPolicy));

    SolutionCostCalculator costCalculator;
    if(solutionCostCalculator==null) costCalculator = getDefaultCostCalculator(stateManager);
    else costCalculator = solutionCostCalculator;
   
    //construct initial solution creator
    AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,costCalculator, constraintManager, addDefaultCostCalculators);
    if(createInitialSolution != null) algorithmListeners.add(new PrioritizedVRAListener(Priority.MEDIUM, createInitialSolution));

    //construct algorithm, i.e. search-strategies and its modules
    int solutionMemory = config.getInt("strategy.memory");
    SearchStrategyManager searchStratManager = new SearchStrategyManager();
    List<HierarchicalConfiguration> strategyConfigs = config.configurationsAt("strategy.searchStrategies.searchStrategy");
    for(HierarchicalConfiguration strategyConfig : strategyConfigs){
      String name = getName(strategyConfig);
      SolutionAcceptor acceptor = getAcceptor(strategyConfig,vrp,algorithmListeners,definedClasses,solutionMemory);
      SolutionSelector selector = getSelector(strategyConfig,vrp,algorithmListeners,definedClasses);
     
      SearchStrategy strategy = new SearchStrategy(selector, acceptor, costCalculator);
      strategy.setName(name);
      List<HierarchicalConfiguration> modulesConfig = strategyConfig.configurationsAt("modules.module");
      for(HierarchicalConfiguration moduleConfig : modulesConfig){
        SearchStrategyModule module = buildModule(moduleConfig,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads, constraintManager, addDefaultCostCalculators);
        strategy.addModule(module);
      }
      searchStratManager.addStrategy(strategy, strategyConfig.getDouble("probability"));
    }
   
    //construct algorithm
    VehicleRoutingAlgorithm metaAlgorithm = new VehicleRoutingAlgorithm(vrp, searchStratManager);
    String maxIterationsString = config.getString("iterations");
        if(maxIterationsString == null) maxIterationsString = config.getString("maxIterations");
        if(maxIterationsString != null) metaAlgorithm.setMaxIterations(Integer.parseInt(maxIterationsString));

    metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager);
    metaAlgorithm.getAlgorithmListeners().addListener(stateManager);
   
    metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager));
    metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
    metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
   
    //define prematureBreak
    PrematureAlgorithmTermination prematureAlgorithmTermination = getPrematureTermination(config, algorithmListeners);
    if(prematureAlgorithmTermination != null) metaAlgorithm.setPrematureAlgorithmTermination(prematureAlgorithmTermination);
        else{
            List<HierarchicalConfiguration> terminationCriteria = config.configurationsAt("terminationCriteria.termination");
            for(HierarchicalConfiguration terminationConfig : terminationCriteria){
                PrematureAlgorithmTermination termination = getTerminationCriterion(terminationConfig, algorithmListeners);
                if(termination != null) metaAlgorithm.addTerminationCriterion(termination);
            }
        }

   
    //misc
//    algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
   
    //register listeners
    registerListeners(metaAlgorithm,algorithmListeners);
    registerInsertionListeners(definedClasses,insertionListeners);
    return metaAlgorithm;
  }

  private static SolutionCostCalculator getDefaultCostCalculator(final StateManager stateManager) {
    return new VariablePlusFixedSolutionCostCalculatorFactory(stateManager).createCalculator();
    }

  private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) {
    if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
      return new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();

    }
    else if(vrp.getFleetSize().equals(FleetSize.FINITE)){
      return new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
    }
    throw new IllegalStateException("fleet size can only be infinite or finite. " +
        "makes sure your config file contains one of these options");
  }

    private static PrematureAlgorithmTermination getTerminationCriterion(HierarchicalConfiguration config, Set<PrioritizedVRAListener> algorithmListeners) {
        String basedOn = config.getString("[@basedOn]");
        if(basedOn == null){
            log.info("set default prematureBreak, i.e. no premature break at all.");
            return null;
        }
        if(basedOn.equals("iterations")){
            log.info("set prematureBreak based on iterations");
            String iter = config.getString("iterations");
            if(iter == null) throw new IllegalStateException("iterations is missing");
            int iterations = Integer.valueOf(iter);
            return new IterationWithoutImprovementTermination(iterations);
        }
        if(basedOn.equals("time")){
            log.info("set prematureBreak based on time");
            String timeString = config.getString("time");
            if(timeString == null) throw new IllegalStateException("time is missing");
            double time = Double.valueOf(timeString);
            TimeTermination timeBreaker = new TimeTermination(time);
            algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, timeBreaker));
            return timeBreaker;
        }
        if(basedOn.equals("variationCoefficient")){
            log.info("set prematureBreak based on variation coefficient");
            String thresholdString = config.getString("threshold");
            String iterationsString = config.getString("iterations");
            if(thresholdString == null) throw new IllegalStateException("threshold is missing");
            if(iterationsString == null) throw new IllegalStateException("iterations is missing");
            double threshold = Double.valueOf(thresholdString);
            int iterations = Integer.valueOf(iterationsString);
            VariationCoefficientTermination variationCoefficientBreaker = new VariationCoefficientTermination(iterations, threshold);
            algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, variationCoefficientBreaker));
            return variationCoefficientBreaker;
        }
        throw new IllegalStateException("prematureBreak basedOn " + basedOn + " is not defined");
    }

  private static PrematureAlgorithmTermination getPrematureTermination(XMLConfiguration config, Set<PrioritizedVRAListener> algorithmListeners) {
    String basedOn = config.getString("prematureBreak[@basedOn]");
    if(basedOn == null){
      log.info("set default prematureBreak, i.e. no premature break at all.");
      return null;
    }
    if(basedOn.equals("iterations")){
      log.info("set prematureBreak based on iterations");
      String iter = config.getString("prematureBreak.iterations");
      if(iter == null) throw new IllegalStateException("prematureBreak.iterations is missing");
      int iterations = Integer.valueOf(iter);
      return new IterationWithoutImprovementTermination(iterations);
    }
    if(basedOn.equals("time")){
      log.info("set prematureBreak based on time");
      String timeString = config.getString("prematureBreak.time");
      if(timeString == null) throw new IllegalStateException("prematureBreak.time is missing");
      double time = Double.valueOf(timeString);
      TimeTermination timeBreaker = new TimeTermination(time);
      algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, timeBreaker));
      return timeBreaker;
    }
    if(basedOn.equals("variationCoefficient")){
      log.info("set prematureBreak based on variation coefficient");
      String thresholdString = config.getString("prematureBreak.threshold");
      String iterationsString = config.getString("prematureBreak.iterations");
      if(thresholdString == null) throw new IllegalStateException("prematureBreak.threshold is missing");
      if(iterationsString == null) throw new IllegalStateException("prematureBreak.iterations is missing");
      double threshold = Double.valueOf(thresholdString);
      int iterations = Integer.valueOf(iterationsString);
      VariationCoefficientTermination variationCoefficientBreaker = new VariationCoefficientTermination(iterations, threshold);
      algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, variationCoefficientBreaker));
      return variationCoefficientBreaker;
    }
    throw new IllegalStateException("prematureBreak basedOn " + basedOn + " is not defined");
  }

  private static void registerInsertionListeners(TypedMap definedClasses, List<InsertionListener> insertionListeners) {
    for(AbstractKey<?> key : definedClasses.keySet()){
      if(key instanceof InsertionStrategyKey){
        InsertionStrategyKey insertionKey = (InsertionStrategyKey) key;
        InsertionStrategy insertionStrategy = definedClasses.get(insertionKey);
        for(InsertionListener l : insertionListeners){
          insertionStrategy.addListener(l);
        }
      }
    }
  }

  private static String getName(HierarchicalConfiguration strategyConfig) {
    if(strategyConfig.containsKey("[@name]")){
      return strategyConfig.getString("[@name]");
    }
    return "";
 

 
  private static void registerListeners(VehicleRoutingAlgorithm metaAlgorithm, Set<PrioritizedVRAListener> algorithmListeners) {
    metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
  }
 
  private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, final SolutionCostCalculator solutionCostCalculator, ConstraintManager constraintManager, boolean addDefaultCostCalculators) {
    List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
    if(modConfigs == null) return null;
    if(modConfigs.isEmpty()) return null;
    if(modConfigs.size() != 1) throw new IllegalStateException("#construction.modules != 1. 1 expected");
    HierarchicalConfiguration modConfig = modConfigs.get(0);
    String insertionName = modConfig.getString("[@name]");
    if(insertionName == null) throw new IllegalStateException("insertion[@name] is missing.");
    String insertionId = modConfig.getString("[@id]");
    if(insertionId == null) insertionId = "noId";
    ModKey modKey = makeKey(insertionName,insertionId);
    InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(modKey);
    InsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
    if(insertionStrategy == null){
      List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
      insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager, addDefaultCostCalculators);
      algorithmListeners.addAll(prioListeners);
      definedClasses.put(insertionStrategyKey,insertionStrategy);
    }
    final InsertionStrategy finalInsertionStrategy = insertionStrategy;

    return new AlgorithmStartsListener() {

      @Override
      public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
        InsertionInitialSolutionFactory insertionInitialSolutionFactory = new InsertionInitialSolutionFactory(finalInsertionStrategy, solutionCostCalculator);
        VehicleRoutingProblemSolution vrpSol = insertionInitialSolutionFactory.createSolution(vrp);
        solutions.add(vrpSol);
      }
    };


  }
 
  private static SolutionSelector getSelector(HierarchicalConfiguration strategyConfig, VehicleRoutingProblem vrp, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedSelectors) {
    String selectorName = strategyConfig.getString("selector[@name]");
    if(selectorName == null) throw new IllegalStateException("no solutionSelector defined. define either \"selectRandomly\" or \"selectBest\"");
    String selectorId = strategyConfig.getString("selector[@id]");
    if(selectorId == null) selectorId="noId";
    ModKey modKey = makeKey(selectorName,selectorId);
    SelectorKey selectorKey = new SelectorKey(modKey);
    SolutionSelector definedSelector = definedSelectors.get(selectorKey);
    if(definedSelector != null) {
      return definedSelector;
    }
    if(selectorName.equals("selectRandomly")){
      SelectRandomly selector = SelectRandomly.getInstance();
      definedSelectors.put(selectorKey, selector);
      return selector;
    }
    if(selectorName.equals("selectBest")){
      SelectBest selector = SelectBest.getInstance();
      definedSelectors.put(selectorKey, selector);
      return selector;
    }
    throw new IllegalStateException("solutionSelector is not know. Currently, it only knows \"selectRandomly\" and \"selectBest\"");
  }
 
  private static ModKey makeKey(String name, String id){
    return new ModKey(name, id);
  }
 
  private static SolutionAcceptor getAcceptor(HierarchicalConfiguration strategyConfig, VehicleRoutingProblem vrp, Set<PrioritizedVRAListener> algorithmListeners, TypedMap typedMap, int solutionMemory) {
    String acceptorName = strategyConfig.getString("acceptor[@name]");
    if(acceptorName == null) throw new IllegalStateException("no solution acceptor is defined");
    String acceptorId = strategyConfig.getString("acceptor[@id]");
    if(acceptorId == null) acceptorId = "noId";
    AcceptorKey acceptorKey = new AcceptorKey(makeKey(acceptorName,acceptorId));
    SolutionAcceptor definedAcceptor = typedMap.get(acceptorKey);
    if(definedAcceptor != null) return definedAcceptor;
    if(acceptorName.equals("acceptNewRemoveWorst")){
      GreedyAcceptance acceptor = new GreedyAcceptance(solutionMemory);
      typedMap.put(acceptorKey, acceptor);
      return acceptor;
    }
    if(acceptorName.equals("acceptNewRemoveFirst")){
      AcceptNewRemoveFirst acceptor = new AcceptNewRemoveFirst(solutionMemory);
      typedMap.put(acceptorKey, acceptor);
      return acceptor;
    }
    if(acceptorName.equals("greedyAcceptance")){
      GreedyAcceptance acceptor = new GreedyAcceptance(solutionMemory);
      typedMap.put(acceptorKey, acceptor);
      return acceptor;
    }
    if(acceptorName.equals("greedyAcceptance_minVehFirst")){
      GreedyAcceptance_minVehFirst acceptor = new GreedyAcceptance_minVehFirst(solutionMemory);
      typedMap.put(acceptorKey, acceptor);
      return acceptor;
    }
    if(acceptorName.equals("schrimpfAcceptance")){
      String nuWarmupIterations = strategyConfig.getString("acceptor.warmup");
      double alpha = strategyConfig.getDouble("acceptor.alpha");
      SchrimpfAcceptance schrimpf = new SchrimpfAcceptance(solutionMemory, alpha);
      if(nuWarmupIterations!=null){
        SchrimpfInitialThresholdGenerator iniThresholdGenerator = new SchrimpfInitialThresholdGenerator(schrimpf, Integer.parseInt(nuWarmupIterations));
        algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, iniThresholdGenerator));
      }
      else{
        double threshold = strategyConfig.getDouble("acceptor.initialThreshold");
        schrimpf.setInitialThreshold(threshold);
      }
      algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, schrimpf));
      typedMap.put(acceptorKey, schrimpf);
      return schrimpf;
    }
    if(acceptorName.equals("experimentalSchrimpfAcceptance")){
      int iterOfSchrimpf = strategyConfig.getInt("acceptor.warmup");
      double alpha = strategyConfig.getDouble("acceptor.alpha");
      ExperimentalSchrimpfAcceptance schrimpf = new ExperimentalSchrimpfAcceptance(solutionMemory, alpha, iterOfSchrimpf);
      algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, schrimpf));
      typedMap.put(acceptorKey, schrimpf);
      return schrimpf;
    }
    else{
      throw new IllegalStateException("solution acceptor " + acceptorName + " is not known");
    }
  }
 
  private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
      final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager, boolean addDefaultCostCalculators) {
    String moduleName = moduleConfig.getString("[@name]");
    if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
    String moduleId = moduleConfig.getString("[@id]");
    if(moduleId == null) moduleId = "noId";
    ModKey modKey = makeKey(moduleName,moduleId);
    StrategyModuleKey strategyModuleKey = new StrategyModuleKey(modKey);
    SearchStrategyModule definedModule = definedClasses.get(strategyModuleKey);
    if(definedModule != null) return definedModule;
   
    if(moduleName.equals("ruin_and_recreate")){
      String ruin_name = moduleConfig.getString("ruin[@name]");
      if(ruin_name == null) throw new IllegalStateException("module.ruin[@name] is missing.");
      String ruin_id = moduleConfig.getString("ruin[@id]");
      if(ruin_id == null) ruin_id = "noId";
      String shareToRuinString = moduleConfig.getString("ruin.share");
      if(shareToRuinString == null) throw new IllegalStateException("module.ruin.share is missing.");
      double shareToRuin = Double.valueOf(shareToRuinString);
      final RuinStrategy ruin;
      ModKey ruinKey = makeKey(ruin_name,ruin_id);
      if(ruin_name.equals("randomRuin")){
        ruin = getRandomRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin);
      }
      else if(ruin_name.equals("radialRuin")){
        JobDistance jobDistance = new AvgServiceAndShipmentDistance(vrp.getTransportCosts());
        ruin = getRadialRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin, jobDistance);
      }
      else throw new IllegalStateException("ruin[@name] " + ruin_name + " is not known. Use either randomRuin or radialRuin.");
     
      String insertionName = moduleConfig.getString("insertion[@name]");
      if(insertionName == null) throw new IllegalStateException("module.insertion[@name] is missing. set it to \"regretInsertion\" or \"bestInsertion\"");
      String insertionId = moduleConfig.getString("insertion[@id]");
      if(insertionId == null) insertionId = "noId";
      ModKey insertionKey = makeKey(insertionName,insertionId);
      InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
      InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
      if(insertion == null){
        List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
        if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
        List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
        insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager, addDefaultCostCalculators);
        algorithmListeners.addAll(prioListeners);
      }
      final InsertionStrategy final_insertion = insertion;
   
      RuinAndRecreateModule rrModule =  new RuinAndRecreateModule("ruin_and_recreate", final_insertion, ruin);
      return rrModule;
    }
    throw new NullPointerException("no module found with moduleName=" + moduleName +
        "\n\tcheck config whether the correct names are used" +
        "\n\tcurrently there are following modules available: " +
        "\n\tbestInsertion" +
        "\n\trandomRuin" +
        "\n\tradialRuin");
  }

  private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
    RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
    RuinStrategy ruin = definedClasses.get(stratKey);
    if(ruin == null){
      ruin = new RadialRuinStrategyFactory(shareToRuin, jobDistance).createStrategy(vrp);
      definedClasses.put(stratKey, ruin);
    }
    return ruin;
  }

  private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
    RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
    RuinStrategy ruin = definedClasses.get(stratKey);
    if(ruin == null){
      ruin = new RandomRuinStrategyFactory(shareToRuin).createStrategy(vrp);
      definedClasses.put(stratKey, ruin);
    }
    return ruin;
  }
 
  private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManager routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager, boolean addDefaultCostCalculators) {
    return InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads, constraintManager, addDefaultCostCalculators);
  }

 
 

}
TOP

Related Classes of jsprit.core.algorithm.io.VehicleRoutingAlgorithms$TypedMap$StrategyModuleKey

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.