mod config; mod corpus; mod evaluation; mod layout; mod output; use rayon::prelude::*; use rand::prelude::*; use rand_pcg::*; use config::*; use corpus::*; use evaluation::*; use layout::*; use std::time::Instant; struct Tournament<'a> { rngs: Vec, top_prelayouts: Vec<(Prelayout, f32)>, corpus: &'a Corpus, } impl<'a> Tournament<'a> { fn new_from_seed_prelayout(seed_prelayout: &Prelayout, corpus: &'a Corpus) -> Tournament<'a> { let mut rngs: Vec = Vec::new(); for _ in 0..NUM_CONTESTANTS { rngs.push(Pcg64::from_entropy()); } let mut top_prelayouts: Vec<(Prelayout, f32)> = Vec::new(); let score = prelayout_fitness(&corpus, &seed_prelayout); for _ in 0..NUM_PERSIST { top_prelayouts.push((seed_prelayout.clone(), score)); } Tournament { rngs, top_prelayouts, corpus, } } fn run_round(&mut self) -> Option { let rngs = &mut self.rngs; let mut tournament = rngs .into_par_iter() .map(|mut rng| { let layout = Prelayout::new_random_from( &self.top_prelayouts[rng.gen_range(0..NUM_PERSIST)].0, &mut rng, ); return (layout, prelayout_fitness(&self.corpus, &layout)); }) .collect::>(); let best = self.top_prelayouts[0].1; tournament.append(&mut self.top_prelayouts); tournament.sort_by(|(_, lscore), (_, rscore)| { if lscore < rscore { std::cmp::Ordering::Less } else { std::cmp::Ordering::Greater } }); let result; if tournament[0].1 < best { result = Some(tournament[0].0); } else { result = None; } for i in 0..NUM_PERSIST { self.top_prelayouts.push(tournament[i]); } result } } fn main() { let corpus = Corpus::load(CORPUS_FILE_NAME).unwrap(); println!("{}", corpus); let seed_layout = Layout::from_verbose(STARTING_LAYOUT_STRING).unwrap(); let seed_evl = Evaluation::evaluate_layout(&corpus, &seed_layout); println!("Starting with\n {}{}", seed_layout, seed_evl); let seed_prelayout = seed_layout.as_prelayout(); let mut tournament = Tournament::new_from_seed_prelayout(&seed_prelayout, &corpus); let mut count: usize = 0; let mut current = Instant::now(); loop { let improvement = tournament.run_round(); if let Some(prelayout) = improvement { let layout = Layout::from_prelayout(&prelayout, &corpus); let evl = Evaluation::evaluate_layout(&corpus, &layout); println!("\n================================================================================\n\n{}{}", layout, evl ); } count += 1; if count > 65535 { let duration = current.elapsed(); let rps = count as f32 / duration.as_millis() as f32 * 1000.0; eprint!( "\u{001b}[2K\u{001b}[1000D{} layouts/s and {} tournaments/s", rps * NUM_CONTESTANTS as f32, rps ); current = Instant::now(); count = 0; } } }