Guest User

Rust Genetic Algorithm for string convergence

a guest
Nov 10th, 2015
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.16 KB | None | 0 0
  1. // Genetic Algorithm for convergence to a given string
  2. // Author: Duncan Dean
  3.  
  4. extern crate rand;
  5. use rand::Rng;
  6.  
  7. fn rand_string(size: u32) -> String {
  8.     let mut rand_string = "".to_string();
  9.     for _ in 0..size {
  10.         rand_string = rand_string + &(rand::thread_rng().gen_range(32, 123) as u8 as char).to_string();
  11.     }
  12.     rand_string
  13. }
  14.  
  15. fn crossover(chrome1: Chromosome, chrome2: Chromosome, cross_prob: f32, solution: &str) -> Chromosome {
  16.     if rand::thread_rng().gen_range::<f32>(0.0, 1.0) <= cross_prob {
  17.         let code_len = chrome1.code.len();
  18.         let rand_index = rand::thread_rng().gen_range(0, code_len);
  19.         let first_half = &chrome1.code[0..rand_index];
  20.         let second_half = &chrome2.code[rand_index..code_len];
  21.         let new_code = first_half.to_string() + second_half;
  22.         Chromosome {
  23.             code: new_code.to_string(),
  24.             cost_score: cost_function(&new_code, solution),
  25.             solution: solution.to_string(),
  26.         }
  27.     } else if chrome1.cost_score < chrome2.cost_score {
  28.         chrome1.clone()
  29.     } else {
  30.         chrome2.clone()
  31.     }
  32. }
  33.  
  34.  
  35. fn cost_function(code: &str, solution: &str) -> u32 {
  36.     let chars: Vec<char> = solution.to_string().chars().collect();
  37.     let code_chars: Vec<char> = code.to_string().chars().collect();
  38.     let mut cost: u32 = 0;
  39.     let mut cost_add;
  40.     for i in 0..chars.len() {
  41.         cost_add = (chars[i] as u8 as i32) - (code_chars[i] as u8 as i32);
  42.         cost = cost + (cost_add * cost_add) as u32;
  43.     }
  44.     cost
  45. }
  46.  
  47.  
  48. #[derive(Clone)]
  49. struct Chromosome {
  50.     code: String,
  51.     cost_score: u32,
  52.     solution: String,
  53. }
  54.  
  55. impl Chromosome {
  56.     fn new(solution: String) -> Chromosome {
  57.         let random_string = &rand_string(solution.len() as u32);
  58.         Chromosome {
  59.             code: random_string.to_string(),
  60.             cost_score: cost_function(random_string, &solution),
  61.             solution: solution,
  62.         }
  63.     }
  64.  
  65.     fn mutate(&mut self, mut_prob:f64) -> Chromosome {
  66.         if rand::thread_rng().gen_range::<f64>(0.0, 1.0) <= mut_prob {
  67.             let rand_index = rand::thread_rng().gen_range(0, self.code.len());
  68.             let mut new_code_vec: Vec<char> = self.code.chars().collect();
  69.             new_code_vec[rand_index] = rand::thread_rng().gen_range(32, 123) as u8 as char;
  70.             self.code = new_code_vec.iter().fold("".to_string(), |acc, s| acc + &s.to_string());
  71.             self.cost_score = cost_function(&self.code, &self.solution);
  72.             self.clone()
  73.  
  74.         } else {
  75.             self.clone()
  76.         }
  77.  
  78.     }
  79.  
  80.  
  81. }
  82.  
  83.  
  84.  
  85. fn main() {
  86.     let solution = "This is the string that we want to converge to.".to_string();
  87.     let gen_number = 5000;
  88.     let mut pop_size = 20; // Must be greater than 1
  89.     let max_pop = pop_size * 10;
  90.     let mut_prob = 0.4;
  91.     let kill_constant = 0.45;
  92.     let cross_prob = 0.6;
  93.     let mut population = Vec::new();
  94.  
  95.  
  96.     // Initialize population
  97.     for i in 0..pop_size {
  98.         population.push(Chromosome::new(solution.to_string()));
  99.         println!("{}, cost: {}", population[i].code, population[i].cost_score);
  100.     }
  101.  
  102.     // Step generation
  103.     for _ in 1..(gen_number + 1) {
  104.         // Mutations
  105.         for i in 0..pop_size {
  106.             population[i] = population[i].mutate(mut_prob);
  107.             //println!("{}, cost: {}", population[i].code, population[i].cost_score);
  108.         }
  109.  
  110.         // Kill the weaklings
  111.         population.sort_by(|ref a, ref b| a.cost_score.cmp(&b.cost_score));
  112.         for _ in 0..((( pop_size as f32)*kill_constant) as u32) {
  113.             population.pop();
  114.         }
  115.         pop_size = population.len();
  116.  
  117.  
  118.  
  119.         // Crossovers
  120.         if pop_size < max_pop {
  121.             for i in 0..(population.len() - 2) {
  122.                 let chrome1 = population[i].clone();
  123.                 let chrome2 = population[i+1].clone();
  124.                 population.push(crossover(chrome1, chrome2, cross_prob, &solution));
  125.                 pop_size += 1;
  126.             }
  127.         }
  128.  
  129.  
  130.  
  131.     }
  132.     println!("\n\nFinal");
  133.     for i in 0..pop_size {
  134.         println!("{}, cost: {}", population[i].code, population[i].cost_score);
  135.     }
  136.  
  137.  
  138.  
  139. }
Advertisement
Add Comment
Please, Sign In to add comment