///|
/// Genetic Algorithm Demo - Sequence optimization using GA operations.
/// Inspired by Biopython's Bio.GA module.
///|
fn main {
println("=== Genetic Algorithm Demo ===")
println("Inspired by Biopython's Bio.GA module")
println("")
println("1. Creating GA Individuals")
let ind1 = @bio.GAIndividual::new(
sequence="ATCGATCG",
fitness=0.5,
generation=0,
id=1,
)
let ind2 = @bio.GAIndividual::new(
sequence="GGCCGGCC",
fitness=0.8,
generation=0,
id=2,
)
println(
" Individual 1: seq=\{ind1.sequence}, fitness=\{ind1.fitness.to_string()}",
)
println(
" Individual 2: seq=\{ind2.sequence}, fitness=\{ind2.fitness.to_string()}",
)
println("")
println("2. Creating a Population")
let individuals = [
@bio.GAIndividual::new(sequence="AAAA", fitness=0.3, generation=0, id=0),
@bio.GAIndividual::new(sequence="CCCC", fitness=0.6, generation=0, id=1),
@bio.GAIndividual::new(sequence="GGGG", fitness=0.9, generation=0, id=2),
@bio.GAIndividual::new(sequence="TTTT", fitness=0.4, generation=0, id=3),
@bio.GAIndividual::new(sequence="ACGT", fitness=0.7, generation=0, id=4),
]
let pop = @bio.GAPopulation::new(individuals~)
println(" Population size: \{pop.individuals.length().to_string()}")
println(" Best fitness: \{pop.best_fitness.to_string()}")
println(" Avg fitness: \{pop.avg_fitness.to_string()}")
println(" Worst fitness: \{pop.worst_fitness.to_string()}")
println("")
println("3. Fitness Functions")
let target = "ACGTACGT"
let fitness_fn = @bio.ga_fitness_match(target)
let test_seqs = ["ACGTACGT", "AAAAACGT", "ACGTAAAA", "AAAAAAAA"]
for seq in test_seqs {
let ind = @bio.GAIndividual::new(sequence=seq)
let fit = fitness_fn(ind)
println(
" Sequence '\{seq}' fitness (match to '\{target}'): \{fit.to_string()}",
)
}
println("")
println("4. Crossover Operations")
let parent1 = @bio.GAIndividual::new(
sequence="AAAA",
fitness=0.8,
generation=0,
id=10,
)
let parent2 = @bio.GAIndividual::new(
sequence="CCCC",
fitness=0.6,
generation=0,
id=11,
)
let (child1, child2) = @bio.ga_single_point_crossover(
parent1,
parent2,
point=2,
)
println(" Parent1: \{parent1.sequence}")
println(" Parent2: \{parent2.sequence}")
println(" Child1 (crossover at 2): \{child1.sequence}")
println(" Child2 (crossover at 2): \{child2.sequence}")
println("")
println("5. Mutation Operations")
let original = @bio.GAIndividual::new(
sequence="AAAA",
fitness=0.0,
generation=0,
id=20,
)
let mutated = @bio.ga_point_mutate(original, 1.0, "ACGT")
println(" Original: \{original.sequence}")
println(" Mutated: \{mutated.sequence}")
println("")
println("6. Selection Operations")
let tournament_winner = @bio.ga_tournament_select(individuals, 3)
println(
" Tournament selection winner: seq=\{tournament_winner.sequence}, fitness=\{tournament_winner.fitness.to_string()}",
)
let roulette_winner = @bio.ga_roulette_select(individuals)
println(
" Roulette selection winner: seq=\{roulette_winner.sequence}, fitness=\{roulette_winner.fitness.to_string()}",
)
println("")
println("7. GA Configuration")
let config = @bio.GAConfig::new(
population_size=50,
sequence_length=8,
max_generations=100,
target="ACGTACGT",
mutation_rate=0.05,
crossover_rate=0.8,
elitism=true,
)
println(" Population size: \{config.population_size.to_string()}")
println(" Max generations: \{config.max_generations.to_string()}")
println(" Mutation rate: \{config.mutation_rate.to_string()}")
println(" Crossover rate: \{config.crossover_rate.to_string()}")
println(" Elitism: \{config.elitism.to_string()}")
println("")
println("8. Running GA Evolution")
let target_seq = "ACGTACGT"
let fit_fn = @bio.ga_fitness_match(target_seq)
let evo_config = @bio.GAConfig::new(
population_size=30,
sequence_length=8,
max_generations=50,
target=target_seq,
mutation_rate=0.05,
crossover_rate=0.85,
elitism=true,
convergence_threshold=0.01,
)
let result = @bio.ga_evolve(evo_config, fit_fn)
println(" Generations reached: \{result.generation_reached.to_string()}")
println(" Converged: \{result.converged.to_string()}")
println(
" Best individual: seq=\{result.best_individual.sequence}, fitness=\{result.best_individual.fitness.to_string()}",
)
println(" Best fitness history (first 5):")
let mut i = 0
while i < 5 && i < result.best_fitness_history.length() {
println(
" Gen \{i.to_string()}: best = \{result.best_fitness_history[i].to_string()}",
)
i = i + 1
}
println(" Avg fitness history (first 5):")
let mut j = 0
while j < 5 && j < result.avg_fitness_history.length() {
println(
" Gen \{j.to_string()}: avg = \{result.avg_fitness_history[j].to_string()}",
)
j = j + 1
}
println("")
println("=== Demo completed successfully! ===")
println("")
println("Key concepts:")
println("- GA evolves sequences toward a target fitness objective")
println("- Selection chooses which individuals reproduce")
println("- Crossover combines two parents to create offspring")
println("- Mutation introduces random variation")
println("- Elitism preserves the best individuals each generation")
}