Skip to content

Commit 8cd42aa

Browse files
committed
Hookup before and after hooks in Select, Crossover and Mutate Wrappers
1 parent ab7e7c5 commit 8cd42aa

File tree

4 files changed

+69
-8
lines changed

4 files changed

+69
-8
lines changed

CHANGELOG.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [0.26.0] - 2025-11-24
88

99
### Added
10-
* Add multiple extension points to the `Evolve` flow
11-
* `after_selection_complete()` - called after selection completes
12-
* `after_crossover_complete()` - called after crossover completes
13-
* `after_mutation_complete()` - called after mutation completes
14-
* `after_generation_complete()` - called at end of generation
15-
* Add reporter hooks `on_crossover_complete()` and `on_mutation_complete()`
16-
* Provides observation points matching the new extension hooks
10+
* Add multiple extension points to the `Evolve` flow in the `Extension` type
11+
* `after_selection_complete()`
12+
* `after_crossover_complete()`
13+
* `after_mutation_complete()`
14+
* `after_generation_complete()`
15+
* Add symmetrical reporter hooks, called before the extension hooks
16+
* `on_selection_complete()` (existing)
17+
* `on_crossover_complete()`
18+
* `on_mutation_complete()`
19+
* `on_generation_complete()` (existing)
1720
* Add `before()` and `after()` hooks to `Select`, `Crossover`, and `Mutate` traits
18-
* Allows customization of population lifecycle operations
21+
* Allows full customization of population lifecycle operations in Evolve
1922
* Default implementations handle age filtering and cardinality updates
2023

2124
### Changed

src/crossover/wrapper.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ pub enum Wrapper<G: EvolveGenotype> {
2626
impl<G: EvolveGenotype> Crossover for Wrapper<G> {
2727
type Genotype = G;
2828

29+
fn before(&mut self, genotype: &G, state: &mut EvolveState<G>, config: &EvolveConfig) {
30+
match self {
31+
Wrapper::Clone(crossover) => crossover.before(genotype, state, config),
32+
Wrapper::MultiGene(crossover) => crossover.before(genotype, state, config),
33+
Wrapper::MultiPoint(crossover) => crossover.before(genotype, state, config),
34+
Wrapper::Rejuvenate(crossover) => crossover.before(genotype, state, config),
35+
Wrapper::SingleGene(crossover) => crossover.before(genotype, state, config),
36+
Wrapper::SinglePoint(crossover) => crossover.before(genotype, state, config),
37+
Wrapper::Uniform(crossover) => crossover.before(genotype, state, config),
38+
}
39+
}
40+
2941
fn call<R: Rng, SR: StrategyReporter<Genotype = G>>(
3042
&mut self,
3143
genotype: &G,
@@ -53,6 +65,18 @@ impl<G: EvolveGenotype> Crossover for Wrapper<G> {
5365
}
5466
}
5567

68+
fn after(&mut self, genotype: &G, state: &mut EvolveState<G>, config: &EvolveConfig) {
69+
match self {
70+
Wrapper::Clone(crossover) => crossover.after(genotype, state, config),
71+
Wrapper::MultiGene(crossover) => crossover.after(genotype, state, config),
72+
Wrapper::MultiPoint(crossover) => crossover.after(genotype, state, config),
73+
Wrapper::Rejuvenate(crossover) => crossover.after(genotype, state, config),
74+
Wrapper::SingleGene(crossover) => crossover.after(genotype, state, config),
75+
Wrapper::SinglePoint(crossover) => crossover.after(genotype, state, config),
76+
Wrapper::Uniform(crossover) => crossover.after(genotype, state, config),
77+
}
78+
}
79+
5680
/// to guard against invalid Crossover strategies which break the internal consistency
5781
/// of the genes, unique genotypes can't simply exchange genes without gene duplication issues
5882
fn require_crossover_indexes(&self) -> bool {

src/mutate/wrapper.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ pub enum Wrapper<G: EvolveGenotype> {
2222
impl<G: EvolveGenotype> Mutate for Wrapper<G> {
2323
type Genotype = G;
2424

25+
fn before(&mut self, genotype: &G, state: &mut EvolveState<G>, config: &EvolveConfig) {
26+
match self {
27+
Wrapper::MultiGene(mutate) => mutate.before(genotype, state, config),
28+
Wrapper::MultiGeneDynamic(mutate) => mutate.before(genotype, state, config),
29+
Wrapper::MultiGeneRange(mutate) => mutate.before(genotype, state, config),
30+
Wrapper::SingleGene(mutate) => mutate.before(genotype, state, config),
31+
Wrapper::SingleGeneDynamic(mutate) => mutate.before(genotype, state, config),
32+
}
33+
}
34+
2535
fn call<R: Rng, SR: StrategyReporter<Genotype = G>>(
2636
&mut self,
2737
genotype: &G,
@@ -42,6 +52,16 @@ impl<G: EvolveGenotype> Mutate for Wrapper<G> {
4252
}
4353
}
4454
}
55+
56+
fn after(&mut self, genotype: &G, state: &mut EvolveState<G>, config: &EvolveConfig) {
57+
match self {
58+
Wrapper::MultiGene(mutate) => mutate.after(genotype, state, config),
59+
Wrapper::MultiGeneDynamic(mutate) => mutate.after(genotype, state, config),
60+
Wrapper::MultiGeneRange(mutate) => mutate.after(genotype, state, config),
61+
Wrapper::SingleGene(mutate) => mutate.after(genotype, state, config),
62+
Wrapper::SingleGeneDynamic(mutate) => mutate.after(genotype, state, config),
63+
}
64+
}
4565
}
4666

4767
impl<G: EvolveGenotype> From<MutateSingleGene<G>> for Wrapper<G> {

src/select/wrapper.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ pub enum Wrapper<G: EvolveGenotype> {
1818
impl<G: EvolveGenotype> Select for Wrapper<G> {
1919
type Genotype = G;
2020

21+
fn before(&mut self, genotype: &G, state: &mut EvolveState<G>, config: &EvolveConfig) {
22+
match self {
23+
Wrapper::Elite(select) => select.before(genotype, state, config),
24+
Wrapper::Tournament(select) => select.before(genotype, state, config),
25+
}
26+
}
27+
2128
fn call<R: Rng, SR: StrategyReporter<Genotype = G>>(
2229
&mut self,
2330
genotype: &G,
@@ -32,6 +39,13 @@ impl<G: EvolveGenotype> Select for Wrapper<G> {
3239
}
3340
}
3441

42+
fn after(&mut self, genotype: &G, state: &mut EvolveState<G>, config: &EvolveConfig) {
43+
match self {
44+
Wrapper::Elite(select) => select.after(genotype, state, config),
45+
Wrapper::Tournament(select) => select.after(genotype, state, config),
46+
}
47+
}
48+
3549
fn extract_elite_chromosomes(
3650
&self,
3751
state: &mut EvolveState<G>,

0 commit comments

Comments
 (0)