Skip to content

feat(moead): MOEA/D-DE, differential evolution in place of the crossover (Li and Zhang 2009) - #418

Merged
tachsin merged 4 commits into
mainfrom
feat/moead-de
Oct 2, 2026
Merged

tachsin merged 4 commits into
mainfrom
feat/moead-de

Conversation

@tachsin

@tachsin tachsin commented Oct 2, 2026

Copy link
Copy Markdown
Owner

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.

…ver (Li and Zhang, 2009)

DifferentialEvolutionCrossover makes each subproblem's child from its own
solution and the scaled difference of two parents, with binomial crossover
and a repair at the bounds (moead::Repair: Bounce by default, or the
paper's random reset). A child whose parents came from the whole
population may replace solutions anywhere, the paper's update range.

Moead's crossover slot takes a sealed MoeadCrossover trait, implemented for
every Crossover and for the new operator, so existing code and seeded runs
are unchanged. Tests: the operator by hand, the paper's F2 (IGD under
0.004, the paper's 0.0028), ZDT1, a checkpoint resume and a portable run.
Moead with crossover=gx.DifferentialEvolutionCrossover(f, cr, repair) runs
MOEA/D-DE on real genomes; other algorithms and genomes reject it. The
MOEA/D settings are applied by one function for both kinds of crossover.
Tests: a ZDT1 run evaluated in Rust, the settings' errors and a resumed
checkpoint.
@tachsin
tachsin merged commit fb3dc01 into main Oct 2, 2026
22 checks passed
@tachsin
tachsin deleted the feat/moead-de branch October 2, 2026 13:44
@github-actions github-actions Bot mentioned this pull request Oct 2, 2026
@tachsin tachsin mentioned this pull request Oct 2, 2026
18 tasks done
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.

1 participant