From 56f07d7945e88ce3093fd63137d1d36ce961560f Mon Sep 17 00:00:00 2001 From: tachsin Date: Fri, 2 Oct 2026 18:54:29 +0300 Subject: [PATCH] docs(ctp): CTP1-CTP8 checked against the published paper and Deb's 2001 book The EMO 2001 paper (LNCS 1993: 284-298, eqs. 4-6, pp. 289-294) has the KanGAL report's equations and parameters for CTP1-CTP7, and Deb's book (section 8.3.5, eqs. 8.45 and 8.46, pp. 352-360) restates them and gives CTP8's two constraints on p. 358, genoxide's exactly; its figure 232 marks the three front pieces genoxide derives. No definition changes. Both sources print f2 without the square root their figures draw, as the report does; the book names g = 1 + x2 (p. 360). The docs, READMEs, Python docstrings, CTP8's reference and the plan now cite the paper and the book, and Ctp8's Rust docs give its pieces' ends as optimal_front computes them. --- docs/problems-plan.md | 55 ++++++++-- examples/ctp1/README.md | 18 ++-- examples/ctp1/main.py | 4 +- examples/ctp1/main.rs | 4 +- examples/ctp2/README.md | 18 ++-- examples/ctp2/main.py | 4 +- examples/ctp2/main.rs | 4 +- examples/ctp3/README.md | 22 ++-- examples/ctp3/main.py | 4 +- examples/ctp3/main.rs | 4 +- examples/ctp4/README.md | 22 ++-- examples/ctp4/main.py | 4 +- examples/ctp4/main.rs | 4 +- examples/ctp5/README.md | 26 +++-- examples/ctp5/main.py | 4 +- examples/ctp5/main.rs | 4 +- examples/ctp6/README.md | 22 ++-- examples/ctp6/main.py | 4 +- examples/ctp6/main.rs | 4 +- examples/ctp7/README.md | 21 ++-- examples/ctp7/main.py | 4 +- examples/ctp7/main.rs | 4 +- examples/ctp8/README.md | 17 +-- examples/ctp8/main.py | 10 +- examples/ctp8/main.rs | 11 +- python/genoxide/problems/__init__.py | 56 +++++----- src/multi/problems/ctp.rs | 152 ++++++++++++++++----------- 27 files changed, 299 insertions(+), 207 deletions(-) diff --git a/docs/problems-plan.md b/docs/problems-plan.md index 12dec314..462fea7a 100644 --- a/docs/problems-plan.md +++ b/docs/problems-plan.md @@ -557,7 +557,7 @@ Deb's part II (as the authors' preprint, IITK report 2012010, hosted by the authors, ), DAS-CMOP and LIR-CMOP (arXiv versions), the CEC 2009 report (20 April 2009 draft), the C-TAEA supplement (DC-DTLZ) and the DTLZ report. BNH, OSY and the Van Veldhuizen constrained problems could not be reached: **U**. CTP's -report was read in batch 7 (below). The PDFs were read as extracted text, so load-bearing constants get a check against the +report was read in batch 7, the published paper and Deb's 2001 book after batch 11 (below). The PDFs were read as extracted text, so load-bearing constants get a check against the typeset paper when implemented. Constraints below are written as the papers print them (mostly "≥ 0 is feasible"); genoxide normalizes to g ≤ 0 (section 2). @@ -573,13 +573,14 @@ typeset paper when implemented. Constraints below are written as the papers prin | OSY | Osyczka, A. and Kundu, S. (1995). A new method to solve generalized multicriteria optimization problems using the simple genetic algorithm. *Structural Optimization* 10(2): 94-99. doi:10.1007/BF01743536 | 6; x₁, x₂, x₆ ∈ [0, 10], x₃, x₅ ∈ [1, 5], x₄ ∈ [0, 6] | f₁ = −[25(x₁ − 2)² + (x₂ − 2)² + (x₃ − 1)² + (x₄ − 4)² + (x₅ − 1)²], f₂ = Σ xᵢ² | 6 (≥ 0) | five pieces with x₄ = x₆ = 0, tabulated in Deb, Pratap and Meyarivan (2001, EMO 2001, LNCS 1993: 284-298; KanGAL report 200005), table 1, and derived again: x₁ ∈ [4.056543, 5] on the third piece and x₃ ∈ [1, 3.731685] on the fourth, where the two meet (the table's 3.732 is not 2 + √3); from (−274, 76) to (−42, 4) | VS(Deb, Pratap and Meyarivan (2001, EMO 2001, LNCS 1993: 284-298; KanGAL report 200005), eq. 3; Van Veldhuizen table B.2); the original U | | Viennet 4, Van Veldhuizen's MOP-C1..C3 | Van Veldhuizen, D. A. (1999). *Multiobjective Evolutionary Algorithms: Classifications, Analyses, and New Innovations.* PhD thesis, AFIT/DS/ENG/99-01 (DTIC ADA364478) | — | — | — | — | **U** (optional) | -#### CTP1-CTP7 (and CTP8) +#### CTP1-CTP8 Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective evolutionary optimization. EMO 2001, LNCS 1993: 284-298. doi:10.1007/3-540-44719-9_20. **VO (batch 7), from the authors' KanGAL report 200005** (October 2000, 15 pages, the EMO paper's preprint; the file `tech-rep5.ps.gz` of the KanGAL site, kept by the Internet Archive, converted -with Ghostscript and read page by page; the LNCS text not compared). KanGAL's list of reports +with Ghostscript and read page by page), **and again in the LNCS text and Deb's 2001 book** (below: +"Checked against the paper and the book"). KanGAL's list of reports (kangal/reports.shtml, through the Internet Archive) and Coello's list of technical reports both number it 200005; the file's title page misprints 200002, which is the number of Deb, Pratap and Moitra's report (the PPSN VI preprint read in batch 9), whose own title page also says 200002. @@ -611,9 +612,8 @@ Findings: corners are at f₁ = 0.33367 and 0.66789. - The code writes each constraint as a ratio, left/right − 1 ≥ 0; genoxide keeps the report's difference (feasible at the same points, finite where the right side is 0). -- **CTP8 isn't in the report** (CTP1-CTP7 only, as Tanabe and Oyama 2017 say); later papers credit - it to Deb's 2001 book, which wasn't read. Its definition is the code's (the table's row), **U** - against the book. +- **CTP8 isn't in the report** (CTP1-CTP7 only, as Tanabe and Oyama 2017 say); it's in Deb's 2001 + book, read after batch 11 (below), whose two constraints are the code's (the table's row): **VO**. - Fronts, derived here: CTP1 three analytic pieces; CTP2 13 pieces of the boundary; CTP3 and CTP4 the 13 points (cos θ k/10, 1 + sin θ k/10); **CTP5 one continuous piece and 15 points**, not 16 points: near v = 0, sin(bπv²)^0.5 grows linearly and the boundary leaves the line at a shallow @@ -625,6 +625,43 @@ Findings: are infeasible by about 3e-8 (sin(kπ) ≈ 1e-15 under a square root). - The report's OSY (eq. 3) and table 1 match genoxide's `Osy`. +**Checked against the paper and the book** (after batch 11; the LNCS text, Deb, Pratap and Meyarivan +2001, LNCS 1993: 284-298, and Deb, K. (2001), *Multi-Objective Optimization Using Evolutionary +Algorithms*, Wiley, section 8.3.5, pp. 352-360, both as rendered pages): + +- **The paper** has the report's equations with the same numbers: CTP1 eq. 4 with the table of a and + b (p. 289), the generator eq. 5 (p. 290), the line eq. 6 (p. 292), and the parameters of CTP2 + (p. 290), CTP3 and CTP4 (p. 291), CTP5 (p. 292), CTP6 (p. 293, with "1 ≤ ((f₂ − e) sin θ + f₁ cos θ) ≤ + 2") and CTP7 (pp. 293-294); the experiments (Rastrigin's g, five variables, 100 × 500, SBX and + polynomial mutation with η = 20) on pp. 294-295. No difference from the report or from genoxide. +- **The book** restates them: CTP1 as eq. 8.45 (p. 353, f₁(x_I) and g(x_II) for any split of the + variables; a and b as in the table), the generator as eq. 8.46 (p. 354), named "CTP2-CTP8", and + the parameters of CTP2 to CTP7 on pp. 355-358, all as in the paper; its figures 225-231 are + reprints of the paper's 5-11. **CTP8** is on p. 358: C₁ with θ = 0.1π, a = 40, b = 0.5, c = 1, d = + 2, e = −2 and C₂ with θ = −0.05π, a = 40, b = 2.0, c = 1, d = 6, e = 0, genoxide's (the code's) + exactly. Its figure 232 (p. 359) marks three Pareto-optimal regions, at f₁ ≈ 0-0.13, 0.33-0.48 and + 0.68-0.82, the three pieces derived here ((0, 3.6958)-(0.1345, 3.3128), (0.3263, 2.7686)-(0.4790, + 2.3372), (0.6823, 1.7654)-(0.8229, 1.3727)); the book says nothing more of CTP8's front. The book + drops the paper's "1 ≤ … ≤ 2" for CTP6. +- **f₂**: the paper's eq. 5 and the book's eq. 8.46 print g (1 − f₁/g), as the report does; neither + corrects it, and the figures of CTP2-CTP7 (the paper's 6-11, the book's 226-231) draw the + unconstrained front as 1 − √f₁ (e.g. CTP7's pieces at f₂ ≈ 0.7 near f₁ = 0.1). genoxide keeps the + code's square root. +- **g and bounds**: the paper and eq. 8.46 leave them open ("the bounds of other variables depend on + the chosen g(x) function"). The book's p. 360 names g₁(x) = 1 + x₂ (the code's) and a + Rastrigin-like g₂(x) = 11 + x₂² − 10 cos(2πx₂), and draws CTP7's decision space for both with x₂ ∈ + [0, 1]. genoxide keeps the code's x₂ ∈ [0, 10] for CTP6-CTP8: CTP6's and CTP8's fronts need g up + to 3.70 (x₂ = 2.70), out of reach with [0, 1], and CTP7's front is the same either way. +- **Fronts against the figures**: CTP3 and CTP4 mark the 13 points; CTP5's figure (the paper's 9, + the book's 229) draws the first stretch from (0, 1) and marks the touches k = 1 to 14 only, not + k = 15 at (0.9908, 0.2801), which is feasible (x₂ ≈ 0.4987) and optimal; CTP7's figure marks the + five inner pieces, not the sixth (f₁ from 0.9871 to 1) or the point (0, 1.0446), on the plot's + edges. Nothing to change. +- The paper's CTP7 text says the bands make "some portions of the unconstrained Pareto-optimal + region feasible", the book's "infeasible": both hold. +- The only fix: the Rust docs of `Ctp8` gave its pieces' ends to three digits off (0.1341, 3.3139, + …); the README's values, from `optimal_front`, were right. + #### Constrained DTLZ (C-DTLZ) Jain, H. and Deb, K. (2014). An evolutionary many-objective optimization algorithm using @@ -899,14 +936,14 @@ the papers report. No front file from another project is used. | Single objective, unconstrained | 59 continuous (18 scalable unimodal, 21 scalable multimodal, 20 fixed-dimension) | 6 binary and combinatorial; whole CEC/BBOB suites | Goldstein-Price; the CEC 2005 and BBOB forms; citations of Rosenbrock, Griewank, Rastrigin (1991), Styblinski-Tang | most: the originals are books and reports that aren't online; the common forms are secondary (Yao, Liu and Lin 1999; CEC 2005) | | Single objective, constrained (CEC 2006) | 24 | | all 24 (the September 2006 report) | g17's better value, g22's claimed better value, g04's variant, the "max" origins | | Multi objective, unconstrained | 25 (SCH1, SCH2, FON, KUR, POL, VNT1-3, ZDT5, DTLZ5-7, scaled DTLZ1/2, convex DTLZ2, inverted DTLZ1, WFG1-9) | MaF1-15, UF1-10, Deb's 1999 problems | ZDT5, DTLZ5-7, WFG (batch 4), scaled/convex/inverted DTLZ (batch 8) | Kursawe, Poloni, Viennet, SCH2's formula; FON secondary | -| Multi objective, constrained | 45 (CONSTR, SRN, TNK, BNH, OSY, CTP1-8, C-DTLZ ×6, MW1-14, DAS-CMOP1-9, DTLZ8-9) | LIR-CMOP1-14, CF1-10, DC-DTLZ ×6, Viennet 4 / MOP-C | CONSTR, SRN, TNK (as NSGA-II restates them), CTP1-7 (the KanGAL report), C-DTLZ, MW, DAS-CMOP, DTLZ8-9, and the optional LIR-CMOP, CF, DC-DTLZ | CTP8 (from the authors' code, the book unread), BNH, OSY; DC2/DC3 parameters | +| Multi objective, constrained | 45 (CONSTR, SRN, TNK, BNH, OSY, CTP1-8, C-DTLZ ×6, MW1-14, DAS-CMOP1-9, DTLZ8-9) | LIR-CMOP1-14, CF1-10, DC-DTLZ ×6, Viennet 4 / MOP-C | CONSTR, SRN, TNK (as NSGA-II restates them), CTP1-8 (the paper, its KanGAL report and Deb's book; g, n and bounds from the authors' code), C-DTLZ, MW, DAS-CMOP, DTLZ8-9, and the optional LIR-CMOP, CF, DC-DTLZ | BNH, OSY; DC2/DC3 parameters | | Engineering design | 8 single-objective (welded beam in two versions, pressure vessel, spring, speed reducer, gear train, three-bar truss, cantilever beam, car side impact) and 11 multi-objective (two-bar truss, welded beam, disc brake, car side impact, speed reducer, gear train, four-bar truss, rocket injector, water resource planning, marine design, crashworthiness) | I-beam, tubular column, concrete beam, stepped cantilever, coil spring, hatch cover, clutch brake, cantilever (Deb) | pressure vessel and cantilever optima (Yang et al. 2013, proofs) | the originals of all the others: secondary (Tanabe and Ishibuchi 2020, Chehouri et al. 2016) or unverified | **Core total: 172 new problems**, on top of the 9 genoxide has (ZDT1-4, ZDT6, DTLZ1-4), and about 75 optional ones. **To check in the originals before implementing** (by library access, since they're paywalled or -in print only): Deb's 2001 book (OSY's regions, CTP8), Binh and Korn (1997), Kursawe (1991), +in print only): Deb's 2001 book (OSY's regions; CTP8 checked, section 1.4), Binh and Korn (1997), Kursawe (1991), Poloni et al. (2000), Viennet et al. (1996), Schwefel (1981; its German edition of 1977 read for problems 1.2 and 2.26 in #241, 2.21 and 2.22 still to check), Dixon and Szegö (1978, Hartmann and Shekel constants), Ragsdell and Phillips (1976), Sandgren (1990), Golinski @@ -1241,7 +1278,7 @@ page); a comparison belongs on the problems' own pages. | 4 | done (#270) | Scalable many-objective problems | DTLZ5, DTLZ6, DTLZ7, ZDT5 (binary), WFG1-WFG9 (13) | an example per problem: `zdt5`, `dtlz5_3obj`, `dtlz6_3obj`, `dtlz7_3obj`, `wfg1` to `wfg9` (2 objectives); later, `wfg_many_objective`: NSGA-III and MOEA/D on WFG4 and WFG9 with 5 objectives, IGD to the sampled front | | 5 | done (#277) | CEC 2006, part 2 | g07-g18 (12) | `cec2006_g07` to `cec2006_g18` | | 6 | done | CEC 2006, part 3, and the low-dimensional classics with tables | g19-g24 (6), Hartmann 3-D, Hartmann 6-D, Shekel 5/7/10, Easom, Eggholder, Schaffer F6 (8) | `cec2006_g19` to `cec2006_g24` and an example per function: `hartmann3`, `hartmann6`, `shekel5`, `shekel7`, `shekel10`, `easom`, `eggholder`, `schaffer_f6` | -| 7 | done | Constrained test problems with tunable difficulty: CTP checked in the authors' KanGAL report 200005 (g, n and bounds from their NSGA-II code, f₂'s square root from its figures and code, CTP8 from the code only), C-DTLZ in the typeset manuscript, with table V's counts as a test (section 1.4) | CTP1-CTP8 (8), C1-DTLZ1, C1-DTLZ3, C2-DTLZ2, convex C2-DTLZ2, C3-DTLZ1, C3-DTLZ4 (6) | an example per problem: `ctp1` to `ctp8` (NSGA-II, the report's settings; CTP3 and CTP5 longer, CTP4 with MOEA/D for 70,000 generations), `c1_dtlz1_3obj`, `c1_dtlz3_3obj` (NSGA-III stops at the barrier in 19 of 20 runs; ignoring the constraint reaches the front), `c2_dtlz2_3obj`, `convex_c2_dtlz2_3obj`, `c3_dtlz1_3obj`, `c3_dtlz4_3obj` (NSGA-III, the paper's settings); the site shades CTP's feasible regions and draws infeasible solutions in 3-D | +| 7 | done | Constrained test problems with tunable difficulty: CTP checked in the authors' KanGAL report 200005 (g, n and bounds from their NSGA-II code, f₂'s square root from its figures and code), and after batch 11 in the published paper and Deb's 2001 book (section 8.3.5), CTP8 there (p. 358, figure 232): all match, C-DTLZ in the typeset manuscript, with table V's counts as a test (section 1.4) | CTP1-CTP8 (8), C1-DTLZ1, C1-DTLZ3, C2-DTLZ2, convex C2-DTLZ2, C3-DTLZ1, C3-DTLZ4 (6) | an example per problem: `ctp1` to `ctp8` (NSGA-II, the report's settings; CTP3 and CTP5 longer, CTP4 with MOEA/D for 70,000 generations), `c1_dtlz1_3obj`, `c1_dtlz3_3obj` (NSGA-III stops at the barrier in 19 of 20 runs; ignoring the constraint reaches the front), `c2_dtlz2_3obj`, `convex_c2_dtlz2_3obj`, `c3_dtlz1_3obj`, `c3_dtlz4_3obj` (NSGA-III, the paper's settings); the site shades CTP's feasible regions and draws infeasible solutions in 3-D | | 8 | done | Scaled and inverted DTLZ, and MW | Convex DTLZ2, scaled DTLZ1, scaled DTLZ2, inverted DTLZ1 (4), MW1-MW14 (14) | an example per problem: `convex_dtlz2`, `scaled_dtlz1`, `scaled_dtlz2`, `inverted_dtlz1` (NSGA-III against MOEA/D or other directions) and `mw1` to `mw14` (NSGA-II, NSGA-III and SMS-EMOA, with the paper's settings and settings that reach the fronts); the `mw` comparison of all fourteen is still to come | | 9 | done ([#357](https://github.com/tachsin/genoxide/pull/357); the marine design after it, once its original was read) | Engineering design, several objectives (`multi::problems::engineering`, section 1.5's "Checked in batch 9") | Two-bar truss, welded beam (2 objectives), disc brake, car side impact (3 objectives), speed reducer (2 objectives), four-bar truss, water resource planning, rocket injector, vehicle crashworthiness, conceptual marine design (10) | an example per problem: `two_bar_truss`, `welded_beam_2obj`, `disc_brake`, `speed_reducer_2obj`, `four_bar_truss` (NSGA-II), `car_side_impact_3obj` (NSGA-III, Jain and Deb's settings), `rocket_injector`, `vehicle_crashworthiness`, `marine_design` (SMS-EMOA), `water_resource_planning` (SPEA2) | | 10a | done | Remaining low-dimensional and classic scalable functions (section 1.1's "Checked in batch 10a") | Beale, Booth, Matyas, Bohachevsky 1-3, Three-hump camel, Dixon-Price, Trid, Powell, Langermann, Shekel's foxholes, Kowalik, Schwefel 2.21, Schwefel 2.22 (15) | an example per function: `beale`, `booth`, `matyas`, `bohachevsky1` to `bohachevsky3`, `three_hump_camel`, `langermann`, `shekel_foxholes` and `kowalik` (30 seeds each of CMA-ES with and without IPOP, DE, PSO or a GA), `dixon_price` (CMA-ES with IPOP, DE and PSO in 5 and 10 dimensions), and `schwefel_2_21`, `schwefel_2_22`, `trid` and `powell` (CMA-ES, sep-CMA-ES, DE, PSO and a GA to errors of 1 … 1e-8) | diff --git a/examples/ctp1/README.md b/examples/ctp1/README.md index c724bfd6..e6f034f7 100644 --- a/examples/ctp1/README.md +++ b/examples/ctp1/README.md @@ -28,20 +28,22 @@ x₁, x₂ in [0, 1] Without the constraints, the best solutions have g = 1 (x₂ = 0), and the front is the curve f₂ = exp(−f₁). Each constraint asks f₂ to stay above another exponential curve, -aⱼ exp(−bⱼ f₁), flatter than the front. The report builds a and b so that the first curve meets +aⱼ exp(−bⱼ f₁), flatter than the front. The paper builds a and b so that the first curve meets the front at f₁ = 1/3 and the second meets the first at f₁ = 2/3, and prints them to three digits, the values used here. With those, the curves cross at f₁ = 0.33367 and 0.66789. The optimal front, derived from the definition, is the highest of the three curves at g = 1: the unconstrained front up to f₁ = 0.33367, the first constraint's boundary up to 0.66789, and the second's up to f₁ = 1, where f₂ = 0.728 e^−0.295 = 0.5420. Two thirds of it lies on constraint -boundaries, as the report says; the rest of the unconstrained front, below them, is infeasible. +boundaries, as the paper says; the rest of the unconstrained front, below them, is infeasible. -The definitions come from the authors' KanGAL report 200005 (October 2000), the paper's preprint: -CTP1 is its eq. 4, with the table of a and b on p. 6. The report leaves g, the number of variables -and their bounds open; genoxide takes them from the authors' NSGA-II code (version 1.1.6, KanGAL), -which has g = 1 + x₂ and two variables in [0, 1]. The report's own experiments used five variables -and a Rastrigin function for g, without giving its formula. +The definitions are the paper's: CTP1 is its eq. 4, with the table of a and b on p. 289. Its +preprint, the authors' KanGAL report 200005 (October 2000, p. 6), and Deb's 2001 book +(*Multi-Objective Optimization Using Evolutionary Algorithms*, Wiley, eq. 8.45 on p. 353) give the +same. All three leave g, the number of variables and their bounds open; genoxide takes them from the +authors' NSGA-II code (version 1.1.6, KanGAL), which has g = 1 + x₂, the g the book names on p. 360, +and two variables in [0, 1]. The paper's own experiments used five variables and a Rastrigin +function for g, without giving its formula. ## What makes it hard @@ -64,7 +66,7 @@ Pareto dominance decides. ## Algorithm -NSGA-II with the settings of the report's experiments: +NSGA-II with the settings of the paper's experiments: - a population of 100, for 500 generations; - simulated binary crossover with η = 20, at a rate of 0.9; diff --git a/examples/ctp1/main.py b/examples/ctp1/main.py index 346ce271..4bf4c4d6 100644 --- a/examples/ctp1/main.py +++ b/examples/ctp1/main.py @@ -1,7 +1,7 @@ """CTP1: minimize two objectives over two variables subject to two constraints, with a front two thirds of which lie on the boundaries of two constraints. -NSGA-II with the settings of the report's experiments, a population of 100 for 500 +NSGA-II with the settings of the paper's experiments, a population of 100 for 500 generations. Prints how many solutions of the final front are feasible, how many pieces of the optimal front they reach, their IGD+ to it and their hypervolume. @@ -52,7 +52,7 @@ def report(name, generations, result): def nsga2(): - """NSGA-II with the settings of the report's experiments: a population of 100, SBX and + """NSGA-II with the settings of the paper's experiments: a population of 100, SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" return gx.Nsga2( problem.genome, diff --git a/examples/ctp1/main.rs b/examples/ctp1/main.rs index 500df653..7fff0093 100644 --- a/examples/ctp1/main.rs +++ b/examples/ctp1/main.rs @@ -1,7 +1,7 @@ //! CTP1: minimize two objectives over two variables subject to two constraints, with //! a front two thirds of which lie on the boundaries of two constraints. //! -//! NSGA-II with the settings of the report's experiments, a population of 100 for 500 +//! NSGA-II with the settings of the paper's experiments, a population of 100 for 500 //! generations. Prints how many solutions of the final front are feasible, how many pieces of //! the optimal front they reach, their IGD+ to it and their hypervolume. //! @@ -24,7 +24,7 @@ const REACH: f64 = 0.02; fn main() -> Result<()> { let problem = Ctp1; - // the settings of the report's experiments: a population of 100 for 500 generations, SBX + // the settings of the paper's experiments: a population of 100 for 500 generations, SBX // and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene let nsga2 = Nsga2::builder(problem.representation(), [Minimize; 2]) .population_size(100) diff --git a/examples/ctp2/README.md b/examples/ctp2/README.md index 3ad398d1..fcb5aebc 100644 --- a/examples/ctp2/README.md +++ b/examples/ctp2/README.md @@ -36,11 +36,13 @@ is 13 pieces of the wave, each starting on the line and ending where the next pi from (0, 1) to about (0.9845, 0.2872). genoxide's `optimal_front` samples the boundaries of the feasible region densely and keeps the feasible non-dominated points. -The definitions come from the authors' KanGAL report 200005 (October 2000), the paper's preprint: -eq. 5 and the parameters that follow it on p. 7. The report leaves g, the number of variables and -their bounds open, and prints f₂ as g (1 − f₁/g); its figures draw the unconstrained front as the -curve 1 − √f₁, and the authors' NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with -g = 1 + x₂ and two variables in [0, 1], which genoxide follows. The report's own experiments used +The definitions are the paper's: eq. 5 and the parameters that follow it, on p. 290. Its preprint, +the authors' KanGAL report 200005 (October 2000, p. 7), and Deb's 2001 book (*Multi-Objective +Optimization Using Evolutionary Algorithms*, Wiley, eq. 8.46 on p. 354 and the parameters on p. 355) +give the same. All three leave g, the number of variables and their bounds open, and print f₂ as g +(1 − f₁/g); their figures draw the unconstrained front as the curve 1 − √f₁, and the authors' +NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with g = 1 + x₂, the g the book names +on p. 360, and two variables in [0, 1], which genoxide follows. The paper's own experiments used five variables and a Rastrigin function for g, without giving its formula. ## What makes it hard @@ -48,7 +50,7 @@ five variables and a Rastrigin function for g, without giving its formula. The front is disconnected: 13 pieces, each about 0.025 wide in f₁, with gaps of about 0.055 between them. An algorithm has to find every piece and keep solutions on all of them, and it can't slide from one piece to the next, since the feasible region between them rises into waves. -The larger b, the more pieces; the report calls finding them all the task. +The larger b, the more pieces; the paper calls finding them all the task. About 45% of random genomes are feasible: the waves cut the region near the front, not far from it. @@ -64,7 +66,7 @@ Pareto dominance decides. ## Algorithm -NSGA-II with the settings of the report's experiments: +NSGA-II with the settings of the paper's experiments: - a population of 100, for 500 generations; - simulated binary crossover with η = 20, at a rate of 0.9; @@ -97,5 +99,5 @@ their lengths, give 99.90% of its hypervolume and an IGD+ of 0.0010. The run's front has 100 solutions, all feasible, on all 13 pieces, with an IGD+ of 0.0016 and 99.78% of the whole front's hypervolume. Over seeds 1 to 20, every run reaches all 13 pieces, with -an IGD+ from 0.0015 to 0.0019 and 99.75% to 99.82% of the hypervolume. The report found the same +an IGD+ from 0.0015 to 0.0019 and 99.75% to 99.82% of the hypervolume. The paper found the same with its five variables: NSGA-II found all the disconnected pieces. diff --git a/examples/ctp2/main.py b/examples/ctp2/main.py index de4fe1c0..742f0cd8 100644 --- a/examples/ctp2/main.py +++ b/examples/ctp2/main.py @@ -1,7 +1,7 @@ """CTP2: minimize two objectives over two variables subject to one constraint, with a front of 13 disconnected pieces of a constraint's wavy boundary. -NSGA-II with the settings of the report's experiments, a population of 100 for 500 +NSGA-II with the settings of the paper's experiments, a population of 100 for 500 generations. Prints how many solutions of the final front are feasible, how many pieces of the optimal front they reach, their IGD+ to it and their hypervolume. @@ -52,7 +52,7 @@ def report(name, generations, result): def nsga2(): - """NSGA-II with the settings of the report's experiments: a population of 100, SBX and + """NSGA-II with the settings of the paper's experiments: a population of 100, SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" return gx.Nsga2( problem.genome, diff --git a/examples/ctp2/main.rs b/examples/ctp2/main.rs index 34aa6b43..712cfbfd 100644 --- a/examples/ctp2/main.rs +++ b/examples/ctp2/main.rs @@ -1,7 +1,7 @@ //! CTP2: minimize two objectives over two variables subject to one constraint, with //! a front of 13 disconnected pieces of a constraint's wavy boundary. //! -//! NSGA-II with the settings of the report's experiments, a population of 100 for 500 +//! NSGA-II with the settings of the paper's experiments, a population of 100 for 500 //! generations. Prints how many solutions of the final front are feasible, how many pieces of //! the optimal front they reach, their IGD+ to it and their hypervolume. //! @@ -24,7 +24,7 @@ const REACH: f64 = 0.02; fn main() -> Result<()> { let problem = Ctp2; - // the settings of the report's experiments: a population of 100 for 500 generations, SBX + // the settings of the paper's experiments: a population of 100 for 500 generations, SBX // and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene let nsga2 = Nsga2::builder(problem.representation(), [Minimize; 2]) .population_size(100) diff --git a/examples/ctp3/README.md b/examples/ctp3/README.md index e931d11f..3c0dcd6e 100644 --- a/examples/ctp3/README.md +++ b/examples/ctp3/README.md @@ -32,16 +32,18 @@ and e = 1. The left side, u, measures the distance above the line f₂ = 1 − t square root, and every point of it near them is dominated by the point itself. The optimal front is 13 points, one per touch, from (0, 1) to (0.9708, 0.2947), derived from the -definition: (cos θ v, 1 + sin θ v) for v = k/10. The report calls them "a singular feasible +definition: (cos θ v, 1 + sin θ v) for v = k/10. The paper calls them "a singular feasible Pareto-optimal solution" in each region. At the points themselves the constraint is exactly 0; in floating point, sin(kπ) is about 1e-15 and its square root 3e-8, so the points are barely infeasible to the computer, and the best solutions sit next to them. -The definitions come from the authors' KanGAL report 200005 (October 2000), the paper's preprint: -eq. 5 on p. 7 and CTP3's parameters on p. 8. The report leaves g, the number of variables and their -bounds open, and prints f₂ as g (1 − f₁/g); its figures draw the unconstrained front as the curve -1 − √f₁, and the authors' NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with -g = 1 + x₂ and two variables in [0, 1], which genoxide follows. +The definitions are the paper's: eq. 5 (p. 290) and CTP3's parameters (p. 291). Its preprint, the +authors' KanGAL report 200005 (October 2000, p. 8), and Deb's 2001 book (*Multi-Objective +Optimization Using Evolutionary Algorithms*, Wiley, eq. 8.46 on p. 354 and the parameters on p. 355) +give the same. All three leave g, the number of variables and their bounds open, and print f₂ as g +(1 − f₁/g); their figures draw the unconstrained front as the curve 1 − √f₁, and the authors' +NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with g = 1 + x₂, the g the book names +on p. 360, and two variables in [0, 1], which genoxide follows. ## What makes it hard @@ -62,9 +64,9 @@ Pareto dominance decides. ## Algorithm -NSGA-II with the settings of the report's experiments, run twice: +NSGA-II with the settings of the paper's experiments, run twice: -- a population of 100, for 500 generations as in the report, then for 3,000; +- a population of 100, for 500 generations as in the paper, then for 3,000; - simulated binary crossover with η = 20, at a rate of 0.9; - polynomial mutation with η = 20, at a rate of 1/n per gene for n genes: 0.5. @@ -93,10 +95,10 @@ back. A good front has a solution next to each of the 13 points, and an IGD+ under 0.01. No finite set of feasible solutions reaches the points' hypervolume, since the points themselves are the limit. -After 500 generations, the report's budget, the front has 45 solutions near 11 of the 13 points, +After 500 generations, the paper's budget, the front has 45 solutions near 11 of the 13 points, an IGD+ of 0.0155 and 96.68% of the hypervolume: the solutions are in the right wedges, not yet at their tips. After 3,000, it has 100 solutions near all 13 points, an IGD+ of 0.0060 and 98.70% of the hypervolume. Over seeds 1 to 20, the 500-generation runs end with an IGD+ from 0.010 to 0.016, none under 0.01, and 13 of them near all 13 points; the 3,000-generation runs all reach every -point, with an IGD+ from 0.0046 to 0.0063. The report saw NSGA-II find a solution very close to +point, with an IGD+ from 0.0046 to 0.0063. The paper saw NSGA-II find a solution very close to each point with its five variables. diff --git a/examples/ctp3/main.py b/examples/ctp3/main.py index 93df94f7..b0b00173 100644 --- a/examples/ctp3/main.py +++ b/examples/ctp3/main.py @@ -1,7 +1,7 @@ """CTP3: minimize two objectives over two variables subject to one constraint, with a front of 13 separate points, where a constraint's boundary touches a line. -NSGA-II with the settings of the report's experiments, a population of 100 for 500 +NSGA-II with the settings of the paper's experiments, a population of 100 for 500 generations, and the same for 3,000. Prints, for each, how many solutions of the final front are feasible, how many of the optimal points they reach, their IGD+ to the front and their hypervolume. @@ -53,7 +53,7 @@ def report(name, generations, result): def nsga2(): - """NSGA-II with the settings of the report's experiments: a population of 100, SBX and + """NSGA-II with the settings of the paper's experiments: a population of 100, SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" return gx.Nsga2( problem.genome, diff --git a/examples/ctp3/main.rs b/examples/ctp3/main.rs index d7ad5c1a..e74c43fb 100644 --- a/examples/ctp3/main.rs +++ b/examples/ctp3/main.rs @@ -1,7 +1,7 @@ //! CTP3: minimize two objectives over two variables subject to one constraint, with //! a front of 13 separate points, where a constraint's boundary touches a line. //! -//! NSGA-II with the settings of the report's experiments, a population of 100 for 500 +//! NSGA-II with the settings of the paper's experiments, a population of 100 for 500 //! generations, and the same for 3,000. Prints, for each, how many solutions of the final front //! are feasible, how many of the optimal points they reach, their IGD+ to the front and their //! hypervolume. @@ -25,7 +25,7 @@ const REACH: f64 = 0.02; fn main() -> Result<()> { let problem = Ctp3; - // the settings of the report's experiments: a population of 100 for 500 generations, SBX + // the settings of the paper's experiments: a population of 100 for 500 generations, SBX // and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene; then // the same for 3,000 generations for generations in [500, 3000] { diff --git a/examples/ctp4/README.md b/examples/ctp4/README.md index cf83b402..d1f0150f 100644 --- a/examples/ctp4/README.md +++ b/examples/ctp4/README.md @@ -36,15 +36,17 @@ The optimal front is the same as CTP3's: 13 points, (cos θ v, 1 + sin θ v) for is exactly 0; in floating point, sin(kπ) is about 1e-15 and its square root 3e-8, so the best feasible solutions sit next to them. -The definitions come from the authors' KanGAL report 200005 (October 2000), the paper's preprint: -eq. 5 on p. 7 and CTP4's parameters on p. 8. The report leaves g, the number of variables and their -bounds open, and prints f₂ as g (1 − f₁/g); its figures draw the unconstrained front as the curve -1 − √f₁, and the authors' NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with -g = 1 + x₂ and two variables in [0, 1], which genoxide follows. +The definitions are the paper's: eq. 5 (p. 290) and CTP4's parameters (p. 291). Its preprint, the +authors' KanGAL report 200005 (October 2000, p. 8), and Deb's 2001 book (*Multi-Objective +Optimization Using Evolutionary Algorithms*, Wiley, eq. 8.46 on p. 354 and the parameters on p. 356) +give the same. All three leave g, the number of variables and their bounds open, and print f₂ as g +(1 − f₁/g); their figures draw the unconstrained front as the curve 1 − √f₁, and the authors' +NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with g = 1 + x₂, the g the book names +on p. 360, and two variables in [0, 1], which genoxide follows. ## What makes it hard -The report puts it this way: "an algorithm now has to travel through a long narrow feasible +The paper puts it this way: "an algorithm now has to travel through a long narrow feasible tunnel in search of the lone Pareto-optimal solution at the end of tunnel". At a height u above the line, a tunnel reaches only about (u/a)²/(bπ) to each side: 6e-6 at u = 0.01, 60 times less than CTP3's. Only 3% of random genomes are feasible, and the tunnels near f₁ = 1 don't connect to the @@ -52,7 +54,7 @@ open region above: the population has to land in each of them. Every step closer an offspring inside a narrower sliver than the last, and the steps of crossover and mutation, which change x₁ and x₂ each on its own, rarely follow a tunnel's slant. -The report found that neither NSGA-II nor Ray et al.'s algorithm got near the 13 points. +The paper found that neither NSGA-II nor Ray et al.'s algorithm got near the 13 points. ## Representation @@ -68,7 +70,7 @@ MOEA/D the subproblem's value, decides. Two runs with the same operators: simulated binary crossover with η = 20, at a rate of 0.9, and polynomial mutation with η = 20, at a rate of 1/n per gene for n genes, 0.5. -- NSGA-II with the settings of the report's experiments, a population of 100 for 500 +- NSGA-II with the settings of the paper's experiments, a population of 100 for 500 generations. - MOEA/D (Zhang and Li, 2007) with 100 subproblems, weight vectors evenly spread on the simplex, Tchebycheff decomposition and genoxide's default neighborhoods of 20, for 70,000 generations: @@ -103,9 +105,9 @@ shades; the tunnels near their tips are narrower than its cells. A good front has a solution next to each of the 13 points, and an IGD+ under 0.01. No finite set of feasible solutions reaches the points' hypervolume, since the points themselves are the limit. -NSGA-II with the report's budget ends in the tunnels, far from their tips: 22 solutions, none +NSGA-II with the paper's budget ends in the tunnels, far from their tips: 22 solutions, none within 0.02 of a point, an IGD+ of 0.097 and 79.18% of the hypervolume. Over seeds 1 to 20 its -IGD+ is 0.070 to 0.139, and only one run comes within 0.02 of a single point: the report's +IGD+ is 0.070 to 0.139, and only one run comes within 0.02 of a single point: the paper's finding again. MOEA/D reaches all 13: 16 solutions, an IGD+ of 0.0066 and 98.57% of the hypervolume. Over seeds diff --git a/examples/ctp4/main.py b/examples/ctp4/main.py index 78e0b0fc..2709e70a 100644 --- a/examples/ctp4/main.py +++ b/examples/ctp4/main.py @@ -1,7 +1,7 @@ """CTP4: minimize two objectives over two variables subject to one constraint, with a front of 13 separate points, each at the end of a long, narrow feasible tunnel. -NSGA-II with the settings of the report's experiments, a population of 100 for 500 +NSGA-II with the settings of the paper's experiments, a population of 100 for 500 generations, and MOEA/D with the same operators for 70,000. Prints, for each, how many solutions of the final front are feasible, how many of the optimal points they reach, their IGD+ to the front and their hypervolume. @@ -53,7 +53,7 @@ def report(name, generations, result): def nsga2(): - """NSGA-II with the settings of the report's experiments: a population of 100, SBX and + """NSGA-II with the settings of the paper's experiments: a population of 100, SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" return gx.Nsga2( problem.genome, diff --git a/examples/ctp4/main.rs b/examples/ctp4/main.rs index c02fec09..899c79bc 100644 --- a/examples/ctp4/main.rs +++ b/examples/ctp4/main.rs @@ -1,7 +1,7 @@ //! CTP4: minimize two objectives over two variables subject to one constraint, with //! a front of 13 separate points, each at the end of a long, narrow feasible tunnel. //! -//! NSGA-II with the settings of the report's experiments, a population of 100 for 500 +//! NSGA-II with the settings of the paper's experiments, a population of 100 for 500 //! generations, and MOEA/D with the same operators for 70,000. Prints, for each, how many //! solutions of the final front are feasible, how many of the optimal points they reach, their //! IGD+ to the front and their hypervolume. @@ -25,7 +25,7 @@ const REACH: f64 = 0.02; fn main() -> Result<()> { let problem = Ctp4; - // the settings of the report's experiments: a population of 100 for 500 generations, SBX + // the settings of the paper's experiments: a population of 100 for 500 generations, SBX // and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene let nsga2 = Nsga2::builder(problem.representation(), [Minimize; 2]) .population_size(100) diff --git a/examples/ctp5/README.md b/examples/ctp5/README.md index 1da569e2..3c927665 100644 --- a/examples/ctp5/README.md +++ b/examples/ctp5/README.md @@ -30,27 +30,31 @@ touches the line f₂ = 1 − 0.7265 f₁ where v² is a multiple of 1/10, at v its touches crowd together as f₁ grows: 16 of them in the objective space, from (0, 1) to (0.9908, 0.2801). -The report describes CTP5's optimal solutions as separate points, like CTP3's. Derived from the +The paper describes CTP5's optimal solutions as separate points, like CTP3's. Derived from the definition, the front is one continuous piece and 15 points. Near v = 0, the wave |sin(bπv²)|^0.5 grows like √(bπ) v, only linearly, and the boundary leaves the line at a slope shallow enough to keep going down in f₂: the whole first stretch of the boundary, from (0, 1) to f₁ = 0.2558, is optimal. Near the other touches, the wave rises like a square root, and only the touches themselves -are optimal, as in CTP3. The report's own figure 16 shows NSGA-II's solutions spread along that +are optimal, as in CTP3. The paper's own figure 16 shows NSGA-II's solutions spread along that first stretch. genoxide's `optimal_front` samples the boundaries of the feasible region densely and keeps the feasible non-dominated points. -The definitions come from the authors' KanGAL report 200005 (October 2000), the paper's preprint: -eq. 5 on p. 7 and CTP5's parameters on p. 9. The report leaves g, the number of variables and their -bounds open, and prints f₂ as g (1 − f₁/g); its figures draw the unconstrained front as the curve -1 − √f₁, and the authors' NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with -g = 1 + x₂ and two variables in [0, 1], which genoxide follows. +The definitions are the paper's: eq. 5 (p. 290) and CTP5's parameters (p. 292). Its preprint, the +authors' KanGAL report 200005 (October 2000, p. 9), and Deb's 2001 book (*Multi-Objective +Optimization Using Evolutionary Algorithms*, Wiley, eq. 8.46 on p. 354 and the parameters on p. 357) +give the same. All three leave g, the number of variables and their bounds open, and print f₂ as g +(1 − f₁/g); their figures draw the unconstrained front as the curve 1 − √f₁, and the authors' +NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with g = 1 + x₂, the g the book names +on p. 360, and two variables in [0, 1], which genoxide follows. The paper's figure 9 (the book's +229) draws the first stretch but marks only the touches for k = 1 to 14: the 16th touch, at (0.9908, +0.2801), is feasible and optimal too. ## What makes it hard The optimal points crowd together: 0.034 apart in f₁ at the right end, against 0.106 between the first two of them. Each is the tip of a narrow feasible wedge, as in CTP3, and the population has to keep a solution at each of 15 tips and along the continuous piece, which takes most of the front's -length and pulls the crowding distance of NSGA-II towards it. The report found this non-uniform +length and pulls the crowding distance of NSGA-II towards it. The paper found this non-uniform spacing "not a great difficulty to NSGA-II". About 43% of random genomes are feasible. ## Representation @@ -64,9 +68,9 @@ Pareto dominance decides. ## Algorithm -NSGA-II with the settings of the report's experiments, run twice: +NSGA-II with the settings of the paper's experiments, run twice: -- a population of 100, for 500 generations as in the report, then for 10,000; +- a population of 100, for 500 generations as in the paper, then for 10,000; - simulated binary crossover with η = 20, at a rate of 0.9; - polynomial mutation with η = 20, at a rate of 1/n per gene for n genes: 0.5. @@ -98,7 +102,7 @@ A good front reaches the continuous piece and all 15 points, with a hypervolume front's. 100 points of the optimal front, one on each point and the rest on the continuous piece, give 99.98% of it. -After 500 generations, the report's budget, the front reaches the continuous piece and 10 of the +After 500 generations, the paper's budget, the front reaches the continuous piece and 10 of the 15 points: an IGD+ of 0.0012, but 96.73% of the hypervolume. After 10,000, it reaches all 16 pieces, with an IGD+ of 0.0007 and 99.02% of the hypervolume. Over seeds 1 to 20, no 500-generation run reaches all 16 pieces (from 10 to 15 of them), while every 10,000-generation diff --git a/examples/ctp5/main.py b/examples/ctp5/main.py index 55e5fdc2..f11f5c18 100644 --- a/examples/ctp5/main.py +++ b/examples/ctp5/main.py @@ -1,7 +1,7 @@ """CTP5: minimize two objectives over two variables subject to one constraint, with a front of one continuous piece and 15 separate points, unevenly spaced. -NSGA-II with the settings of the report's experiments, a population of 100 for 500 +NSGA-II with the settings of the paper's experiments, a population of 100 for 500 generations, and the same for 10,000. Prints, for each, how many solutions of the final front are feasible, how many of the optimal points they reach, their IGD+ to the front and their hypervolume. @@ -53,7 +53,7 @@ def report(name, generations, result): def nsga2(): - """NSGA-II with the settings of the report's experiments: a population of 100, SBX and + """NSGA-II with the settings of the paper's experiments: a population of 100, SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" return gx.Nsga2( problem.genome, diff --git a/examples/ctp5/main.rs b/examples/ctp5/main.rs index ea8397e5..ecbdb348 100644 --- a/examples/ctp5/main.rs +++ b/examples/ctp5/main.rs @@ -1,7 +1,7 @@ //! CTP5: minimize two objectives over two variables subject to one constraint, with //! a front of one continuous piece and 15 separate points, unevenly spaced. //! -//! NSGA-II with the settings of the report's experiments, a population of 100 for 500 +//! NSGA-II with the settings of the paper's experiments, a population of 100 for 500 //! generations, and the same for 10,000. Prints, for each, how many solutions of the final front //! are feasible, how many of the optimal points they reach, their IGD+ to the front and their //! hypervolume. @@ -25,7 +25,7 @@ const REACH: f64 = 0.02; fn main() -> Result<()> { let problem = Ctp5; - // the settings of the report's experiments: a population of 100 for 500 generations, SBX + // the settings of the paper's experiments: a population of 100 for 500 generations, SBX // and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene; then // the same for 10,000 generations for generations in [500, 10000] { diff --git a/examples/ctp6/README.md b/examples/ctp6/README.md index 1574c484..341d262a 100644 --- a/examples/ctp6/README.md +++ b/examples/ctp6/README.md @@ -25,7 +25,7 @@ subject to cos θ (f₂ − e) − sin θ f₁ ≥ a |sin(bπ (sin θ (f₂ − x₁ in [0, 1], x₂ in [0, 10] ``` -The report's section on difficulty in the whole search space gives CTP6 very different +The paper's section on difficulty in the whole search space gives CTP6 very different parameters: θ = 0.1π, a = 40, b = 0.5, c = 1, d = 2 and e = −2. Turned by θ = 0.1π, the coordinate v = sin θ (f₂ + 2) + cos θ f₁ runs across the objective space, and the wave 40 sin²(πv/2) is 0 only where v is an even number. The left side, u, stays between 1.6 and 12.4 @@ -35,18 +35,20 @@ v = 2, 4, 6, …, parallel to the front and to each other, with infeasible bands The unconstrained front, f₂ = 1 − √f₁ at g = 1, lies in the infeasible band below v = 2. The optimal front is the lower edge of the first feasible band, one continuous piece from (0, 3.6958) to (1, 0.8813), found by sampling the boundaries of the feasible region. On it, v runs from 1.76 -to 1.84; the report puts the front where v is between 1 and 2. +to 1.84; the paper puts the front where v is between 1 and 2. -The definitions come from the authors' KanGAL report 200005 (October 2000), the paper's preprint: -eq. 5 on p. 7 and CTP6's parameters on p. 10. The report leaves g, the number of variables and -their bounds open, and prints f₂ as g (1 − f₁/g); its figures draw the unconstrained front as the -curve 1 − √f₁, and the authors' NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) -with g = 1 + x₂, x₁ in [0, 1] and x₂ in [0, 10], which genoxide follows. +The definitions are the paper's: eq. 5 (p. 290) and CTP6's parameters (p. 293). Its preprint, the +authors' KanGAL report 200005 (October 2000, p. 10), and Deb's 2001 book (*Multi-Objective +Optimization Using Evolutionary Algorithms*, Wiley, eq. 8.46 on p. 354 and the parameters on p. 357) +give the same. All three leave g, the number of variables and their bounds open, and print f₂ as g +(1 − f₁/g); their figures draw the unconstrained front as the curve 1 − √f₁, and the authors' +NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with g = 1 + x₂, the g the book names +on p. 360, and x₁ in [0, 1] and x₂ in [0, 10], which genoxide follows. ## What makes it hard Solutions in the upper feasible bands have to cross the infeasible bands between them, -"infeasible holes of differing widths", in the report's words, to reach the band that holds the +"infeasible holes of differing widths", in the paper's words, to reach the band that holds the front. 22% of random genomes are feasible. Once the population is in the right band, the front is its lower edge: every optimal solution meets the constraint exactly, and just below it lies infeasible space. @@ -63,7 +65,7 @@ violation, which leads the search across the infeasible bands. ## Algorithm -NSGA-II with the settings of the report's experiments: +NSGA-II with the settings of the paper's experiments: - a population of 100, for 500 generations; - simulated binary crossover with η = 20, at a rate of 0.9; @@ -95,5 +97,5 @@ of the optimal front, spread evenly along it, give 99.31% of its hypervolume and The run's front has 100 solutions, all feasible, an IGD+ of 0.0052 and 98.61% of the whole front's hypervolume. Over seeds 1 to 20, every run reaches the front, with an IGD+ from 0.0046 to -0.0053 and 98.56% to 98.75% of the hypervolume. The report found NSGA-II "very near to the true +0.0053 and 98.56% to 98.75% of the hypervolume. The paper found NSGA-II "very near to the true Pareto-optimal front" with its five variables too. diff --git a/examples/ctp6/main.py b/examples/ctp6/main.py index d72c8122..1ecf4db5 100644 --- a/examples/ctp6/main.py +++ b/examples/ctp6/main.py @@ -1,7 +1,7 @@ """CTP6: minimize two objectives over two variables subject to one constraint, with a front behind infeasible bands that cross the whole objective space. -NSGA-II with the settings of the report's experiments, a population of 100 for 500 +NSGA-II with the settings of the paper's experiments, a population of 100 for 500 generations. Prints how many solutions of the final front are feasible, how many pieces of the optimal front they reach, their IGD+ to it and their hypervolume. @@ -52,7 +52,7 @@ def report(name, generations, result): def nsga2(): - """NSGA-II with the settings of the report's experiments: a population of 100, SBX and + """NSGA-II with the settings of the paper's experiments: a population of 100, SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" return gx.Nsga2( problem.genome, diff --git a/examples/ctp6/main.rs b/examples/ctp6/main.rs index bf4e946c..35be82b9 100644 --- a/examples/ctp6/main.rs +++ b/examples/ctp6/main.rs @@ -1,7 +1,7 @@ //! CTP6: minimize two objectives over two variables subject to one constraint, with //! a front behind infeasible bands that cross the whole objective space. //! -//! NSGA-II with the settings of the report's experiments, a population of 100 for 500 +//! NSGA-II with the settings of the paper's experiments, a population of 100 for 500 //! generations. Prints how many solutions of the final front are feasible, how many pieces of //! the optimal front they reach, their IGD+ to it and their hypervolume. //! @@ -24,7 +24,7 @@ const REACH: f64 = 0.02; fn main() -> Result<()> { let problem = Ctp6; - // the settings of the report's experiments: a population of 100 for 500 generations, SBX + // the settings of the paper's experiments: a population of 100 for 500 generations, SBX // and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene let nsga2 = Nsga2::builder(problem.representation(), [Minimize; 2]) .population_size(100) diff --git a/examples/ctp7/README.md b/examples/ctp7/README.md index 6e678605..8ede1175 100644 --- a/examples/ctp7/README.md +++ b/examples/ctp7/README.md @@ -38,21 +38,26 @@ feasible f₂ is 1.0446, on the edge of a band, and that point is optimal too, s smaller f₁. The front was found by sampling the boundaries of the feasible region. -The definitions come from the authors' KanGAL report 200005 (October 2000), the paper's preprint: -eq. 5 on p. 7 and CTP7's parameters on pp. 10-11. The report leaves g, the number of variables and -their bounds open, and prints f₂ as g (1 − f₁/g); its figures draw the unconstrained front as the -curve 1 − √f₁, and the authors' NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) -with g = 1 + x₂, x₁ in [0, 1] and x₂ in [0, 10], which genoxide follows. +The definitions are the paper's: eq. 5 (p. 290) and CTP7's parameters (pp. 293-294). Its preprint, +the authors' KanGAL report 200005 (October 2000, pp. 10-11), and Deb's 2001 book (*Multi-Objective +Optimization Using Evolutionary Algorithms*, Wiley, eq. 8.46 on p. 354 and the parameters on p. 358) +give the same. All three leave g, the number of variables and their bounds open, and print f₂ as g +(1 − f₁/g); their figures draw the unconstrained front as the curve 1 − √f₁, and the authors' +NSGA-II code (version 1.1.6, KanGAL) computes g (1 − √(f₁/g)) with g = 1 + x₂, the g the book names +on p. 360, and x₁ in [0, 1] and x₂ in [0, 10], which genoxide follows. The book shows CTP7's +decision space with x₂ in [0, 1] (p. 360); the front is the same. The paper's figure 11 (the book's +231) marks the five inner pieces, not the sixth at f₁ = 1 or the point at f₁ = 0, on the plot's +edges. ## What makes it hard -The report: "In order to find all such disconnected regions, an algorithm has to maintain an +The paper: "In order to find all such disconnected regions, an algorithm has to maintain an adequate diversity right from the beginning of a simulation run. Moreover, the algorithm also has to maintain its solutions feasible as it proceeds towards the Pareto-optimal region." A group of solutions that converges in one band can't cross into the next: the bands run from far above the front down to it. 47% of random genomes are feasible. -In the report's experiments, with five variables and a Rastrigin g, CTP7 was the hardest problem: +In the paper's experiments, with five variables and a Rastrigin g, CTP7 was the hardest problem: neither algorithm got close to the front. With the two variables and g = 1 + x₂ of the authors' code, converging is easy, since x₂ = 0 is optimal everywhere, and the difficulty is the diversity alone. @@ -68,7 +73,7 @@ Pareto dominance decides. ## Algorithm -NSGA-II with the settings of the report's experiments: +NSGA-II with the settings of the paper's experiments: - a population of 100, for 500 generations; - simulated binary crossover with η = 20, at a rate of 0.9; diff --git a/examples/ctp7/main.py b/examples/ctp7/main.py index b47fb3c8..bbaf85c7 100644 --- a/examples/ctp7/main.py +++ b/examples/ctp7/main.py @@ -1,7 +1,7 @@ """CTP7: minimize two objectives over two variables subject to one constraint, with a front of six disconnected pieces between infeasible bands. -NSGA-II with the settings of the report's experiments, a population of 100 for 500 +NSGA-II with the settings of the paper's experiments, a population of 100 for 500 generations. Prints how many solutions of the final front are feasible, how many pieces of the optimal front they reach, their IGD+ to it and their hypervolume. @@ -52,7 +52,7 @@ def report(name, generations, result): def nsga2(): - """NSGA-II with the settings of the report's experiments: a population of 100, SBX and + """NSGA-II with the settings of the paper's experiments: a population of 100, SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" return gx.Nsga2( problem.genome, diff --git a/examples/ctp7/main.rs b/examples/ctp7/main.rs index 1ae3c3c1..7dd28a22 100644 --- a/examples/ctp7/main.rs +++ b/examples/ctp7/main.rs @@ -1,7 +1,7 @@ //! CTP7: minimize two objectives over two variables subject to one constraint, with //! a front of six disconnected pieces between infeasible bands. //! -//! NSGA-II with the settings of the report's experiments, a population of 100 for 500 +//! NSGA-II with the settings of the paper's experiments, a population of 100 for 500 //! generations. Prints how many solutions of the final front are feasible, how many pieces of //! the optimal front they reach, their IGD+ to it and their hypervolume. //! @@ -24,7 +24,7 @@ const REACH: f64 = 0.02; fn main() -> Result<()> { let problem = Ctp7; - // the settings of the report's experiments: a population of 100 for 500 generations, SBX + // the settings of the paper's experiments: a population of 100 for 500 generations, SBX // and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene let nsga2 = Nsga2::builder(problem.representation(), [Minimize; 2]) .population_size(100) diff --git a/examples/ctp8/README.md b/examples/ctp8/README.md index 7d91456c..7c3f44f7 100644 --- a/examples/ctp8/README.md +++ b/examples/ctp8/README.md @@ -2,7 +2,7 @@ title: CTP8 category: multi-objective summary: Minimize two objectives subject to two constraints, bands parallel to the front and bands across it, which leave feasible patches and a front of three disconnected pieces, with NSGA-II. -reference: "Deb, K. (2001). Multi-Objective Optimization Using Evolutionary Algorithms. Wiley, Chichester." +reference: "Deb, K. (2001). Multi-Objective Optimization Using Evolutionary Algorithms. Wiley, Chichester. Section 8.3.5, eq. 8.46 and p. 358." reference_url: "" optimum: "three pieces of CTP6's front, from (0, 3.6958) to (0.1345, 3.3128), (0.3263, 2.7686) to (0.4790, 2.3372) and (0.6823, 1.7654) to (0.8229, 1.3727); hypervolume 0.6540 in objectives scaled by the ideal and nadir points (reference point (1.1, 1.1))" languages: [rust, python] @@ -37,12 +37,15 @@ front is the parts of CTP6's front that the second constraint allows: three piec (0.6823, 1.7654) to (0.8229, 1.3727), found by sampling the boundaries of the feasible region. Only 10% of random genomes are feasible. -CTP8 isn't in the EMO 2001 paper, which has CTP1 to CTP7. Later papers credit it to Deb's book -(2001, *Multi-Objective Optimization Using Evolutionary Algorithms*, Wiley), which I couldn't -read. The definition here is the one in the NSGA-II code of Deb's group (version 1.1.6, KanGAL), -with the same g, variables and bounds as its CTP6 and CTP7; the parameters of the two constraints -come from there. The constraint's form is the one of the EMO 2001 paper, checked in the authors' -KanGAL report 200005 (eq. 5). +CTP8 isn't in the EMO 2001 paper, which has CTP1 to CTP7: it's in Deb's book (2001, *Multi-Objective +Optimization Using Evolutionary Algorithms*, Wiley), section 8.3.5, as the two constraints above +(its C₁ and C₂, p. 358), of the form of eq. 8.46 (p. 354), which the book names "CTP2-CTP8". The +NSGA-II code of Deb's group (version 1.1.6, KanGAL) has the same parameters. The book's figure 232 +(p. 359) marks three Pareto-optimal regions, at f₁ from 0 to about 0.13, 0.33 to 0.48 and 0.68 to +0.82: the three pieces above. Like the paper for CTP2 to CTP7, the book leaves g, the number of +variables and their bounds open, and prints f₂ as g (1 − f₁/g), while its figures draw the curve 1 − +√f₁; genoxide takes g (1 − √(f₁/g)), g = 1 + x₂ (the g the book names on p. 360), x₁ in [0, 1] and +x₂ in [0, 10] from the code, as for CTP6 and CTP7. ## What makes it hard diff --git a/examples/ctp8/main.py b/examples/ctp8/main.py index 53f72e50..f33934a1 100644 --- a/examples/ctp8/main.py +++ b/examples/ctp8/main.py @@ -1,9 +1,9 @@ """CTP8: minimize two objectives over two variables subject to two constraints, with a front of three disconnected pieces, behind two kinds of infeasible bands. -NSGA-II with the settings of the report's experiments, a population of 100 for 500 -generations. Prints how many solutions of the final front are feasible, how many pieces of -the optimal front they reach, their IGD+ to it and their hypervolume. +NSGA-II with the settings of the EMO 2001 paper's experiments, a population of 100 for +500 generations. Prints how many solutions of the final front are feasible, how many pieces +of the optimal front they reach, their IGD+ to it and their hypervolume. With ``GENOXIDE_TRACE=``, it also writes a trace of its run for the plot on the example's page, with trace.py. @@ -52,8 +52,8 @@ def report(name, generations, result): def nsga2(): - """NSGA-II with the settings of the report's experiments: a population of 100, SBX and - polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" + """NSGA-II with the settings of the EMO 2001 paper's experiments: a population of 100, + SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene.""" return gx.Nsga2( problem.genome, objectives=problem.objectives, diff --git a/examples/ctp8/main.rs b/examples/ctp8/main.rs index b4dd30f8..4ba82bb9 100644 --- a/examples/ctp8/main.rs +++ b/examples/ctp8/main.rs @@ -1,9 +1,9 @@ //! CTP8: minimize two objectives over two variables subject to two constraints, with //! a front of three disconnected pieces, behind two kinds of infeasible bands. //! -//! NSGA-II with the settings of the report's experiments, a population of 100 for 500 -//! generations. Prints how many solutions of the final front are feasible, how many pieces of -//! the optimal front they reach, their IGD+ to it and their hypervolume. +//! NSGA-II with the settings of the EMO 2001 paper's experiments, a population of 100 for +//! 500 generations. Prints how many solutions of the final front are feasible, how many pieces +//! of the optimal front they reach, their IGD+ to it and their hypervolume. //! //! With `GENOXIDE_TRACE=`, it also writes a trace of its run for the plot on //! the example's page, with `trace.rs`. @@ -24,8 +24,9 @@ const REACH: f64 = 0.02; fn main() -> Result<()> { let problem = Ctp8; - // the settings of the report's experiments: a population of 100 for 500 generations, SBX - // and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n per gene + // the settings of the EMO 2001 paper's experiments: a population of 100 for 500 + // generations, SBX and polynomial mutation with η = 20, crossover at 0.9 and mutation at 1/n + // per gene let nsga2 = Nsga2::builder(problem.representation(), [Minimize; 2]) .population_size(100) .crossover(SimulatedBinaryCrossover::new(20.0)?) diff --git a/python/genoxide/problems/__init__.py b/python/genoxide/problems/__init__.py index 88b99168..df1ef2aa 100644 --- a/python/genoxide/problems/__init__.py +++ b/python/genoxide/problems/__init__.py @@ -2426,9 +2426,9 @@ class Ctp1(MultiProblem[Real]): Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective evolutionary optimization. Evolutionary Multi-Criterion Optimization (EMO 2001), LNCS 1993: - 284-298, checked in the authors' KanGAL report 200005; g = 1 + x₂, the two variables, their - bounds and f₂'s square root as in the authors' NSGA-II code, since the report leaves them - open and prints f₂ without the root that its figures and the code have. + 284-298, eq. 4, the same in the authors' KanGAL report 200005 and in Deb's 2001 book (eq. + 8.45); g = 1 + x₂, the two variables and their bounds as in the authors' NSGA-II code, + since all three leave them open. """ _type: ClassVar[str] = "ctp1" @@ -2445,9 +2445,10 @@ class Ctp2(MultiProblem[Real]): Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective evolutionary optimization. Evolutionary Multi-Criterion Optimization (EMO 2001), LNCS 1993: - 284-298, checked in the authors' KanGAL report 200005; g = 1 + x₂, the two variables, their - bounds and f₂'s square root as in the authors' NSGA-II code, since the report leaves them - open and prints f₂ without the root that its figures and the code have. + 284-298, the same in the authors' KanGAL report 200005 and in Deb's 2001 book (section + 8.3.5); g = 1 + x₂, the two variables, their bounds and f₂'s square root as in the authors' + NSGA-II code, since all three leave them open and print f₂ without the root that their + figures and the code have. """ _type: ClassVar[str] = "ctp2" @@ -2460,9 +2461,10 @@ class Ctp3(MultiProblem[Real]): Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective evolutionary optimization. Evolutionary Multi-Criterion Optimization (EMO 2001), LNCS 1993: - 284-298, checked in the authors' KanGAL report 200005; g = 1 + x₂, the two variables, their - bounds and f₂'s square root as in the authors' NSGA-II code, since the report leaves them - open and prints f₂ without the root that its figures and the code have. + 284-298, the same in the authors' KanGAL report 200005 and in Deb's 2001 book (section + 8.3.5); g = 1 + x₂, the two variables, their bounds and f₂'s square root as in the authors' + NSGA-II code, since all three leave them open and print f₂ without the root that their + figures and the code have. """ _type: ClassVar[str] = "ctp3" @@ -2475,9 +2477,10 @@ class Ctp4(MultiProblem[Real]): Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective evolutionary optimization. Evolutionary Multi-Criterion Optimization (EMO 2001), LNCS 1993: - 284-298, checked in the authors' KanGAL report 200005; g = 1 + x₂, the two variables, their - bounds and f₂'s square root as in the authors' NSGA-II code, since the report leaves them - open and prints f₂ without the root that its figures and the code have. + 284-298, the same in the authors' KanGAL report 200005 and in Deb's 2001 book (section + 8.3.5); g = 1 + x₂, the two variables, their bounds and f₂'s square root as in the authors' + NSGA-II code, since all three leave them open and print f₂ without the root that their + figures and the code have. """ _type: ClassVar[str] = "ctp4" @@ -2491,9 +2494,10 @@ class Ctp5(MultiProblem[Real]): Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective evolutionary optimization. Evolutionary Multi-Criterion Optimization (EMO 2001), LNCS 1993: - 284-298, checked in the authors' KanGAL report 200005; g = 1 + x₂, the two variables, their - bounds and f₂'s square root as in the authors' NSGA-II code, since the report leaves them - open and prints f₂ without the root that its figures and the code have. + 284-298, the same in the authors' KanGAL report 200005 and in Deb's 2001 book (section + 8.3.5); g = 1 + x₂, the two variables, their bounds and f₂'s square root as in the authors' + NSGA-II code, since all three leave them open and print f₂ without the root that their + figures and the code have. """ _type: ClassVar[str] = "ctp5" @@ -2508,9 +2512,10 @@ class Ctp6(MultiProblem[Real]): Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective evolutionary optimization. Evolutionary Multi-Criterion Optimization (EMO 2001), LNCS 1993: - 284-298, checked in the authors' KanGAL report 200005; g = 1 + x₂, the two variables, their - bounds and f₂'s square root as in the authors' NSGA-II code, since the report leaves them - open and prints f₂ without the root that its figures and the code have. + 284-298, the same in the authors' KanGAL report 200005 and in Deb's 2001 book (section + 8.3.5); g = 1 + x₂, the two variables, their bounds and f₂'s square root as in the authors' + NSGA-II code, since all three leave them open and print f₂ without the root that their + figures and the code have. """ _type: ClassVar[str] = "ctp6" @@ -2525,9 +2530,10 @@ class Ctp7(MultiProblem[Real]): Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective evolutionary optimization. Evolutionary Multi-Criterion Optimization (EMO 2001), LNCS 1993: - 284-298, checked in the authors' KanGAL report 200005; g = 1 + x₂, the two variables, their - bounds and f₂'s square root as in the authors' NSGA-II code, since the report leaves them - open and prints f₂ without the root that its figures and the code have. + 284-298, the same in the authors' KanGAL report 200005 and in Deb's 2001 book (section + 8.3.5); g = 1 + x₂, the two variables, their bounds and f₂'s square root as in the authors' + NSGA-II code, since all three leave them open and print f₂ without the root that their + figures and the code have. """ _type: ClassVar[str] = "ctp7" @@ -2539,9 +2545,11 @@ class Ctp8(MultiProblem[Real]): x₁ in [0, 1], x₂ in [0, 10]. The front is three disconnected pieces of CTP6's, from about (0, 3.6958) to (0.8229, 1.3727). - Deb, K. (2001). Multi-Objective Optimization Using Evolutionary Algorithms. Wiley, as later - papers credit it; the book wasn't read, and the definition is the one in the NSGA-II code - of Deb's group. Not in the EMO 2001 paper, which has CTP1-CTP7. + Deb, K. (2001). Multi-Objective Optimization Using Evolutionary Algorithms. Wiley, section + 8.3.5: eq. 8.46 with the two constraints of p. 358, the parameters of the NSGA-II code of + Deb's group too; the book's figure 232 marks the three pieces. Not in the EMO 2001 paper, + which has CTP1-CTP7. g = 1 + x₂, the variables, their bounds and f₂'s square root as for + :class:`Ctp6`. """ _type: ClassVar[str] = "ctp8" diff --git a/src/multi/problems/ctp.rs b/src/multi/problems/ctp.rs index 699d7e87..2a15c511 100644 --- a/src/multi/problems/ctp.rs +++ b/src/multi/problems/ctp.rs @@ -2,19 +2,27 @@ //! two constraints each, whose constraints make the optimal front disconnected, a set of points, //! or hidden behind infeasible bands. //! -//! The definitions were checked in the authors' KanGAL report 200005 (October 2000), the preprint -//! of the EMO 2001 paper (the number in KanGAL's list of reports; the file's title page misprints -//! 200002, the number of Deb, Pratap and Moitra's report of the same year): CTP1 is its eq. 4 -//! (p. 6) with the table of a and b on p. 6, and CTP2 to CTP7 its eq. 5 (p. 7) with the -//! parameters on pp. 7-11. The report leaves the function g, the number of variables and their -//! bounds open (its experiments use "Rastrigin's function as the g functional" and five -//! variables, without the formula); genoxide takes them from the authors' -//! NSGA-II code (version 1.1.6, KanGAL), which defines every CTP problem with two variables, -//! `g = 1 + x₂`, x₁ in [0, 1] and x₂ in [0, 1] (CTP1-CTP5) or [0, 10] (CTP6-CTP8). The report's -//! eq. 5 prints `f₂ = g (1 − f₁/g)`; its figures 6-11 draw the unconstrained front as the curve -//! `f₂ = 1 − √f₁`, and the authors' code computes `f₂ = g (1 − √(f₁/g))`, which genoxide uses. -//! CTP8 isn't in the report: it's credited to Deb's 2001 book (not read), and its definition -//! here is the authors' code's, CTP6's constraint with a second one like CTP7's (b = 2). +//! The definitions were checked in three sources, which agree. The published EMO 2001 paper +//! (LNCS 1993: 284-298) has CTP1 as its eq. 4 with the table of a and b (p. 289), and CTP2 to +//! CTP7 as its eq. 5 (p. 290) with the parameters on pp. 290-294; its preprint, the authors' +//! KanGAL report 200005 (October 2000; the number in KanGAL's list of reports, the file's title +//! page misprints 200002, the number of Deb, Pratap and Moitra's report of the same year), has +//! the same equations on pp. 6-11. Deb's 2001 book restates them in section 8.3.5, pp. 352-360: +//! CTP1 as eq. 8.45 (p. 353), the generator as eq. 8.46 (p. 354), named "CTP2-CTP8" there, the +//! parameters of CTP2 to CTP7 on pp. 355-358, and CTP8, which the paper doesn't have, as two +//! constraints of that form (p. 358, figure 232 on p. 359). +//! +//! None of them fixes the number of variables or their bounds (the paper's experiments use +//! "Rastrigin's function as the g functional" and five variables, without the formula, and the +//! book says that the bounds of the variables other than x₁ "depend on the chosen g(x) +//! function"); genoxide takes them from the authors' NSGA-II code (version 1.1.6, KanGAL), +//! which defines every CTP problem with two variables, `g = 1 + x₂`, x₁ in [0, 1] and x₂ in +//! [0, 1] (CTP1-CTP5) or [0, 10] (CTP6-CTP8). The book names that g, `g₁(x) = 1 + x₂` (p. 360), +//! and shows CTP7's decision space with x₂ in [0, 1]; CTP6's and CTP8's fronts need x₂ up to +//! 2.7, so [0, 10] is kept, and CTP7's front is the same either way. The paper's eq. 5, the +//! report's and the book's eq. 8.46 all print `f₂ = g (1 − f₁/g)`; their figures draw the +//! unconstrained front as the curve `f₂ = 1 − √f₁`, and the authors' code computes +//! `f₂ = g (1 − √(f₁/g))`, which genoxide uses. use super::{MultiProblem, Piece, evenly, non_dominated, pieces_front}; use crate::constraint::at_most; @@ -31,7 +39,7 @@ const REFERENCE: &str = "Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrain const REFERENCE_URL: &str = "https://doi.org/10.1007/3-540-44719-9_20"; const BOOK: &str = "Deb, K. (2001). Multi-Objective Optimization Using Evolutionary Algorithms. \ - Wiley, Chichester."; + Wiley, Chichester. Section 8.3.5, eq. 8.46 and p. 358."; // bounds that are valid by construction: x₁ in [0, 1], x₂ in [0, `x2`] fn bounds(x2: f64) -> Real { @@ -45,7 +53,7 @@ fn violation(values: &[f64]) -> f64 { // ---- the constraint of CTP2-CTP8 ----------------------------------------------------------------- -// the constraint of the report's eq. 5, `cos θ (f₂ − e) − sin θ f₁ ≥ a |sin(bπ (sin θ (f₂ − e) + +// the constraint of the paper's eq. 5, `cos θ (f₂ − e) − sin θ f₁ ≥ a |sin(bπ (sin θ (f₂ − e) + // cos θ f₁)^c)|^d`, with sin θ and cos θ computed once #[derive(Clone, Copy, Debug)] struct Wave { @@ -320,7 +328,8 @@ fn extremes(front: &[[f64; 2]]) -> ([f64; 2], [f64; 2]) { // ---- CTP1 ---------------------------------------------------------------------------------------- -// CTP1's a and b, the table of the report (p. 6), which the authors' code uses too +// CTP1's a and b, the table of the paper (p. 289), the report (p. 6) and the book (p. 353), +// which the authors' code uses too const CTP1_A: [f64; 2] = [0.858, 0.728]; const CTP1_B: [f64; 2] = [0.541, 0.295]; @@ -332,29 +341,32 @@ const CTP1_B: [f64; 2] = [0.541, 0.295]; /// the three curves `exp(−f₁)`, `0.858 exp(−0.541 f₁)` and `0.728 exp(−0.295 f₁)`, at g = 1 up to /// f₁ = ln(0.858)/(−0.459) ≈ 0.33367, on the first constraint's boundary up to /// f₁ = ln(0.858/0.728)/0.246 ≈ 0.66789, and on the second's to f₁ = 1: from (0, 1) to -/// (1, 0.728 e^−0.295), a front whose two thirds lie on constraint boundaries, as the report says. +/// (1, 0.728 e^−0.295), a front whose two thirds lie on constraint boundaries, as the paper says. /// /// [`constraints`](MultiProblem::constraints) gives `aⱼ exp(−bⱼ f₁) − f₂` for j = 1, 2. /// /// Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for multi-objective /// evolutionary optimization. *Evolutionary Multi-Criterion Optimization (EMO 2001)*, LNCS 1993: -/// 284-298, eq. 4 and its table of a and b, checked in the authors' KanGAL report 200005 -/// (p. 6). The report builds a and b by a procedure for J constraints, and prints them to three -/// digits, the values the authors' code uses and genoxide too. +/// 284-298, eq. 4 and its table of a and b (p. 289), the same in the authors' KanGAL report +/// 200005 (p. 6) and in Deb's 2001 book (eq. 8.45, p. 353). They build a and b by a procedure +/// for J constraints, and print them to three digits, the values the authors' code uses and +/// genoxide too. /// -/// What was checked where, for all the CTP problems: the definitions in the authors' KanGAL -/// report 200005 (October 2000, the EMO paper's preprint, whose title page misprints 200002; the -/// published paper wasn't compared): -/// CTP1 is its eq. 4 with the table of a and b (p. 6), and CTP2-CTP7 its eq. 5 (p. 7) with the -/// parameters on pp. 7-11. The report leaves g, the number of variables and their bounds open -/// (its experiments use "Rastrigin's function as the g functional" and five variables, without -/// the formula); genoxide takes them from the authors' NSGA-II code (version 1.1.6, KanGAL), -/// which defines every CTP problem with two variables, `g = 1 + x₂`, x₁ in [0, 1] and x₂ in -/// [0, 1] (CTP1-CTP5) or [0, 10] (CTP6-CTP8). The report's eq. 5 prints `f₂ = g (1 − f₁/g)`; -/// its figures 6-11 draw the unconstrained front as the curve `f₂ = 1 − √f₁`, and the authors' -/// code computes `f₂ = g (1 − √(f₁/g))`, which CTP2-CTP8 use. The code writes each constraint -/// as a ratio, `left/right − 1 ≥ 0`; genoxide keeps the report's difference, which is feasible -/// at the same points and finite where the right-hand side is 0. +/// What was checked where, for all the CTP problems: the definitions in the published paper +/// (pp. 289-294), its preprint, the authors' KanGAL report 200005 (October 2000, whose title +/// page misprints 200002; pp. 6-11), and Deb's 2001 book (section 8.3.5, pp. 352-360), which +/// agree: CTP1 is eq. 4 (the book's eq. 8.45) with the table of a and b, and CTP2-CTP7 eq. 5 +/// (the book's eq. 8.46) with the parameters that follow it; CTP8 is the book's alone (p. 358). +/// None of them fixes the number of variables or their bounds (the paper's experiments use +/// "Rastrigin's function as the g functional" and five variables, without the formula); +/// genoxide takes them from the authors' NSGA-II code (version 1.1.6, KanGAL), which defines +/// every CTP problem with two variables, `g = 1 + x₂`, x₁ in [0, 1] and x₂ in [0, 1] +/// (CTP1-CTP5) or [0, 10] (CTP6-CTP8); the book names that g, `g₁(x) = 1 + x₂` (p. 360). The +/// paper's eq. 5, like the report's and the book's eq. 8.46, prints `f₂ = g (1 − f₁/g)`; their +/// figures draw the unconstrained front as the curve `f₂ = 1 − √f₁`, and the authors' code +/// computes `f₂ = g (1 − √(f₁/g))`, which CTP2-CTP8 use. The code writes each constraint as a +/// ratio, `left/right − 1 ≥ 0`; genoxide keeps the paper's difference, which is feasible at the +/// same points and finite where the right-hand side is 0. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] pub struct Ctp1; @@ -579,7 +591,7 @@ ctp!( /// a = 0.2, b = 10, c = 1, d = 6 and e = 1. /// /// Bounds [0, 1]². The constraint's boundary waves above the line `(f₂ − e) cos θ = f₁ sin θ` - /// (the report's eq. 6), `f₂ = 1 − 0.7265 f₁`, and touches it where the sine is 0: the + /// (the paper's eq. 6), `f₂ = 1 − 0.7265 f₁`, and touches it where the sine is 0: the /// unconstrained front below the line is infeasible, and the front is 13 disconnected pieces /// of the boundary, each starting on the line, from (0, 1) to about (0.9845, 0.2872). /// [`optimal_front`](MultiProblem::optimal_front) samples the boundaries of the feasible @@ -590,9 +602,10 @@ ctp!( /// /// Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for /// multi-objective evolutionary optimization. *Evolutionary Multi-Criterion Optimization - /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5 and the parameters that follow it, checked in the - /// authors' KanGAL report 200005 (p. 7); f₂'s square root, g, the variables and their bounds - /// as in the authors' code (see [`Ctp1`]'s notes). + /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5 and the parameters that follow it (p. 290), the + /// same in the authors' KanGAL report 200005 (p. 7) and in Deb's 2001 book (eq. 8.46, p. 355); + /// f₂'s square root, g, the variables and their bounds as in the authors' code (see + /// [`Ctp1`]'s notes). Ctp2, "CTP2", REFERENCE, x2 in [0, 1.0], [wave(-0.2, 0.2, 10.0, 1, 6.0, 1.0)] ); @@ -610,9 +623,10 @@ ctp!( /// /// Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for /// multi-objective evolutionary optimization. *Evolutionary Multi-Criterion Optimization - /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5, checked in the authors' KanGAL report 200005 - /// (p. 8: d = 0.5 and a = 0.1, the rest as CTP2); f₂'s square root, g, the variables and - /// their bounds as in the authors' code (see [`Ctp1`]'s notes). + /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5 (p. 291: d = 0.5 and a = 0.1, the rest as CTP2), + /// the same in the authors' KanGAL report 200005 (p. 8) and in Deb's 2001 book (p. 355), whose + /// figures (the paper's 7, the book's 227) mark the 13 points; f₂'s square root, g, the + /// variables and their bounds as in the authors' code (see [`Ctp1`]'s notes). Ctp3, "CTP3", REFERENCE, x2 in [0, 1.0], [wave(-0.2, 0.1, 10.0, 1, 0.5, 1.0)] ); @@ -625,9 +639,9 @@ ctp!( /// /// Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for /// multi-objective evolutionary optimization. *Evolutionary Multi-Criterion Optimization - /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5, checked in the authors' KanGAL report 200005 - /// (p. 8: a = 0.75, the rest as CTP3); f₂'s square root, g, the variables and their bounds as - /// in the authors' code (see [`Ctp1`]'s notes). + /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5 (p. 291: a = 0.75, the rest as CTP3), the same in + /// the authors' KanGAL report 200005 (p. 8) and in Deb's 2001 book (p. 356); f₂'s square root, + /// g, the variables and their bounds as in the authors' code (see [`Ctp1`]'s notes). Ctp4, "CTP4", REFERENCE, x2 in [0, 1.0], [wave(-0.2, 0.75, 10.0, 1, 0.5, 1.0)] ); @@ -644,9 +658,11 @@ ctp!( /// /// Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for /// multi-objective evolutionary optimization. *Evolutionary Multi-Criterion Optimization - /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5, checked in the authors' KanGAL report 200005 - /// (p. 9: c = 2, the rest as CTP3); f₂'s square root, g, the variables and their bounds as in - /// the authors' code (see [`Ctp1`]'s notes). + /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5 (p. 292: c = 2, the rest as CTP3), the same in the + /// authors' KanGAL report 200005 (p. 9) and in Deb's 2001 book (p. 357); f₂'s square root, g, + /// the variables and their bounds as in the authors' code (see [`Ctp1`]'s notes). The + /// paper's figure 9 (the book's 229) draws the first stretch and marks the points for + /// k = 1, …, 14, not the last one, at f₁ ≈ 0.9908, which is feasible and optimal too. Ctp5, "CTP5", REFERENCE, x2 in [0, 1.0], [wave(-0.2, 0.1, 10.0, 2, 0.5, 1.0)] ); @@ -662,11 +678,11 @@ ctp!( /// /// Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for /// multi-objective evolutionary optimization. *Evolutionary Multi-Criterion Optimization - /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5, checked in the authors' KanGAL report 200005 - /// (p. 10); f₂'s square root, g, the variables and their bounds as in the authors' code (see - /// [`Ctp1`]'s notes). The report says the front is where - /// `1 ≤ (f₂ − e) sin θ + f₁ cos θ ≤ 2`; on the front found here, that coordinate runs from - /// 1.76 to 1.84. + /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5 (p. 293), the same in the authors' KanGAL report + /// 200005 (p. 10) and in Deb's 2001 book (p. 357); f₂'s square root, g, the variables and + /// their bounds as in the authors' code (see [`Ctp1`]'s notes). The paper and the report say + /// the front is where `1 ≤ (f₂ − e) sin θ + f₁ cos θ ≤ 2` (the book leaves it out); on the + /// front found here, that coordinate runs from 1.76 to 1.84. Ctp6, "CTP6", REFERENCE, x2 in [0, 10.0], [wave(0.1, 40.0, 0.5, 1, 2.0, -2.0)] ); @@ -684,9 +700,12 @@ ctp!( /// /// Deb, K., Pratap, A. and Meyarivan, T. (2001). Constrained test problems for /// multi-objective evolutionary optimization. *Evolutionary Multi-Criterion Optimization - /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5, checked in the authors' KanGAL report 200005 - /// (pp. 10-11); f₂'s square root, g, the variables and their bounds as in the authors' code - /// (see [`Ctp1`]'s notes). + /// (EMO 2001)*, LNCS 1993: 284-298, eq. 5 (pp. 293-294), the same in the authors' KanGAL + /// report 200005 (pp. 10-11) and in Deb's 2001 book (p. 358); f₂'s square root, g, the + /// variables and their bounds as in the authors' code (see [`Ctp1`]'s notes). The paper's + /// figure 11 (the book's 231) marks the five inner pieces; the sixth, at f₁ = 1, and the point + /// at f₁ = 0 lie on the plot's edges. The book shows CTP7's decision space with g = 1 + x₂ and + /// x₂ in [0, 1] (p. 360); the front is the same with x₂ in [0, 10]. Ctp7, "CTP7", REFERENCE, x2 in [0, 10.0], [wave(-0.05, 40.0, 5.0, 1, 6.0, 0.0)] ); @@ -696,15 +715,19 @@ ctp!( /// the front and bands across it. /// /// Bounds x₁ in [0, 1], x₂ in [0, 10]. The front is three disconnected pieces of CTP6's, - /// from about (0, 3.6958) to (0.1341, 3.3139), (0.3264, 2.7696) to (0.4787, 2.3379) and - /// (0.6824, 1.7656) to (0.8228, 1.3728) (derived by sampling the boundaries of the feasible + /// from about (0, 3.6958) to (0.1345, 3.3128), (0.3263, 2.7686) to (0.4790, 2.3372) and + /// (0.6823, 1.7654) to (0.8229, 1.3727) (derived by sampling the boundaries of the feasible /// region). /// - /// CTP8 isn't in the EMO 2001 paper, which has CTP1-CTP7; later papers credit it to /// Deb, K. (2001). *Multi-Objective Optimization Using Evolutionary Algorithms.* Wiley, - /// which wasn't read. The definition here is the one in the NSGA-II code of Deb's group - /// (version 1.1.6, KanGAL), with CTP6's g, variables and bounds; not yet checked against the - /// book ([#168](https://github.com/tachsin/genoxide/issues/168)). + /// section 8.3.5: the form of eq. 8.46 (p. 354) with the two constraints C₁ (θ = 0.1π, a = 40, + /// b = 0.5, c = 1, d = 2, e = −2) and C₂ (θ = −0.05π, a = 40, b = 2.0, c = 1, d = 6, e = 0) + /// of p. 358, the parameters of the NSGA-II code of Deb's group (version 1.1.6, KanGAL) too. + /// The book's figure 232 (p. 359) marks three Pareto-optimal regions, at f₁ from 0 to about + /// 0.13, 0.33 to 0.48 and 0.68 to 0.82, the pieces derived here. CTP8 isn't in the EMO 2001 + /// paper, which has CTP1-CTP7. The book leaves g, the variables and their bounds open, as for + /// CTP2-CTP7, and prints f₂ without the square root; they're the code's, as for CTP6 (see + /// [`Ctp1`]'s notes). Ctp8, "CTP8", BOOK, x2 in [0, 10.0], [ wave(0.1, 40.0, 0.5, 1, 2.0, -2.0), @@ -754,7 +777,7 @@ mod tests { ] } - // the report's procedure for CTP1's a and b (p. 6), for J constraints: its table gives them + // the paper's procedure for CTP1's a and b (p. 289), for J constraints: its table gives them // for J = 2, to three digits #[test] fn ctp1_parameters_follow_the_reports_procedure() { @@ -818,7 +841,7 @@ mod tests { assert_eq!(Ctp1.representation().bounds()[1], 0.0..=1.0); } - // the report's eq. 6: the optimal solutions of CTP2-CTP5 lie on the line + // the paper's eq. 6: the optimal solutions of CTP2-CTP5 lie on the line // (f₂ − e) cos θ = f₁ sin θ, where the constraint's right-hand side is 0: v = k/b #[test] fn the_points_on_the_line_are_on_the_boundary() { @@ -898,7 +921,8 @@ mod tests { #[test] fn the_fronts_have_their_shapes() { - // (pieces, of which single points), as the report's figures 6-11 draw them + // (pieces, of which single points), derived; the paper's figures 6-11 and the book's + // 226-232 draw the same, but don't mark CTP5's last point or CTP7's pieces at the edges assert_eq!(pieces(Ctp2::front()), (13, 0)); assert_eq!(pieces(Ctp3::front()), (13, 13)); assert_eq!(pieces(Ctp4::front()), (13, 13)); @@ -910,7 +934,7 @@ mod tests { assert_eq!(Ctp3::front(), Ctp4::front()); assert_eq!(Ctp3::front().len(), 13); assert_eq!(Ctp3::front()[12], Ctp3::waves()[0].on_line(1.2)); - // CTP6's lies where 1 ≤ (f₂ − e) sin θ + f₁ cos θ ≤ 2, as the report says: 1.76 to 1.84 + // CTP6's lies where 1 ≤ (f₂ − e) sin θ + f₁ cos θ ≤ 2, as the paper says: 1.76 to 1.84 let (sin, cos) = Ctp6::waves()[0].angle(); for [f1, f2] in Ctp6::front() { let v = sin * (f2 + 2.0) + cos * f1;