Skip to main content

logic_eval/prove/
prover.rs

1use super::repr::{
2    ApplyResult, ClauseId, ExprId, ExprKind, ExprView, TermDeepView, TermElem, TermId, TermStorage,
3    TermStorageLen, TermView, TermViewMut, UniqueTermArray,
4};
5use crate::{
6    ExprIn, Int2Name, Intern, Map, Name2Int, NameIn, TermIn,
7    parse::{
8        VAR_PREFIX,
9        repr::{Predicate, Term},
10        text::Name,
11    },
12};
13use indexmap::IndexMap;
14use logic_eval_util::reference::Ref;
15use std::{
16    borrow::Borrow,
17    collections::VecDeque,
18    fmt::{self, Debug, Write},
19    hash::Hash,
20    iter,
21    ops::{self, Range},
22};
23
24pub(crate) type ClauseMap = IndexMap<Predicate<Integer>, Vec<ClauseId>>;
25
26#[derive(Debug)]
27pub(crate) struct Prover {
28    uni_op: UnificationOperator,
29
30    /// Nodes created during proof search.
31    nodes: Vec<Node>,
32
33    /// Variable assignments.
34    ///
35    /// For example, `assignment[X] = a` means that `X(term id)` is assigned to
36    /// `a(term id)`. If a value is identical to its index, it means the term is
37    /// not assigned to anything.
38    assignments: Vec<usize>,
39
40    /// A given query.
41    query: ExprId,
42
43    /// Variables in the root node(query).
44    ///
45    /// This could be used to find what terms these variables are assigned to.
46    query_vars: Vec<TermId>,
47
48    /// Task queue containing node index.
49    queue: VecDeque<usize>,
50
51    /// A buffer containing mapping between variables and temporary variables.
52    ///
53    /// This buffer is used when we convert variables into temporary variables
54    /// for a clause. After the conversion, this buffer get empty.
55    temp_var_buf: Map<TermId, TermId>,
56
57    /// A monotonically increasing integer that is used for generating
58    /// temporary variables.
59    temp_var_int: u32,
60}
61
62impl Prover {
63    pub(crate) fn new() -> Self {
64        Self {
65            uni_op: UnificationOperator::new(),
66            nodes: Vec::new(),
67            assignments: Vec::new(),
68            query: ExprId(0),
69            query_vars: Vec::new(),
70            queue: VecDeque::new(),
71            temp_var_buf: Map::default(),
72            temp_var_int: 0,
73        }
74    }
75
76    fn clear(&mut self) {
77        self.uni_op.clear();
78        self.nodes.clear();
79        self.assignments.clear();
80        self.query_vars.clear();
81        self.queue.clear();
82    }
83
84    pub(crate) fn prove<'a, 'int, Int: Intern>(
85        &'a mut self,
86        query: ExprIn<'int, Int>,
87        clause_map: &'a ClauseMap,
88        stor: &'a mut TermStorage<Integer>,
89        nimap: &'a mut NameIntMap<'int, Int>,
90    ) -> ProveCx<'a, 'int, Int> {
91        self.clear();
92
93        let old_nimap_state = nimap.state();
94        let query = query.map(&mut |name| nimap.name_to_int(name));
95
96        let old_stor_len = stor.len();
97        self.query = stor.insert_expr(query);
98
99        stor.get_expr(self.query)
100            .with_term(&mut |term: TermView<'_, Integer>| {
101                term.with_variable(&mut |term| self.query_vars.push(term.id));
102            });
103
104        self.nodes.push(Node {
105            kind: NodeKind::Expr(self.query),
106            uni_delta: 0..0,
107            parent: self.nodes.len(),
108        });
109        self.queue.push_back(0);
110
111        ProveCx::new(self, clause_map, stor, nimap, old_stor_len, old_nimap_state)
112    }
113
114    /// Evaluates the given node with all possible clauses in the clause
115    /// dataset, then returns whether a proof search path is complete or not.
116    ///
117    /// If it reached an end of paths, it returns proof search result within
118    /// `Some`. The proof search result is either true or false, which means
119    /// the expression in the given node is true or not.
120    fn evaluate_node(
121        &mut self,
122        node_index: usize,
123        clause_map: &ClauseMap,
124        stor: &mut TermStorage<Integer>,
125    ) -> Option<bool> {
126        let node = self.nodes[node_index].clone();
127        let node_expr = match node.kind {
128            NodeKind::Expr(expr_id) => expr_id,
129            NodeKind::Leaf(eval) => {
130                self.find_assignment(node_index);
131                return Some(eval);
132            }
133        };
134
135        let predicate = stor.get_expr(node_expr).leftmost_term().predicate();
136        let similar_clauses = if let Some(v) = clause_map.get(&predicate) {
137            v.as_slice()
138        } else {
139            &[]
140        };
141
142        let old_len = self.nodes.len();
143        for clause in similar_clauses {
144            let head = stor.get_term(clause.head);
145
146            if !stor.get_expr(node_expr).is_unifiable(head) {
147                continue;
148            }
149
150            let clause = Self::convert_var_into_temp(
151                *clause,
152                stor,
153                &mut self.temp_var_buf,
154                &mut self.temp_var_int,
155            );
156            if let Some(new_node) = self.unify_node_with_clause(node_index, clause, stor) {
157                self.nodes.push(new_node);
158                self.queue.push_back(self.nodes.len() - 1);
159            }
160        }
161
162        // We may need to apply true or false to the leftmost term of the node
163        // expression due to unification failure or exhaustive search.
164        // - Unification failure means the leftmost term should be false.
165        // - But we need to consider exhaustive search possibility at the same
166        //   time.
167
168        let expr = stor.get_expr(node_expr);
169        let eval = self.nodes.len() > old_len;
170        let mut need_apply = None;
171
172        let lost_possibility = match assume_leftmost_term(expr, eval) {
173            AssumeResult::Incomplete { lost } => lost,
174            AssumeResult::Complete { lost, .. } => lost,
175        };
176        if lost_possibility {
177            need_apply = Some(!eval);
178        } else if !eval {
179            need_apply = Some(false);
180        }
181
182        if let Some(to) = need_apply {
183            let mut expr = stor.get_expr_mut(node_expr);
184            let kind = match expr.apply_to_leftmost_term(to) {
185                ApplyResult::Expr => NodeKind::Expr(expr.id()),
186                ApplyResult::Complete(eval) => NodeKind::Leaf(eval),
187            };
188            self.nodes.push(Node {
189                kind,
190                uni_delta: 0..0,
191                parent: node_index,
192            });
193            self.queue.push_back(self.nodes.len() - 1);
194        }
195
196        return None;
197
198        // === Internal helper functions ===
199
200        enum AssumeResult {
201            /// The whole expression could not completely evaluated even though
202            /// the assumption is realized.
203            Incomplete {
204                /// Whether or not the assumption will make us lose some search
205                /// possibilities.
206                lost: bool,
207            },
208
209            /// The whole expression will be completely evaluated if the
210            /// assumption is realized.
211            Complete {
212                /// Evalauted as true or false.
213                eval: bool,
214                lost: bool,
215            },
216        }
217
218        fn assume_leftmost_term(expr: ExprView<'_, Integer>, to: bool) -> AssumeResult {
219            match expr.as_kind() {
220                ExprKind::Term(_) => AssumeResult::Complete {
221                    eval: to,
222                    lost: false,
223                },
224                ExprKind::Not(inner) => match assume_leftmost_term(inner, to) {
225                    res @ AssumeResult::Incomplete { .. } => res,
226                    AssumeResult::Complete { eval, lost } => {
227                        AssumeResult::Complete { eval: !eval, lost }
228                    }
229                },
230                ExprKind::And(mut args) => {
231                    // Unlike 'Or', even if 'And' contains variables and the
232                    // whole expression will be evaluated false, those variables
233                    // must be ignored. They don't belong to 'lost'.
234                    match assume_leftmost_term(args.next().unwrap(), to) {
235                        res @ AssumeResult::Incomplete { .. } => res,
236                        AssumeResult::Complete { eval, lost } => {
237                            if !eval {
238                                AssumeResult::Complete { eval: false, lost }
239                            } else {
240                                AssumeResult::Incomplete { lost }
241                            }
242                        }
243                    }
244                }
245                ExprKind::Or(mut args) => {
246                    // The whole 'Or' is true if any argument is true. But we
247                    // will lose possible search paths if we ignore right
248                    // variables.
249                    match assume_leftmost_term(args.next().unwrap(), to) {
250                        res @ AssumeResult::Incomplete { .. } => res,
251                        AssumeResult::Complete { eval, lost } => {
252                            if eval {
253                                let right_var = args.any(|arg| arg.contains_variable());
254                                AssumeResult::Complete {
255                                    eval: true,
256                                    lost: lost | right_var,
257                                }
258                            } else {
259                                AssumeResult::Incomplete { lost }
260                            }
261                        }
262                    }
263                }
264            }
265        }
266    }
267
268    /// Replaces variables in a clause with other temporary variables.
269    ///
270    // Why we replace variables with temporary variables in clauses before
271    // unifying?
272    // 1. That's because variables in different clauses are actually different
273    // from each other even they have the same identity. Variable's identity
274    // is valid only in the one clause where they belong.
275    // 2. Also, we apply this method whenever unification happens because one
276    // clause can be used mupltiple times in a single proof search path. Then
277    // it is considered as a different clause.
278    fn convert_var_into_temp(
279        mut clause_id: ClauseId,
280        stor: &mut TermStorage<Integer>,
281        temp_var_buf: &mut Map<TermId, TermId>,
282        temp_var_int: &mut u32,
283    ) -> ClauseId {
284        debug_assert!(temp_var_buf.is_empty());
285
286        let mut f = |terms: &mut UniqueTermArray<Integer>, term_id: TermId| {
287            let term = terms.get_mut(term_id);
288            if term.is_variable() {
289                let src = term.id();
290
291                temp_var_buf.entry(src).or_insert_with(|| {
292                    let temp_term = Term {
293                        functor: Integer::temporary(*temp_var_int),
294                        args: [].into(),
295                    };
296                    *temp_var_int += 1;
297                    terms.insert(temp_term)
298                });
299            }
300        };
301
302        stor.get_term_mut(clause_id.head).with_terminal(&mut f);
303
304        if let Some(body) = clause_id.body {
305            stor.get_expr_mut(body).with_terminal(&mut f);
306        }
307
308        for (src, dst) in temp_var_buf.drain() {
309            let mut head = stor.get_term_mut(clause_id.head);
310            head.replace(src, dst);
311            clause_id.head = head.id();
312
313            if let Some(body) = clause_id.body {
314                let mut body = stor.get_expr_mut(body);
315                body.replace_term(src, dst);
316                clause_id.body = Some(body.id());
317            }
318        }
319
320        clause_id
321    }
322
323    fn unify_node_with_clause(
324        &mut self,
325        node_index: usize,
326        clause: ClauseId,
327        stor: &mut TermStorage<Integer>,
328    ) -> Option<Node> {
329        debug_assert!(self.uni_op.ops.is_empty());
330
331        let NodeKind::Expr(node_expr) = self.nodes[node_index].kind else {
332            unreachable!()
333        };
334
335        if !stor
336            .get_expr(node_expr)
337            .leftmost_term()
338            .unify(stor.get_term(clause.head), &mut |op| {
339                self.uni_op.push_op(op)
340            })
341        {
342            return None;
343        }
344        let (node_expr, clause, uni_delta) = self.uni_op.consume_ops(stor, node_expr, clause);
345
346        if let Some(body) = clause.body {
347            let mut lhs = stor.get_expr_mut(node_expr);
348            lhs.replace_leftmost_term(body);
349            return Some(Node {
350                kind: NodeKind::Expr(lhs.id()),
351                uni_delta,
352                parent: node_index,
353            });
354        }
355
356        let mut lhs = stor.get_expr_mut(node_expr);
357        let kind = match lhs.apply_to_leftmost_term(true) {
358            ApplyResult::Expr => NodeKind::Expr(lhs.id()),
359            ApplyResult::Complete(eval) => NodeKind::Leaf(eval),
360        };
361        Some(Node {
362            kind,
363            uni_delta,
364            parent: node_index,
365        })
366    }
367
368    /// Finds all assignments from the given node to the root node.
369    ///
370    /// Then, the assignment information is stored at [`Self::assignments`].
371    fn find_assignment(&mut self, node_index: usize) {
372        // Collects unification records.
373        self.assignments.clear();
374
375        let mut cur_index = node_index;
376        loop {
377            let node = &self.nodes[cur_index];
378            let range = node.uni_delta.clone();
379
380            for (from, to) in self.uni_op.get_record(range).iter().cloned() {
381                let (from, to) = (from.0, to.0);
382
383                for i in self.assignments.len()..=from.max(to) {
384                    self.assignments.push(i);
385                }
386
387                let root_from = find(&mut self.assignments, from);
388                let root_to = find(&mut self.assignments, to);
389                self.assignments[root_from] = root_to;
390            }
391
392            if node.parent == cur_index {
393                break;
394            }
395            cur_index = node.parent;
396        }
397
398        return;
399
400        // === Internal helper functions ===
401
402        fn find(buf: &mut [usize], i: usize) -> usize {
403            if buf[i] == i {
404                i
405            } else {
406                let root = find(buf, buf[i]);
407                buf[i] = root;
408                root
409            }
410        }
411    }
412}
413
414#[derive(Debug)]
415struct UnificationOperator {
416    ops: Vec<UnifyOp>,
417
418    /// History of unification.
419    ///
420    /// A pair of term ids means that `pair.0` is assiend to `pair.1`. For
421    /// example, `(X, a)` means `X` is assigned to `a`.
422    record: Vec<(TermId, TermId)>,
423}
424
425impl UnificationOperator {
426    const fn new() -> Self {
427        Self {
428            ops: Vec::new(),
429            record: Vec::new(),
430        }
431    }
432
433    fn clear(&mut self) {
434        self.ops.clear();
435        self.record.clear();
436    }
437
438    fn push_op(&mut self, op: UnifyOp) {
439        self.ops.push(op);
440    }
441
442    #[must_use]
443    fn consume_ops(
444        &mut self,
445        stor: &mut TermStorage<Integer>,
446        mut left: ExprId,
447        mut right: ClauseId,
448    ) -> (ExprId, ClauseId, Range<usize>) {
449        let record_start = self.record.len();
450
451        for op in self.ops.drain(..) {
452            match op {
453                UnifyOp::Left { from, to } => {
454                    let mut expr = stor.get_expr_mut(left);
455                    expr.replace_term(from, to);
456                    left = expr.id();
457
458                    self.record.push((from, to));
459                }
460                UnifyOp::Right { from, to } => {
461                    if let Some(right_body) = right.body {
462                        let mut expr = stor.get_expr_mut(right_body);
463                        expr.replace_term(from, to);
464                        right.body = Some(expr.id());
465
466                        self.record.push((from, to));
467                    }
468                }
469            }
470        }
471
472        (left, right, record_start..self.record.len())
473    }
474
475    fn get_record(&self, range: Range<usize>) -> &[(TermId, TermId)] {
476        &self.record[range]
477    }
478}
479
480#[derive(Debug, Clone)]
481struct Node {
482    kind: NodeKind,
483    uni_delta: Range<usize>,
484    parent: usize,
485}
486
487#[derive(Debug, Clone, Copy)]
488enum NodeKind {
489    /// A non-terminal node containig an expression id that needs to be
490    /// evaluated.
491    Expr(ExprId),
492
493    /// A terminal node containing whether a proof path ends with true or false.
494    Leaf(bool),
495}
496
497#[derive(Debug)]
498enum UnifyOp {
499    Left { from: TermId, to: TermId },
500    Right { from: TermId, to: TermId },
501}
502
503pub struct ProveCx<'a, 'int, Int: Intern> {
504    prover: &'a mut Prover,
505    clause_map: &'a ClauseMap,
506    stor: &'a mut TermStorage<Integer>,
507    nimap: &'a mut NameIntMap<'int, Int>,
508    old_stor_len: TermStorageLen,
509    old_nimap_state: NameIntMapState,
510}
511
512impl<'a, 'int, Int: Intern> ProveCx<'a, 'int, Int> {
513    fn new(
514        prover: &'a mut Prover,
515        clause_map: &'a ClauseMap,
516        stor: &'a mut TermStorage<Integer>,
517        nimap: &'a mut NameIntMap<'int, Int>,
518        old_stor_len: TermStorageLen,
519        old_nimap_state: NameIntMapState,
520    ) -> Self {
521        Self {
522            prover,
523            clause_map,
524            stor,
525            nimap,
526            old_stor_len,
527            old_nimap_state,
528        }
529    }
530
531    pub fn prove_next(&mut self) -> Option<EvalView<'_, 'int, Int>> {
532        while let Some(node_index) = self.prover.queue.pop_front() {
533            if let Some(proof_result) =
534                self.prover
535                    .evaluate_node(node_index, self.clause_map, self.stor)
536            {
537                // Returns Some(EvalView) only if the result is TRUE.
538                if proof_result {
539                    return Some(EvalView {
540                        query_vars: &self.prover.query_vars,
541                        terms: &self.stor.terms.buf,
542                        assignments: &self.prover.assignments,
543                        int2name: &self.nimap.int2name,
544                        start: 0,
545                        end: self.prover.query_vars.len(),
546                    });
547                }
548            }
549        }
550        None
551    }
552
553    pub fn is_true(mut self) -> bool {
554        self.prove_next().is_some()
555    }
556}
557
558impl<Int: Intern> Drop for ProveCx<'_, '_, Int> {
559    fn drop(&mut self) {
560        self.stor.truncate(self.old_stor_len.clone());
561        self.nimap.revert(self.old_nimap_state.clone());
562    }
563}
564
565pub struct EvalView<'a, 'int, Int: Intern> {
566    query_vars: &'a [TermId],
567    terms: &'a [TermElem<Integer>],
568    assignments: &'a [usize],
569    int2name: &'a Int2Name<'int, Int>,
570    /// Inclusive
571    start: usize,
572    /// Exclusive
573    end: usize,
574}
575
576impl<Int: Intern> EvalView<'_, '_, Int> {
577    const fn len(&self) -> usize {
578        self.end - self.start
579    }
580}
581
582impl<'a, 'int, Int: Intern> Iterator for EvalView<'a, 'int, Int> {
583    type Item = Assignment<'a, 'int, Int>;
584
585    fn next(&mut self) -> Option<Self::Item> {
586        if self.start < self.end {
587            let from = self.query_vars[self.start];
588            self.start += 1;
589
590            Some(Assignment {
591                buf: self.terms,
592                from,
593                assignments: self.assignments,
594                int2name: self.int2name,
595            })
596        } else {
597            None
598        }
599    }
600
601    fn size_hint(&self) -> (usize, Option<usize>) {
602        let len = <Self>::len(self);
603        (len, Some(len))
604    }
605}
606
607impl<Int: Intern> ExactSizeIterator for EvalView<'_, '_, Int> {
608    fn len(&self) -> usize {
609        <Self>::len(self)
610    }
611}
612
613impl<Int: Intern> iter::FusedIterator for EvalView<'_, '_, Int> {}
614
615pub struct Assignment<'a, 'int, Int: Intern> {
616    buf: &'a [TermElem<Integer>],
617    from: TermId,
618    assignments: &'a [usize],
619    int2name: &'a Int2Name<'int, Int>,
620}
621
622impl<'a, 'int, Int: Intern> Assignment<'a, 'int, Int> {
623    /// Creates left hand side term of the assignment.
624    ///
625    /// To create a term, this method could allocate memory for the term.
626    pub fn lhs(&self) -> TermIn<'int, Int> {
627        Self::term_view_to_term(self.lhs_view(), self.int2name)
628    }
629
630    /// Creates right hand side term of the assignment.
631    ///
632    /// To create a term, this method could allocate memory for the term.
633    pub fn rhs(&self) -> TermIn<'int, Int> {
634        Self::term_deep_view_to_term(self.rhs_view(), self.int2name)
635    }
636
637    /// Returns left hand side variable name of the assignment.
638    ///
639    /// Note that assignment's left hand side is always variable.
640    pub fn get_lhs_variable(&self) -> &NameIn<'int, Int> {
641        let int = self.lhs_view().get_contained_variable().unwrap();
642        self.int2name.get(&int).unwrap()
643    }
644
645    fn term_view_to_term(
646        view: TermView<'_, Integer>,
647        int2name: &Int2Name<'int, Int>,
648    ) -> TermIn<'int, Int> {
649        let functor = view.functor();
650        let args = view.args();
651
652        let functor = if let Some(name) = int2name.get(functor) {
653            name.clone()
654        } else {
655            let mut debug_string = String::new();
656            write!(&mut debug_string, "{:?}", functor).unwrap();
657            Name::with_intern(&debug_string, int2name.interner())
658        };
659
660        let args = args
661            .into_iter()
662            .map(|arg| Self::term_view_to_term(arg, int2name))
663            .collect();
664
665        Term { functor, args }
666    }
667
668    fn term_deep_view_to_term(
669        view: TermDeepView<'_, Integer>,
670        int2name: &Int2Name<'int, Int>,
671    ) -> TermIn<'int, Int> {
672        let functor = view.functor();
673        let args = view.args();
674
675        let functor = if let Some(name) = int2name.get(functor) {
676            name.clone()
677        } else {
678            let mut debug_string = String::new();
679            write!(&mut debug_string, "{:?}", functor).unwrap();
680            Name::with_intern(&debug_string, int2name.interner())
681        };
682
683        let args = args
684            .into_iter()
685            .map(|arg| Self::term_deep_view_to_term(arg, int2name))
686            .collect();
687
688        Term { functor, args }
689    }
690
691    const fn lhs_view(&self) -> TermView<'_, Integer> {
692        TermView {
693            buf: self.buf,
694            id: self.from,
695        }
696    }
697
698    const fn rhs_view(&self) -> TermDeepView<'_, Integer> {
699        TermDeepView {
700            buf: self.buf,
701            links: self.assignments,
702            id: self.from,
703        }
704    }
705}
706
707impl<Int: Intern> fmt::Display for Assignment<'_, '_, Int> {
708    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
709        let view = format::NamedTermView::new(self.lhs_view(), self.int2name);
710        fmt::Display::fmt(&view, f)?;
711
712        f.write_str(" = ")?;
713
714        let view = format::NamedTermDeepView::new(self.rhs_view(), self.int2name);
715        fmt::Display::fmt(&view, f)
716    }
717}
718
719impl<Int: Intern> fmt::Debug for Assignment<'_, '_, Int> {
720    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
721        let lhs = format::NamedTermView::new(self.lhs_view(), self.int2name);
722        let rhs = format::NamedTermDeepView::new(self.rhs_view(), self.int2name);
723
724        f.debug_struct("Assignment")
725            .field("lhs", &lhs)
726            .field("rhs", &rhs)
727            .finish()
728    }
729}
730
731impl ExprView<'_, Integer> {
732    fn is_unifiable(&self, other: TermView<'_, Integer>) -> bool {
733        match self.as_kind() {
734            ExprKind::Term(term) => term.is_unifiable(other),
735            ExprKind::Not(inner) => inner.is_unifiable(other),
736            ExprKind::And(mut args) | ExprKind::Or(mut args) => {
737                args.next().unwrap().is_unifiable(other)
738            }
739        }
740    }
741
742    fn contains_variable(&self) -> bool {
743        match self.as_kind() {
744            ExprKind::Term(term) => term.contains_variable(),
745            ExprKind::Not(inner) => inner.contains_variable(),
746            ExprKind::And(mut args) | ExprKind::Or(mut args) => {
747                args.any(|arg| arg.contains_variable())
748            }
749        }
750    }
751}
752
753impl TermView<'_, Integer> {
754    fn unify<F: FnMut(UnifyOp)>(self, other: Self, f: &mut F) -> bool {
755        if self.is_variable() {
756            f(UnifyOp::Left {
757                from: self.id,
758                to: other.id,
759            });
760            true
761        } else if other.is_variable() {
762            f(UnifyOp::Right {
763                from: other.id,
764                to: self.id,
765            });
766            true
767        } else if self.functor() == other.functor() {
768            let zip = self.args().zip(other.args());
769            // Unifies only if all arguments are unifiable.
770            if self.arity() == other.arity() && zip.clone().all(|(l, r)| l.is_unifiable(r)) {
771                for (l, r) in zip {
772                    l.unify(r, f);
773                }
774                true
775            } else {
776                false
777            }
778        } else {
779            false
780        }
781    }
782
783    fn is_unifiable(&self, other: Self) -> bool {
784        if self.is_variable() || other.is_variable() {
785            true
786        } else if self.functor() == other.functor() {
787            if self.arity() == other.arity() {
788                self.args()
789                    .zip(other.args())
790                    .all(|(l, r)| l.is_unifiable(r))
791            } else {
792                false
793            }
794        } else {
795            false
796        }
797    }
798
799    /// Returns true if this term is a variable.
800    ///
801    /// e.g. Terms like `X`, `Y` will return true.
802    fn is_variable(&self) -> bool {
803        self.arity() == 0 && self.functor().is_variable()
804    }
805
806    /// Returns true if this term is a variable or contains variable in it.
807    ///
808    /// e.g. Terms like `X` of `f(X)` will return true.
809    fn contains_variable(&self) -> bool {
810        self.is_variable() || self.args().any(|arg| arg.contains_variable())
811    }
812
813    fn get_contained_variable(&self) -> Option<Integer> {
814        if self.is_variable() {
815            Some(*self.functor())
816        } else {
817            self.args().find_map(|arg| arg.get_contained_variable())
818        }
819    }
820
821    fn with_variable<F: FnMut(&Self)>(&self, f: &mut F) {
822        if self.is_variable() {
823            f(self);
824        } else {
825            for arg in self.args() {
826                arg.with_variable(f);
827            }
828        }
829    }
830}
831
832impl TermViewMut<'_, Integer> {
833    fn is_variable(&self) -> bool {
834        self.arity() == 0 && self.functor().is_variable()
835    }
836}
837
838#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
839pub struct Integer(u32);
840
841impl Integer {
842    const VAR_FLAG: u32 = 0x1 << 31;
843    const TEMPORARY_FLAG: u32 = 0x1 << 30;
844
845    pub(crate) fn from_text<T: AsRef<str>>(s: &Name<T>, mut index: u32) -> Self {
846        if s.is_variable() {
847            index |= Self::VAR_FLAG;
848        }
849        Self(index)
850    }
851
852    pub(crate) const fn temporary(int: u32) -> Self {
853        Self(int | Self::VAR_FLAG | Self::TEMPORARY_FLAG)
854    }
855
856    pub(crate) const fn is_variable(self) -> bool {
857        (Self::VAR_FLAG & self.0) == Self::VAR_FLAG
858    }
859
860    pub(crate) const fn is_temporary_variable(self) -> bool {
861        let mask: u32 = Self::VAR_FLAG | Self::TEMPORARY_FLAG;
862        (mask & self.0) == mask
863    }
864}
865
866impl Debug for Integer {
867    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
868        let mask: u32 = Self::VAR_FLAG | Self::TEMPORARY_FLAG;
869        let index = !mask & self.0;
870
871        if self.is_variable() {
872            f.write_char(VAR_PREFIX)?;
873        }
874        if self.is_temporary_variable() {
875            f.write_char('#')?;
876        }
877        index.fmt(f)
878    }
879}
880
881impl ops::AddAssign<u32> for Integer {
882    fn add_assign(&mut self, rhs: u32) {
883        self.0 += rhs;
884    }
885}
886
887/// Only mapping of user-input clauses and queries are stored in this map.
888/// Auto-generated variables or something like that are not stored here.
889#[derive(Debug)]
890pub(crate) struct NameIntMap<'int, Int: Intern> {
891    pub(crate) name2int: Name2Int<'int, Int>,
892    pub(crate) int2name: Int2Name<'int, Int>,
893    next_int: u32,
894}
895
896impl<'int, Int: Intern> NameIntMap<'int, Int> {
897    pub(crate) fn new(interner: Ref<'int, Int>) -> Self {
898        Self {
899            name2int: IdxMap::new(interner),
900            int2name: IdxMap::new(interner),
901            next_int: 0,
902        }
903    }
904
905    pub(crate) fn name_to_int(&mut self, name: NameIn<'int, Int>) -> Integer {
906        if let Some(int) = self.name2int.get(&name) {
907            *int
908        } else {
909            let int = Integer::from_text(&name, self.next_int);
910
911            self.name2int.insert(name.clone(), int);
912            self.int2name.insert(int, name);
913
914            self.next_int += 1;
915            int
916        }
917    }
918
919    pub(crate) fn state(&self) -> NameIntMapState {
920        NameIntMapState {
921            name2int_len: self.name2int.len(),
922            int2name_len: self.int2name.len(),
923            next_int: self.next_int,
924        }
925    }
926
927    pub(crate) fn revert(
928        &mut self,
929        NameIntMapState {
930            name2int_len,
931            int2name_len,
932            next_int,
933        }: NameIntMapState,
934    ) {
935        self.name2int.truncate(name2int_len);
936        self.int2name.truncate(int2name_len);
937        self.next_int = next_int;
938    }
939}
940
941#[derive(Debug)]
942pub(crate) struct IdxMap<'int, K, V, Int> {
943    map: IndexMap<K, V>,
944    pub(crate) interner: Ref<'int, Int>,
945}
946
947impl<'int, K, V, Int> IdxMap<'int, K, V, Int> {
948    pub(crate) fn new(interner: Ref<'int, Int>) -> Self {
949        Self {
950            map: IndexMap::default(),
951            interner,
952        }
953    }
954
955    pub(crate) fn interner(&self) -> &'int Int {
956        self.interner.as_ref()
957    }
958
959    pub(crate) fn len(&self) -> usize {
960        self.map.len()
961    }
962
963    pub(crate) fn truncate(&mut self, len: usize) {
964        self.map.truncate(len);
965    }
966
967    pub(crate) fn get<Q>(&self, key: &Q) -> Option<&V>
968    where
969        K: Borrow<Q>,
970        Q: Hash + Eq + ?Sized,
971    {
972        self.map.get(key)
973    }
974
975    pub(crate) fn insert(&mut self, key: K, value: V) -> Option<V>
976    where
977        K: Hash + Eq,
978    {
979        self.map.insert(key, value)
980    }
981}
982
983#[derive(Debug, Clone, PartialEq, Eq)]
984pub(crate) struct NameIntMapState {
985    name2int_len: usize,
986    int2name_len: usize,
987    next_int: u32,
988}
989
990pub(crate) mod format {
991    use super::*;
992
993    pub struct NamedTermView<'a, 'int, Int: Intern> {
994        view: TermView<'a, Integer>,
995        int2name: &'a Int2Name<'int, Int>,
996    }
997
998    impl<'a, 'int, Int: Intern> NamedTermView<'a, 'int, Int> {
999        pub(crate) const fn new(
1000            view: TermView<'a, Integer>,
1001            int2name: &'a Int2Name<'int, Int>,
1002        ) -> Self {
1003            Self { view, int2name }
1004        }
1005
1006        pub fn is(&self, term: &TermIn<'int, Int>) -> bool {
1007            let functor = self.view.functor();
1008            let Some(functor) = self.int2name.get(functor) else {
1009                return false;
1010            };
1011
1012            if functor != &term.functor {
1013                return false;
1014            }
1015
1016            self.args().zip(&term.args).all(|(l, r)| l.is(r))
1017        }
1018
1019        pub fn contains(&self, term: &TermIn<'int, Int>) -> bool {
1020            if self.is(term) {
1021                return true;
1022            }
1023
1024            self.args().any(|arg| arg.contains(term))
1025        }
1026
1027        fn args(&self) -> impl Iterator<Item = Self> {
1028            self.view.args().map(|arg| Self {
1029                view: arg,
1030                int2name: self.int2name,
1031            })
1032        }
1033    }
1034
1035    impl<'a, 'int, Int: Intern> fmt::Display for NamedTermView<'a, 'int, Int> {
1036        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1037            let Self { view, int2name } = self;
1038
1039            let functor = view.functor();
1040            let args = view.args();
1041            let num_args = args.len();
1042
1043            write_int(functor, int2name, f)?;
1044
1045            if num_args > 0 {
1046                f.write_char('(')?;
1047                for (i, arg) in args.enumerate() {
1048                    fmt::Display::fmt(&Self::new(arg, int2name), f)?;
1049                    if i + 1 < num_args {
1050                        f.write_str(", ")?;
1051                    }
1052                }
1053                f.write_char(')')?;
1054            }
1055            Ok(())
1056        }
1057    }
1058
1059    impl<'a, 'int, Int: Intern> fmt::Debug for NamedTermView<'a, 'int, Int> {
1060        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1061            let Self { view, int2name } = self;
1062
1063            let functor = view.functor();
1064            let args = view.args();
1065            let num_args = args.len();
1066
1067            if num_args == 0 {
1068                write_int(functor, int2name, f)
1069            } else {
1070                let mut d = if let Some(name) = int2name.get(functor) {
1071                    f.debug_tuple(name.as_ref())
1072                } else {
1073                    let mut debug_string = String::new();
1074                    write!(&mut debug_string, "{:?}", functor)?;
1075                    f.debug_tuple(&debug_string)
1076                };
1077
1078                for arg in args {
1079                    d.field(&Self::new(arg, int2name));
1080                }
1081                d.finish()
1082            }
1083        }
1084    }
1085
1086    pub(crate) struct NamedTermDeepView<'a, 'int, Int: Intern> {
1087        view: TermDeepView<'a, Integer>,
1088        int2name: &'a Int2Name<'int, Int>,
1089    }
1090
1091    impl<'a, 'int, Int: Intern> NamedTermDeepView<'a, 'int, Int> {
1092        pub(crate) const fn new(
1093            view: TermDeepView<'a, Integer>,
1094            int2name: &'a Int2Name<'int, Int>,
1095        ) -> Self {
1096            Self { view, int2name }
1097        }
1098    }
1099
1100    impl<'a, 'int, Int: Intern> fmt::Display for NamedTermDeepView<'a, 'int, Int> {
1101        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1102            let Self { view, int2name } = self;
1103
1104            let functor = view.functor();
1105            let args = view.args();
1106            let num_args = args.len();
1107
1108            write_int(functor, int2name, f)?;
1109
1110            if num_args > 0 {
1111                f.write_char('(')?;
1112                for (i, arg) in args.enumerate() {
1113                    fmt::Display::fmt(&Self::new(arg, int2name), f)?;
1114                    if i + 1 < num_args {
1115                        f.write_str(", ")?;
1116                    }
1117                }
1118                f.write_char(')')?;
1119            }
1120            Ok(())
1121        }
1122    }
1123
1124    impl<'a, 'int, Int: Intern> fmt::Debug for NamedTermDeepView<'a, 'int, Int> {
1125        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1126            let Self { view, int2name } = self;
1127
1128            let functor = view.functor();
1129            let args = view.args();
1130            let num_args = args.len();
1131
1132            if num_args == 0 {
1133                write_int(functor, int2name, f)
1134            } else {
1135                let mut d = if let Some(name) = int2name.get(functor) {
1136                    f.debug_tuple(name.as_ref())
1137                } else {
1138                    let mut debug_string = String::new();
1139                    write!(&mut debug_string, "{:?}", functor)?;
1140                    f.debug_tuple(&debug_string)
1141                };
1142
1143                for arg in args {
1144                    d.field(&Self::new(arg, int2name));
1145                }
1146                d.finish()
1147            }
1148        }
1149    }
1150
1151    pub struct NamedExprView<'a, 'int, Int: Intern> {
1152        view: ExprView<'a, Integer>,
1153        int2name: &'a Int2Name<'int, Int>,
1154    }
1155
1156    impl<'a, 'int, Int: Intern> NamedExprView<'a, 'int, Int> {
1157        pub(crate) const fn new(
1158            view: ExprView<'a, Integer>,
1159            int2name: &'a Int2Name<'int, Int>,
1160        ) -> Self {
1161            Self { view, int2name }
1162        }
1163
1164        pub fn contains_term(&self, term: &TermIn<'int, Int>) -> bool {
1165            match self.view.as_kind() {
1166                ExprKind::Term(view) => NamedTermView {
1167                    view,
1168                    int2name: self.int2name,
1169                }
1170                .contains(term),
1171                ExprKind::Not(view) => NamedExprView {
1172                    view,
1173                    int2name: self.int2name,
1174                }
1175                .contains_term(term),
1176                ExprKind::And(args) | ExprKind::Or(args) => args.into_iter().any(|view| {
1177                    NamedExprView {
1178                        view,
1179                        int2name: self.int2name,
1180                    }
1181                    .contains_term(term)
1182                }),
1183            }
1184        }
1185    }
1186
1187    impl<'a, 'int, Int: Intern> fmt::Display for NamedExprView<'a, 'int, Int> {
1188        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1189            let Self { view, int2name } = self;
1190
1191            match view.as_kind() {
1192                ExprKind::Term(term) => fmt::Display::fmt(
1193                    &NamedTermView {
1194                        view: term,
1195                        int2name,
1196                    },
1197                    f,
1198                )?,
1199                ExprKind::Not(inner) => {
1200                    f.write_str("\\+ ")?;
1201                    if matches!(inner.as_kind(), ExprKind::And(_) | ExprKind::Or(_)) {
1202                        f.write_char('(')?;
1203                        fmt::Display::fmt(&Self::new(inner, int2name), f)?;
1204                        f.write_char(')')?;
1205                    } else {
1206                        fmt::Display::fmt(&Self::new(inner, int2name), f)?;
1207                    }
1208                }
1209                ExprKind::And(args) => {
1210                    let num_args = args.len();
1211                    for (i, arg) in args.enumerate() {
1212                        if matches!(arg.as_kind(), ExprKind::Or(_)) {
1213                            f.write_char('(')?;
1214                            fmt::Display::fmt(&Self::new(arg, int2name), f)?;
1215                            f.write_char(')')?;
1216                        } else {
1217                            fmt::Display::fmt(&Self::new(arg, int2name), f)?;
1218                        }
1219                        if i + 1 < num_args {
1220                            f.write_str(", ")?;
1221                        }
1222                    }
1223                }
1224                ExprKind::Or(args) => {
1225                    let num_args = args.len();
1226                    for (i, arg) in args.enumerate() {
1227                        fmt::Display::fmt(&Self::new(arg, int2name), f)?;
1228                        if i + 1 < num_args {
1229                            f.write_str("; ")?;
1230                        }
1231                    }
1232                }
1233            }
1234            Ok(())
1235        }
1236    }
1237
1238    impl<'a, 'int, Int: Intern> fmt::Debug for NamedExprView<'a, 'int, Int> {
1239        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1240            let Self { view, int2name } = self;
1241
1242            match view.as_kind() {
1243                ExprKind::Term(term) => fmt::Debug::fmt(&NamedTermView::new(term, int2name), f),
1244                ExprKind::Not(inner) => f
1245                    .debug_tuple("Not")
1246                    .field(&NamedExprView::new(inner, int2name))
1247                    .finish(),
1248                ExprKind::And(args) => {
1249                    let mut d = f.debug_tuple("And");
1250                    for arg in args {
1251                        d.field(&NamedExprView::new(arg, int2name));
1252                    }
1253                    d.finish()
1254                }
1255                ExprKind::Or(args) => {
1256                    let mut d = f.debug_tuple("Or");
1257                    for arg in args {
1258                        d.field(&NamedExprView::new(arg, int2name));
1259                    }
1260                    d.finish()
1261                }
1262            }
1263        }
1264    }
1265
1266    fn write_int<'int, Int: Intern>(
1267        int: &Integer,
1268        map: &Int2Name<'int, Int>,
1269        f: &mut fmt::Formatter<'_>,
1270    ) -> fmt::Result {
1271        if let Some(name) = map.get(int) {
1272            f.write_str(name.as_ref())
1273        } else {
1274            fmt::Debug::fmt(int, f)
1275        }
1276    }
1277}