From f27bab283008c06667d440161bbfcd5a4a3eed43 Mon Sep 17 00:00:00 2001 From: tweise Date: Sun, 26 Apr 2020 08:20:08 +0800 Subject: [PATCH] fixed UMDA for JSSP --- README.md | 4 +- pom.xml | 2 +- .../examples/jssp/EJSSPExperimentStage.java | 70 ++- .../examples/jssp/JSSPExperimentOld.java | 479 ------------------ .../aitoa/examples/jssp/JSSPSpreadModel.java | 125 ----- .../aitoa/examples/jssp/JSSPUMDAModel.java | 56 +- .../jssp/TestHybridFFAUMDAOnJSSP11.java | 2 +- .../algorithms/jssp/TestHybridUMDAOnJSSP.java | 2 +- .../jssp/TestHybridUMDAOnJSSP10.java | 2 +- .../aitoa/algorithms/jssp/TestUMDAOnJSSP.java | 3 +- .../jssp/TestUMDAWithFitnessOnJSSP.java | 2 +- .../jssp/TestUMDAWithFitnessOnJSSP2.java | 2 +- .../examples/jssp/TestJSSPSpreadModel.java | 48 -- .../examples/jssp/TestJSSPUMDAModel.java | 8 +- 14 files changed, 114 insertions(+), 691 deletions(-) delete mode 100644 src/main/java/aitoa/examples/jssp/JSSPExperimentOld.java delete mode 100644 src/main/java/aitoa/examples/jssp/JSSPSpreadModel.java delete mode 100644 src/test/java/aitoa/examples/jssp/TestJSSPSpreadModel.java diff --git a/README.md b/README.md index 075a40f..47c63fb 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ First, you need to add the following repository, which is a repository that can ``` Than you can add the dependency on our `aitoa-code` repository into your `dependencies` section. -Here, `0.8.53` is the current version of `aitoa-code`. +Here, `0.8.54` is the current version of `aitoa-code`. Notice that you may have more dependencies in your `dependencies` section, say on `junit`, but here I just put the one for `aitoa-code` as example. ```xml @@ -52,7 +52,7 @@ Notice that you may have more dependencies in your `dependencies` section, say o com.github.thomasWeise aitoa-code - 0.8.53 + 0.8.54 ``` diff --git a/pom.xml b/pom.xml index 57d3d03..a19656f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ aitoa aitoa-code - 0.8.53 + 0.8.54 jar aitoa-code Example Source Codes from the Book "Introduction to Optimization Algorithms" diff --git a/src/main/java/aitoa/examples/jssp/EJSSPExperimentStage.java b/src/main/java/aitoa/examples/jssp/EJSSPExperimentStage.java index 9ad7074..b111428 100644 --- a/src/main/java/aitoa/examples/jssp/EJSSPExperimentStage.java +++ b/src/main/java/aitoa/examples/jssp/EJSSPExperimentStage.java @@ -14,6 +14,7 @@ import aitoa.algorithms.HillClimber2; import aitoa.algorithms.HillClimber2WithRestarts; import aitoa.algorithms.HillClimberWithRestarts; +import aitoa.algorithms.HybridEDA; import aitoa.algorithms.MA; import aitoa.algorithms.MAWithClearing; import aitoa.algorithms.RandomSampling; @@ -508,19 +509,68 @@ public void configureBuilderForProblem( IMetaheuristic>> getAlgorithms(// final JSSPMakespanObjectiveFunction problem) { + final ArrayList>> list = new ArrayList<>(); - for (int i = 10; i <= 16; i++) { - final int lambda = (1 << i); - for (int j = 6; j <= 8; j++) { - final int mu = lambda / (1 << j); - list.add(() -> new EDA<>(mu, lambda, // - new JSSPUMDAModel(problem.instance))); - list.add(() -> new EDA<>(mu, lambda, // - new JSSPSpreadModel(problem.instance, 16))); - } - } + + list.add(() -> new EDA<>(1, 1 << 5, // + new JSSPUMDAModel(problem.instance, 64L))); + list.add(() -> new EDA<>(2, 1 << 5, // + new JSSPUMDAModel(problem.instance, 32L))); + + list.add(() -> new EDA<>(1, 1 << 10, // + new JSSPUMDAModel(problem.instance, 64L))); + list.add(() -> new EDA<>(2, 1 << 10, // + new JSSPUMDAModel(problem.instance, 32L))); + + list.add(() -> new EDA<>(1, 1 << 15, // + new JSSPUMDAModel(problem.instance, 64L))); + list.add(() -> new EDA<>(2, 1 << 15, // + new JSSPUMDAModel(problem.instance, 32L))); + + return list.stream(); + } + }, + + /** + * the twelfth stage: estimation of distribution algorithm with + * local search + */ + STAGE_12 { + + /** + * Get a stream of algorithm suppliers for a given problem + * + * @param problem + * the problem + * @return the stream of suppliers + */ + @Override + public + Stream>> + getAlgorithms(// + final JSSPMakespanObjectiveFunction problem) { + + final ArrayList>> list = + new ArrayList<>(); + + list.add(() -> new HybridEDA<>(1, 16, Integer.MAX_VALUE, // + new JSSPUMDAModel(problem.instance, 64L))); + list.add(() -> new HybridEDA<>(2, 16, Integer.MAX_VALUE, // + new JSSPUMDAModel(problem.instance, 32L))); + list.add(() -> new HybridEDA<>(4, 16, Integer.MAX_VALUE, // + new JSSPUMDAModel(problem.instance, 16L))); + + list.add(() -> new HybridEDA<>(1, 32, Integer.MAX_VALUE, // + new JSSPUMDAModel(problem.instance, 64L))); + list.add(() -> new HybridEDA<>(2, 32, Integer.MAX_VALUE, // + new JSSPUMDAModel(problem.instance, 32L))); + list.add(() -> new HybridEDA<>(4, 32, Integer.MAX_VALUE, // + new JSSPUMDAModel(problem.instance, 16L))); + return list.stream(); } }; diff --git a/src/main/java/aitoa/examples/jssp/JSSPExperimentOld.java b/src/main/java/aitoa/examples/jssp/JSSPExperimentOld.java deleted file mode 100644 index 900c3da..0000000 --- a/src/main/java/aitoa/examples/jssp/JSSPExperimentOld.java +++ /dev/null @@ -1,479 +0,0 @@ -package aitoa.examples.jssp; - -import java.io.IOException; -import java.nio.file.Path; - -import aitoa.algorithms.EA; -import aitoa.algorithms.EAWithClearing; -import aitoa.algorithms.EAWithFitness; -import aitoa.algorithms.EDA; -import aitoa.algorithms.EDAWithFitness; -import aitoa.algorithms.HillClimber; -import aitoa.algorithms.HillClimber2; -import aitoa.algorithms.HillClimber2WithRestarts; -import aitoa.algorithms.HillClimberWithRestarts; -import aitoa.algorithms.HybridEDA; -import aitoa.algorithms.HybridEDAWithFitness; -import aitoa.algorithms.IntFFA; -import aitoa.algorithms.MA; -import aitoa.algorithms.MAWithClearing; -import aitoa.algorithms.MAWithFitness; -import aitoa.algorithms.RandomSampling; -import aitoa.algorithms.SimulatedAnnealing; -import aitoa.algorithms.SingleRandomSample; -import aitoa.algorithms.TemperatureSchedule; -import aitoa.examples.jssp.trees.JSSPTreeRepresentationMapping; -import aitoa.examples.jssp.trees.JobStatistic; -import aitoa.searchSpaces.trees.Node; -import aitoa.searchSpaces.trees.NodeTypeSet; -import aitoa.searchSpaces.trees.NodeTypeSetBuilder; -import aitoa.searchSpaces.trees.TreeBinaryOperator; -import aitoa.searchSpaces.trees.TreeNullaryOperator; -import aitoa.searchSpaces.trees.TreeSpace; -import aitoa.searchSpaces.trees.TreeUnaryOperator; -import aitoa.searchSpaces.trees.math.ATan2; -import aitoa.searchSpaces.trees.math.Add; -import aitoa.searchSpaces.trees.math.Divide; -import aitoa.searchSpaces.trees.math.DoubleConstant; -import aitoa.searchSpaces.trees.math.MathFunction; -import aitoa.searchSpaces.trees.math.Max; -import aitoa.searchSpaces.trees.math.Min; -import aitoa.searchSpaces.trees.math.Multiply; -import aitoa.searchSpaces.trees.math.Subtract; -import aitoa.structure.BlackBoxProcessBuilder; -import aitoa.structure.IBinarySearchOperator; -import aitoa.structure.IBlackBoxProcess; -import aitoa.structure.IMetaheuristic; -import aitoa.structure.IModel; -import aitoa.structure.IUnarySearchOperator; -import aitoa.structure.LogFormat; -import aitoa.utils.ConsoleIO; -import aitoa.utils.Experiment; -import aitoa.utils.IOUtils; -import aitoa.utils.RandomUtils; - -/** - * This is the main class used to generate all the data from our - * JSSP experiments. It will run a very long time and is not - * parallelized at all. - */ -public class JSSPExperimentOld { - - /** the instances to be used */ - public static final String[] INSTANCES = { // - "abz7", //$NON-NLS-1$ - "la24", //$NON-NLS-1$ - "yn4", //$NON-NLS-1$ - "swv15" };//$NON-NLS-1$ - - /** - * Run all the experiments in a full-factorial experimental - * design. - * - * @param args - * only first element considered: the destination path - * @throws IOException - * if I/O fails - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static final void main(final String[] args) - throws IOException { - final Path out = IOUtils.canonicalizePath( - (args.length > 0) ? args[0] : "results");//$NON-NLS-1$ - - for (final String instId : JSSPExperimentOld.INSTANCES) { - // load the instance - final JSSPInstance inst = new JSSPInstance(instId); - final int upperBound = - JSSPExperimentOld.__get_makespan_upper_bound(inst); - boolean plainEDADone = false; - -// random samplers - JSSPExperimentOld.run(new SingleRandomSample<>(), null, - null, inst, out); - JSSPExperimentOld.run(new RandomSampling<>(), null, null, - inst, out); - - for (final IUnarySearchOperator unary : // - new IUnarySearchOperator[] { // - new JSSPUnaryOperator1Swap(), // - new JSSPUnaryOperator1SwapR(inst), // -// new JSSPUnaryOperator12Swap(), - new JSSPUnaryOperatorNSwap() }) { - - if (!(unary instanceof JSSPUnaryOperator1SwapR)) { -// plain hill climbers which do not enumerate their neighborhood - JSSPExperimentOld.run(new HillClimber<>(), unary, null, - inst, out); - -// hill climbers which do not enumerate neighborhood with -// restarts - JSSPExperimentOld.run( - new HillClimberWithRestarts<>(256), // $NON-NLS-1$ - unary, null, inst, out); - // end restart settings - } // only use basic unary ops - -// hill climbers with neighborhood enumeration - if (unary.canEnumerate()) { - JSSPExperimentOld.run(new HillClimber2<>(), unary, - null, inst, out); - JSSPExperimentOld.run(new HillClimber2WithRestarts<>(), - unary, null, inst, out); - } // end enumerable unary ops - -// simulated annealing - if (!(unary instanceof JSSPUnaryOperator1SwapR)) { - for (final double Ts : new double[] { 20d, 0.5d * 20d, - 0.25d * 20d }) { - JSSPExperimentOld.run( - new SimulatedAnnealing<>( - new TemperatureSchedule.Logarithmic(Ts, 1)), - unary, null, inst, out); - } // end start temperature - for (final double ep : new double[] { 2e-7d, 4e-7d, - 8e-7d }) { - JSSPExperimentOld.run(new SimulatedAnnealing<>( - new TemperatureSchedule.Exponential(20d, ep)), - unary, null, inst, out); - } // end epsilon - } // only use basic unary ops - -// create the binary search operator - final IBinarySearchOperator[] binops = - new IBinarySearchOperator[] { - new JSSPBinaryOperatorSequence(inst), - new JSSPBinaryOperatorUniform(inst) }; - for (final IBinarySearchOperator< - int[]> binary : binops) { -// evolutionary algorithms - for (final int mu : new int[] { 16, 32, 64, 512, 2048, - 4096 }) { - for (final int lambda : new int[] { mu }) { - for (final double cr : new double[] { 0, 0.05, - 0.3 }) { - if ((cr <= 0d) && (binary != binops[0])) { - continue; // test only binary op for cr=0 - } - if (!(unary instanceof JSSPUnaryOperator1SwapR)) { -// the plain EA - JSSPExperimentOld.run(new EA<>(cr, mu, lambda), - unary, binary, inst, out); -// the EA with pruning, i.e., which enforces population diversity - JSSPExperimentOld.run( - new EAWithClearing<>(cr, mu, lambda), - unary, binary, inst, out); -// the EA with frequency fitness assignment - JSSPExperimentOld.run( - new EAWithFitness<>(cr, mu, lambda, - new IntFFA(upperBound)), - unary, binary, inst, out); - } // only use basic unary ops - } // end enumerate cr - - if (unary.canEnumerate()) { - for (final int steps : new int[] { - Integer.MAX_VALUE, 10, 100 }) { -// memetic algorithms here rely on enumeration and use cr=1 - JSSPExperimentOld.run( - new MAWithClearing<>(mu, lambda, steps), - unary, binary, inst, out); - JSSPExperimentOld.run( - new MA<>(mu, lambda, steps), unary, binary, - inst, out); - // the EA with frequency fitness assignment - JSSPExperimentOld.run( - new MAWithFitness<>(mu, lambda, steps, - new IntFFA(upperBound)), - unary, binary, inst, out); - } - } // end memetic algorithm - } // end lambda - } // end mu - } // end binary op - -// the estimation of distribution algorithms - for (final IModel model : new IModel[] { - new JSSPUMDAModel(inst) }) { // models for EDAs -// test different number of samples - for (final int lambda : new int[] { 16, 64, 256, - 1024 }) { - int[] mus; - if (lambda > 16) { - if (lambda > 64) { - mus = new int[] { 1, 2, 4, 16, 64 }; - } else { - mus = new int[] { 1, 2, 4, 16 }; - } - } else { - mus = new int[] { 1, 2, 4 }; - } - for (final int mu : mus) { - if (!plainEDADone) { -// only do EDA once - JSSPExperimentOld.run( - new EDA<>(mu, lambda, model), null, null, - inst, out); -// and the version with fitness - JSSPExperimentOld.run( - new EDAWithFitness<>(mu, lambda, model, - new IntFFA(upperBound)), - null, null, inst, out); - } - - if (unary.canEnumerate()) { - if (!(unary instanceof JSSPUnaryOperator1SwapR)) { - for (final int steps : new int[] { - Integer.MAX_VALUE, 10, 100 }) { - JSSPExperimentOld.run(new HybridEDA<>(mu, - lambda, steps, model), unary, null, inst, - out); - JSSPExperimentOld.run( - new HybridEDAWithFitness<>(mu, lambda, - steps, model, - new IntFFA(upperBound)), - unary, null, inst, out); - } - } // only use randomized enumeration - } // can enumerate - } // mu - } // lambda - } // models - plainEDADone = true; - } // end unary operators - - // random sampling with gp - for (final int maxDepth : new int[] { 6, 8 }) { - JSSPExperimentOld.__runGP(new RandomSampling<>(), - maxDepth, inst, out); - // evolutionary algorithms - for (final int mu : new int[] { 16, 128, 1024 }) { - for (final int lambda : new int[] { mu }) { - for (final double cr : new double[] { 0.05, 0.3 }) { - // the plain EA - JSSPExperimentOld.__runGP(new EA<>(cr, mu, lambda), - maxDepth, inst, out); -// the EA with pruning, i.e., which enforces population diversity - JSSPExperimentOld.__runGP( - new EAWithClearing<>(cr, mu, lambda), maxDepth, - inst, out); - JSSPExperimentOld.__runGP( - new EAWithFitness<>(cr, mu, lambda, - new IntFFA(upperBound)), - maxDepth, inst, out); - } // end enumerate cr - } // end lambda - } // end mu - } // end maxDepth - } // end instances - } - - /** the maximum time */ - private static final long MAX_TIME = 3L * 60L * 1000L; - - /** the number of runs */ - private static final int N_RUNS = 101; - - /** - * Apply a metaheuristic algorithm with the given operators to - * the specified instance and log the results to the provided - * directory. - * - * @param algorithm - * the algorithm - * @param unary - * the unary search operator, or {@code null} - * @param binary - * the binary search operator, or {@code null} - * @param inst - * the instance - * @param baseDir - * the base directory - * @throws IOException - * if I/O fails - */ - public static final void - run(final IMetaheuristic algorithm, - final IUnarySearchOperator unary, - final IBinarySearchOperator binary, - final JSSPInstance inst, final Path baseDir) - throws IOException { - - // create the process builder - final BlackBoxProcessBuilder builder = - new BlackBoxProcessBuilder<>(); -// set the maximum runtime - builder.setMaxTime(JSSPExperimentOld.MAX_TIME); - - // create the algorithm directory - final String algoName = Experiment.nameFromObjectsMerge(// - algorithm, unary, binary); - // create the instance bane - final String instName = - Experiment.nameFromObjectPrepare(inst); - - // setup the data - final JSSPSearchSpace searchSpace = - new JSSPSearchSpace(inst); - builder.setSearchSpace(searchSpace); - builder.setSolutionSpace(new JSSPSolutionSpace(inst)); - builder.setRepresentationMapping( - new JSSPRepresentationMapping(inst)); - builder.setObjectiveFunction( - new JSSPMakespanObjectiveFunction(inst)); - builder - .setNullarySearchOperator(new JSSPNullaryOperator(inst)); - if (unary != null) { - builder.setUnarySearchOperator(unary); - } - if (binary != null) { - builder.setBinarySearchOperator(binary); - } - // iterate over the random seeds - for (final long seed : RandomUtils - .uniqueRandomSeeds(instName, JSSPExperimentOld.N_RUNS)) { - final Path file = Experiment.logFile(baseDir, algoName, - instName, seed, false); - if (file == null) { - ConsoleIO.stdout(((((("Logfile for run " + algoName)//$NON-NLS-1$ - + ';') + instName) + ';') + seed) - + " already exists, skipping run."); //$NON-NLS-1$ - } else { - ConsoleIO.stdout("Now performing run '"//$NON-NLS-1$ - + file + "'."); //$NON-NLS-1$ - - builder.setRandSeed(seed); - builder.setLogPath(file); - try (final IBlackBoxProcess process = builder.get()) { - algorithm.solve(process); - process.printLogSection("ALGORITHM_SETUP", //$NON-NLS-1$ - (bw) -> { - try { - algorithm.printSetup(bw); - } catch (final IOException ioe) { - throw new RuntimeException(ioe); - } - }); - } - } - } - } - - /** - * Apply a metaheuristic algorithm with the given operators to - * the specified instance and log the results to the provided - * directory. - * - * @param algorithm - * the algorithm - * @param inst - * the instance - * @param maxDepth - * the maximum depth - * @param baseDir - * the base directory - * @throws IOException - * if I/O fails - */ - @SuppressWarnings("unchecked") - private static final void __runGP( - final IMetaheuristic algorithm, - final int maxDepth, final JSSPInstance inst, - final Path baseDir) throws IOException { - - // create the process builder - final BlackBoxProcessBuilder builder = - new BlackBoxProcessBuilder<>(); -// set the maximum runtime - builder.setMaxTime(JSSPExperimentOld.MAX_TIME); - - // create the algorithm directory - final String algoName = Experiment.nameFromObjectsMerge(// - "gp" + maxDepth, algorithm); //$NON-NLS-1$ - // create the instance bane - final String instName = - Experiment.nameFromObjectPrepare(inst); - - final TreeSpace searchSpace = new TreeSpace(maxDepth); - - final NodeTypeSetBuilder ntsb = new NodeTypeSetBuilder(); - final NodeTypeSetBuilder.Builder nodes = - ntsb.rootNodeTypeSet(); - nodes.add(Add.class, nodes, nodes); - nodes.add(ATan2.class, nodes, nodes); - nodes.add(Divide.class, nodes, nodes); - nodes.add(DoubleConstant.type()); - nodes.add(Max.class, nodes, nodes); - nodes.add(Min.class, nodes, nodes); - nodes.add(Multiply.class, nodes, nodes); - nodes.add(Subtract.class, nodes, nodes); - nodes.add(JobStatistic.type()); - final NodeTypeSet> root = - ntsb.build(); - - // setup the data - builder.setSearchSpace(searchSpace); - builder.setSolutionSpace(new JSSPSolutionSpace(inst)); - builder.setRepresentationMapping( - new JSSPTreeRepresentationMapping(inst)); - builder.setObjectiveFunction( - new JSSPMakespanObjectiveFunction(inst)); - builder.setNullarySearchOperator( - new TreeNullaryOperator(root, maxDepth)); - - builder - .setUnarySearchOperator(new TreeUnaryOperator(maxDepth)); - - builder.setBinarySearchOperator( - new TreeBinaryOperator(maxDepth)); - - // iterate over the random seeds - for (final long seed : RandomUtils - .uniqueRandomSeeds(instName, JSSPExperimentOld.N_RUNS)) { - final Path file = Experiment.logFile(baseDir, algoName, - instName, seed, false); - if (file == null) { - ConsoleIO.stdout(((((("Logfile for run " + algoName)//$NON-NLS-1$ - + ';') + instName) + ';') + seed) - + " already exists, skipping run."); //$NON-NLS-1$ - } else { - ConsoleIO.stdout("Now performing run '"//$NON-NLS-1$ - + file + "'."); //$NON-NLS-1$ - - builder.setRandSeed(seed); - builder.setLogPath(file); - try (final IBlackBoxProcess process = builder.get()) { - algorithm.solve(process); - process.printLogSection( - LogFormat.ALGORITHM_SETUP_LOG_SECTION, (bw) -> { - try { - algorithm.printSetup(bw); - } catch (final IOException ioe) { - throw new RuntimeException(ioe); - } - }); - } - } - } - } - - /** - * Get the upper bound for the makespan of any solution for a - * JSSP instance - * - * @param instance - * the instance - * @return the upper bound - */ - private static final int - __get_makespan_upper_bound(final JSSPInstance instance) { - return ((int) (new JSSPMakespanObjectiveFunction(instance) - .upperBound() + 0.5)); - } -} diff --git a/src/main/java/aitoa/examples/jssp/JSSPSpreadModel.java b/src/main/java/aitoa/examples/jssp/JSSPSpreadModel.java deleted file mode 100644 index 9aeb454..0000000 --- a/src/main/java/aitoa/examples/jssp/JSSPSpreadModel.java +++ /dev/null @@ -1,125 +0,0 @@ -package aitoa.examples.jssp; - -import java.util.Arrays; - -/** - * A modified univariate model for the use in an EDA for the - * JSSP. In the {@linkplain JSSPUMDAModel original UMDA model}, - * we remember how often each job id occurred at every index. We - * then try to sample solutions which approximately represent - * this distribution. The original model was univariate, since we - * consider each index of the schedule representation separately. - *

- * However, now we realize that if a certain job was contained at - * a position {@code i} in a solution, it may not be best to - * only consider position {@code i} as a good location - * for that job. If it occurred at {@code i+1} or {@code i-2}, - * that may also be OK. Thus, instead of just increasing the - * probability of sampling it at index {@code i}, we also - * increase the sampling probability at adjacent indices. We - * define a base "spread" value, say {@code 16}. Then the - * frequency at index {@code i} of the given job is increased by - * {@code 16}. The frequencies at {@code i+1} and {@code i-1} are - * increased by {@code 8}, those at {@code i-2} and {@code i+2} - * by {@code 4}, and so on. If we hit the start or end of the - * schedule, then we instead add double the values at the indices - * at the "other" side. - */ -public final class JSSPSpreadModel extends JSSPUMDAModel { - - /** the spread base */ - public final int spreadBase; - - /** - * create a model for the given jssp instance - * - * @param instance - * the instance - * @param _spreadBase - * the spread base - */ - public JSSPSpreadModel(final JSSPInstance instance, - final int _spreadBase) { - super(instance); - - if (_spreadBase < 1) { - throw new IllegalArgumentException( - "Spread base must be >= 1, but is " //$NON-NLS-1$ - + _spreadBase); - } - this.spreadBase = _spreadBase; - } - - /** - * create a model for the given jssp instance - * - * @param instance - * the instance - */ - public JSSPSpreadModel(final JSSPInstance instance) { - this(instance, 16); - } - - /** - * create a JSSP spread model from a string - * - * @param strings - * the strings - */ - private JSSPSpreadModel(final String[] strings) { - this(new JSSPInstance(strings[0]), // - (strings.length > 1) ? Integer.parseInt(strings[1]) - : 16); - } - - /** - * create a JSSP spread model from a string - * - * @param string - * the strings - */ - public JSSPSpreadModel(final String string) { - this(string.split("_")); //$NON-NLS-1$ - } - - /** {@inheritDoc} */ - @Override - public void initialize() { - for (final long[] l : this.m_counts) { - Arrays.fill(l, this.spreadBase); - } - } - - /** {@inheritDoc} */ - @Override - public final void update(final Iterable selected) { - for (final int[] sel : selected) { - for (int j = sel.length; (--j) >= 0;) { - final int job = sel[j]; - int spread = this.spreadBase; - - this.m_counts[j][job] += spread; - distributeToNeighbors: for (int i = 1;; i++) { - spread >>>= 1; - if (spread <= 0) { - break distributeToNeighbors; - } - if (j >= i) { - this.m_counts[j - i][job] += - ((j + i) < sel.length) ? spread : (spread << 1); - } - if ((j + i) < sel.length) { - this.m_counts[j + i][job] += - (j >= i) ? spread : (spread << 1); - } - } - } - } - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return "spread_" + this.spreadBase; //$NON-NLS-1$ - } -} diff --git a/src/main/java/aitoa/examples/jssp/JSSPUMDAModel.java b/src/main/java/aitoa/examples/jssp/JSSPUMDAModel.java index 0b603d2..b4e3b3e 100644 --- a/src/main/java/aitoa/examples/jssp/JSSPUMDAModel.java +++ b/src/main/java/aitoa/examples/jssp/JSSPUMDAModel.java @@ -16,33 +16,47 @@ public class JSSPUMDAModel implements IModel { /** the counters */ - final long[][] m_counts; + private final long[][] m_counts; /** * the permutation used for picking indices to fill in a random * order */ - final int[] m_perm; + private final int[] m_perm; /** the probability vector */ - final long[] m_prob; + private final long[] m_prob; /** the jobs we can choose from */ - final int[] m_jobChoseFrom; + private final int[] m_jobChoseFrom; /** the remaining number of times a job can be scheduled */ - final int[] m_jobRemainingTimes; + private final int[] m_jobRemainingTimes; /** the number of machines */ - final int m_m; + private final int m_m; + + /** the probability multiplier */ + public final long multiplier; /** * create a model for the given jssp instance * * @param instance * the instance + * @param _multiplier + * the probability multiplier */ - public JSSPUMDAModel(final JSSPInstance instance) { + public JSSPUMDAModel(final JSSPInstance instance, + final long _multiplier) { super(); + if (_multiplier <= 0L) { + throw new IllegalArgumentException( + "Multiplier must be greater than 0, but is " //$NON-NLS-1$ + + _multiplier); + } + + this.multiplier = _multiplier; + int n = instance.n; this.m_m = instance.m; int l = this.m_m * n; @@ -62,18 +76,29 @@ public JSSPUMDAModel(final JSSPInstance instance) { } /** - * create a JSSP UMDA model from a string + * create a JSSP umda model from a string * - * @param instance - * the instance id + * @param strings + * the strings + */ + private JSSPUMDAModel(final String[] strings) { + this(new JSSPInstance(strings[0]), // + (strings.length > 1) ? Long.parseLong(strings[1]) : 1L); + } + + /** + * create a JSSP umda model from a string + * + * @param string + * the strings */ - public JSSPUMDAModel(final String instance) { - this(new JSSPInstance(instance)); + public JSSPUMDAModel(final String string) { + this(string.split("_")); //$NON-NLS-1$ } /** {@inheritDoc} */ @Override - public void initialize() { + public final void initialize() { for (final long[] l : this.m_counts) { Arrays.fill(l, 1L); } @@ -82,9 +107,10 @@ public void initialize() { /** {@inheritDoc} */ @Override public void update(final Iterable selected) { + this.initialize(); for (final int[] sel : selected) { for (int j = sel.length; (--j) >= 0;) { - ++this.m_counts[j][sel[j]]; + this.m_counts[j][sel[j]] += this.multiplier; } } } @@ -136,7 +162,7 @@ public final void sample(final int[] dest, /** {@inheritDoc} */ @Override public String toString() { - return "umda"; //$NON-NLS-1$ + return "umda_" + this.multiplier; //$NON-NLS-1$ } /** diff --git a/src/test/java/aitoa/algorithms/jssp/TestHybridFFAUMDAOnJSSP11.java b/src/test/java/aitoa/algorithms/jssp/TestHybridFFAUMDAOnJSSP11.java index 16b4139..1a8efe6 100644 --- a/src/test/java/aitoa/algorithms/jssp/TestHybridFFAUMDAOnJSSP11.java +++ b/src/test/java/aitoa/algorithms/jssp/TestHybridFFAUMDAOnJSSP11.java @@ -27,7 +27,7 @@ public class TestHybridFFAUMDAOnJSSP11 final int mu = 1 + rand.nextInt(lambda); return new HybridEDAWithFitness<>(mu, lambda, 11, - new JSSPUMDAModel(instance), + new JSSPUMDAModel(instance, 1 + rand.nextInt(2)), new IntFFA((int) (0.5d + new JSSPMakespanObjectiveFunction(instance) .upperBound()))); diff --git a/src/test/java/aitoa/algorithms/jssp/TestHybridUMDAOnJSSP.java b/src/test/java/aitoa/algorithms/jssp/TestHybridUMDAOnJSSP.java index ac3c0e8..5f01c18 100644 --- a/src/test/java/aitoa/algorithms/jssp/TestHybridUMDAOnJSSP.java +++ b/src/test/java/aitoa/algorithms/jssp/TestHybridUMDAOnJSSP.java @@ -25,6 +25,6 @@ public class TestHybridUMDAOnJSSP final int mu = 1 + rand.nextInt(lambda); return new HybridEDA<>(mu, lambda, Integer.MAX_VALUE, - new JSSPUMDAModel(instance)); + new JSSPUMDAModel(instance, 1 + rand.nextInt(2))); } } diff --git a/src/test/java/aitoa/algorithms/jssp/TestHybridUMDAOnJSSP10.java b/src/test/java/aitoa/algorithms/jssp/TestHybridUMDAOnJSSP10.java index 61d2555..56ecc0b 100644 --- a/src/test/java/aitoa/algorithms/jssp/TestHybridUMDAOnJSSP10.java +++ b/src/test/java/aitoa/algorithms/jssp/TestHybridUMDAOnJSSP10.java @@ -25,6 +25,6 @@ public class TestHybridUMDAOnJSSP10 final int mu = 1 + rand.nextInt(lambda); return new HybridEDA<>(mu, lambda, 10, - new JSSPUMDAModel(instance)); + new JSSPUMDAModel(instance, 1 + rand.nextInt(2))); } } diff --git a/src/test/java/aitoa/algorithms/jssp/TestUMDAOnJSSP.java b/src/test/java/aitoa/algorithms/jssp/TestUMDAOnJSSP.java index d796289..25bfd9e 100644 --- a/src/test/java/aitoa/algorithms/jssp/TestUMDAOnJSSP.java +++ b/src/test/java/aitoa/algorithms/jssp/TestUMDAOnJSSP.java @@ -23,6 +23,7 @@ public class TestUMDAOnJSSP extends TestMetaheuristicOnJSSP { final int lambda = 1 + rand.nextInt(64); final int mu = 1 + rand.nextInt(lambda); - return new EDA<>(mu, lambda, new JSSPUMDAModel(instance)); + return new EDA<>(mu, lambda, + new JSSPUMDAModel(instance, 1 + rand.nextInt(2))); } } diff --git a/src/test/java/aitoa/algorithms/jssp/TestUMDAWithFitnessOnJSSP.java b/src/test/java/aitoa/algorithms/jssp/TestUMDAWithFitnessOnJSSP.java index e61a70e..8fe2867 100644 --- a/src/test/java/aitoa/algorithms/jssp/TestUMDAWithFitnessOnJSSP.java +++ b/src/test/java/aitoa/algorithms/jssp/TestUMDAWithFitnessOnJSSP.java @@ -27,7 +27,7 @@ public class TestUMDAWithFitnessOnJSSP final int mu = 1 + rand.nextInt(lambda); return new EDAWithFitness<>(mu, lambda, - new JSSPUMDAModel(instance), + new JSSPUMDAModel(instance, 1 + rand.nextInt(2)), new IntFFA( (int) (new JSSPMakespanObjectiveFunction(instance) .upperBound()))); diff --git a/src/test/java/aitoa/algorithms/jssp/TestUMDAWithFitnessOnJSSP2.java b/src/test/java/aitoa/algorithms/jssp/TestUMDAWithFitnessOnJSSP2.java index 669f574..1c03b43 100644 --- a/src/test/java/aitoa/algorithms/jssp/TestUMDAWithFitnessOnJSSP2.java +++ b/src/test/java/aitoa/algorithms/jssp/TestUMDAWithFitnessOnJSSP2.java @@ -20,7 +20,7 @@ public class TestUMDAWithFitnessOnJSSP2 protected IMetaheuristic getAlgorithm(final JSSPInstance instance) { return new EDAWithFitness<>(1024, 8192, - new JSSPUMDAModel(instance), + new JSSPUMDAModel(instance, 3), new IntFFA( (int) (new JSSPMakespanObjectiveFunction(instance) .upperBound()))); diff --git a/src/test/java/aitoa/examples/jssp/TestJSSPSpreadModel.java b/src/test/java/aitoa/examples/jssp/TestJSSPSpreadModel.java deleted file mode 100644 index b897a4f..0000000 --- a/src/test/java/aitoa/examples/jssp/TestJSSPSpreadModel.java +++ /dev/null @@ -1,48 +0,0 @@ -package aitoa.examples.jssp; - -import java.util.Arrays; - -import aitoa.structure.IModel; -import aitoa.structure.IModelTest; -import aitoa.structure.ISpace; - -/** test the univariate model for the JSSP */ -public class TestJSSPSpreadModel extends IModelTest { - - /** the space we use */ - private static final JSSPInstance PROBLEM = - new JSSPInstance("swv18"); //$NON-NLS-1$ - - /** the space we use */ - private static final JSSPSearchSpace SPACE = - new JSSPSearchSpace(TestJSSPSpreadModel.PROBLEM); - - /** the operator we use */ - private static final IModel OP = - new JSSPSpreadModel(TestJSSPSpreadModel.PROBLEM, 16); - - /** {@inheritDoc} */ - @Override - protected ISpace getSpace() { - return TestJSSPSpreadModel.SPACE; - } - - /** {@inheritDoc} */ - @Override - protected IModel getModel(final ISpace space) { - return TestJSSPSpreadModel.OP; - } - - /** {@inheritDoc} */ - @Override - protected boolean equals(final int[] a, final int[] b) { - return Arrays.equals(a, b); - } - - /** {@inheritDoc} */ - @Override - protected int[] createValid() { - return JSSPTestUtils - .createValidX(TestJSSPSpreadModel.PROBLEM); - } -} diff --git a/src/test/java/aitoa/examples/jssp/TestJSSPUMDAModel.java b/src/test/java/aitoa/examples/jssp/TestJSSPUMDAModel.java index c75d5d9..38dba05 100644 --- a/src/test/java/aitoa/examples/jssp/TestJSSPUMDAModel.java +++ b/src/test/java/aitoa/examples/jssp/TestJSSPUMDAModel.java @@ -24,7 +24,7 @@ public class TestJSSPUMDAModel extends IModelTest { /** the operator we use */ private static final IModel OP = - new JSSPUMDAModel(TestJSSPUMDAModel.PROBLEM); + new JSSPUMDAModel(TestJSSPUMDAModel.PROBLEM, 1L); /** {@inheritDoc} */ @Override @@ -57,16 +57,14 @@ protected int[] createValid() { @Test(timeout = 3600000) public final void testModelTraining() { final JSSPInstance demo = new JSSPInstance("demo"); //$NON-NLS-1$ - final JSSPUMDAModel model = new JSSPUMDAModel(demo); + final JSSPUMDAModel model = new JSSPUMDAModel(demo, 1000L); for (int z = 100; (--z) >= 0;) { model.initialize(); final int[] template = JSSPTestUtils.createValidX(demo); final ArrayList list = new ArrayList<>(); list.add(template); - for (int i = 1000; (--i) >= 0;) { - model.update(list); - } + model.update(list); final int[] dest = new int[demo.m * demo.n]; checker: {