1use smallvec::SmallVec;
4
5use crate::{
6 heap::{heap::Heap, query_heap::QueryHeap, symbol_db::SymbolDB},
7 predicate_modules::{PredReturn, PredicateFunction},
8 program::{
9 clause::Clause,
10 hypothesis::Hypothesis,
11 predicate_table::{Predicate, PredicateTable},
12 },
13 resolution::{
14 build::{build, re_build_bound_arg_terms},
15 unification::unify,
16 },
17 Config,
18};
19
20pub type Binding = (usize, usize);
22#[derive(Debug)]
23pub(super) struct Env {
24 pub(super) goal: usize,
25 pub(super) bindings: Box<[Binding]>,
26 pub(super) choices: Vec<Clause>,
27 pred_function: Option<PredicateFunction>,
28 pred_function_tried: bool,
29 pub(crate) got_choices: bool,
30 pub(super) new_clause: bool,
31 pub(super) invent_pred: bool,
32 pub(super) children: usize,
33 pub(super) depth: usize,
34 total_choice_count: usize,
35 heap_point: usize, }
37
38impl Env {
39 pub fn new(goal: usize, depth: usize, heap_point: usize) -> Self {
40 Env {
41 goal,
42 bindings: Box::new([]),
43 choices: Vec::new(),
44 pred_function: None,
45 pred_function_tried: false,
46 got_choices: false,
47 new_clause: false,
48 invent_pred: false,
49 children: 0,
50 depth,
51 total_choice_count: 0,
52 heap_point,
53 }
54 }
55
56 pub fn get_choices(
57 &mut self,
58 heap: &mut QueryHeap,
59 hypothesis: &mut Hypothesis,
60 predicate_table: &PredicateTable,
61 ) {
62 self.got_choices = true;
63 self.heap_point = heap.heap_len();
64 let (symbol, arity) = heap.str_symbol_arity(self.goal);
65
66 self.choices.clear();
67 self.choices.extend_from_slice(hypothesis);
68
69 if symbol == 0 {
70 if let Some(clauses) = predicate_table.get_variable_clauses(arity) {
72 self.choices.extend_from_slice(clauses);
73 }
74 self.choices
77 .extend(predicate_table.get_body_clauses(arity).cloned());
78 self.total_choice_count = self.choices.len();
79 } else {
80 match predicate_table.get_predicate((symbol, arity)) {
81 Some(Predicate::Function(pred_function)) => {
82 self.pred_function = Some(*pred_function)
83 }
84 Some(Predicate::Clauses(clauses)) => {
85 self.choices.extend_from_slice(clauses);
86 self.total_choice_count = self.choices.len();
87 }
88 None => {
89 if let Some(clauses) = predicate_table.get_variable_clauses(arity) {
90 self.choices.extend_from_slice(clauses);
91 self.total_choice_count = self.choices.len();
92 }
93 }
94 }
95 };
96 }
97
98 pub fn undo_try(
99 &mut self,
100 hypothesis: &mut Hypothesis,
101 heap: &mut QueryHeap,
102 h_clauses: &mut usize,
103 invented_preds: &mut usize,
104 debug: bool,
105 ) -> usize {
106 if debug {
107 eprintln!(
108 "[UNDO_TRY] goal={} addr={}",
109 heap.term_string(self.goal),
110 self.goal
111 );
112 }
113 if self.new_clause {
114 let clause = hypothesis.pop_clause();
115 if debug {
116 eprintln!(
117 "[UNDO_CLAUSE] depth={} clause={}",
118 self.depth,
119 clause.to_string(heap)
120 );
121 }
122 *h_clauses -= 1;
123 self.new_clause = false;
124 if self.invent_pred {
125 *invented_preds -= 1;
126 self.invent_pred = false;
127 }
128 }
129 heap.unbind(&self.bindings);
130 heap.truncate(self.heap_point);
131 self.children
132 }
133
134 pub fn try_choices(
135 &mut self,
136 heap: &mut QueryHeap,
137 hypothesis: &mut Hypothesis,
138 allow_new_clause: bool,
139 allow_new_pred: bool,
140 predicate_table: &PredicateTable,
141 config: Config,
142 debug: bool,
143 ) -> Option<Vec<Env>> {
144 if self.depth > config.max_depth {
145 if debug {
146 eprintln!(
147 "[FAIL_ON_DEPTH] depth={} goal={}",
148 self.depth,
149 heap.term_string(self.goal),
150 );
151 }
152 return None;
153 }
154
155 if let Some(pred_function) = self.pred_function {
156 if !self.pred_function_tried {
157 self.pred_function_tried = true;
158 match pred_function(heap, hypothesis, self.goal, predicate_table, config) {
159 PredReturn::True => return Some(Vec::new()),
160 PredReturn::False => {
161 }
163 PredReturn::Binding(bindings) => {
164 self.bindings = bindings.into_boxed_slice();
165 heap.bind(&self.bindings);
166 return Some(Vec::new());
167 }
168 }
169 }
170 }
171
172 let mut choices_tried = 0;
173
174 'choices: while let Some(clause) = self.choices.pop() {
175 if debug {
176 eprintln!("[CALL] {}", clause.to_string(heap));
177 }
178
179 choices_tried += 1;
180 let head = clause.head();
181
182 if clause.meta() {
183 if !allow_new_clause {
184 continue;
185 } else if !allow_new_pred
186 && heap.str_symbol_arity(head).0 == 0
187 && heap.str_symbol_arity(self.goal).0 == 0
188 {
189 continue;
190 }
191 }
192
193 if let Some(mut substitution) = unify(heap, head, self.goal) {
194 for constraints in &hypothesis.constraints {
195 if !substitution.check_constraints(&constraints, heap) {
196 continue 'choices;
197 }
198 }
199
200 if debug {
201 eprintln!(
202 "[MATCH] depth={} goal={} clause={}, choices_remaining={}",
203 self.depth,
204 heap.term_string(self.goal),
205 clause.to_string(heap),
206 self.choices.len()
207 );
208 }
209
210 re_build_bound_arg_terms(heap, &mut substitution);
211
212 let mut invented_pred_addr: Option<usize> = None;
214 if clause.meta() {
215 if heap.str_symbol_arity(head).0 == 0 && heap.str_symbol_arity(self.goal).0 == 0
216 {
217 self.invent_pred = true;
218 let pred_symbol = SymbolDB::set_const(format!("pred_{}", hypothesis.len()));
219 let pred_addr = heap.set_const(pred_symbol);
220 substitution.set_arg(0, pred_addr);
221
222 substitution =
223 substitution.push((heap.deref_addr(self.goal + 1), pred_addr, true));
224 invented_pred_addr = Some(pred_addr);
225 }
226 }
227
228 let new_goals: Vec<usize> = clause
230 .body()
231 .iter()
232 .map(|&body_literal| build(heap, &mut substitution, None, body_literal))
233 .collect();
234
235 if clause.meta() {
237 self.new_clause = true;
238
239 let new_clause_literals: Vec<usize> = clause
240 .iter()
241 .map(|literal| build(heap, &mut substitution, clause.meta_vars, *literal))
242 .collect();
243
244 let mut constraints = Vec::with_capacity(16);
245 for i in 0..32 {
246 if clause.constrained_var(i) {
247 constraints.push(unsafe { substitution.get_arg(i).unwrap_unchecked() });
248 }
249 }
250
251 let new_clause = Clause::new(new_clause_literals, None, None);
252 if debug {
253 eprintln!(
254 "[ADD_CLAUSE] depth={} goal={} clause={}",
255 self.depth,
256 heap.term_string(self.goal),
257 new_clause.to_string(heap)
258 );
259 if invented_pred_addr.is_some() {
260 eprintln!(
261 "[INVENT_PRED] invented predicate for goal={}",
262 heap.term_string(self.goal)
263 );
264 }
265 }
266 hypothesis.push_clause(new_clause, SmallVec::from_vec(constraints));
267 if debug {
268 eprintln!("[HYPOTHESIS]:\n{}", hypothesis.to_string(heap));
269 }
270 }
271
272 self.bindings = substitution.get_bindings();
273 self.children = new_goals.len();
274 if debug {
275 eprintln!("Bindings: {:?}", self.bindings);
276 }
277 heap.bind(&self.bindings);
278
279 return Some(
280 new_goals
281 .into_iter()
282 .map(|goal| Env::new(goal, self.depth + 1, heap.heap_len()))
283 .collect(),
284 );
285 }
286 }
287 if debug {
288 eprintln!(
289 "[NO_MATCH] depth={} goal={} tried {} choices, Originally had {} choices",
290 self.depth,
291 heap.term_string(self.goal),
292 choices_tried,
293 self.total_choice_count
294 );
295 }
296 None
297 }
298}
299
300pub struct Proof<'a> {
306 stack: Vec<Env>,
307 pointer: usize,
308 pub hypothesis: Hypothesis,
309 pub heap: QueryHeap<'a>,
310 h_clauses: usize,
311 invented_preds: usize,
312}
313
314impl<'a> Proof<'a> {
315 pub fn new(heap: QueryHeap<'a>, goals: &[usize]) -> Self {
316 let hypothesis = Hypothesis::new();
317 let stack = goals
318 .iter()
319 .map(|goal| Env::new(*goal, 0, heap.heap_len()))
320 .collect();
321 Proof {
322 stack,
323 pointer: 0,
324 hypothesis,
325 heap,
326 h_clauses: 0,
327 invented_preds: 0,
328 }
329 }
330
331 pub fn with_hypothesis(heap: QueryHeap<'a>, goals: &[usize], hypothesis: Hypothesis) -> Self {
333 let h_clauses = hypothesis.len();
334 let stack = goals
335 .iter()
336 .map(|goal| Env::new(*goal, 0, heap.heap_len()))
337 .collect();
338 Proof {
339 stack,
340 pointer: 0,
341 hypothesis,
342 heap,
343 h_clauses,
344 invented_preds: 0,
345 }
346 }
347
348 pub fn prove(&mut self, predicate_table: &PredicateTable, config: Config) -> bool {
349 if self.pointer == self.stack.len() {
351 if config.debug {
352 eprintln!(
353 "[RESTART] pointer={} stack_len={} h_clauses={}",
354 self.pointer,
355 self.stack.len(),
356 self.h_clauses
357 );
358 eprintln!("[RESTART_HYPOTHESIS]");
359 for (i, c) in self.hypothesis.iter().enumerate() {
360 eprintln!(" [{}]: {}", i, c.to_string(&self.heap));
361 }
362 }
363
364 self.pointer -= 1;
365 self.stack[self.pointer].undo_try(
366 &mut self.hypothesis,
367 &mut self.heap,
368 &mut self.h_clauses,
369 &mut self.invented_preds,
370 config.debug,
371 );
372 }
373
374 while self.pointer < self.stack.len() {
375 if self.stack[self.pointer].got_choices {
376 if config.debug {
377 eprintln!(
378 "[RETRY] goal={} addr={}",
379 self.heap.term_string(self.stack[self.pointer].goal),
380 self.stack[self.pointer].goal
381 );
382 }
383 } else {
384 self.stack[self.pointer].get_choices(
385 &mut self.heap,
386 &mut self.hypothesis,
387 &predicate_table,
388 );
389 if config.debug {
390 eprintln!(
391 "[TRY] goal={} addr={}",
392 self.heap.term_string(self.stack[self.pointer].goal),
393 self.stack[self.pointer].goal
394 );
395 }
396 }
397 match self.stack[self.pointer].try_choices(
398 &mut self.heap,
399 &mut self.hypothesis,
400 self.h_clauses < config.max_clause,
401 self.invented_preds < config.max_pred,
402 predicate_table,
403 config,
404 config.debug,
405 ) {
406 Some(new_goals) => {
407 if self.stack[self.pointer].new_clause {
408 self.h_clauses += 1;
409 }
410 if self.stack[self.pointer].invent_pred {
411 self.invented_preds += 1;
412 }
413 self.pointer += 1;
414 self.stack.splice(self.pointer..self.pointer, new_goals);
415 }
416 None => {
417 if self.pointer == 0 {
418 if config.debug {
419 eprintln!("[FAILED] First goal exhausted");
420 }
421 return false;
422 }
423 self.stack[self.pointer].got_choices = false;
427 self.stack[self.pointer].choices.clear();
428 self.stack[self.pointer].pred_function_tried = false;
429
430 self.pointer -= 1;
431 let children = self.stack[self.pointer].undo_try(
432 &mut self.hypothesis,
433 &mut self.heap,
434 &mut self.h_clauses,
435 &mut self.invented_preds,
436 config.debug,
437 );
438 self.stack
439 .drain((self.pointer + 1)..(self.pointer + 1 + children));
440 }
441 }
442 }
443 true
444 }
445}
446
447#[cfg(test)]
448mod tests {}