boggle_maker/
genetic_boggle_maker.rs

1use genetic_algorithm::strategy::evolve::prelude::*;
2use word_trie::trie::Trie;
3use crate::boggle_board::Board;
4use crate::total_boggle_score_calculator::TotalBoggleScoreCalculator;
5
6
7#[derive(Clone, Debug)]
8struct BoggleFitness<'a> {
9    score_calc: TotalBoggleScoreCalculator<'a>,
10}
11
12impl <'a> BoggleFitness<'a> {
13    pub fn new(dictionary : &'a Trie, x_size:usize, y_size:usize)->Self{
14        let score_calc = TotalBoggleScoreCalculator::new(dictionary, x_size, y_size);
15
16        Self{
17            score_calc
18        }
19    }
20
21    fn get_board_score(&mut self,board:&Vec<char>) -> u32{         
22        self.score_calc.score(board)
23    }
24}
25
26impl Fitness for BoggleFitness<'_> {
27    type Genotype = ListGenotype<char>;
28
29    fn calculate_for_chromosome(
30        &mut self,
31        chromosome: &FitnessChromosome<Self>,
32        _genotype: &FitnessGenotype<Self>,
33    ) -> Option<FitnessValue> {
34
35        let score = self.get_board_score(&chromosome.genes);
36        Some(score as FitnessValue)
37    }
38
39    
40}
41
42///generates a boggle board instance by given width, length, target score 
43/// and a trie to be used for calculation of the scores
44///this method is using genetic algorithm for finding the best fit for the target score
45pub fn make(width : usize, length : usize, target_score: isize , dictionary: &Trie) 
46-> Option<Board> {
47    let allele_lists = vec![
48        'a', 'b', 'c', 'd', 'e', 
49        'f', 'g', 'h', 'i', 'j', 
50        'k', 'l', 'm', 'n', 'o',
51        'p', 'q', 'r', 's', 't', 
52        'u', 'v', 'w', 'x', 'y', 
53        'z',
54    ];
55
56    //define the geno type
57    let genotype = ListGenotype::builder()
58     .with_genes_size(width * length)
59     .with_allele_list(allele_lists)
60     .with_genes_hashing(false) // optional, defaults to false
61     .build()
62     .unwrap();
63
64     let evolve_builder = Evolve::builder()
65        .with_genotype(genotype)
66        .with_target_population_size(100)
67        .with_max_stale_generations(25)
68        .with_mutate(MutateSingleGene::new(0.2))
69        .with_crossover(CrossoverUniform::new())
70        .with_select(SelectElite::new(0.8))
71        .with_extension(ExtensionMassDegeneration::new(2, 10))
72         .with_reporter(EvolveReporterSimple::new(50))
73        // .with_par_fitness(true)
74        .with_target_fitness_score(target_score)
75        //.with_select(SelectTournament::new(4, 0.9))
76        //.with_mutate(MutateMultiGeneDynamic::new(2, 0.1, 250))
77        //.with_reporter(EvolveReporterDuration::new())
78        .with_fitness(BoggleFitness::new(dictionary,width,length));
79
80    let (evolve, _) = evolve_builder.call_speciated(10).unwrap();
81        if let Some(best_chromosome) = evolve.best_chromosome() {
82        let board = Board::new(best_chromosome.genes, width, length, best_chromosome.fitness_score);
83
84        Some(board)
85        //println!("{:?}",best_chromosome.genes);
86    } else {
87        //println!("Invalid solution with fitness score: None");
88        None
89    }
90}