Skip to content

feat: the constrained DTLZ8 and DTLZ9, the DC-DTLZ and the DAS-CMOP problems, each with its own example - #414

Merged
tachsin merged 17 commits into
tachsin:mainfrom
tachsinatalay-code:feat/problems-batch-11
Oct 2, 2026
Merged

tachsin merged 17 commits into
tachsin:mainfrom
tachsinatalay-code:feat/problems-batch-11

Conversation

@tachsinatalay-code

Copy link
Copy Markdown
Contributor

Batch 11 of #260: the advanced constrained multi-objective suites, 17 problems, each with its own example.

The problems

All are in multi::problems::all::<M>() and gx.problems, with their fronts.

  • DTLZ8 and DTLZ9 ({Dtlz8, Dtlz9}::<M>::new(n), 10M variables by default), from the TIK-112 report, sections 8.8-8.9, eqs. 28-29. The block sums run from ⌊(j−1)n/M⌋+1 to ⌊jn/M⌋, as the plan's erratum says.
    • DTLZ8 needs at least 3 objectives, since its last constraint takes the smallest sum of two different objectives other than f_M.
    • DTLZ8's front, derived: the line f₁ = … = f_{M−1} = t, f_M = 1 − 4t for t in [0, 1/6], plus part of the plane 2f_M + fᵢ + fⱼ = 1. On that part, one objective s is in [(1−t)/4, (1−2t)/2] and the others are equal. For M ≥ 4 it's a 2-D surface, not the whole hyperplane the plan implied.
    • DTLZ9's front: the curve f₁ = … = f_{M−1} = cos θ, f_M = sin θ. The report prints no mean here, so the objectives are sums.
  • DC-DTLZ ({Dc1Dtlz1, Dc1Dtlz3, Dc2Dtlz1, Dc2Dtlz3, Dc3Dtlz1, Dc3Dtlz3}::<M>::new(n), with_parameters(n, a, b)), from Li, Chen, Fu and Yao (2019), the supplement and arXiv.
    • Compared with the authors' C++ code (EMOC), read only, since it has no license: a = 3, and b = 0.5 except DC2-DTLZ1's 0.9.
    • DC3's constraints cover the M−1 position variables plus g. This is the only reading that fits the supplement's table 2 (feasible shares of 3⁻ᵐ); "j = 1…m" would make the whole front infeasible.
    • Where this differs from EMOC: it keeps DTLZ3's g factor of 100, as the supplement says the objectives are C1-DTLZ3's. EMOC has 10.
    • Unresolved in the sources: n isn't given anywhere (assumed M + 4 and M + 9). The supplement's DC1 feasible share (10.1%) fits b = 0.95, against its own text's 0.5; the text is followed.
    • The fronts are derived, and agree with EMOC's sampled fronts within a mean distance of 0.011 both ways.
  • DAS-CMOP1-9 (DasCmop1 … DasCmop9), from Fan et al. (2020), arXiv v3, tables 2-3 and figure 6. A Difficulty triplet sets the difficulty: the paper's 16 standard triplets of table 3, or any. The defaults are 30 variables and figure 6's triplet.
    • Ambiguities settled by the authors' Java code (read only): g sums from j = 2, a_k² = 0.3 and b_k² = 1.2 are squares, at ζ = 0 the type II constraint is never active, and at ζ = 1 it is |g − 0.5| ≤ 1e-4.
    • The fronts are sampled, as the paper's are: the first feasible point on each ray α + g(1, …, 1), computed exactly (ellipses and spheres are quadratic in g along a ray), then filtered for non-dominance. With 2 objectives, 20,000 rays plus the ends of the type I intervals; with 3, Das-Dennis points at 288 divisions. Cached per triplet.
    • Agreement with the authors' 144 front files: mean distance under 0.01 for 130 files (theirs to ours) and 140 (ours to theirs). Every exception is a point of theirs that breaks the constraints, the point x₁ = 1 at η = 0.5 (feasible only in exact arithmetic), or a corner region of DAS-CMOP8/9 that their files omit and that is non-dominated.

Examples

17 examples at orders 179-195, the free range between C3-DTLZ4 (178) and convex DTLZ2 (200); no existing example moves. Rust and Python give identical output and identical traces.

