1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! The crossover phase where two parent chromosomes create two children chromosomes. The
//! [selection](crate::select) phase determines the order the parent pairing (overall with fitter
//! first).
//!
//! The selection_rate is the fraction of parents which are selected for
//! reproduction. This selection adds offspring to the population, the other
//! parents do not. The population now grows by the added offspring, as the
//! parents are not replaced yet. Value should typically be between 0.4 and
//! 0.8. High values risk of premature convergence. Low values reduce diversity
//! if overused.
//!
//! The crossover_rate (or recombination-rate) is the fraction of selected parents to crossover,
//! the remaining parents just clone as offspring. Value should typically be between 0.5 and 0.8.
//! High values converge faster, but risk losing good solutions. Low values have poor exploration
//! and risk of premature convergence
//!
//! Normally the crossover adds children to the popluation, thus increasing the population_size
//! above the target_population_size. Selection will reduce this again in the next generation
pub use Clone as CrossoverClone;
pub use MultiGene as CrossoverMultiGene;
pub use MultiPoint as CrossoverMultiPoint;
pub use Rejuvenate as CrossoverRejuvenate;
pub use SingleGene as CrossoverSingleGene;
pub use SinglePoint as CrossoverSinglePoint;
pub use Uniform as CrossoverUniform;
pub use Wrapper as CrossoverWrapper;
use crate;
use crate;
use crateStrategyReporter;
use Rng;
/// This is just a shortcut for `Self::Genotype`
pub type CrossoverGenotype<C> = Genotype;
/// This is just a shortcut for `EvolveState<Self::Genotype>,`
pub type CrossoverEvolveState<C> = ;
/// This is just a shortcut
pub type CrossoverAllele<C> = Allele;
/// # Optional Custom User implementation (rarely needed)
///
/// For the user API, the Crossover Trait has an associated Genotype. This way the user can
/// implement a specialized Crossover alterative with access to the user's Genotype specific
/// methods at hand.
///
/// # Example
/// ```rust
/// use genetic_algorithm::strategy::evolve::prelude::*;
/// use std::time::Instant;
/// use itertools::Itertools;
/// use rand::Rng;
///
/// #[derive(Clone, Debug)]
/// struct CustomCrossover {
/// pub selection_rate: f32,
/// };
/// impl Crossover for CustomCrossover {
/// type Genotype = MultiRangeGenotype<f32>;
///
/// fn call<R: Rng, SR: StrategyReporter<Genotype = Self::Genotype>>(
/// &mut self,
/// genotype: &Self::Genotype,
/// state: &mut EvolveState<Self::Genotype>,
/// config: &EvolveConfig,
/// reporter: &mut SR,
/// _rng: &mut R,
/// ) {
/// let now = Instant::now();
/// let existing_population_size = state.population.chromosomes.len();
/// let selected_population_size =
/// (existing_population_size as f32 * self.selection_rate).ceil() as usize;
///
/// // Important!!! Append offspring as recycled clones from parents (will crossover later)
/// // Use population's methods for safe chromosome recycling
/// state.population.extend_from_within(selected_population_size);
///
/// // Skip the parents, iterate over the freshly appended offspring
/// let iterator = state
/// .population
/// .chromosomes
/// .iter_mut()
/// .skip(existing_population_size);
///
/// // Crossover the offspring clones
/// for (offspring1, offspring2) in iterator.tuples() {
/// // Custom logic, for instance, swap all genes with even index
/// for even_index in (0..genotype.genes_size()).filter(|x| x % 2 == 0) {
/// std::mem::swap(&mut offspring1.genes[even_index], &mut offspring2.genes[even_index]);
/// // MultiRangeGenotype specific methods are available if needed
/// }
/// // Important!!! Remember to reset the chromosome metadata after manipulation
/// offspring1.reset_metadata(genotype.genes_hashing);
/// offspring2.reset_metadata(genotype.genes_hashing);
/// }
///
/// // Optionally, log one ore more events
/// reporter.on_crossover_event(
/// CrossoverEvent("MyEvent".to_string()),
/// genotype,
/// state,
/// config,
/// );
///
/// // Optionally, keep track of duration for reporting
/// state.add_duration(StrategyAction::Crossover, now.elapsed());
/// }
/// }
/// ```
;