@@ 28,19 28,38 @@ pub struct EvolutionResult<TInput, TResult> {
pub iterations: usize
}
-pub fn evolution_algorithm<TChromosome: Clone, TResult: Clone, const DParents: usize>(
+pub fn evolution_algorithm
+ <TChromosome: Clone,
+ TResult: Clone,
+ const DParents: usize,
+ TSelection: Selection<TChromosome, TResult>,
+ TPairing: Pairing<DParents, Chromosome = TChromosome, Out = TResult>,
+ TCrossover: Crossover<DParents, Chromosome = TChromosome, Out = TResult>,
+ TReplacement: Replacement<TChromosome, TResult>,
+ TPerturbation: PerturbationOperator<Chromosome = TChromosome>>(
initial_population: Population<TChromosome>,
parents_count: usize,
fitness: &impl FitnessFunction<In = TChromosome, Out = TResult>,
- selection: &impl Selection<TChromosome, TResult>,
- pairing: &impl Pairing<DParents, Chromosome = TChromosome, Out = TResult>,
- crossover: &impl Crossover<DParents, Chromosome = TChromosome, Out = TResult>,
- perturbation: &impl PerturbationOperator<Chromosome = TChromosome>,
- replacement: &impl Replacement<TChromosome, TResult>,
+ selection: &mut TSelection,
+ pairing: &mut TPairing,
+ crossover: &mut TCrossover,
+ perturbation: &mut TPerturbation,
+ replacement: &mut TReplacement,
better_than: &impl BetterThanOperator<TResult>,
// TODO: termination condition
iterations: usize,
rng: &mut dyn RngCore,
+ mut evolution: impl FnMut(
+ usize,
+ &EvolutionStats<TChromosome, TResult>,
+ &EvaluatedPopulation<TChromosome, TResult>,
+
+ &mut TSelection,
+ &mut TPairing,
+ &mut TCrossover,
+ &mut TPerturbation,
+ &mut TReplacement
+ )
) -> Result<EvolutionResult<TChromosome, TResult>, Box<dyn Error>> {
let mut current_population = initial_population.evaluate(fitness)?;
@@ 84,6 103,17 @@ pub fn evolution_algorithm<TChromosome: Clone, TResult: Clone, const DParents: u
// Replace
current_population = replacement.replace(current_population, evaluated_offsprings, better_than, rng);
+
+ evolution(
+ iteration,
+ &stats,
+ ¤t_population,
+ selection,
+ pairing,
+ crossover,
+ perturbation,
+ replacement
+ );
}
let best_candidate = last_best_candidate.evaluated_chromosome.clone();
@@ 124,10 154,10 @@ pub mod tests {
population,
50,
&one_max,
- &TournamentSelection::new(5, 0.8),
- &AdjacentPairing::new(),
- &BinaryOnePointCrossover::new(),
- &CombinedPerturbation::new(
+ &mut TournamentSelection::new(5, 0.8),
+ &mut AdjacentPairing::new(),
+ &mut BinaryOnePointCrossover::new(),
+ &mut CombinedPerturbation::new(
vec![
Box::new(MutationPerturbation::new(
Box::new(BinaryStringSingleBitPerturbation::new()),
@@ 137,10 167,11 @@ pub mod tests {
0.3))
]
),
- &BestReplacement::new(),
+ &mut BestReplacement::new(),
&MinimizingOperator,
1000,
- &mut rng
+ &mut rng,
+ |_, _, _, _, _, _, _, _| ()
).unwrap();
assert_eq!(
@@ 93,16 93,16 @@ fn run_evolution_algorithm(instance: &TSPInstance<Dyn>, optimal_cost: f64, base_
// Create combined perturbation with two mutations wrapped in MutationPerturbation
let swap_mutation = MutationPerturbation::new(Box::new(SwapPerturbation::new()), 0.5);
let reverse_mutation = MutationPerturbation::new(Box::new(ReverseSubsequencePerturbation::new()), 0.5);
- let combined_perturbation = CombinedPerturbation::new(vec![
+ let mut combined_perturbation = CombinedPerturbation::new(vec![
Box::new(swap_mutation),
Box::new(reverse_mutation),
]);
// Set up other components
- let crossover = EdgeRecombinationCrossover::new();
- let selection = TournamentSelection::new(5, 0.8);
- let replacement = BestReplacement::new();
- let pairing = AdjacentPairing::new();
+ let mut crossover = EdgeRecombinationCrossover::new();
+ let mut selection = TournamentSelection::new(5, 0.8);
+ let mut replacement = BestReplacement::new();
+ let mut pairing = AdjacentPairing::new();
let better_than_operator = MinimizingOperator::new();
// Create initial population
@@ 116,18 116,29 @@ fn run_evolution_algorithm(instance: &TSPInstance<Dyn>, optimal_cost: f64, base_
// Run evolution algorithm
let parents_count = 250;
- let result = evolution_algorithm::<_, _, 2>(
+ let result = evolution_algorithm(
initial_population.clone(),
parents_count,
instance,
- &selection,
- &pairing,
- &crossover,
- &combined_perturbation,
- &replacement,
+ &mut selection,
+ &mut pairing,
+ &mut crossover,
+ &mut combined_perturbation,
+ &mut replacement,
&better_than_operator,
5000, // max iterations
&mut rng,
+ |iteration, stats, _, _, _, _, perturbation, _| {
+ let iters_till_end = 5000 - iteration + 1;
+ let iters_since_better =
+ iteration - stats.best_candidates.last().map(|c| c.iteration).unwrap_or(0);
+ MutationPerturbation::apply_to_mutations(
+ perturbation,
+ &mut |p| {
+ p.probability = (0.5 * (1.0 + (iters_since_better as f64 / iters_till_end as f64))).min(1.0);
+ }
+ );
+ }
)?;
// Plot the best solution