/** * */ package vroom.trsp.util; import gurobi.GRB; import umontreal.iro.lecuyer.rng.MRG32k3a; import umontreal.iro.lecuyer.rng.RandomStream; import vroom.common.heuristics.alns.ALNSComponentHandler; import vroom.common.heuristics.alns.IPALNSSolutionPool; import vroom.common.heuristics.alns.SimpleSolutionPool; import vroom.common.utilities.IDistance; import vroom.common.utilities.Utilities.Math.DeviationMeasure; import vroom.common.utilities.optimization.IComponentHandler; import vroom.common.utilities.params.ClassParameterKey; import vroom.common.utilities.params.GlobalParameters; import vroom.common.utilities.params.ParameterKey; import vroom.common.utilities.params.ParameterKey.BooleanParameterKey; import vroom.common.utilities.params.ParameterKey.DoubleParameterKey; import vroom.common.utilities.params.ParameterKey.IntegerParameterKey; import vroom.common.utilities.params.ParameterKey.StringParameterKey; import vroom.common.utilities.params.RequiredParameter; import vroom.common.utilities.ssj.IRandomSource; import vroom.trsp.TRSPSolver; import vroom.trsp.datamodel.ITRSPSolutionHasher; import vroom.trsp.datamodel.NodeSetSolutionHasher; import vroom.trsp.datamodel.TRSPInstance; import vroom.trsp.datamodel.TRSPSolution; import vroom.trsp.datamodel.costDelegates.TRSPCostDelegate; import vroom.trsp.datamodel.costDelegates.TRSPLevenshteinDistance; import vroom.trsp.datamodel.costDelegates.TRSPTourBalance; import vroom.trsp.datamodel.costDelegates.TRSPWorkingTime; import vroom.trsp.optimization.biobj.HierarchicalParetoSelector; import vroom.trsp.optimization.constructive.TRSPConstructiveHeuristic; /** * <code>TRSPGlobalParameters</code> is a containing class to store the values of the the TRSP algorithm * <p> * Creation date: May 19, 2011 - 10:51:00 AM * * @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a * href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a * href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a> * @version 1.0 */ public class TRSPGlobalParameters extends GlobalParameters implements IRandomSource { // Adaptive destroy/repair selection /** * The length <em>l</em> of a segment (in number of iterations) in the adaptive process */ public static final IntegerParameterKey ALNS_A_L = new IntegerParameterKey( "ALNS_A_L", 100); /** The reaction factor <em>r</em> */ public static final DoubleParameterKey ALNS_A_R = new DoubleParameterKey( "ALNS_A_R", 0.1); /** Value for σ<sub>1</sub>, the score increment for new best solution */ public static final DoubleParameterKey ALNS_A_SIGMA1 = new DoubleParameterKey( "ALNS_A_SIGMA1", 33d); /** * Value for σ<sub>2</sub>, the score increment for improving new current solution */ public static final DoubleParameterKey ALNS_A_SIGMA2 = new DoubleParameterKey( "ALNS_A_SIGMA2", 9d); /** * Value for σ<sub>3</sub>, the score increment for non-improving new current solution */ public static final DoubleParameterKey ALNS_A_SIGMA3 = new DoubleParameterKey( "ALNS_A_SIGMA3", 13d); @SuppressWarnings("rawtypes") public static final ClassParameterKey<IComponentHandler> ALNS_COMP_HANDLER = new ClassParameterKey<IComponentHandler>( "ALNS_COMP_HANDLER", IComponentHandler.class, ALNSComponentHandler.class); // Cost delegates /** The cost delegate used in the ALNS procedure */ public static final ClassParameterKey<TRSPCostDelegate> ALNS_COST_DELEGATE = new ClassParameterKey<TRSPCostDelegate>( "ALNS_COST_DELEGATE", TRSPCostDelegate.class, TRSPWorkingTime.class); // Destroy operators /** * The randomness parameter <em>p</em> of destroy procedures (p ≥ 1, the lower p, the more randomness is introduced) */ public static final DoubleParameterKey ALNS_DES_P = new DoubleParameterKey( "ALNS_DES_P", 8d); // Repair operators /** * The noise switch <em>η</em> for repair operators */ public static final BooleanParameterKey ALNS_REP_NOISE = new BooleanParameterKey( "ALNS_REP_NOISE", Boolean.TRUE); /** * The noise parameter <em>η</em> for repair operators */ public static final DoubleParameterKey ALNS_REP_ETA = new DoubleParameterKey( "ALNS_REP_ETA", 0.025d); @RequiredParameter /** The maximum number of iterations*/ public static final IntegerParameterKey ALNS_MAX_IT = new IntegerParameterKey( "ALNS_MAX_IT" ); @RequiredParameter /** The maximum time allowed for the ALNS to finish*/ public static final IntegerParameterKey ALNS_MAX_TIME = new IntegerParameterKey( "ALNS_MAX_TIME"); // Objective function /** * The penalty for unserved request in the objective function, expressed as the proportion of the initial solution * cost */ public static final DoubleParameterKey ALNS_OBJ_GAMMA = new DoubleParameterKey( "ALNS_OBJ_GAMMA", 1.0d); /** The number of iterations to be performed in parallel */ public static final IntegerParameterKey ALNS_PALNS_IT_P = new IntegerParameterKey( "ALNS_PALNS_IT_P"); // Main parameters /** The type of {@linkplain IPALNSSolutionPool solution pool} */ @SuppressWarnings("rawtypes") public static final ClassParameterKey<IPALNSSolutionPool> ALNS_PALNS_POOL = new ClassParameterKey<IPALNSSolutionPool>( "ALNS_PALNS_POOL", IPALNSSolutionPool.class, SimpleSolutionPool.class); /** {@code true} iif the diversified solution pool should auto-adjust its weights */ public static final BooleanParameterKey ALNS_PALNS_DIV_AUTOADJUST = new BooleanParameterKey( "ALNS_PALNS_DIV_AUTOADJUST", Boolean.TRUE); /** The type of {@linkplain IDistance diversity metric} */ @SuppressWarnings("rawtypes") public static final ClassParameterKey<IDistance> ALNS_PALNS_DIV_METRIC = new ClassParameterKey<IDistance>( "ALNS_PALNS_DIV_METRIC", IDistance.class, TRSPLevenshteinDistance.class); /** The size of the PALNS pool */ public static final IntegerParameterKey ALNS_PALNS_POOL_SIZE = new IntegerParameterKey( "ALNS_PALNS_POOL_SIZE", 10); /** {@code true} iif the parallel version of the ALNS should be used */ public static final BooleanParameterKey ALNS_PARALLEL = new BooleanParameterKey( "ALNS_PARALLEL", Boolean.TRUE); /** * Fraction of the initial temperature to be reached at the termination of the method (default 0.002 for 0.2%) */ public static final DoubleParameterKey ALNS_SA_ALPHA = new DoubleParameterKey( "ALNS_SA_ALPHA", 0.002); /** * Initial probability of accepting a solution representing a degradation of {@linkplain #ALNS_SA_W <em>w</em>} * (default 0.5) */ public static final DoubleParameterKey ALNS_SA_P = new DoubleParameterKey( "ALNS_SA_P", 0.5); /** * Reference degradation <em>w</em> for the determination of the start temperature (default 0.05) */ public static final DoubleParameterKey ALNS_SA_W = new DoubleParameterKey( "ALNS_SA_W", 0.05); // Simulated annealing /** Minimum proportion ξ<sub>min</sub> of requests to be removed at each destroy */ public static final DoubleParameterKey ALNS_XI_MIN = new DoubleParameterKey( "ALNS_XI_MIN", 0.1); /** Maximum proportion ξ<sub>max</sub> of requests to be removed at each destroy */ public static final DoubleParameterKey ALNS_XI_MAX = new DoubleParameterKey( "ALNS_XI_MAX", 0.4); /** A flag use to enable the logging of each temporary solution */ public static final BooleanParameterKey ALNS_ENABLE_LOGGING = new BooleanParameterKey( "ALNS_ENABLE_LOGGING", Boolean.FALSE); /** The cost delegate used in the ALNS procedure */ public static final ParameterKey<DeviationMeasure> BALANCE_COST_DELEGATE_MEASURE = new ParameterKey<DeviationMeasure>( "BALANCE_COST_DELEGATE_MEASURE", DeviationMeasure.class, DeviationMeasure.MaxMinGap); /** The cost delegate used in the ALNS procedure */ public static final DoubleParameterKey BALANCE_COST_DELEGATE_PENALTY = new DoubleParameterKey( "BALANCE_COST_DELEGATE_PENALTY", 1d); /** * The {@linkplain HierarchicalParetoSelector#getAllowedDegradation() allowed degradation} for solution selection */ public static final DoubleParameterKey BIOBJ_ALLOWED_DEG = new DoubleParameterKey( "BIOBJ_ALLOWED_DEG", 1.0d); /** * {@code true} if LS should be enabled for bi-objective variant */ public static final BooleanParameterKey BIOBJ_ENABLE_LS = new BooleanParameterKey( "BIOBJ_ENABLE_LS", Boolean.TRUE); /** * {@code true} the problem is a bi-objective variant */ public static final BooleanParameterKey BIOBJ_ENABLE_PR = new BooleanParameterKey( "BIOBJ_ENABLE_PR", Boolean.TRUE); /** * A flag set to {@code true} if the initial solution should be used as reference solution in biobjective setting, * {@code false} if the previous solution should be used */ public static final BooleanParameterKey BIOBJ_INIT_AS_REF = new BooleanParameterKey( "BIOBJ_INIT_AS_REF", Boolean.TRUE); public static final boolean CTR_CHK_FWD_FEAS = true; /** The cost delegate used in the initialization phase */ public static final ClassParameterKey<TRSPCostDelegate> INIT_COST_DELEGATE = new ClassParameterKey<TRSPCostDelegate>( "INIT_COST_DELEGATE", TRSPCostDelegate.class, TRSPTourBalance.class); /** The cost delegate used in the randomized heuristic solver procedure */ public static final ClassParameterKey<TRSPCostDelegate> RCH_COST_DELEGATE = new ClassParameterKey<TRSPCostDelegate>( "RCH_COST_DELEGATE", TRSPCostDelegate.class, TRSPWorkingTime.class); /** * The type of heuristic used for RCH: {@code true} to use giant tours and split, {@code false} to generate only * feasible tours */ public static final BooleanParameterKey RCH_GIANT_SPLIT = new BooleanParameterKey( "RCH_GIANT_SPLIT", Boolean.TRUE); /** * {@code true} if TW feasibility should be checked when building a giant tour */ public static final BooleanParameterKey RCH_GIANT_TW_CHECK = new BooleanParameterKey( "RCH_GIANT_TW_CHECK", Boolean.TRUE); /** * A list of the constructive heuristics to be used, with the randomization parameter in parenthesis (e.g., * RNN(6),RNI(3)) */ @RequiredParameter public static final StringParameterKey RCH_HEURISTICS = new StringParameterKey( "RCH_HEURISTICS"); @RequiredParameter /** * The number of tour generation iterations of the randomized constructive heuristic solver. */ public static final IntegerParameterKey RCH_MAX_IT = new IntegerParameterKey( "RCH_MAX_IT" ); /** The solution hasher used in the randomized constructive heuristic solver */ public static final ClassParameterKey<ITRSPSolutionHasher> RCH_POOL_HASHER = new ClassParameterKey<ITRSPSolutionHasher>( "RCH_POOL_HASHER", ITRSPSolutionHasher.class, NodeSetSolutionHasher.class); /** * The randomization factor of the randomized constructive heuristics, between 1 (high randomness) and +infty (no * randomness) (default: 5) */ public static final DoubleParameterKey RCH_RND_FACTOR = new DoubleParameterKey( "RCH_RND_FACTOR", 5d); /** * {@code true} if PR should be enabled for bi-objective variant */ public static final BooleanParameterKey RUN_BIOBJ = new BooleanParameterKey( "RUN_BIOBJ", Boolean.FALSE); /** The path to the file containing the best known solutions */ @RequiredParameter public static final StringParameterKey RUN_BKS_FILE = new StringParameterKey( "RUN_BKS_FILE"); @RequiredParameter /** The type of instances: <code>true</code> for instances of the sCVRPTW, * <code>false</code> for instances of the TRSP (default: <code>false</code>)*/ public static final BooleanParameterKey RUN_CVRPTW = new BooleanParameterKey( "RUN_CVRPTW", Boolean.FALSE); /** A flag to force the definition of the fwd slack time in TRSPSolution even if {@code RUN_CVRPTW=true} */ public static final BooleanParameterKey FORCE_FWD_SLK = new BooleanParameterKey( "FORCE_FWD_SLK", Boolean.FALSE); /** * <code>true</code> to ensure the reproducibility of runs, <code>false</code> to improve performance */ @RequiredParameter public static final BooleanParameterKey RUN_ENSURE_REP = new BooleanParameterKey( "RUN_ENSURE_REP", Boolean.TRUE); /** The file pattern of the files containing instances to be run */ @RequiredParameter public static final StringParameterKey RUN_FILE_PATTERN = new StringParameterKey( "RUN_FILE_PATTERN", "R?C?\\d+.100_\\d+\\-\\d+\\-\\d+\\-\\d+.txt"); /** The folder containing instances to be run */ @RequiredParameter public static final StringParameterKey RUN_INSTANCE_FOLDER = new StringParameterKey( "RUN_INSTANCE_FOLDER"); /** The number of replicas for each instance */ @RequiredParameter public static final IntegerParameterKey RUN_NUM_REPLICAS = new IntegerParameterKey( "RUN_NUM_REPLICAS", 1); /** The folder containing the dynamic info of instances to be run */ public static final StringParameterKey RUN_REL_DATE_FOLDER = new StringParameterKey( "RUN_REL_DATE_FOLDER"); /** The degrees of dynamism accepted */ public static final ParameterKey<int[]> RUN_DODS = new ParameterKey<int[]>( "RUN_DODS", int[].class); /** The seeds for the run */ @RequiredParameter public static final ParameterKey<long[]> RUN_SEEDS = new ParameterKey<long[]>( "RUN_SEEDS", long[].class); /** The run class that will be used */ public static final ClassParameterKey<?> RUN_CLASS = new ClassParameterKey<>( "RUN_CLASS", Object.class); /** The solver that will be used in this run */ public static final ClassParameterKey<TRSPSolver> RUN_SOLVER = new ClassParameterKey<TRSPSolver>( "RUN_SOLVER", TRSPSolver.class); /** {@code true} if only the regret repair should be used to solve time slices */ public static final BooleanParameterKey RUN_REGRET_ONLY = new BooleanParameterKey( "RUN_REGRET_ONLY", false); /** The constructive heuristic that will be used in this run */ public static final ClassParameterKey<TRSPConstructiveHeuristic> RUN_INIT_HEUR = new ClassParameterKey<TRSPConstructiveHeuristic>( "RUN_INIT_HEUR", TRSPConstructiveHeuristic.class); /** The number of parallels runs */ @RequiredParameter public static final IntegerParameterKey RUN_THREADS = new IntegerParameterKey( "RUN_THREADS", 1); /** The speed of the simulation ({@code simTime = wallTime * speed} ) */ @RequiredParameter public static final DoubleParameterKey RUN_SIM_SPEED = new DoubleParameterKey( "RUN_SIM_SPEED", 1d); /** * The base duration of the simulation with 100% dynamic requests (overrides {@link #RUN_SIM_SPEED}) */ public static final DoubleParameterKey RUN_SIM_DURATION = new DoubleParameterKey( "RUN_SIM_DURATION"); /** A value between 0 and 1 indicating until which time of the horizon the algorithm should expect new requests */ @RequiredParameter public static final DoubleParameterKey RUN_CUTOFF_TIME = new DoubleParameterKey( "RUN_CUTOFF_TIME", 1d); /** * <code>true</code> to enable the writing of the mathematical model to a file */ @RequiredParameter public static final BooleanParameterKey RUN_WRITE_LP = new BooleanParameterKey( "RUN_WRITE_LP", Boolean.FALSE); /** * <code>true</code> to enable the debug mode */ public static final BooleanParameterKey RUN_DEBUG = new BooleanParameterKey( "RUN_DEBUG", Boolean.FALSE); // Cost delegates /** The cost delegate used in the ALNS procedure */ public static final ClassParameterKey<TRSPCostDelegate> SC_COST_DELEGATE = new ClassParameterKey<TRSPCostDelegate>( "SC_COST_DELEGATE", TRSPCostDelegate.class, TRSPWorkingTime.class); /** Enable/Disable the set covering post-optimization */ public static final BooleanParameterKey SC_ENABLED = new BooleanParameterKey( "SC_ENABLED", Boolean.TRUE); /** Enable/Disable the set covering post-optimization */ public static final BooleanParameterKey TOUR_POOL_ENABLED = new BooleanParameterKey( "TOUR_POOL_ENABLED", Boolean.FALSE); @RequiredParameter /** The type of subproblem to solve: <code>true</code> for set partitioning, <code>false</code> for set covering (default)*/ public static final BooleanParameterKey SC_FORCE_EQUAL = new BooleanParameterKey( "SC_FORCE_EQUAL", Boolean.FALSE); @RequiredParameter /** The path of the file containing the values for the GRBEnv*/ public static final StringParameterKey SC_GRBENV_FILE = new StringParameterKey( "SC_GRBENV_FILE", "dafaults_grb.env"); @RequiredParameter /** The maximum time allowed for the post optimization to finish (in seconds)*/ public static final DoubleParameterKey SC_MAX_TIME = new DoubleParameterKey( "SC_MAX_TIME", GRB.INFINITY); /** The path of the file containing the MPA parameters */ public static final StringParameterKey MPA_CONFIG_FILE = new StringParameterKey( "MPA_CONFIG_FILE"); ; @RequiredParameter /** The number of Threads to use for parallelization*/ public static final IntegerParameterKey THREAD_COUNT = new IntegerParameterKey( "THREAD_COUNT", Runtime.getRuntime() .availableProcessors()); /** The path of a file that contains the experimental setting */ public static final StringParameterKey EXPE_CONFIG_FILE = new StringParameterKey( "EXPE_CONFIG_FILE"); private RandomStream mALNSRndStream; private RandomStream mInitRndStream; private RandomStream mHashRndStream; private RandomStream mMainRndStream; private RandomStream mRCHRndStream; @Override public TRSPGlobalParameters clone() { return (TRSPGlobalParameters) super.clone(); } /** * Returns the random stream used in the initialization procedure * * @return the random stream used in the initialization procedure */ public RandomStream getInitRndStream() { initRndStreams(); return mInitRndStream; } /** * Returns the random stream used in the ALNS procedure * * @return the random stream used in the ALNS procedure */ public RandomStream getALNSRndStream() { initRndStreams(); return mALNSRndStream; } /** * Returns the random stream used in the hashing procedure * * @return the random stream used in the hashing procedure */ public RandomStream getHashRndStream() { initRndStreams(); return mHashRndStream; } @Override public RandomStream getRandomStream() { initRndStreams(); return mMainRndStream; } /** * Returns the random stream used in the RCH procedure * * @return the random stream used in the RCH procedure */ public RandomStream getRCHRndStream() { initRndStreams(); return mRCHRndStream; } /** * Returns the number of threads to be used * <p> * This method returns the minimum between the number of available processors and the {@link #THREAD_COUNT} value * </p> * * @return the number of threads to be used */ public int getThreadCount() { return get(THREAD_COUNT); } /** * Returns the simulation speed depending on the degree of dynamism and the length of the planning horizon * * @param instance * @return the simulation speed */ public double getSimSpeed(TRSPInstance instance) { if (isSet(RUN_SIM_DURATION)) { double horiz = instance.getMainDepot().getTimeWindow().width(); double dod = instance.getDod(); double dur = get(RUN_SIM_DURATION); return (horiz / dur) / dod; } else { return get(RUN_SIM_SPEED); } } private void initRndStreams() { if (mMainRndStream == null) { mMainRndStream = new MRG32k3a("TRSP_Main"); ((MRG32k3a) mMainRndStream).setSeed(get(RUN_SEEDS)); mInitRndStream = new MRG32k3a("TRSP_ALNS"); ((MRG32k3a) mInitRndStream).setSeed(get(RUN_SEEDS)); mALNSRndStream = new MRG32k3a("TRSP_ALNS"); ((MRG32k3a) mALNSRndStream).setSeed(get(RUN_SEEDS)); mRCHRndStream = new MRG32k3a("TRSP_RCH"); ((MRG32k3a) mRCHRndStream).setSeed(get(RUN_SEEDS)); mHashRndStream = new MRG32k3a("TRSP_Hash"); ((MRG32k3a) mHashRndStream).setSeed(get(RUN_SEEDS)); } }; /** * Returns {@code true} if the problem at hand is bi-objective, {@code false} otherwise * * @return {@code true} if the problem at hand is bi-objective, {@code false} otherwise */ public boolean isBiObjective() { return get(RUN_BIOBJ); } /** * Returns <code>true</code> if instances that will be solved in this VM are instances of the sCVRPTW, * <code>false</code> if they are instances of the TRSP * * @return <code>true</code> if instances that will be solved in this VM are instances of the sCVRPTW, * <code>false</code> if they are instances of the TRSP */ public boolean isCVRPTW() { return get(RUN_CVRPTW); } /** * Returns {@code true} if the problem at hand is dynamic, {@code false} otherwise * * @return {@code true} if the problem at hand is dynamic, {@code false} otherwise */ public boolean isDynamic() { return isSet(RUN_REL_DATE_FOLDER); } /** * Instantiate a new cost delegate for the ALNS of the type defined by {@link #ALNS_COST_DELEGATE} * * @param initialSolution * the initial solution of the ALNS * @return a new ALNS cost delegate * @see #ALNS_COST_DELEGATE */ public TRSPCostDelegate newALNSCostDelegate(TRSPSolution initialSolution) { Object[] args = new Object[0]; Class<?>[] classes = new Class<?>[0]; Class<?> clazz = get(ALNS_COST_DELEGATE); if (TRSPTourBalance.class == clazz) { return new TRSPTourBalance(initialSolution.getCostDelegate(), get(BALANCE_COST_DELEGATE_MEASURE), get(BALANCE_COST_DELEGATE_PENALTY)); } else { return newInstanceSafe(ALNS_COST_DELEGATE, classes, args); } } /** * Instantiate a new cost delegate for the initialization of the type defined by {@link #INIT_COST_DELEGATE} * * @return a new ALNS cost delegate * @see #INIT_COST_DELEGATE */ public TRSPCostDelegate newInitCostDelegate() { return newInstance(INIT_COST_DELEGATE); } /** * Instantiate a new cost delegate for the set covering of the type defined by {@link #SC_COST_DELEGATE} * * @return a new ALNS cost delegate * @see #SC_COST_DELEGATE */ public TRSPCostDelegate newSCCostDelegate() { return newInstance(SC_COST_DELEGATE); } @Override public <T> T set(vroom.common.utilities.params.ParameterKey<? super T> key, T value) { if (key == RUN_SEEDS && mMainRndStream != null) throw new IllegalStateException( "Cannot set the RUN_SEEDS once the random stream has been initialized"); return super.set(key, value); } @Override public Object setNoCheck(ParameterKey<?> key, Object value) { return super.setNoCheck(key, value); } @Override public void setRandomStream(RandomStream stream) { throw new UnsupportedOperationException("Cannot set the base random stream"); } }