use std::sync::Arc;
use genetic_algorithms::chromosomes::Binary as BinaryChromosome;
use genetic_algorithms::configuration::ProblemSolving;
use genetic_algorithms::fitness::count_true;
use genetic_algorithms::ga::{Ga, TerminationCause};
use genetic_algorithms::genotypes::Binary;
use genetic_algorithms::initializers::binary_random_initialization;
use genetic_algorithms::operations::{Crossover, Mutation, Selection, Survivor};
use genetic_algorithms::population::Population;
use genetic_algorithms::stats::GenerationStats;
use genetic_algorithms::traits::{
ChromosomeT, ConfigurationT, CrossoverConfig, MutationConfig, SelectionConfig, StoppingConfig,
};
use genetic_algorithms::LogObserver;
fn main() {
const N_BITS: usize = 100;
const POP_SIZE: usize = 50;
const MAX_GENERATIONS: usize = 1000;
const FITNESS_TARGET: f64 = N_BITS as f64;
let fitness_fn = |dna: &[Binary]| count_true(dna);
let mut ga = Ga::new()
.with_genes_per_chromosome(N_BITS)
.with_population_size(POP_SIZE)
.with_initialization_fn(binary_random_initialization)
.with_fitness_fn(fitness_fn)
.with_selection_method(Selection::RouletteWheel)
.with_crossover_method(Crossover::SinglePoint)
.with_mutation_method(Mutation::BitFlip)
.with_survivor_method(Survivor::Fitness)
.with_problem_solving(ProblemSolving::FixedFitness)
.with_fitness_target(FITNESS_TARGET)
.with_max_generations(MAX_GENERATIONS)
.with_observer(Arc::new(LogObserver))
.build()
.expect("Failed to build GA configuration");
println!("== OneMax Binary Example ==");
println!(
"Chromosome: {} bits, Population: {}, Max generations: {}, Target fitness: {}",
N_BITS, POP_SIZE, MAX_GENERATIONS, FITNESS_TARGET
);
println!("Operators: Selection=RouletteWheel, Crossover=SinglePoint, Mutation=BitFlip");
println!("-------------------------------------------------------");
let report_interval = 50;
let result = ga.run_with_callback(
Some(
|gen: &usize,
pop: &Population<BinaryChromosome>,
_stats: &GenerationStats,
_cause: &TerminationCause|
-> std::ops::ControlFlow<()> {
let avg_fitness =
pop.chromosomes.iter().map(|c| c.fitness()).sum::<f64>() / pop.size() as f64;
println!(
"Generation {:4}: best = {:6.2}, avg = {:6.2}",
gen, pop.best_chromosome.fitness, avg_fitness
);
std::ops::ControlFlow::Continue(())
},
),
report_interval,
);
match result {
Ok(population) => {
println!("-------------------------------------------------------");
println!(
"Finished. Best fitness: {}",
population.best_chromosome.fitness
);
if (population.best_chromosome.fitness - FITNESS_TARGET).abs() < f64::EPSILON {
println!("SUCCESS: Found the global optimum (all bits are 1)!");
} else {
println!("Did not reach optimum. Try increasing generations or population size.");
}
}
Err(e) => {
println!("GA failed: {:?}", e);
}
}
}