1use std::collections::BTreeMap;
27
28use crate::{ProofExpr, ProofTerm};
29
30#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
32enum Key {
33 Sym(String, usize),
37 Star,
39}
40
41struct Node<T> {
42 children: BTreeMap<Key, Node<T>>,
43 values: Vec<T>,
45}
46
47impl<T> Default for Node<T> {
48 fn default() -> Self {
49 Node { children: BTreeMap::new(), values: Vec::new() }
50 }
51}
52
53pub struct DiscTree<T> {
58 root: Node<T>,
59}
60
61impl<T> Default for DiscTree<T> {
62 fn default() -> Self {
63 Self::new()
64 }
65}
66
67impl<T> DiscTree<T> {
68 pub fn new() -> Self {
69 DiscTree { root: Node::default() }
70 }
71
72 pub fn insert_term(&mut self, pattern: &ProofTerm, value: T) {
74 let mut keys = Vec::new();
75 flatten_term(pattern, &mut keys);
76 self.insert_keys(&keys, value);
77 }
78
79 pub fn insert_expr(&mut self, pattern: &ProofExpr, value: T) {
81 let mut keys = Vec::new();
82 flatten_expr(pattern, &mut keys);
83 self.insert_keys(&keys, value);
84 }
85
86 pub fn candidates_term(&self, query: &ProofTerm) -> Vec<&T> {
89 let mut keys = Vec::new();
90 flatten_term(query, &mut keys);
91 self.candidates_keys(&keys)
92 }
93
94 pub fn candidates_expr(&self, query: &ProofExpr) -> Vec<&T> {
97 let mut keys = Vec::new();
98 flatten_expr(query, &mut keys);
99 self.candidates_keys(&keys)
100 }
101
102 fn insert_keys(&mut self, keys: &[Key], value: T) {
103 let mut node = &mut self.root;
104 for key in keys {
105 node = node.children.entry(key.clone()).or_default();
106 }
107 node.values.push(value);
108 }
109
110 fn candidates_keys(&self, keys: &[Key]) -> Vec<&T> {
111 let jump = subterm_jumps(keys);
112 let mut out = Vec::new();
113 retrieve(&self.root, keys, &jump, 0, &mut out);
114 out
115 }
116}
117
118fn subterm_jumps(keys: &[Key]) -> Vec<usize> {
120 let mut jump = vec![0usize; keys.len()];
121 fill_jumps(keys, 0, &mut jump);
122 jump
123}
124
125fn fill_jumps(keys: &[Key], i: usize, jump: &mut [usize]) -> usize {
126 let end = match &keys[i] {
127 Key::Star => i + 1,
128 Key::Sym(_, arity) => {
129 let mut j = i + 1;
130 for _ in 0..*arity {
131 j = fill_jumps(keys, j, jump);
132 }
133 j
134 }
135 };
136 jump[i] = end;
137 end
138}
139
140fn retrieve<'a, T>(
141 node: &'a Node<T>,
142 keys: &[Key],
143 jump: &[usize],
144 i: usize,
145 out: &mut Vec<&'a T>,
146) {
147 if i == keys.len() {
148 out.extend(node.values.iter());
149 return;
150 }
151 match &keys[i] {
152 sym @ Key::Sym(..) => {
153 if let Some(child) = node.children.get(sym) {
155 retrieve(child, keys, jump, i + 1, out);
156 }
157 if let Some(star) = node.children.get(&Key::Star) {
159 retrieve(star, keys, jump, jump[i], out);
160 }
161 }
162 Key::Star => {
163 let mut landings = Vec::new();
166 skip_pattern_subterm(node, 1, &mut landings);
167 for landing in landings {
168 retrieve(landing, keys, jump, i + 1, out);
169 }
170 }
171 }
172}
173
174fn skip_pattern_subterm<'a, T>(node: &'a Node<T>, pending: usize, out: &mut Vec<&'a Node<T>>) {
176 if pending == 0 {
177 out.push(node);
178 return;
179 }
180 for (key, child) in &node.children {
181 let need = pending - 1
182 + match key {
183 Key::Sym(_, arity) => *arity,
184 Key::Star => 0,
185 };
186 skip_pattern_subterm(child, need, out);
187 }
188}
189
190fn flatten_term(t: &ProofTerm, out: &mut Vec<Key>) {
191 match t {
192 ProofTerm::Variable(_) => out.push(Key::Star),
193 ProofTerm::Constant(s) => out.push(Key::Sym(format!("c:{s}"), 0)),
194 ProofTerm::BoundVarRef(s) => out.push(Key::Sym(format!("b:{s}"), 0)),
195 ProofTerm::Function(name, args) => {
196 out.push(Key::Sym(format!("f:{name}"), args.len()));
197 for a in args {
198 flatten_term(a, out);
199 }
200 }
201 ProofTerm::Group(args) => {
202 out.push(Key::Sym("(,)".to_string(), args.len()));
203 for a in args {
204 flatten_term(a, out);
205 }
206 }
207 }
208}
209
210fn flatten_expr(e: &ProofExpr, out: &mut Vec<Key>) {
211 match e {
212 ProofExpr::Predicate { name, args, .. } => {
213 out.push(Key::Sym(format!("p:{name}"), args.len()));
214 for a in args {
215 flatten_term(a, out);
216 }
217 }
218 ProofExpr::Identity(l, r) => {
219 out.push(Key::Sym("=".to_string(), 2));
220 flatten_term(l, out);
221 flatten_term(r, out);
222 }
223 ProofExpr::Atom(s) => out.push(Key::Sym(format!("a:{s}"), 0)),
224 ProofExpr::And(l, r) => {
225 out.push(Key::Sym("∧".to_string(), 2));
226 flatten_expr(l, out);
227 flatten_expr(r, out);
228 }
229 ProofExpr::Or(l, r) => {
230 out.push(Key::Sym("∨".to_string(), 2));
231 flatten_expr(l, out);
232 flatten_expr(r, out);
233 }
234 ProofExpr::Implies(l, r) => {
235 out.push(Key::Sym("→".to_string(), 2));
236 flatten_expr(l, out);
237 flatten_expr(r, out);
238 }
239 ProofExpr::Iff(l, r) => {
240 out.push(Key::Sym("↔".to_string(), 2));
241 flatten_expr(l, out);
242 flatten_expr(r, out);
243 }
244 ProofExpr::Not(p) => {
245 out.push(Key::Sym("¬".to_string(), 1));
246 flatten_expr(p, out);
247 }
248 _ => out.push(Key::Star),
251 }
252}