1use std::ops::Deref;
2use std::rc::Rc;
3
4use radix_trie::Trie;
5
6use super::*;
7
8#[derive(Clone, Debug)]
9pub struct Path {
10 pub pred: Ident,
11 pub idx: usize,
12 pub ctx: usize,
13 link: PathLink,
14}
15
16impl Path {
17 pub fn new(pred: Ident) -> Path {
18 Path {
19 pred,
20 idx: 0,
21 ctx: 0,
22 link: PathLink::new(pred),
23 }
24 }
25
26 pub fn jump(&self, idx: usize) -> Path {
27 let mut res = self.clone();
28 res.idx = idx;
29 res.link = res.link.link(self.pred, idx);
30 res
31 }
32
33 pub fn call(&self, pred: Ident, ctx: usize) -> Path {
34 let mut res = self.clone();
35 res.pred = pred;
36 res.idx = 0;
37 res.ctx = ctx;
38 res.link = res.link.link(pred, 0);
39 res
40 }
41}
42
43#[derive(Clone, Debug)]
44enum PathLinkData {
45 Nil,
46 Cons {
47 link: Rc<PathLinkData>,
48 pred: Ident,
49 idx: usize,
50 },
51}
52
53#[derive(Clone, Debug)]
54struct PathLink(Rc<PathLinkData>);
55
56impl PathLink {
57 fn new(pred: Ident) -> PathLink {
58 PathLink(Rc::new(PathLinkData::Cons {
59 link: Rc::new(PathLinkData::Nil),
60 pred,
61 idx: 0,
62 }))
63 }
64
65 fn link(&self, pred: Ident, idx: usize) -> PathLink {
66 PathLink(Rc::new(PathLinkData::Cons {
67 link: Rc::new(PathLinkData::Nil),
68 pred,
69 idx,
70 }))
71 }
72
73 fn to_usize_vec(&self) -> Vec<usize> {
74 let mut vec: Vec<usize> = Vec::new();
75 let mut path = self.0.clone();
76
77 while let PathLinkData::Cons { link, pred, idx } = path.deref() {
78 vec.push(*idx);
79 vec.push(pred.index);
80 path = link.clone();
81 }
82
83 vec.reverse();
84 vec
85 }
86}
87
88#[derive(Debug, Clone)]
89struct PathInfo {
90 counter: usize,
91 vsids_score: isize,
92 vsids_tmsp: usize,
93}
94
95const ALPHA: f32 = 0.95;
96
97impl PathInfo {
98 fn new(tmsp: usize) -> PathInfo {
99 PathInfo {
100 counter: 0,
101 vsids_score: 0,
102 vsids_tmsp: tmsp,
103 }
104 }
105
106 fn bump_score(&mut self, tmsp: usize, inc: isize) {
107 self.decay_update(tmsp);
108 self.vsids_score += inc;
109 }
110
111 fn decay_update(&mut self, tmsp: usize) {
112 let powered = ALPHA.powi((tmsp - self.vsids_tmsp) as i32);
113 self.vsids_score = ((self.vsids_score as f32) * powered) as isize;
114 self.vsids_tmsp = tmsp;
115 }
116}
117
118#[derive(Debug, Clone)]
119pub struct PathTree {
120 time_stamp: usize,
121 map: Trie<Vec<usize>, PathInfo>,
122}
123
124impl Default for PathTree {
125 fn default() -> Self {
126 Self::new()
127 }
128}
129
130impl PathTree {
131 pub fn new() -> PathTree {
132 PathTree {
133 time_stamp: 0,
134 map: Trie::new(),
135 }
136 }
137
138 pub fn conflict_update(&mut self, path: &Path) {
139 let mut vec = path.link.to_usize_vec();
140 assert_eq!(vec.len() % 2, 0);
141
142 let mut new_counter = 4;
143
144 while !vec.is_empty() {
145 let info = if let Some(info) = self.map.get_mut(&vec) {
146 info
147 } else {
148 let info = PathInfo::new(self.time_stamp);
149 self.map.insert(vec.clone(), info);
150 self.map.get_mut(&vec).unwrap()
151 };
152
153 info.counter = std::cmp::max(info.counter, new_counter);
154 info.bump_score(self.time_stamp, new_counter as isize * 100);
155
156 vec.pop().unwrap();
157 vec.pop().unwrap();
158
159 if new_counter == 1 {
160 break;
161 } else {
162 new_counter /= 2;
163 }
164 }
165 }
166
167 pub fn branch_update(&mut self, path: &Path) {
168 let vec = path.link.to_usize_vec();
169 assert_eq!(vec.len() % 2, 0);
170
171 let info = if let Some(info) = self.map.get_mut(&vec) {
172 info
173 } else {
174 let info = PathInfo::new(self.time_stamp);
175 self.map.insert(vec.clone(), info);
176 self.map.get_mut(&vec).unwrap()
177 };
178
179 info.counter = info.counter.saturating_sub(1);
180 info.bump_score(self.time_stamp, -200);
181
182 self.time_stamp += 1;
183 }
184
185 pub fn get_counter(&self, path: &Path) -> isize {
186 self.map
187 .get(&path.link.to_usize_vec())
188 .map(|info| info.counter)
189 .unwrap_or(0) as isize
190 }
191
192 pub fn get_mixed_vsids_score(&mut self, path: &Path) -> isize {
193 self.map
194 .get_mut(&path.link.to_usize_vec())
195 .map(|info| {
196 info.decay_update(self.time_stamp);
197 info.vsids_score
198 })
199 .unwrap_or(0)
200 }
201}