1use std::sync::Arc;
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 = hypothesis.iter().map(|clause| clause.clone()).collect();
67
68 if symbol == 0 {
69 if let Some(clauses) = predicate_table.get_variable_clauses(arity) {
71 self.choices.extend(clauses.iter().map(|c| c.clone()));
72 }
73 self.choices.extend(
76 predicate_table
77 .get_body_clauses(arity)
78 .into_iter()
79 .map(|c| c),
80 );
81 self.total_choice_count = self.choices.len();
82 } else {
83 match predicate_table.get_predicate((symbol, arity)) {
84 Some(Predicate::Function(pred_function)) => {
85 self.pred_function = Some(pred_function)
86 }
87 Some(Predicate::Clauses(clauses)) => {
88 self.choices.extend(clauses.iter().map(|c| c.clone()));
89 self.total_choice_count = self.choices.len();
90 }
91 None => {
92 if let Some(clauses) = predicate_table.get_variable_clauses(arity) {
93 self.choices.extend(clauses.iter().map(|c| c.clone()));
94 self.total_choice_count = self.choices.len();
95 }
96 }
97 }
98 };
99 }
100
101 pub fn undo_try(
102 &mut self,
103 hypothesis: &mut Hypothesis,
104 heap: &mut QueryHeap,
105 h_clauses: &mut usize,
106 invented_preds: &mut usize,
107 debug: bool,
108 ) -> usize {
109 if debug {
110 eprintln!(
111 "[UNDO_TRY] goal={} addr={}",
112 heap.term_string(self.goal),
113 self.goal
114 );
115 }
116 if self.new_clause {
117 let clause = hypothesis.pop_clause();
118 if debug {
119 eprintln!(
120 "[UNDO_CLAUSE] depth={} clause={}",
121 self.depth,
122 clause.to_string(heap)
123 );
124 }
125 *h_clauses -= 1;
126 self.new_clause = false;
127 if self.invent_pred {
128 *invented_preds -= 1;
129 self.invent_pred = false;
130 }
131 }
132 heap.unbind(&self.bindings);
133 heap.truncate(self.heap_point);
134 self.children
135 }
136
137 pub fn try_choices(
138 &mut self,
139 heap: &mut QueryHeap,
140 hypothesis: &mut Hypothesis,
141 allow_new_clause: bool,
142 allow_new_pred: bool,
143 predicate_table: Arc<PredicateTable>,
144 config: Config,
145 debug: bool,
146 ) -> Option<Vec<Env>> {
147 if self.depth > config.max_depth {
148 if debug {
149 eprintln!(
150 "[FAIL_ON_DEPTH] depth={} goal={}",
151 self.depth,
152 heap.term_string(self.goal),
153 );
154 }
155 return None;
156 }
157
158 if let Some(pred_function) = self.pred_function {
159 if !self.pred_function_tried {
160 self.pred_function_tried = true;
161 match pred_function(heap, hypothesis, self.goal, predicate_table.clone(), config) {
162 PredReturn::True => return Some(Vec::new()),
163 PredReturn::False => {
164 }
166 PredReturn::Binding(bindings) => {
167 self.bindings = bindings.into_boxed_slice();
168 heap.bind(&self.bindings);
169 return Some(Vec::new());
170 }
171 }
172 }
173 }
174
175 let mut choices_tried = 0;
176
177 'choices: while let Some(clause) = self.choices.pop() {
178 if debug{
179 eprintln!(
180 "[CALL] {}",
181 clause.to_string(heap)
182 );
183 }
184
185 choices_tried += 1;
186 let head = clause.head();
187
188 if clause.meta() {
189 if !allow_new_clause {
190 continue;
191 } else if !allow_new_pred
192 && heap.str_symbol_arity(head).0 == 0
193 && heap.str_symbol_arity(self.goal).0 == 0
194 {
195 continue;
196 }
197 }
198
199 if let Some(mut substitution) = unify(heap, head, self.goal) {
200 for constraints in &hypothesis.constraints {
201 if !substitution.check_constraints(&constraints, heap) {
202 continue 'choices;
203 }
204 }
205
206 if debug {
207 eprintln!(
208 "[MATCH] depth={} goal={} clause={}, choices_remaining={}",
209 self.depth,
210 heap.term_string(self.goal),
211 clause.to_string(heap),
212 self.choices.len()
213 );
214 }
215
216 re_build_bound_arg_terms(heap, &mut substitution);
217
218 let mut invented_pred_addr: Option<usize> = None;
220 if clause.meta() {
221 if heap.str_symbol_arity(head).0 == 0 && heap.str_symbol_arity(self.goal).0 == 0
222 {
223 self.invent_pred = true;
224 let pred_symbol = SymbolDB::set_const(format!("pred_{}", hypothesis.len()));
225 let pred_addr = heap.set_const(pred_symbol);
226 substitution.set_arg(0, pred_addr);
227
228 substitution =
229 substitution.push((heap.deref_addr(self.goal + 1), pred_addr, true));
230 invented_pred_addr = Some(pred_addr);
231 }
232 }
233
234 let new_goals: Vec<usize> = clause
236 .body()
237 .iter()
238 .map(|&body_literal| build(heap, &mut substitution, None, body_literal))
239 .collect();
240
241 if clause.meta() {
243 self.new_clause = true;
244
245 let new_clause_literals: Vec<usize> = clause
246 .iter()
247 .map(|literal| build(heap, &mut substitution, clause.meta_vars, *literal))
248 .collect();
249
250 let mut constraints = Vec::with_capacity(16);
251 for i in 0..32 {
252 if clause.constrained_var(i) {
253 constraints.push(unsafe { substitution.get_arg(i).unwrap_unchecked() });
254 }
255 }
256
257 let new_clause = Clause::new(new_clause_literals, None, None);
258 if debug {
259 eprintln!(
260 "[ADD_CLAUSE] depth={} goal={} clause={}",
261 self.depth,
262 heap.term_string(self.goal),
263 new_clause.to_string(heap)
264 );
265 if invented_pred_addr.is_some() {
266 eprintln!(
267 "[INVENT_PRED] invented predicate for goal={}",
268 heap.term_string(self.goal)
269 );
270 }
271 }
272 hypothesis.push_clause(new_clause, constraints.into());
273 if debug {
274 eprintln!("[HYPOTHESIS]:\n{}", hypothesis.to_string(heap));
275 }
276 }
277
278 self.bindings = substitution.get_bindings();
279 self.children = new_goals.len();
280 if debug {
281 eprintln!("Bindings: {:?}", self.bindings);
282 }
283 heap.bind(&self.bindings);
284
285 return Some(
286 new_goals
287 .into_iter()
288 .map(|goal| Env::new(goal, self.depth + 1, heap.heap_len()))
289 .collect(),
290 );
291 }
292 }
293 if debug {
294 eprintln!(
295 "[NO_MATCH] depth={} goal={} tried {} choices, Originally had {} choices",
296 self.depth,
297 heap.term_string(self.goal),
298 choices_tried,
299 self.total_choice_count
300 );
301 }
302 None
303 }
304}
305
306pub struct Proof {
312 stack: Vec<Env>,
313 pointer: usize,
314 pub hypothesis: Hypothesis,
315 pub heap: QueryHeap,
316 h_clauses: usize,
317 invented_preds: usize,
318}
319
320impl Proof {
321 pub fn new(heap: QueryHeap, goals: &[usize]) -> Self {
322 let hypothesis = Hypothesis::new();
323 let stack = goals.iter().map(|goal| Env::new(*goal, 0, heap.heap_len())).collect();
324 Proof {
325 stack,
326 pointer: 0,
327 hypothesis,
328 heap,
329 h_clauses: 0,
330 invented_preds: 0,
331 }
332 }
333
334 pub fn with_hypothesis(heap: QueryHeap, goals: &[usize], hypothesis: Hypothesis) -> Self {
336 let h_clauses = hypothesis.len();
337 let stack = goals.iter().map(|goal| Env::new(*goal, 0, heap.heap_len())).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(
349 &mut self,
350 predicate_table: Arc<PredicateTable>,
351 config: Config,
352 ) -> bool {
353 if self.pointer == self.stack.len() {
355 if config.debug {
356 eprintln!(
357 "[RESTART] pointer={} stack_len={} h_clauses={}",
358 self.pointer,
359 self.stack.len(),
360 self.h_clauses
361 );
362 eprintln!("[RESTART_HYPOTHESIS]");
363 for (i, c) in self.hypothesis.iter().enumerate() {
364 eprintln!(" [{}]: {}", i, c.to_string(&self.heap));
365 }
366 }
367
368 self.pointer -= 1;
369 self.stack[self.pointer].undo_try(
370 &mut self.hypothesis,
371 &mut self.heap,
372 &mut self.h_clauses,
373 &mut self.invented_preds,
374 config.debug,
375 );
376 }
377
378 while self.pointer < self.stack.len() {
379 if self.stack[self.pointer].got_choices {
380 if config.debug {
381 eprintln!(
382 "[RETRY] goal={} addr={}",
383 self.heap.term_string(self.stack[self.pointer].goal),
384 self.stack[self.pointer].goal
385 );
386 }
387 } else {
388 self.stack[self.pointer].get_choices(
389 &mut self.heap,
390 &mut self.hypothesis,
391 &predicate_table,
392 );
393 if config.debug {
394 eprintln!(
395 "[TRY] goal={} addr={}",
396 self.heap.term_string(self.stack[self.pointer].goal),
397 self.stack[self.pointer].goal
398 );
399 }
400 }
401 match self.stack[self.pointer].try_choices(
402 &mut self.heap,
403 &mut self.hypothesis,
404 self.h_clauses < config.max_clause,
405 self.invented_preds < config.max_pred,
406 predicate_table.clone(),
407 config,
408 config.debug,
409 ) {
410 Some(new_goals) => {
411 if self.stack[self.pointer].new_clause {
412 self.h_clauses += 1;
413 }
414 if self.stack[self.pointer].invent_pred {
415 self.invented_preds += 1;
416 }
417 self.pointer += 1;
418 self.stack.splice(self.pointer..self.pointer, new_goals);
419 }
420 None => {
421 if self.pointer == 0 {
422 if config.debug {
423 eprintln!("[FAILED] First goal exhausted");
424 }
425 return false;
426 }
427 self.stack[self.pointer].got_choices = false;
431 self.stack[self.pointer].choices.clear();
432 self.stack[self.pointer].pred_function_tried = false;
433
434 self.pointer -= 1;
435 let children = self.stack[self.pointer].undo_try(
436 &mut self.hypothesis,
437 &mut self.heap,
438 &mut self.h_clauses,
439 &mut self.invented_preds,
440 config.debug,
441 );
442 self.stack
443 .drain((self.pointer + 1)..(self.pointer + 1 + children));
444 }
445 }
446 }
447 true
448 }
449}
450
451#[cfg(test)]
452mod tests {}