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
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::rc::Rc;
use rand;
use super::super::{AstNode, Mutatable};
use super::super::ast::{NodeInTree, find_nodes_and_parents, replace_to_root};
pub fn crossover_tree<T: AstNode+Mutatable+Clone, R: rand::Rng+Sized>(ast1: &T, ast2: &T, rng: &mut R) -> (Box<T>, Box<T>) {
let nodes1 = group_by_type(find_nodes_and_parents(ast1));
let nodes2 = group_by_type(find_nodes_and_parents(ast2));
let shared_node_types = nodes1.iter()
.filter_map(|(typ, _)| nodes2.get(typ).map(|_| *typ))
.collect::<Vec<usize>>();
let typ = rng.choose(&shared_node_types).unwrap();
let nap1 = rng.choose(&nodes1.get(typ).unwrap()).unwrap();
let nap2 = rng.choose(&nodes2.get(typ).unwrap()).unwrap();
let child1 = replace_to_root::<T>(&nap1, nap2.node.copy());
let child2 = replace_to_root::<T>(&nap2, nap1.node.copy());
(child1, child2)
}
fn group_by_type(naps: Vec<Rc<NodeInTree>>) -> BTreeMap<usize, Vec<Rc<NodeInTree>>> {
let mut ret : BTreeMap<usize, Vec<Rc<NodeInTree>>> = BTreeMap::new();
for nap in naps {
let values: &mut Vec<Rc<NodeInTree>> = match ret.entry(nap.node.node_type()) {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => v.insert(vec![])
};
values.push(nap);
}
ret
}