diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 7ea76e8..89a1c51 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -11,7 +11,7 @@ body:
id: version
attributes:
label: Unsga3 version / commit
- placeholder: "0.1.2 or git SHA"
+ placeholder: "0.1.4 or git SHA"
validations:
required: true
- type: textarea
diff --git a/.grok/skills/unsga3-oracle/SKILL.md b/.grok/skills/unsga3-oracle/SKILL.md
index 28b6fc0..f5336a0 100644
--- a/.grok/skills/unsga3-oracle/SKILL.md
+++ b/.grok/skills/unsga3-oracle/SKILL.md
@@ -16,8 +16,11 @@ Repo root: Unsga3. Confirm `Unsga3.slnx` / `tools/OracleCompare` exist before ru
| Problem | Partitions | Pop | Gens | C# tournament |
|---------|------------|-----|------|----------------|
| zdt1 | 12 | 52 | 100 | default (`RankNicheDistance`) |
+| zdt2 | 12 | 52 | **250** | `--pymoo-mode` (`PymooCompatible`) |
| dtlz2 | 12 | 92 | 150 | `--pymoo-mode` (`PymooCompatible`) |
+ZDT2 **gens=100** is an early-stress snapshot (collapse on Bend, C#, and pymoo), not the quality bar. Quality protocol matches unsga3-bend A/B (gens=250, PymooCompatible). `RankNicheDistance` is an optional unpublished Wilcoxon ZDT2 mating mode — do not silently switch all ZDT defaults to it. ZDT1 and DTLZ2 unchanged.
+
IGD = **mean** nearest Euclidean distance (pymoo-compatible). Docs: `docs/EQUIVALENCE.md`, `docs/RESEARCH-STANDARDS.md`.
Requires: .NET 10 SDK; Python 3 + `pip install pymoo` for pymoo side / multi-seed.
@@ -31,8 +34,10 @@ Ask which mode if unclear; default **quick** when validating a small fix, **full
```powershell
dotnet build tools/OracleCompare -c Release
dotnet run --project tools/OracleCompare -c Release --no-build -- --problem zdt1 --partitions 12 --pop 52 --gens 100 --seed 1
+dotnet run --project tools/OracleCompare -c Release --no-build -- --problem zdt2 --partitions 12 --pop 52 --seed 1 --pymoo-mode
dotnet run --project tools/OracleCompare -c Release --no-build -- --problem dtlz2 --partitions 12 --pop 92 --gens 150 --seed 1 --pymoo-mode
python tools/oracle/run_pymoo_oracle.py --problem zdt1 --partitions 12 --pop 52 --gens 100 --seed 1
+python tools/oracle/run_pymoo_oracle.py --problem zdt2 --partitions 12 --pop 52 --seed 1
python tools/oracle/run_pymoo_oracle.py --problem dtlz2 --partitions 12 --pop 92 --gens 150 --seed 1
```
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9efa1e..23df1ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- Docs and XML comments describe `initialPopulation` and hybrid loops in generic terms (domain-adapter warm-start / grid-seed). No product-repo names.
+## [0.1.4] — 2026-09-19
+
+### Changed
+
+- **ZDT2 oracle/smoke protocol:** quality bar is **gens=250** + `PymooCompatible` (docs and harness defaults). gens=100 is an early-stress snapshot (collapse on Bend, C#, and pymoo), not the quality bar. `RankNicheDistance` stays an optional unpublished Wilcoxon ZDT2 mating mode. ZDT1 (100) and DTLZ2 (150) unchanged. **No algorithm or public API change.** Matches [unsga3-bend](https://github.com/AppSprout-dev/unsga3-bend) A/B honesty.
+
## [0.1.3] — 2026-08-10
### Added
@@ -60,7 +66,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- Benchmarks: ZDT1–4/6, DTLZ1–4/7, Sphere / Ackley / Rosenbrock
- Metrics: IGD, GD, 2-D HV; self-tests + GitHub Packages publish workflow
-[Unreleased]: https://github.com/AppSprout-dev/Unsga3/compare/v0.1.2...HEAD
+[Unreleased]: https://github.com/AppSprout-dev/Unsga3/compare/v0.1.4...HEAD
+[0.1.4]: https://github.com/AppSprout-dev/Unsga3/compare/v0.1.3...v0.1.4
+[0.1.3]: https://github.com/AppSprout-dev/Unsga3/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/AppSprout-dev/Unsga3/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/AppSprout-dev/Unsga3/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/AppSprout-dev/Unsga3/releases/tag/v0.1.0
diff --git a/CITATION.cff b/CITATION.cff
index 4901fe4..8f72c6d 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -21,8 +21,8 @@ keywords:
- C#
- .NET
license: MIT
-version: 0.1.2
-date-released: "2026-08-10"
+version: 0.1.4
+date-released: "2026-09-19"
references:
- type: article
authors:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 21fc8c0..20f7b5a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,6 +28,9 @@ dotnet run --project samples/BasicUsage -c Release
# single seed
dotnet run --project tools/OracleCompare -c Release -- --problem dtlz2 --partitions 12 --pop 92 --gens 150 --seed 1 --pymoo-mode
python tools/oracle/run_pymoo_oracle.py --problem dtlz2 --partitions 12 --pop 92 --gens 150 --seed 1
+# ZDT2 quality protocol: omitted --gens is 250 + --pymoo-mode (matches unsga3-bend).
+# --gens 100 is an early-stress snapshot. RankNicheDistance (omit --pymoo-mode) is optional.
+dotnet run --project tools/OracleCompare -c Release -- --problem zdt2 --partitions 12 --pop 52 --seed 1 --pymoo-mode
# multi-seed Mann–Whitney / Wilcoxon (writes docs/WILCOXON-RESULTS.md)
python tools/oracle/run_multiseed_wilcoxon.py --problems zdt1 dtlz2 --seeds 15
diff --git a/Directory.Build.props b/Directory.Build.props
index 354025f..dd1aa22 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -12,7 +12,7 @@
https://github.com/AppSprout-dev/Unsga3
https://github.com/AppSprout-dev/Unsga3
optimization;nsga;nsga3;unsga3;multi-objective;evolutionary;moea
- 0.1.3
+ 0.1.4
README.md
diff --git a/README.md b/README.md
index 77f51fa..0bbb696 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
**U-NSGA-III** (Unified NSGA-III) for .NET — single-, multi-, and many-objective evolutionary optimization with Das–Dennis reference directions, SBX crossover, polynomial mutation, and **niching-based tournament selection** ([Seada & Deb, 2016](https://ieeexplore.ieee.org/document/7271063)).
-> **v0.1.2** — production-usable core with pymoo-aligned normalization.
+> **v0.1.4** — production-usable core with pymoo-aligned normalization. ZDT2 quality protocol is gens=250 (docs/defaults; no algorithm/API change).
> **15-seed IGD vs pymoo `UNSGA3`:** ZDT1 **median 0.053 vs 0.070** (we win; MWU *p*≈0.05); DTLZ2 **median 0.0045 vs 0.0028** (~1.6×, same order; pymoo still ahead).
> Details: [`docs/WILCOXON-RESULTS.md`](docs/WILCOXON-RESULTS.md) · single-seed notes: [`docs/ORACLE-RESULTS.md`](docs/ORACLE-RESULTS.md)
@@ -121,7 +121,7 @@ API docs used: [HTTP](https://docs.typesafe.ai/api.md) · [Python SDK](https://d
|-----|----------|
| [docs/ORACLE-RESULTS.md](docs/ORACLE-RESULTS.md) | Single-seed C# vs pymoo |
| [docs/WILCOXON-RESULTS.md](docs/WILCOXON-RESULTS.md) | Multi-seed Mann–Whitney / Wilcoxon |
-| [docs/EQUIVALENCE.md](docs/EQUIVALENCE.md) | Protocol & intentional deltas |
+| [docs/EQUIVALENCE.md](docs/EQUIVALENCE.md) | Protocol & intentional deltas (ZDT2 quality A/B = gens=250, `PymooCompatible`; matches unsga3-bend) |
| [docs/RESEARCH-STANDARDS.md](docs/RESEARCH-STANDARDS.md) | Literature + indicator standards |
| [docs/NOTICE.md](docs/NOTICE.md) | Attribution (papers + validation tools) |
| [docs/ROADMAP.md](docs/ROADMAP.md) | Near / medium term plan |
diff --git a/docs/EQUIVALENCE.md b/docs/EQUIVALENCE.md
index 21507fe..dcdca66 100644
--- a/docs/EQUIVALENCE.md
+++ b/docs/EQUIVALENCE.md
@@ -22,6 +22,16 @@ See also **[RESEARCH-STANDARDS.md](RESEARCH-STANDARDS.md)** for the literature +
5. **Tolerance:** median IGD within ~1–2× of pymoo on ZDT/DTLZ is the practical bar.
15-seed: ZDT1 median **better** than pymoo (ratio 0.76, MWU n.s.); DTLZ2 median ~**1.6×** (pymoo still ahead).
+Published A/B budgets (ZDT1 / DTLZ2 unchanged; ZDT2 matches unsga3-bend protocol honesty):
+
+| Problem | Pop | Gens | Partitions | C# tournament (quality) |
+|---------|-----|------|------------|-------------------------|
+| ZDT1 | 52 | 100 | 12 | `RankNicheDistance` (published Wilcoxon) |
+| ZDT2 | 52 | **250** | 12 | `PymooCompatible` (A/B quality) |
+| DTLZ2 | 92 | 150 | 12 | `PymooCompatible` |
+
+ZDT2 **gens=100** is an early-stress snapshot (collapse on Bend, C#, and pymoo), not the quality bar. `RankNicheDistance` on ZDT2 is an optional unpublished Wilcoxon mating mode — do not silently switch all ZDT defaults to it. C# has no published ZDT2 IGD / Wilcoxon table; do not invent one.
+
## Problems (must-pass)
| Class | Problems | M | In library |
diff --git a/docs/ORACLE-RESULTS.md b/docs/ORACLE-RESULTS.md
index c3f3396..ff46d94 100644
--- a/docs/ORACLE-RESULTS.md
+++ b/docs/ORACLE-RESULTS.md
@@ -20,13 +20,21 @@ Reproduce:
# Python
pip install pymoo
python tools/oracle/run_pymoo_oracle.py --problem zdt1 --partitions 12 --pop 52 --gens 100 --seed 1
+python tools/oracle/run_pymoo_oracle.py --problem zdt2 --partitions 12 --pop 52 --seed 1
python tools/oracle/run_pymoo_oracle.py --problem dtlz2 --partitions 12 --pop 92 --gens 150 --seed 1
# C#
dotnet run --project tools/OracleCompare -c Release -- --problem zdt1 --partitions 12 --pop 52 --gens 100 --seed 1
+dotnet run --project tools/OracleCompare -c Release -- --problem zdt2 --partitions 12 --pop 52 --seed 1 --pymoo-mode
dotnet run --project tools/OracleCompare -c Release -- --problem dtlz2 --partitions 12 --pop 92 --gens 150 --seed 1 --pymoo-mode
```
+Omitted `--gens` on `--problem zdt2` is **250** (quality protocol). `--gens 100` is an early-stress snapshot. ZDT1 stays 100; DTLZ2 stays 150.
+
+### ZDT2 protocol honesty (matches unsga3-bend)
+
+C# never published a hard ZDT2 oracle / Wilcoxon table. The unpublished Wilcoxon harness used **gens=100** and **`RankNicheDistance`**. That budget collapses on Bend, C#, and pymoo (axis pile near `f1≈0`). **gens=250 + `PymooCompatible`** is the quality A/B bar (15-seed: 0/15 collapse on both stacks; see [unsga3-bend PR #17](https://github.com/AppSprout-dev/unsga3-bend/pull/17) / `docs/ZDT2_COLLAPSE.md`). `RankNicheDistance` remains an **optional** Wilcoxon mating mode — do not silently switch all ZDT defaults to it. This repo does not invent a ZDT2 IGD table here.
+
## Results (seed=1)
| Problem | Settings | pymoo IGD | C# default IGD | C# `PymooCompatible` IGD | Verdict |
@@ -69,9 +77,12 @@ Deep-dive vs pymoo `HyperplaneNormalization` / `ReferenceDirectionSurvival` (pym
| Test | Bar |
|------|-----|
| ZDT1 seed=1, 100 gen, default tournament | IGD ≤ 1.5 × 0.0629 |
+| ZDT2 seed=2, 250 gen, default `RankNicheDistance` | IGD < 0.75 (loose CI smoke, not oracle parity) |
| DTLZ2 seed=1, 150 gen, pymoo-mode | IGD ≤ 3 × 0.00350 (currently ~1.15×) |
| DTLZ2 short smoke (80 gen) | IGD < 0.15 |
+ZDT2 quality A/B is gens=250 + `PymooCompatible` (not the loose smoke bar). ZDT1 / DTLZ2 shipping bars are unchanged.
+
## Known remaining deltas (intentional / minor)
| Item | Status |
diff --git a/docs/RESEARCH-STANDARDS.md b/docs/RESEARCH-STANDARDS.md
index e56a5d0..967dad7 100644
--- a/docs/RESEARCH-STANDARDS.md
+++ b/docs/RESEARCH-STANDARDS.md
@@ -77,9 +77,12 @@ Typical ZDT: r = (1.1, 1.1). Always document r; never compare HV across differen
1. Same problem definition (bounds, n, evaluate)
2. Same Das–Dennis partitions → identical ref set size
3. Same pop, gens, SBX/PM η, p_m = 1/n
+ - ZDT1: pop=52, **gens=100**
+ - ZDT2 quality A/B: pop=52, **gens=250**, `PymooCompatible` (matches unsga3-bend). gens=100 is an early-stress snapshot, not the quality bar. `RankNicheDistance` is optional, not the ZDT2 default.
+ - DTLZ2: pop=92, **gens=150**, `PymooCompatible`
4. Fixed seed **or** 15–31 seeds → median + IQR IGD
5. Compare IGD (and HV for M=2) to pymoo `UNSGA3`
-6. Shipping bar: median IGD within ~1–2% of pymoo on ZDT1/DTLZ2 (or non-inferior Wilcoxon)
+6. Shipping bar: median IGD within ~1–2% of pymoo on ZDT1/DTLZ2 (or non-inferior Wilcoxon). ZDT2 has no published C# Wilcoxon table; quality budget is 250 gens.
Export path: dump final `F` as CSV from both sides; compute IGD in this library.
diff --git a/docs/WILCOXON-RESULTS.md b/docs/WILCOXON-RESULTS.md
index 91f8851..be2f04c 100644
--- a/docs/WILCOXON-RESULTS.md
+++ b/docs/WILCOXON-RESULTS.md
@@ -7,8 +7,11 @@ Generated by `tools/oracle/run_multiseed_wilcoxon.py`. IGD = mean nearest Euclid
| Problem | Pop | Gens | Partitions | C# tournament | Seeds |
|---------|-----|------|------------|---------------|-------|
| zdt1 | 52 | 100 | 12 | RankNicheDistance | 15 |
+| zdt2 (quality A/B; not in this table) | 52 | **250** | 12 | PymooCompatible | — |
| dtlz2 | 92 | 150 | 12 | PymooCompatible | 15 |
+ZDT2 **gens=100** is an early-stress snapshot, not the quality bar. C# never published a hard ZDT2 Wilcoxon table; the unpublished harness used gens=100 + `RankNicheDistance` (optional mating mode — do not silently switch all ZDT defaults to it). Quality protocol matches [unsga3-bend](https://github.com/AppSprout-dev/unsga3-bend) A/B honesty: gens=250 + `PymooCompatible`. ZDT1 and DTLZ2 numbers below are unchanged. Do not invent a ZDT2 IGD table here.
+
Hypothesis tests (α = 0.05, two-sided):
- **Mann–Whitney U** (Wilcoxon rank-sum): independent samples, H₀: same IGD distribution.
diff --git a/tests/Unsga3.Tests/Benchmarks/IgdSmokeTests.cs b/tests/Unsga3.Tests/Benchmarks/IgdSmokeTests.cs
index bcad18f..673b73f 100644
--- a/tests/Unsga3.Tests/Benchmarks/IgdSmokeTests.cs
+++ b/tests/Unsga3.Tests/Benchmarks/IgdSmokeTests.cs
@@ -9,6 +9,9 @@ namespace Unsga3.Tests.Benchmarks;
///
/// Fixed-seed IGD smoke bars — not full pymoo equivalence (see docs/EQUIVALENCE.md).
/// Bounds are intentionally loose; tighten after oracle harness lands.
+/// ZDT2 quality A/B is gens=250 +
+/// (matches unsga3-bend). The ZDT2 smoke below keeps ctor-default
+/// and a loose IGD bar.
///
public class IgdSmokeTests
{
@@ -40,10 +43,13 @@ public void Zdt2_runs_with_measurable_igd()
var problem = new Zdt2Problem();
var dirs = ReferenceDirections.DasDennis(2, 12);
var algo = new Unsga3Algorithm(dirs, populationSize: 52, seed: 2);
- var result = algo.Run(problem, maxGenerations: 150);
+ var result = algo.Run(problem, maxGenerations: 250);
var obtained = result.NonDominatedSolutions.Select(i => i.Objectives).ToArray();
double igd = PerformanceIndicators.InvertedGenerationalDistance(obtained, ParetoFronts.Zdt2());
- // ZDT2 non-convex; mean-IGD smoke bar (not oracle parity).
+ // Loose CI smoke, not oracle parity. Quality A/B is gens=250 + PymooCompatible
+ // (matches unsga3-bend). gens=100 is an early-stress snapshot (collapse on
+ // Bend, C#, and pymoo). This test keeps the ctor default RankNicheDistance
+ // (optional unpublished Wilcoxon ZDT2 mating mode) and IGD < 0.75.
Assert.True(igd < 0.75, $"ZDT2 IGD={igd}");
}
diff --git a/tools/OracleCompare/Program.cs b/tools/OracleCompare/Program.cs
index d5e1236..738e0c9 100644
--- a/tools/OracleCompare/Program.cs
+++ b/tools/OracleCompare/Program.cs
@@ -10,11 +10,16 @@
// Fixed-protocol C# side of the pymoo oracle (see tools/oracle/run_pymoo_oracle.py).
//
// dotnet run --project tools/OracleCompare -- --problem zdt1 --partitions 12 --pop 52 --gens 100 --seed 1 --pymoo-mode
+// # ZDT2 quality protocol (matches unsga3-bend A/B): gens=250 + --pymoo-mode.
+// # Omitted --gens on --problem zdt2 is 250. gens=100 is an early-stress snapshot.
+// # RankNicheDistance (omit --pymoo-mode) is optional, not the ZDT2 A/B default.
+// dotnet run --project tools/OracleCompare -- --problem zdt2 --partitions 12 --pop 52 --seed 1 --pymoo-mode
string problemName = "zdt1";
int partitions = 12;
int? pop = null;
int gens = 100;
+bool gensExplicit = false;
int seed = 1;
bool pymooMode = false;
string? outDir = null;
@@ -26,13 +31,21 @@
case "--problem": problemName = args[++i]; break;
case "--partitions": partitions = int.Parse(args[++i], CultureInfo.InvariantCulture); break;
case "--pop": pop = int.Parse(args[++i], CultureInfo.InvariantCulture); break;
- case "--gens": gens = int.Parse(args[++i], CultureInfo.InvariantCulture); break;
+ case "--gens":
+ gens = int.Parse(args[++i], CultureInfo.InvariantCulture);
+ gensExplicit = true;
+ break;
case "--seed": seed = int.Parse(args[++i], CultureInfo.InvariantCulture); break;
case "--pymoo-mode": pymooMode = true; break;
case "--out-dir": outDir = args[++i]; break;
}
}
+// Quality protocol: ZDT2 A/B default is gens=250 (unsga3-bend honesty).
+// ZDT1 stays 100; DTLZ2 callers still pass --gens 150. Explicit --gens always wins.
+if (!gensExplicit && problemName.Equals("zdt2", StringComparison.OrdinalIgnoreCase))
+ gens = 250;
+
IProblem problem;
int m;
double[][] pf;
diff --git a/tools/oracle/run_multiseed_wilcoxon.py b/tools/oracle/run_multiseed_wilcoxon.py
index d6fe8ec..34e85ed 100644
--- a/tools/oracle/run_multiseed_wilcoxon.py
+++ b/tools/oracle/run_multiseed_wilcoxon.py
@@ -5,6 +5,11 @@
Protocol matches docs/EQUIVALENCE.md and docs/RESEARCH-STANDARDS.md:
15 independent seeds (default), fixed SBX/PM/Das–Dennis settings.
+ZDT2 quality protocol is gens=250 + PymooCompatible (matches unsga3-bend A/B).
+gens=100 is an early-stress snapshot. RankNicheDistance (csharp_pymoo_mode=False)
+is an optional unpublished Wilcoxon mating mode — not the ZDT2 A/B default.
+ZDT1 and DTLZ2 budgets are unchanged.
+
Usage:
python tools/oracle/run_multiseed_wilcoxon.py
python tools/oracle/run_multiseed_wilcoxon.py --problems zdt1 dtlz2 --seeds 15 --skip-pymoo
@@ -38,7 +43,10 @@ class Protocol:
PROTOCOLS: dict[str, Protocol] = {
"zdt1": Protocol("zdt1", partitions=12, pop=52, gens=100, n_obj=2, csharp_pymoo_mode=False),
- "zdt2": Protocol("zdt2", partitions=12, pop=52, gens=100, n_obj=2, csharp_pymoo_mode=False),
+ # Quality A/B (unsga3-bend honesty): 250 gens, PymooCompatible.
+ # Optional: csharp_pymoo_mode=False (RankNicheDistance) + gens=100 is the
+ # unpublished Wilcoxon ZDT2 mating snapshot — do not treat it as the default.
+ "zdt2": Protocol("zdt2", partitions=12, pop=52, gens=250, n_obj=2, csharp_pymoo_mode=True),
"dtlz2": Protocol("dtlz2", partitions=12, pop=92, gens=150, n_obj=3, csharp_pymoo_mode=True),
}
diff --git a/tools/oracle/run_pymoo_oracle.py b/tools/oracle/run_pymoo_oracle.py
index 01418cd..955e871 100644
--- a/tools/oracle/run_pymoo_oracle.py
+++ b/tools/oracle/run_pymoo_oracle.py
@@ -9,6 +9,9 @@
Usage:
python run_pymoo_oracle.py
python run_pymoo_oracle.py --problem zdt1 --partitions 12 --pop 52 --gens 100 --seed 1
+ python run_pymoo_oracle.py --problem zdt2 --partitions 12 --pop 52 --seed 1
+ # omitted --gens on zdt2 is 250 (quality protocol; matches unsga3-bend A/B).
+ # --gens 100 is an early-stress snapshot, not the quality bar.
"""
from __future__ import annotations
@@ -20,15 +23,33 @@
import numpy as np
+def default_gens(problem: str) -> int:
+ """Quality-protocol generations when --gens is omitted.
+
+ ZDT2 A/B default is 250 (unsga3-bend honesty). ZDT1 stays 100.
+ DTLZ2 stays 100 here so existing callers that omit --gens are unchanged;
+ the published DTLZ2 oracle still passes --gens 150.
+ """
+ if problem == "zdt2":
+ return 250
+ return 100
+
+
def main() -> int:
p = argparse.ArgumentParser()
p.add_argument("--problem", default="zdt1", choices=["zdt1", "zdt2", "dtlz2"])
p.add_argument("--partitions", type=int, default=12)
p.add_argument("--pop", type=int, default=None, help="default = n_ref_dirs")
- p.add_argument("--gens", type=int, default=100)
+ p.add_argument(
+ "--gens",
+ type=int,
+ default=None,
+ help="generations (default: zdt2=250, else 100; explicit value always wins)",
+ )
p.add_argument("--seed", type=int, default=1)
p.add_argument("--out-dir", type=Path, default=Path(__file__).resolve().parent / "out")
args = p.parse_args()
+ gens = args.gens if args.gens is not None else default_gens(args.problem)
try:
from pymoo.algorithms.moo.unsga3 import UNSGA3
@@ -56,12 +77,12 @@ def main() -> int:
algo = UNSGA3(ref_dirs, pop_size=pop)
print(f"pymoo UNSGA3 | problem={args.problem} M={n_obj} refs={len(ref_dirs)} "
- f"pop={pop} gens={args.gens} seed={args.seed}")
+ f"pop={pop} gens={gens} seed={args.seed}")
res = minimize(
problem,
algo,
- ("n_gen", args.gens),
+ ("n_gen", gens),
seed=args.seed,
verbose=False,
save_history=False,
@@ -71,7 +92,7 @@ def main() -> int:
igd = float(IGD(pf)(F))
args.out_dir.mkdir(parents=True, exist_ok=True)
- stem = f"pymoo_{args.problem}_p{args.partitions}_pop{pop}_g{args.gens}_s{args.seed}"
+ stem = f"pymoo_{args.problem}_p{args.partitions}_pop{pop}_g{gens}_s{args.seed}"
f_path = args.out_dir / f"{stem}_F.csv"
meta_path = args.out_dir / f"{stem}_meta.json"
np.savetxt(f_path, F, delimiter=",")
@@ -83,7 +104,7 @@ def main() -> int:
"partitions": args.partitions,
"n_ref_dirs": int(len(ref_dirs)),
"pop_size": pop,
- "n_gen": args.gens,
+ "n_gen": gens,
"seed": args.seed,
"n_solutions": int(F.shape[0]),
"igd": igd,