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