diff --git a/rust-pvz-genetics/src/genetics/manipulations.rs b/rust-pvz-genetics/src/genetics/manipulations.rs index 3151a5f..8289c4c 100644 --- a/rust-pvz-genetics/src/genetics/manipulations.rs +++ b/rust-pvz-genetics/src/genetics/manipulations.rs @@ -2,29 +2,35 @@ use std::{collections::HashMap, mem::swap}; use rand::{RngExt, SeedableRng, rngs::StdRng}; -use crate::genetics::{gene::Gene, genome::*}; +use crate::genetics::genome::*; pub struct PairGenomeModificator { genome_a: Genome, genome_b: Genome, generator: StdRng } + +pub struct SingleGenomeModificator { + genome: Genome, + generator: StdRng +} + impl PairGenomeModificator { - pub fn new(genome_a: &Genome,genome_b: &Genome) -> Self { + pub fn new(genome_a: Genome,genome_b: Genome) -> Self { return Self { - genome_a: genome_a.clone(), - genome_b: genome_b.clone(), + genome_a, + genome_b, generator: rand::make_rng(), }; } - pub fn with_seed(genome_a: &Genome, genome_b: &Genome, seed: u64) -> Self { + pub fn with_seed(genome_a: Genome, genome_b: Genome, seed: u64) -> Self { return Self { - genome_a: genome_a.clone(), - genome_b: genome_b.clone(), + genome_a, + genome_b, generator: StdRng::seed_from_u64(seed) }; } - pub fn allelic_crossingover(&mut self,chance: Option) { + pub fn allelic_crossingover(mut self,chance: Option) -> (Genome, Genome) { let amount: usize = *[self.genome_a.graph.len(),self.genome_b.graph.len()].iter().min().unwrap_or(&0); for i in 0..amount { @@ -32,11 +38,12 @@ impl PairGenomeModificator { if computed != 0 {continue;} swap(&mut self.genome_a.graph[i].0, &mut self.genome_b.graph[i].0); } + + (self.genome_a,self.genome_b) } - pub fn categoric_crossingover(&mut self, chance: Option) { + pub fn categoric_crossingover(mut self, chance: Option) -> (Genome,Genome) { let threshold = chance.unwrap_or(2).max(2); - // Собираем индексы по категориям для каждого генома let mut categories_a: HashMap> = HashMap::new(); let mut categories_b: HashMap> = HashMap::new(); @@ -47,7 +54,6 @@ impl PairGenomeModificator { categories_b.entry(gene.place.clone()).or_default().push(i); } - // Проходим по категориям которые есть в обоих геномах for (category, indices_a) in &categories_a { let Some(indices_b) = categories_b.get(category) else { continue; }; @@ -57,14 +63,32 @@ impl PairGenomeModificator { let fi = indices_a[self.generator.random_range(0..indices_a.len())]; let si = indices_b[self.generator.random_range(0..indices_b.len())]; - // Копируем и меняем местами let gene_a = self.genome_a.graph[fi].0.clone(); let gene_b = self.genome_b.graph[si].0.clone(); self.genome_a.graph[fi].0 = gene_b; self.genome_b.graph[si].0 = gene_a; } + (self.genome_a,self.genome_b) } - pub fn finish(self) -> (Genome,Genome) { + pub fn combine(mut self) -> (Genome,Genome){ + (self.genome_a,self.genome_b) + } + pub fn cancel(self) -> (Genome,Genome) { (self.genome_a,self.genome_b) } } + +impl SingleGenomeModificator { + pub fn new(genome: Genome) -> Self { + return Self { + genome, + generator: rand::make_rng(), + }; + } + pub fn with_seed(genome: Genome, seed: u64) -> Self { + return Self { + genome, + generator: StdRng::seed_from_u64(seed) + }; + } +} diff --git a/rust-pvz-genetics/src/genetics/plant_templates.rs b/rust-pvz-genetics/src/genetics/plant_templates.rs index 7f95fe5..ae91664 100644 --- a/rust-pvz-genetics/src/genetics/plant_templates.rs +++ b/rust-pvz-genetics/src/genetics/plant_templates.rs @@ -5,7 +5,7 @@ pub fn peashooter_template() -> Genome { Gene::new("Peashooter","root", GeneType::pure_producer(|_|{Flow::empty()})), Gene::new("Peashooter","stem", GeneType::fill_all()), Gene::new("Peashooter","head",GeneType::random_distribution()), - Gene::new("Peashooter","leaf",GeneType::modifier(|_|{None})), + Gene::new("Peashooter","leaf",GeneType::modifier(|_|{Flow::empty()})), Gene::new("Peashooter","face",GeneType::consumer(|_|{})) ],vec![ (0,1), @@ -19,7 +19,7 @@ pub fn sunflower_template() -> Genome { Genome::from_edges(vec![ Gene::new("Sunflower","root", GeneType::Dummy), Gene::new("Sunflower","stem", GeneType::Dummy), - Gene::new("Sunflower","head", GeneType::modifier(|_|{None})), + Gene::new("Sunflower","head", GeneType::modifier(|_|{Flow::empty()})), Gene::new("Sunflower","face", GeneType::consumer(|_|{})), ], vec![ (0,1), @@ -30,7 +30,7 @@ pub fn sunflower_template() -> Genome { pub fn cherry_bomb_template() -> Genome { Genome::from_edges(vec![ - Gene::new("Cherry bomb","root", GeneType::modifier(|_|{None})), + Gene::new("Cherry bomb","root", GeneType::modifier(|_|{Flow::empty()})), Gene::new("Cherry bomb","head", GeneType::consumer(|_|{})), Gene::new("Cherry bomb","head", GeneType::consumer(|_|{})), Gene::new("Cherry bomb","face", GeneType::Dummy), diff --git a/rust-pvz-genetics/src/genetics/tests.rs b/rust-pvz-genetics/src/genetics/tests.rs index c7b0cf9..2b8e627 100644 --- a/rust-pvz-genetics/src/genetics/tests.rs +++ b/rust-pvz-genetics/src/genetics/tests.rs @@ -2,6 +2,7 @@ use crate::genetics::{flow::Flow, gene::{Gene, GeneType}, genome::Genome, manipu #[test] fn test_display() { + println!("{}",peashooter_template()); assert!(peashooter_template().to_string() == "(Peashooter) root\n\t(Peashooter) stem\n\t\t(Peashooter) head\n\t\t\t(Peashooter) leaf\n\t\t\t(Peashooter) face\n"); } @@ -9,7 +10,15 @@ fn test_display() { fn test_allelic_crossingover() { let mut peashooter = peashooter_template(); let mut sunflower = sunflower_template(); - PairGenomeModificator::with_seed(&mut peashooter, &mut sunflower,3996684975687038250u64).allelic_crossingover(None); + + println!("Peashooter:\n{}",peashooter); + println!("Sunflower:\n{}",sunflower); + + (peashooter,sunflower) = PairGenomeModificator::with_seed(peashooter, sunflower,3996684975687038250u64).allelic_crossingover(None); + + println!("Peashooter:\n{}",peashooter); + println!("Sunflower:\n{}",sunflower); + assert!(peashooter.to_string() == Genome::from_edges(vec![ Gene::new("Sunflower","root", GeneType::Dummy), Gene::new("Peashooter","stem", GeneType::fill_all()), @@ -22,11 +31,12 @@ fn test_allelic_crossingover() { (2,3), (2,4) ]).unwrap().to_string()); + assert!(sunflower.to_string() == Genome::from_edges(vec![ Gene::new("Peashooter","root", GeneType::pure_producer(|_|{Flow::empty()})), Gene::new("Sunflower","stem", GeneType::Dummy), - Gene::new("Sunflower","head", GeneType::modifier(|_|{None})), - Gene::new("Peashooter","leaf",GeneType::modifier(|_|{None})), + Gene::new("Sunflower","head", GeneType::modifier(|_|{Flow::empty()})), + Gene::new("Peashooter","leaf",GeneType::modifier(|_|{Flow::empty()})), ], vec![ (0,1), (1,2),