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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use rand::Rng;
pub trait Tree
where Self: Sized
{
const TERMINAL_PROPORTION: f32;
fn rand_tree<R: Rng>(tg: &mut TreeGen<R>) -> Self {
Self::rand_node(tg, 0)
}
fn rand_node<R: Rng>(tg: &mut TreeGen<R>, current_depth: usize) -> Self {
if tg.condition(current_depth, Self::TERMINAL_PROPORTION) {
Self::rand_terminal(tg, current_depth)
} else {
Self::rand_nonterminal(tg, current_depth)
}
}
fn rand_terminal<R: Rng>(tg: &mut TreeGen<R>, current_depth: usize) -> Self;
fn rand_nonterminal<R: Rng>(tg: &mut TreeGen<R>, current_depth: usize) -> Self;
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum TreeGenMode {
Full,
Grow,
}
#[derive(PartialEq, Eq, Debug)]
pub struct TreeGen<'a, R>
where R: 'a + Rng
{
pub rng: &'a mut R,
pub mode: TreeGenMode,
pub min_depth: usize,
pub max_depth: usize,
pub chosen_depth: usize,
}
impl<'a, R> TreeGen<'a, R>
where R: 'a + Rng
{
pub fn full(rng: &mut R, min_depth: usize, max_depth: usize) -> TreeGen<R> {
let chosen_depth = rng.gen_range(min_depth, max_depth + 1);
TreeGen {
rng: rng,
mode: TreeGenMode::Full,
min_depth: min_depth,
max_depth: max_depth,
chosen_depth: chosen_depth,
}
}
pub fn grow(rng: &mut R, min_depth: usize, max_depth: usize) -> TreeGen<R> {
let chosen_depth = rng.gen_range(min_depth, max_depth + 1);
TreeGen {
rng: rng,
mode: TreeGenMode::Grow,
min_depth: min_depth,
max_depth: max_depth,
chosen_depth: chosen_depth,
}
}
pub fn half_and_half(rng: &mut R, min_depth: usize, max_depth: usize) -> TreeGen<R> {
if rng.gen() {
Self::full(rng, min_depth, max_depth)
} else {
Self::grow(rng, min_depth, max_depth)
}
}
pub fn condition(&mut self, current_depth: usize, term_prob: f32) -> bool {
match self.mode {
TreeGenMode::Full => current_depth == self.chosen_depth,
TreeGenMode::Grow => {
(current_depth == self.chosen_depth) ||
(current_depth >= self.min_depth && self.next_f32() < term_prob)
}
}
}
}
impl<'a, R> Rng for TreeGen<'a, R>
where R: 'a + Rng
{
fn next_u32(&mut self) -> u32 {
self.rng.next_u32()
}
fn next_u64(&mut self) -> u64 {
self.rng.next_u64()
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.rng.fill_bytes(dest)
}
}