Example Main method Result
DAS-CMOP4-6 NSGA-II, η 5, the paper's 300 × 1000 IGD+ ≤ 0.01 in 20, 20 and 19 of 20 seeds
DAS-CMOP7-8 NSGA-III, 276 directions, η 5 20/20 at ≥ 99% of a same-size front sample's hypervolume
DC1-DTLZ1 NSGA-III (C-NSGA-III's settings), 1,000 gen.; SMS-EMOA as contrast 20/20
DC1-DTLZ3 NSGA-III, 2,000 gen. 13/20 at the target, the rest within 2%
DC2-DTLZ1/3 NSGA-III on plain DTLZ, then scored by DC2 20/20 and 18/20
DC3-DTLZ1/3 NSGA-III without the constraint on g 18/20 and 20/20
DTLZ8 SMS-EMOA, 20,000 gen. 99.5-100.7% of the sample's hypervolume
DTLZ9 SMS-EMOA, 20,000 gen. 99.8-99.9%, IGD+ 0.0025 (the sample's own)
DAS-CMOP1-3, 9 NSGA-II / NSGA-III don't reach the front: IGD+ about 0.7, 0.15, 0.16, 0.19

DAS-CMOP1-3 and 9: their distance variables are linked, and reaching the front needs differential-evolution-style variation, as the paper's MOEA/D-CDP has. None of the operators available to genoxide's multi-objective algorithms moves linked variables together. NSGA-II, NSGA-III, MOEA/D and SMS-EMOA were tried with SBX, blend and arithmetic crossover; all fail, as the paper's NSGA-II-CDP does. The READMEs say so. A DE-style variation for the multi-objective algorithms would close this gap.

DC2 and DC3: the main runs drop some constraints and score the result with the real problem, following the C1-DTLZ3 example. Each example also shows constraint dominance alone stalling, as the C-TAEA paper's C-NSGA-III does: no feasible solution on DC2 in 20 of 20 runs, and stuck in a band of g on DC3.

DTLZ8 and DTLZ9: each also shows NSGA-II for the report's 500 generations failing (DTLZ9 IGD+ about 4).

Tests

Locally, rebased on today's main:

  • Lint: fmt, clippy with and without features, and cargo doc with and without features, all with -D warnings on Rust 1.99 (WSL).
  • Rust: cargo test --all-features passes, including 649 lib tests and the doc tests.
  • Python: mypy --strict genoxide reports no issues, and pytest passes (991 passed, 1 skipped).
  • Examples: all 17 run in both languages with identical output and traces, and examples/check_traces.py passes for all traces.

@tachsin tachsin mentioned this pull request Oct 2, 2026
18 tasks done
tachsin added a commit that referenced this pull request Oct 2, 2026
…ver (Li and Zhang 2009) (#418)

MOEA/D-DE (Li and Zhang 2009): differential-evolution variation for
MOEA/D, for Pareto sets with complicated shapes and for constrained
problems. Fan et al.'s DAS-CMOP problems (#414) need it. NSGA-II doesn't
reach DAS-CMOP1, 2, 3 or 9's fronts, and neither does the paper's
NSGA-II-CDP; the paper's MOEA/D-CDP with DE variation does.

**API:** `multi::DifferentialEvolutionCrossover::new(f, cr)?` goes in
`Moead`'s existing `.crossover(...)` slot.
- The slot takes a sealed `moead::MoeadCrossover<R>`, implemented for
every `Crossover<R>` and for the DE operator on `Real` only. Existing
code compiles unchanged, and DE on another genome is a compile error.
- As in the paper's step 2.1, a DE child whose parents came from the
whole population may replace solutions anywhere, at most n_r of them.
SBX keeps neighborhood-only replacement.
- `Moead` already compares solutions by Deb's rules (CDP), as Fan et
al.'s MOEA/D-CDP does; the docs now say so.
- Python: `gx.DifferentialEvolutionCrossover(f, cr, repair)`.

**Checked in the paper:** steps 2.1-2.5, eq. 6 (binomial crossover), eq.
7 (polynomial mutation), and section IV-A's settings: CR 1.0, F 0.5, η
20, p_m 1/n, T 20, δ 0.9, n_r 2. Documented differences:
- children are bred and evaluated a generation at a time;
- replacement requires strictly better;
- the ideal point uses feasible values only.

**Repair, one measured deviation:** an out-of-bounds gene gets a random
value between the parent's gene and the bound it crossed
(`Repair::Bounce`, the default), not a random value anywhere in its
range (step 2.3's text, kept as `Repair::Random`). On the paper's F2,
over 10 seeds:

| Repair | IGD |
|---|---|
| Paper (reported mean) | 0.0028 |
| Bounce | 0.0026-0.0039 |
| Random | 0.007-0.031 |

**On DAS-CMOP** (1,000 generations, 300 weight vectors, T = 30, δ =
0.2), the share of seeds reaching 99% of the front sample's hypervolume:

| Problem | MOEA/D-DE | SBX MOEA/D |
|---|---|---|
| DAS-CMOP1 | 20/20 | 0-69% of the hypervolume |
| DAS-CMOP2 | 20/20 | 0-69% of the hypervolume |
| DAS-CMOP3 | 20/20 | 0-69% of the hypervolume |
| DAS-CMOP9 | converges onto the front (largest distance 0.004) | |

DAS-CMOP9 ends at 97.3-98.0% of the hypervolume. That is above the 96.8%
that even each weight vector's exact optimum would give.

**Tests:**
- The operator against hand-computed children, and the setting errors.
- Replacement across the whole population for DE only.
- The paper's F2 (IGD < 0.004, where SBX stays above 0.04) and ZDT1.
- A checkpoint resume.
- `portable_runs` entries; existing seeded `Moead` results are
unchanged.
- Python tests.
@tachsin
tachsin merged commit 4a1eb69 into tachsin:main Oct 2, 2026
22 checks passed
@github-actions github-actions Bot mentioned this pull request Oct 2, 2026
tachsin pushed a commit that referenced this pull request Oct 2, 2026
## 🤖 New release

* `genoxide`: 0.13.0 -> 0.13.1 (✓ API compatible changes)
* `genoxide-python`: 0.13.0 -> 0.13.1

<details><summary><i><b>Changelog</b></i></summary><p>

## `genoxide`

<blockquote>

##
[0.13.1](v0.13.0...v0.13.1)
- 2026-10-02

### <!-- 0 -->Added

- shift and rotation wrappers and seventeen CEC- and BBOB-style
functions, each with its own example
([#409](#409))
- *(moead)* MOEA/D-DE, differential evolution in place of the crossover
(Li and Zhang 2009)
([#418](#418))
- the constrained DTLZ8 and DTLZ9, the DC-DTLZ and the DAS-CMOP
problems, each with its own example
([#414](#414))
- *(problems)* gradients for batch 10b's functions, and gradients and
constraint values through Shifted and Rotated
([#420](#420))
- *(problems)* binary and combinatorial problems, batch 12, each with
its own example ([#421](#421))

### <!-- 4 -->Documentation

- *(ctp)* CTP1-CTP8 checked against the published paper and Deb's 2001
book ([#419](#419))
</blockquote>



</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants