From c1a44fd2a6e772a8bc039f1cd3385d087843f12c Mon Sep 17 00:00:00 2001 From: Eremey Valetov Date: Sat, 28 Feb 2026 19:24:05 -0500 Subject: [PATCH] Add tutorial READMEs and fix tutorial return codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add README.md files for moeo/tutorial/Lesson{1-4}, smp/tutorial/Lesson{1-4}, and mo/tutorial/Lesson9 — these tutorials had no documentation. Fix return 1 → return 0 in 28 tutorial main() functions across mo/ and smp/ that unconditionally returned failure status. --- mo/tutorial/Lesson1/firstImprHC_maxSAT.cpp | 2 +- .../Lesson1/lesson1_combinedContinuator.cpp | 2 +- .../Lesson1/lesson1_evalContinuator.cpp | 2 +- mo/tutorial/Lesson1/lesson1_firstImprHC.cpp | 2 +- .../Lesson1/lesson1_fitContinuator.cpp | 2 +- .../Lesson1/lesson1_fullEvalContinuator.cpp | 2 +- .../Lesson1/lesson1_iterContinuator.cpp | 2 +- mo/tutorial/Lesson1/lesson1_neutralHC.cpp | 2 +- mo/tutorial/Lesson1/lesson1_randomBestHC.cpp | 2 +- mo/tutorial/Lesson1/lesson1_simpleHC.cpp | 2 +- mo/tutorial/Lesson2/testNeighborhood.cpp | 2 +- .../Lesson3/testSimulatedAnnealing.cpp | 2 +- mo/tutorial/Lesson4/testSimpleTS.cpp | 2 +- mo/tutorial/Lesson5/testILS.cpp | 2 +- mo/tutorial/Lesson6/adaptiveWalks.cpp | 2 +- mo/tutorial/Lesson6/autocorrelation.cpp | 2 +- mo/tutorial/Lesson6/densityOfStates.cpp | 2 +- mo/tutorial/Lesson6/fdc.cpp | 2 +- mo/tutorial/Lesson6/fitnessCloud.cpp | 2 +- mo/tutorial/Lesson6/neutralDegree.cpp | 2 +- mo/tutorial/Lesson6/neutralWalk.cpp | 2 +- mo/tutorial/Lesson6/sampling.cpp | 2 +- mo/tutorial/Lesson6/testMetropolisHasting.cpp | 2 +- mo/tutorial/Lesson6/testRandomNeutralWalk.cpp | 2 +- mo/tutorial/Lesson6/testRandomWalk.cpp | 2 +- mo/tutorial/Lesson7/hybridAlgo.cpp | 2 +- mo/tutorial/Lesson9/README.md | 48 +++++++++++ mo/tutorial/Lesson9/VNS.cpp | 2 +- moeo/tutorial/Lesson1/README.md | 84 +++++++++++++++++++ moeo/tutorial/Lesson2/README.md | 31 +++++++ moeo/tutorial/Lesson3/README.md | 32 +++++++ moeo/tutorial/Lesson4/README.md | 35 ++++++++ smp/tutorial/Lesson1/README.md | 23 +++++ smp/tutorial/Lesson1/lesson1_eoEasyEA.cpp | 6 +- smp/tutorial/Lesson2/README.md | 30 +++++++ smp/tutorial/Lesson3/README.md | 27 ++++++ smp/tutorial/Lesson4/README.md | 31 +++++++ 37 files changed, 371 insertions(+), 30 deletions(-) create mode 100644 mo/tutorial/Lesson9/README.md create mode 100644 moeo/tutorial/Lesson1/README.md create mode 100644 moeo/tutorial/Lesson2/README.md create mode 100644 moeo/tutorial/Lesson3/README.md create mode 100644 moeo/tutorial/Lesson4/README.md create mode 100644 smp/tutorial/Lesson1/README.md create mode 100644 smp/tutorial/Lesson2/README.md create mode 100644 smp/tutorial/Lesson3/README.md create mode 100644 smp/tutorial/Lesson4/README.md diff --git a/mo/tutorial/Lesson1/firstImprHC_maxSAT.cpp b/mo/tutorial/Lesson1/firstImprHC_maxSAT.cpp index 97f48ae31..e115d0d32 100644 --- a/mo/tutorial/Lesson1/firstImprHC_maxSAT.cpp +++ b/mo/tutorial/Lesson1/firstImprHC_maxSAT.cpp @@ -218,5 +218,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_combinedContinuator.cpp b/mo/tutorial/Lesson1/lesson1_combinedContinuator.cpp index ba2d3de30..2d1aba51e 100644 --- a/mo/tutorial/Lesson1/lesson1_combinedContinuator.cpp +++ b/mo/tutorial/Lesson1/lesson1_combinedContinuator.cpp @@ -247,5 +247,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_evalContinuator.cpp b/mo/tutorial/Lesson1/lesson1_evalContinuator.cpp index 69cc1a3a7..5098649ae 100644 --- a/mo/tutorial/Lesson1/lesson1_evalContinuator.cpp +++ b/mo/tutorial/Lesson1/lesson1_evalContinuator.cpp @@ -214,5 +214,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_firstImprHC.cpp b/mo/tutorial/Lesson1/lesson1_firstImprHC.cpp index db0158fce..9f70bb301 100644 --- a/mo/tutorial/Lesson1/lesson1_firstImprHC.cpp +++ b/mo/tutorial/Lesson1/lesson1_firstImprHC.cpp @@ -192,5 +192,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_fitContinuator.cpp b/mo/tutorial/Lesson1/lesson1_fitContinuator.cpp index a72ca7963..7f64a737c 100644 --- a/mo/tutorial/Lesson1/lesson1_fitContinuator.cpp +++ b/mo/tutorial/Lesson1/lesson1_fitContinuator.cpp @@ -209,5 +209,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_fullEvalContinuator.cpp b/mo/tutorial/Lesson1/lesson1_fullEvalContinuator.cpp index 34ec620e0..b63397a42 100644 --- a/mo/tutorial/Lesson1/lesson1_fullEvalContinuator.cpp +++ b/mo/tutorial/Lesson1/lesson1_fullEvalContinuator.cpp @@ -214,5 +214,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_iterContinuator.cpp b/mo/tutorial/Lesson1/lesson1_iterContinuator.cpp index 01671a8b7..305ca1d2f 100644 --- a/mo/tutorial/Lesson1/lesson1_iterContinuator.cpp +++ b/mo/tutorial/Lesson1/lesson1_iterContinuator.cpp @@ -211,5 +211,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_neutralHC.cpp b/mo/tutorial/Lesson1/lesson1_neutralHC.cpp index f00439209..d42f1b331 100644 --- a/mo/tutorial/Lesson1/lesson1_neutralHC.cpp +++ b/mo/tutorial/Lesson1/lesson1_neutralHC.cpp @@ -196,5 +196,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_randomBestHC.cpp b/mo/tutorial/Lesson1/lesson1_randomBestHC.cpp index 868033b31..a6732c522 100644 --- a/mo/tutorial/Lesson1/lesson1_randomBestHC.cpp +++ b/mo/tutorial/Lesson1/lesson1_randomBestHC.cpp @@ -192,5 +192,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson1/lesson1_simpleHC.cpp b/mo/tutorial/Lesson1/lesson1_simpleHC.cpp index 013b6731e..f91bafe83 100644 --- a/mo/tutorial/Lesson1/lesson1_simpleHC.cpp +++ b/mo/tutorial/Lesson1/lesson1_simpleHC.cpp @@ -193,5 +193,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson2/testNeighborhood.cpp b/mo/tutorial/Lesson2/testNeighborhood.cpp index fbc99827a..892544286 100644 --- a/mo/tutorial/Lesson2/testNeighborhood.cpp +++ b/mo/tutorial/Lesson2/testNeighborhood.cpp @@ -237,5 +237,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson3/testSimulatedAnnealing.cpp b/mo/tutorial/Lesson3/testSimulatedAnnealing.cpp index 661657c7b..51153b5f5 100644 --- a/mo/tutorial/Lesson3/testSimulatedAnnealing.cpp +++ b/mo/tutorial/Lesson3/testSimulatedAnnealing.cpp @@ -228,5 +228,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson4/testSimpleTS.cpp b/mo/tutorial/Lesson4/testSimpleTS.cpp index 767c5834d..1453865f5 100644 --- a/mo/tutorial/Lesson4/testSimpleTS.cpp +++ b/mo/tutorial/Lesson4/testSimpleTS.cpp @@ -262,5 +262,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson5/testILS.cpp b/mo/tutorial/Lesson5/testILS.cpp index 2efbc1144..42e68aa1b 100644 --- a/mo/tutorial/Lesson5/testILS.cpp +++ b/mo/tutorial/Lesson5/testILS.cpp @@ -226,5 +226,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/adaptiveWalks.cpp b/mo/tutorial/Lesson6/adaptiveWalks.cpp index 1976f577b..ef7021d4e 100644 --- a/mo/tutorial/Lesson6/adaptiveWalks.cpp +++ b/mo/tutorial/Lesson6/adaptiveWalks.cpp @@ -207,5 +207,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/autocorrelation.cpp b/mo/tutorial/Lesson6/autocorrelation.cpp index f034efc43..2f9dfc0a7 100644 --- a/mo/tutorial/Lesson6/autocorrelation.cpp +++ b/mo/tutorial/Lesson6/autocorrelation.cpp @@ -222,5 +222,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/densityOfStates.cpp b/mo/tutorial/Lesson6/densityOfStates.cpp index 9e2eeddca..9459b33db 100644 --- a/mo/tutorial/Lesson6/densityOfStates.cpp +++ b/mo/tutorial/Lesson6/densityOfStates.cpp @@ -190,5 +190,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/fdc.cpp b/mo/tutorial/Lesson6/fdc.cpp index a066e70ad..d0a00cdae 100644 --- a/mo/tutorial/Lesson6/fdc.cpp +++ b/mo/tutorial/Lesson6/fdc.cpp @@ -188,5 +188,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/fitnessCloud.cpp b/mo/tutorial/Lesson6/fitnessCloud.cpp index ad92e9502..001505eb4 100644 --- a/mo/tutorial/Lesson6/fitnessCloud.cpp +++ b/mo/tutorial/Lesson6/fitnessCloud.cpp @@ -213,5 +213,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/neutralDegree.cpp b/mo/tutorial/Lesson6/neutralDegree.cpp index 55a346a11..f5664d8bf 100644 --- a/mo/tutorial/Lesson6/neutralDegree.cpp +++ b/mo/tutorial/Lesson6/neutralDegree.cpp @@ -211,5 +211,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/neutralWalk.cpp b/mo/tutorial/Lesson6/neutralWalk.cpp index a94a20bca..fc117349b 100644 --- a/mo/tutorial/Lesson6/neutralWalk.cpp +++ b/mo/tutorial/Lesson6/neutralWalk.cpp @@ -247,5 +247,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/sampling.cpp b/mo/tutorial/Lesson6/sampling.cpp index 77c5fef66..5e7cfd2b1 100644 --- a/mo/tutorial/Lesson6/sampling.cpp +++ b/mo/tutorial/Lesson6/sampling.cpp @@ -252,5 +252,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/testMetropolisHasting.cpp b/mo/tutorial/Lesson6/testMetropolisHasting.cpp index d70858714..32b4921c0 100644 --- a/mo/tutorial/Lesson6/testMetropolisHasting.cpp +++ b/mo/tutorial/Lesson6/testMetropolisHasting.cpp @@ -197,5 +197,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/testRandomNeutralWalk.cpp b/mo/tutorial/Lesson6/testRandomNeutralWalk.cpp index 596501f5e..ebe9aec70 100644 --- a/mo/tutorial/Lesson6/testRandomNeutralWalk.cpp +++ b/mo/tutorial/Lesson6/testRandomNeutralWalk.cpp @@ -274,5 +274,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson6/testRandomWalk.cpp b/mo/tutorial/Lesson6/testRandomWalk.cpp index cfae94ece..d78845557 100644 --- a/mo/tutorial/Lesson6/testRandomWalk.cpp +++ b/mo/tutorial/Lesson6/testRandomWalk.cpp @@ -239,5 +239,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson7/hybridAlgo.cpp b/mo/tutorial/Lesson7/hybridAlgo.cpp index fb0667d03..7e7ad9dae 100644 --- a/mo/tutorial/Lesson7/hybridAlgo.cpp +++ b/mo/tutorial/Lesson7/hybridAlgo.cpp @@ -218,5 +218,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/mo/tutorial/Lesson9/README.md b/mo/tutorial/Lesson9/README.md new file mode 100644 index 000000000..204275b18 --- /dev/null +++ b/mo/tutorial/Lesson9/README.md @@ -0,0 +1,48 @@ +# Variable Neighborhood Search (VNS) + +VNS on the N-Queens problem, using multiple neighborhood structures to +escape local optima. + +The N-Queens problem places N queens on an N x N chessboard so that no two +queens attack each other. The representation is a permutation (one queen +per column) and the fitness counts conflicts (minimized). + +## Running + +From the `build/mo/tutorial/Lesson9` directory: + +```shell +./VNS -V=12 +``` + +This runs VNS on a 12-queens instance with a 3-second time limit. + +## How it works + +VNS alternates between perturbation (shaking) and local search using +different neighborhood structures. Here, two neighborhoods are used: + +```c++ +shiftNeighborhood shiftNH((vecSize-1) * (vecSize-1)); +swapNeighborhood swapNH(vecSize * (vecSize-1) / 2); +``` + +Each has its own hill-climber and mutation operator: + +```c++ +moSimpleHC ls1(shiftNH, fullEval, shiftEval); +moSimpleHC ls2(swapNH, fullEval, swapEval); + +moRndVectorVNSelection selectNH(ls1, shiftMut, true); +selectNH.add(ls2, swapMut); +``` + +`moRndVectorVNSelection` randomly picks which neighborhood/local search +to apply at each iteration. Forward (`moForwardVectorVNSelection`) and +backward (`moBackwardVectorVNSelection`) selection strategies are also +available. The search runs until the `moTimeContinuator` time limit: + +```c++ +moTimeContinuator cont(3); // 3 seconds +moVNS vns(selectNH, acceptCrit, fullEval, cont); +``` diff --git a/mo/tutorial/Lesson9/VNS.cpp b/mo/tutorial/Lesson9/VNS.cpp index cadac8a44..7814e82a1 100644 --- a/mo/tutorial/Lesson9/VNS.cpp +++ b/mo/tutorial/Lesson9/VNS.cpp @@ -284,5 +284,5 @@ int main(int argc, char **argv) catch (exception& e) { cout << "Exception: " << e.what() << '\n'; } - return 1; + return 0; } diff --git a/moeo/tutorial/Lesson1/README.md b/moeo/tutorial/Lesson1/README.md new file mode 100644 index 000000000..52c036157 --- /dev/null +++ b/moeo/tutorial/Lesson1/README.md @@ -0,0 +1,84 @@ +# How to run your first multi-objective EA? + +In this lesson you will solve the Schaffer SCH1 bi-objective problem with +NSGA-II using the ParadisEO-MOEO framework. + +The SCH1 problem minimizes two objectives over a single real-valued +variable x in [0, 2]: + +- f1(x) = x^2 +- f2(x) = (x - 2)^2 + +## 1. Running + +From the `build/moeo/tutorial/Lesson1` directory: + +```shell +./Sch1 --help +./Sch1 --popSize=100 --maxGen=100 +``` + +Parameters can also be read from a file: + +```shell +./Sch1 @Sch1.param +``` + +## 2. Browsing the code + +Open `Sch1.cpp` and follow along. + +First, define the objective vector traits. This tells MOEO how many +objectives the problem has and whether each is minimizing or maximizing: + +```c++ +class Sch1ObjectiveVectorTraits : public moeoObjectiveVectorTraits +{ +public: + static bool minimizing (int) { return true; } + static bool maximizing (int) { return false; } + static unsigned int nObjectives () { return 2; } +}; +``` + +The solution class `Sch1` inherits from `moeoRealVector` — a real-valued +decision vector that also carries an objective vector: + +```c++ +class Sch1 : public moeoRealVector < Sch1ObjectiveVector > +{ +public: + Sch1() : moeoRealVector < Sch1ObjectiveVector > (1) {} +}; +``` + +The evaluator computes both objectives and stores them via +`objectiveVector()`: + +```c++ +void operator () (Sch1 & _sch1) +{ + if (_sch1.invalidObjectiveVector()) { + Sch1ObjectiveVector objVec; + double x = _sch1[0]; + objVec[0] = x * x; + objVec[1] = (x - 2.0) * (x - 2.0); + _sch1.objectiveVector(objVec); + } +} +``` + +The algorithm itself is a single line — `moeoNSGAII` takes the generation +limit, evaluator, crossover, and mutation as constructor arguments: + +```c++ +moeoNSGAII < Sch1 > nsgaII (MAX_GEN, eval, xover, P_CROSS, mutation, P_MUT); +``` + +After the run, extract the Pareto front with `moeoUnboundedArchive`: + +```c++ +moeoUnboundedArchive < Sch1 > arch; +arch(pop); +arch.sortedPrintOn(cout); +``` diff --git a/moeo/tutorial/Lesson2/README.md b/moeo/tutorial/Lesson2/README.md new file mode 100644 index 000000000..865d37906 --- /dev/null +++ b/moeo/tutorial/Lesson2/README.md @@ -0,0 +1,31 @@ +# Multi-objective EA on the flow-shop scheduling problem + +This lesson solves a more realistic combinatorial problem: the bi-objective +permutation flow-shop, which minimizes both makespan and total flow time. + +## Running + +From the `build/moeo/tutorial/Lesson2` directory: + +```shell +./FlowShopEA @FlowShopEA.param +``` + +The parameter file specifies the problem instance, population size, operator +rates, and fitness assignment strategy. + +## How it works + +The code uses ParadisEO's `do_make_*` factory functions to build all +components from command-line parameters: + +```c++ +eoEvalFuncCounter& eval = do_make_eval(parser, state); +eoInit& init = do_make_genotype(parser, state); +eoGenOp& op = do_make_op(parser, state); +``` + +The flow-shop representation is defined in `FlowShop.h` — a +permutation-based `moeoVector` with a bi-objective vector. Different +Pareto-based fitness assignment strategies (NSGA-II, SPEA2, IBEA, etc.) +can be selected via parameters. diff --git a/moeo/tutorial/Lesson3/README.md b/moeo/tutorial/Lesson3/README.md new file mode 100644 index 000000000..ba88c45ac --- /dev/null +++ b/moeo/tutorial/Lesson3/README.md @@ -0,0 +1,32 @@ +# User-friendly multi-objective EA + +Same flow-shop problem as Lesson 2, but with a complete algorithmic pipeline +built from reusable `do_make_*` helpers: stopping criteria, checkpointing, +statistics, and the full evolution engine. + +## Running + +From the `build/moeo/tutorial/Lesson3` directory: + +```shell +./FlowShopEA2 @FlowShopEA2.param +``` + +## How it works + +The main program is essentially a sequence of factory calls: + +```c++ +eoEvalFuncCounter& eval = do_make_eval(parser, state); +eoInit& init = do_make_genotype(parser, state); +eoPop& pop = do_make_pop(parser, state, init); +eoContinue& term = do_make_continue_moeo(parser, state, eval); +eoCheckPoint& checkpoint = do_make_checkpoint_moeo(parser, state, ...); +eoAlgo& algo = do_make_ea_moeo(parser, state, ...); +do_make_run(parser, state, algo, pop); +``` + +`do_make_continue_moeo` builds continuators (generation limit, fitness +target, etc.) from parameters. `do_make_checkpoint_moeo` adds statistics, +population snapshots, and archive tracking. `do_make_ea_moeo` constructs +the selection and replacement strategy. diff --git a/moeo/tutorial/Lesson4/README.md b/moeo/tutorial/Lesson4/README.md new file mode 100644 index 000000000..5a7a59c80 --- /dev/null +++ b/moeo/tutorial/Lesson4/README.md @@ -0,0 +1,35 @@ +# Dominance-based multi-objective local search (DMLS) + +Same flow-shop problem as Lessons 2-3, but solved with local search instead +of an evolutionary algorithm. This combines ParadisEO-MO local search +components with the MOEO multi-objective framework. + +## Running + +From the `build/moeo/tutorial/Lesson4` directory: + +```shell +./FlowShopDMLS @FlowShopDMLS.param +``` + +## How it works + +The program uses `moShiftNeighbor` and `moOrderNeighborhood` from +ParadisEO-MO, with `moeoFullEvalByCopy` to adapt the full solution +evaluator for neighbor evaluation: + +```c++ +typedef moShiftNeighbor Neighbor; + +moOrderNeighborhood neighborhood((nhSize-1) * (nhSize-1)); +moeoFullEvalByCopy moEval(eval); +``` + +At each iteration, DMLS explores all non-dominated solutions in the +archive via local search moves and updates the archive with any improving +neighbors: + +```c++ +moeoFirstImprovingNeighborhoodExplorer explor(neighborhood, moEval); +moeoUnifiedDominanceBasedLS algo(checkpoint, eval, arch, explor, select); +``` diff --git a/smp/tutorial/Lesson1/README.md b/smp/tutorial/Lesson1/README.md new file mode 100644 index 000000000..b2089cc0d --- /dev/null +++ b/smp/tutorial/Lesson1/README.md @@ -0,0 +1,23 @@ +# Master/Workers wrapping with eoEasyEA + +Wraps a standard eoEasyEA with the ParadisEO-SMP parallel evaluation model, +applied to the Quadratic Assignment Problem (QAP). + +The QAP assigns facilities to locations to minimize cost (flow x distance). +The representation is a permutation. + +## Running + +From the `build/smp/tutorial/Lesson1` directory: + +```shell +./lesson1_eoEasyEA lesson1_eoEasyEA.param +``` + +## How it works + +The key idea: ParadisEO-SMP parallelizes evaluation by wrapping an existing +sequential algorithm. The algorithm code itself stays the same. `QAP.h` +defines the problem representation and evaluation, `QAPGA.h` defines the GA +operators, and `parserStruct.h` + `utils.h` handle parameter parsing and +instance loading. See also `lesson1_data.dat` for the problem instance. diff --git a/smp/tutorial/Lesson1/lesson1_eoEasyEA.cpp b/smp/tutorial/Lesson1/lesson1_eoEasyEA.cpp index 84ba99288..8d5c23e54 100644 --- a/smp/tutorial/Lesson1/lesson1_eoEasyEA.cpp +++ b/smp/tutorial/Lesson1/lesson1_eoEasyEA.cpp @@ -23,8 +23,8 @@ same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. -ParadisEO WebSite : http://paradiseo.gforge.inria.fr -Contact: paradiseo-help@lists.gforge.inria.fr +ParadisEO WebSite : https://nojhan.github.io/paradiseo/ +Contact: https://github.com/nojhan/paradiseo/issues */ /** @@ -125,5 +125,5 @@ int main(int argc, char **argv) delete[] b; - return 1; + return 0; } diff --git a/smp/tutorial/Lesson2/README.md b/smp/tutorial/Lesson2/README.md new file mode 100644 index 000000000..b6758329c --- /dev/null +++ b/smp/tutorial/Lesson2/README.md @@ -0,0 +1,30 @@ +# Homogeneous island model + +Three islands running the same algorithm (`eoEasyEA`) with a complete +topology — all islands exchange individuals with all others. + +Same QAP problem as Lesson 1. + +## Running + +From the `build/smp/tutorial/Lesson2` directory: + +```shell +./lesson2_homogeneous +``` + +The problem instance is loaded from `../lessonData.dat`. + +## How it works + +All islands share the same operators (evaluation, selection, crossover, +mutation, replacement) but can have different parameters. The topology +and island model are set up with: + +```c++ +Topology topo; +IslandModel model(topo); +``` + +Each island gets its own population and generation limit, then the model +runs them in parallel and handles migration. diff --git a/smp/tutorial/Lesson3/README.md b/smp/tutorial/Lesson3/README.md new file mode 100644 index 000000000..814c4db8d --- /dev/null +++ b/smp/tutorial/Lesson3/README.md @@ -0,0 +1,27 @@ +# Heterogeneous island model + +Two islands running different algorithms: an `eoEasyEA` on the QAP problem +and a PSO on a bitstring problem, connected via conversion functions. + +## Running + +From the `build/smp/tutorial/Lesson3` directory: + +```shell +./lesson3_heterogeneous +``` + +## How it works + +When islands use different representations, you need conversion functions +to translate individuals during migration. In this example, `fromBase()` +and `toBase()` convert between the QAP permutation and the PSO bitstring: + +```c++ +Indi2 fromBase(Indi& i, unsigned size) { ... } +Indi toBase(Indi2& i) { ... } +``` + +The conversions here are dummy placeholders (they just create random +individuals), but in a real application you would implement meaningful +mappings between representations. diff --git a/smp/tutorial/Lesson4/README.md b/smp/tutorial/Lesson4/README.md new file mode 100644 index 000000000..6c28c023a --- /dev/null +++ b/smp/tutorial/Lesson4/README.md @@ -0,0 +1,31 @@ +# Dynamic island topology + +Three islands start with a ring topology and switch to a complete topology +after 10 seconds of computation. + +Same QAP problem as Lessons 1-2. + +## Running + +From the `build/smp/tutorial/Lesson4` directory: + +```shell +./lesson4_topology +``` + +## How it works + +A callback function registered with the islands triggers the topology +change: + +```c++ +void changeTopo(IslandModel* _model, AbstractTopology& _topo) +{ + // ... after 10 seconds: + _model->setTopology(_topo); +} +``` + +The topology can be changed at runtime via `model.setTopology()`, so you +can implement adaptive communication patterns based on time, convergence, +or any other criterion.