-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathevolve_heterogeneous.rs
More file actions
83 lines (72 loc) · 3.13 KB
/
evolve_heterogeneous.rs
File metadata and controls
83 lines (72 loc) · 3.13 KB
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
//! Heterogeneous optimization using Evolve strategy with MultiRangeGenotype.
//! Each gene has its own range and mutation type, enabling mixed parameter optimization.
//! This example optimizes 4 heterogeneous parameters: a boolean flag, a categorical choice,
//! a continuous value, and a discrete integer.
use genetic_algorithm::strategy::evolve::prelude::*;
const POPULATION_SIZE: usize = 100;
#[derive(Clone, Debug)]
pub struct HeterogeneousFitness {
precision: f32,
}
impl Fitness for HeterogeneousFitness {
type Genotype = MultiRangeGenotype<f32>;
fn calculate_for_chromosome(
&mut self,
chromosome: &FitnessChromosome<Self>,
_genotype: &FitnessGenotype<Self>,
) -> Option<FitnessValue> {
// Gene 0: boolean flag (0.0 or 1.0) - want enabled (1.0)
let flag = chromosome.genes[0];
// Gene 1: algorithm choice (0,1,2,3,4) - want algorithm 3
let algorithm = chromosome.genes[1];
// Gene 2: learning rate (0.001 to 1.0) - want 0.01
let learning_rate = chromosome.genes[2];
// Gene 3: batch size (16 to 512) - want 64
let batch_size = chromosome.genes[3];
let score = (flag - 1.0).abs()
+ (algorithm - 3.0).abs()
+ (learning_rate - 0.01).abs() * 100.0
+ (batch_size - 64.0).abs() / 100.0;
Some((score / self.precision) as FitnessValue)
}
}
fn main() {
env_logger::init();
let genotype = MultiRangeGenotype::<f32>::builder()
.with_allele_ranges(vec![
0.0..=1.0, // Gene 0: boolean flag
0.0..=4.0, // Gene 1: algorithm choice (5 options)
0.001..=1.0, // Gene 2: learning rate (continuous)
16.0..=512.0, // Gene 3: batch size (discrete)
])
.with_mutation_types(vec![
MutationType::Discrete, // boolean: 0 or 1
MutationType::Discrete, // enum: 0,1,2,3,4
MutationType::StepScaled(vec![0.1, 0.01, 0.001]), // continuous refinement
MutationType::Discrete, // integer steps
])
.build()
.unwrap();
println!("{}", genotype);
let evolve = Evolve::builder()
.with_genotype(genotype)
.with_target_population_size(POPULATION_SIZE)
.with_max_stale_generations(1000)
.with_target_fitness_score(0)
.with_fitness(HeterogeneousFitness { precision: 1e-3 })
.with_fitness_ordering(FitnessOrdering::Minimize)
.with_mutate(MutateSingleGene::new(0.2))
.with_crossover(CrossoverSingleGene::new(0.7, 0.8))
.with_select(SelectTournament::new(0.5, 0.02, 4))
.with_reporter(EvolveReporterSimple::new(100))
.call()
.unwrap();
println!("{}", evolve);
if let Some((best_genes, best_fitness_score)) = evolve.best_genes_and_fitness_score() {
println!("flag: {}", best_genes[0]);
println!("algorithm: {}", best_genes[1]);
println!("learning_rate: {}", best_genes[2]);
println!("batch_size: {}", best_genes[3]);
println!("fitness: {}", best_fitness_score);
}
}