1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
use std::{collections::HashMap, ops::RangeFrom}; use super::{id_iter::IdIter, Id}; /// Acts as a generator and cache for ANN node identities. /// /// For any evolution process you should only ever use exactly one [`IdGenerator`] and pass it around whenever one is required, /// as several operations and gurantees rely on the cache inside the generator to function as defined. /// Usually it suffices to use the `<operation>_with_context` functions on the [`crate::Genome`] and let the [`crate::GenomeContext`] handle the identity generation. /// /// ``` /// use set_genome::IdGenerator; /// let id_generator = IdGenerator::default(); /// ``` #[derive(Debug)] pub struct IdGenerator { id_gen: RangeFrom<usize>, id_cache: HashMap<(Id, Id), Vec<Id>>, } impl Default for IdGenerator { fn default() -> Self { IdGenerator { id_gen: 0.., id_cache: HashMap::new(), } } } impl IdGenerator { /// Returns the next unique identity. /// /// ``` /// # use set_genome::{IdGenerator, Id}; /// let mut id_generator = IdGenerator::default(); /// assert_eq!(id_generator.next_id(), Id(0)); /// assert_eq!(id_generator.next_id(), Id(1)); /// ``` pub fn next_id(&mut self) -> Id { self.id_gen.next().map(Id).unwrap() } /// Returns an iterator over identities for the given cache key which automatically extends the cache with new entries when iterated beyond the entries cached so far. /// /// ``` /// # use set_genome::{IdGenerator, Id}; /// // cache is initially empty /// let mut id_generator = IdGenerator::default(); /// // ask for any arbitrary cache entry /// let mut id_iter = id_generator.cached_id_iter((Id(9), Id(9))); /// // we get the next available id /// assert_eq!(id_iter.next(), Some(Id(0))); /// // the id_iter advanced the generator /// assert_eq!(id_generator.next_id(), Id(1)); /// // asking for the same entry later returns the cached entry and then fresh ones /// let mut id_iter = id_generator.cached_id_iter((Id(9), Id(9))); /// assert_eq!(id_iter.next(), Some(Id(0))); /// assert_eq!(id_iter.next(), Some(Id(2))); /// ``` pub fn cached_id_iter(&mut self, cache_key: (Id, Id)) -> IdIter { let cache_entry = self.id_cache.entry(cache_key).or_insert_with(Vec::new); IdIter::new(cache_entry, &mut self.id_gen) } } #[cfg(test)] mod tests { use super::{Id, IdGenerator}; #[test] fn get_new_id() { let mut test_id_manager = IdGenerator::default(); assert_eq!(test_id_manager.next_id(), Id(0)); assert_eq!(test_id_manager.next_id(), Id(1)); assert_eq!(test_id_manager.next_id(), Id(2)); } #[test] fn iter_cached_ids() { let mut test_id_manager = IdGenerator::default(); let mut test_id_iter_0 = test_id_manager.cached_id_iter((Id(4), Id(2))); assert_eq!(test_id_iter_0.next(), Some(Id(0))); assert_eq!(test_id_iter_0.next(), Some(Id(1))); let mut test_id_iter_1 = test_id_manager.cached_id_iter((Id(4), Id(2))); assert_eq!(test_id_iter_1.next(), Some(Id(0))); // cached entry assert_eq!(test_id_iter_1.next(), Some(Id(1))); // cached entry assert_eq!(test_id_iter_1.next(), Some(Id(2))); // new entry } }