Skip to main content

razor_chase/chase/impl/
basic.rs

1//! Provides a "basic" implementation of the Chase.
2//!
3//! This implementation is used as a reference for the correctness of other implementations of the
4//! [Chase].
5//!
6//! **Note**: The performance of `chase::impl::basic` is not a concern.
7//!
8//! [Chase]: ../../index.html#the-chase
9//!
10use crate::chase::*;
11use razor_fol::syntax::*;
12use std::{collections::{HashMap, HashSet}, fmt, iter};
13use itertools::{Either, Itertools};
14
15/// Is a straight forward implementation for [`WitnessTermTrait`], where elements are of type
16/// [`E`].
17///
18/// [`WitnessTermTrait`]: ../../trait.WitnessTermTrait.html
19/// [`E`]: ../../struct.E.html
20#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
21pub enum WitnessTerm {
22    /// Wraps an instance of [`E`], witnessing itself.
23    ///
24    /// [`E`]: ../../struct.E.html
25    Elem { element: E },
26
27    /// Wraps an instance of [`C`] as a witness term.
28    ///
29    /// [`C`]: ../../../formula/syntax/struct.C.html
30    Const { constant: C },
31
32    /// Corresponds to a composite witness term, made by applying an instance of [`F`] to a list of
33    /// witness terms.
34    ///
35    /// [`F`]: ../../../formula/syntax/struct.F.html
36    App { function: F, terms: Vec<Self> },
37}
38
39impl WitnessTerm {
40    /// Given a `term` and an assignment function `assign` from variables of the term to elements
41    /// of a [`Model`], constructs a [`WitnessTerm`].
42    ///
43    /// [`WitnessTerm`]: ./enum.WitnessTerm.html
44    /// [`Model`]: ./struct.Model.html
45    fn witness(term: &Term, assign: &impl Fn(&V) -> E) -> Self {
46        match term {
47            Term::Const { constant } => Self::Const { constant: constant.clone() },
48            Term::Var { variable } => Self::Elem { element: assign(&variable) },
49            Term::App { function, terms } => {
50                let terms = terms
51                    .iter()
52                    .map(|t| Self::witness(t, assign))
53                    .collect();
54                Self::App { function: function.clone(), terms }
55            }
56        }
57    }
58}
59
60impl WitnessTermTrait for WitnessTerm {
61    type ElementType = E;
62}
63
64impl fmt::Display for WitnessTerm {
65    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
66        match self {
67            Self::Elem { element } => write!(f, "{}", element),
68            Self::Const { constant } => write!(f, "{}", constant),
69            Self::App { function, terms } => {
70                let ts: Vec<String> = terms.iter().map(|t| t.to_string()).collect();
71                write!(f, "{}[{}]", function, ts.join(", "))
72            }
73        }
74    }
75}
76
77impl fmt::Debug for WitnessTerm {
78    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79        write!(f, "{}", self.to_string())
80    }
81}
82
83impl From<C> for WitnessTerm {
84    fn from(constant: C) -> Self {
85        WitnessTerm::Const { constant }
86    }
87}
88
89impl From<E> for WitnessTerm {
90    fn from(element: E) -> Self {
91        WitnessTerm::Elem { element }
92    }
93}
94
95impl FApp for WitnessTerm {
96    fn apply(function: F, terms: Vec<Self>) -> Self {
97        WitnessTerm::App { function, terms }
98    }
99}
100
101/// Is a basic instance of [`ModelTrait`] with terms of type [`WitnessTerm`].
102///
103/// [`ModelTrait`]: ../../trait.ModelTrait.html
104/// [`WitnessTerm`]: ./enum.WitnessTerm.html
105pub struct Model {
106    /// Is a unique identifier for this model.
107    id: u64,
108
109    /// Keeps track of the next index to assign to a new element of this model.
110    element_index: i32,
111
112    /// Maps *flat* witness terms to elements of this model.
113    ///
114    /// **Hint**: Flat (witness) terms are terms that do not contain any composite sub-terms,
115    /// consisting of functions applications.
116    rewrites: HashMap<WitnessTerm, E>,
117
118    /// Contains a list of relational facts that are true in this model.
119    facts: HashSet<Observation<WitnessTerm>>,
120
121    /// Maintains a list of rewrite rules from elements to elements with which they have been
122    /// identified.
123    ///
124    /// **Explanation**: When augmenting a model with a list of [observations] (such as observations
125    /// that come from the head of a sequent being evaluated), identity observations are
126    /// augmented by collapsing elements, that is, removing one element in favor of the other one.
127    /// However, other augmenting observations may still point to an element that was removed as a
128    /// result of augmenting an `Identity` observation.
129    ///
130    /// `equality_history` is used to keep track of identifications of elements temporarily during
131    /// the time a model is being augmented in a [chase-step]. `equality_history` in a model becomes
132    /// outdated after the [chase-step] ends.
133    ///
134    /// [observations]: ../../enum.Observation.html
135    /// [chase-step]: ../../index.html#chase-step
136    equality_history: HashMap<E, E>,
137}
138
139impl Model {
140    /// Creates a new empty instance of this model.
141    pub fn new() -> Self {
142        Self {
143            id: rand::random(),
144            element_index: 0,
145            rewrites: HashMap::new(),
146            facts: HashSet::new(),
147            equality_history: HashMap::new(),
148        }
149    }
150
151    /// Applies the rewrite rules in `equality_history` of the receiver to reduce an element to
152    /// the representative element of the equational class to which it belongs.
153    fn history(&self, element: &E) -> E {
154        let mut result = element;
155        let mut next;
156        while {
157            next = self.equality_history.get(result);
158            next.is_some() && next.unwrap() != result
159        } { result = next.unwrap() }
160
161        result.clone()
162    }
163
164    /// Creates a new element for the given `witness` and records that `witness` denotes the new
165    /// element.
166    fn new_element(&mut self, witness: WitnessTerm) -> E {
167        let element = E(self.element_index);
168        self.element_index = self.element_index + 1;
169        self.rewrites.insert(witness, element.clone());
170        element
171    }
172
173    /// Records the given `witness` in the receiver model and returns the element, denoted by
174    /// `witness`.
175    ///
176    /// **Note**: `record` creates new elements that are denoted by `witness` and all sub-terms of
177    /// `witness` and adds them to the domain of the receiver.
178    fn record(&mut self, witness: &WitnessTerm) -> E {
179        match witness {
180            WitnessTerm::Elem { element } => {
181                let element = self.history(element);
182                if let Some(_) = self.domain().iter().find(|e| element.eq(e)) {
183                    element.clone()
184                } else {
185                    panic!("something is wrong: element does not exist in the model's domain")
186                }
187            }
188            WitnessTerm::Const { .. } => {
189                if let Some(e) = self.rewrites.get(&witness) {
190                    (*e).clone()
191                } else {
192                    self.new_element(witness.clone())
193                }
194            }
195            WitnessTerm::App { function, terms } => {
196                let terms: Vec<WitnessTerm> = terms
197                    .into_iter()
198                    .map(|t| self.record(t).into())
199                    .collect();
200                let witness = WitnessTerm::App { function: function.clone(), terms };
201                if let Some(e) = self.rewrites.get(&witness) {
202                    (*e).clone()
203                } else {
204                    self.new_element(witness)
205                }
206            }
207        }
208    }
209
210    /// Replaces all instances of `from` with `to` in the `rewrite` of the receiver and is used
211    /// when augmenting the model with an `Identity` [`Observation`].
212    ///
213    /// **Note**: When augmenting a model with an `Identity`, we simply replace all instances of one
214    /// side of the identity (i.e., the element denoted by one [witness term]) with the other
215    /// one.
216    ///
217    /// [`Observation`]: ../../enum.Observation.html
218    /// [witness term]: ../../trait.WitnessTermTrait.html
219    fn reduce_rewrites(&mut self, from: &E, to: &E) {
220        let mut new_rewrite: HashMap<WitnessTerm, E> = HashMap::new();
221        self.rewrites.iter().for_each(|(k, v)| {
222            // k is a flat term and cannot be an element:
223            let key = if let WitnessTerm::App { function, terms } = k {
224                let mut new_terms: Vec<WitnessTerm> = Vec::new();
225                terms.iter().for_each(|t| {
226                    if let WitnessTerm::Elem { element } = t {
227                        if element == to {
228                            new_terms.push(WitnessTerm::Elem { element: from.clone() });
229                        } else {
230                            new_terms.push(t.clone());
231                        }
232                    } else {
233                        new_terms.push(t.clone());
234                    }
235                });
236                WitnessTerm::App { function: function.clone(), terms: new_terms }
237            } else {
238                k.clone()
239            };
240
241            let value = if v == to {
242                from.clone()
243            } else {
244                v.clone()
245            };
246            new_rewrite.insert(key, value);
247        });
248        self.rewrites = new_rewrite;
249    }
250
251    /// Replaces all instances of `from` with `to` in the `facts` of the receiver and is used
252    /// when augmenting the model with an `Identity` [`Observation`].
253    ///
254    /// **Note**: When augmenting a model with an identity, we simply replace all instances of one
255    /// side of the identity (i.e., the element corresponding to its [witness term]) with the other
256    /// one.
257    ///
258    /// [`Observation`]: ../../enum.Observation.html
259    /// [witness term]: ../../trait.WitnessTermTrait.html
260    fn reduce_facts(&mut self, from: &E, to: &E) {
261        self.facts = self.facts.iter().map(|f| {
262            if let Observation::Fact { ref relation, ref terms } = f {
263                let terms: Vec<WitnessTerm> = terms.iter().map(|t| {
264                    if let WitnessTerm::Elem { element } = t {
265                        if element == to {
266                            from.clone().into()
267                        } else {
268                            (*t).clone()
269                        }
270                    } else {
271                        (*t).clone() // should never happen
272                    }
273                }).collect();
274                Observation::Fact { relation: relation.clone(), terms }
275            } else {
276                f.clone() // should never happen
277            }
278        }).collect();
279    }
280}
281
282impl Clone for Model {
283    fn clone(&self) -> Self {
284        Self {
285            id: rand::random(),
286            element_index: self.element_index.clone(),
287            rewrites: self.rewrites.clone(),
288            facts: self.facts.clone(),
289            // In the `basic` implementation, a model is cloned after being processed in a
290            // chase-step, so its `equality_history` does not need to persist after cloning it.
291            equality_history: HashMap::new(),
292        }
293    }
294}
295
296impl ModelTrait for Model {
297    type TermType = WitnessTerm;
298
299    fn get_id(&self) -> u64 { self.id }
300
301    fn domain(&self) -> Vec<&E> {
302        self.rewrites.values().into_iter().unique().collect()
303    }
304
305    fn facts(&self) -> Vec<&Observation<Self::TermType>> {
306        self.facts.iter().sorted().into_iter().dedup().collect()
307    }
308
309    fn observe(&mut self, observation: &Observation<WitnessTerm>) {
310        match observation {
311            Observation::Fact { relation, terms } => {
312                let terms: Vec<WitnessTerm> = terms
313                    .into_iter()
314                    .map(|t| self.record(t).into())
315                    .collect();
316                let observation = Observation::Fact { relation: relation.clone(), terms };
317                self.facts.insert(observation);
318            }
319            Observation::Identity { left, right } => {
320                let left = self.record(left);
321                let right = self.record(right);
322                let (from, to) = if left > right {
323                    (right, left)
324                } else {
325                    (left, right)
326                };
327
328                // Since the underlying ElementType of the WitnessTerm, used for constructing this
329                // type of model is not a reference to an object (unlike chase::impl::reference),
330                // the following two steps are necessary to guarantee correctness:
331                self.reduce_rewrites(&from, &to);
332                self.reduce_facts(&from, &to);
333
334                self.equality_history.insert(to, from);
335            }
336        }
337    }
338
339    fn is_observed(&self, observation: &Observation<WitnessTerm>) -> bool {
340        match observation {
341            Observation::Fact { relation, terms } => {
342                let terms: Vec<Option<&E>> = terms.iter().map(|t| self.element(t)).collect();
343                if terms.iter().any(|e| e.is_none()) {
344                    false
345                } else {
346                    let terms: Vec<WitnessTerm> = terms
347                        .into_iter()
348                        .map(|e| e.unwrap().clone().into())
349                        .collect();
350                    let obs = Observation::Fact { relation: relation.clone(), terms };
351                    self.facts.iter().find(|f| obs.eq(f)).is_some()
352                }
353            }
354            Observation::Identity { left, right } => {
355                let left = self.element(left);
356                left.is_some() && left == self.element(right)
357            }
358        }
359    }
360
361    fn witness(&self, element: &E) -> Vec<&WitnessTerm> {
362        self.rewrites.iter()
363            .filter(|(_, e)| *e == element)
364            .map(|(t, _)| t)
365            .collect()
366    }
367
368    fn element(&self, witness: &WitnessTerm) -> Option<&E> {
369        match witness {
370            WitnessTerm::Elem { element } => {
371                self.domain().into_iter().find(|e| e.eq(&element))
372            }
373            WitnessTerm::Const { .. } => self.rewrites.get(witness).map(|e| e),
374            WitnessTerm::App { function, terms } => {
375                let terms: Vec<Option<&E>> = terms.iter().map(|t| self.element(t)).collect();
376                if terms.iter().any(|e| e.is_none()) {
377                    None
378                } else {
379                    let terms: Vec<WitnessTerm> = terms
380                        .into_iter()
381                        .map(|e| e.unwrap().clone().into())
382                        .collect();
383                    self.rewrites.get(&WitnessTerm::App { function: (*function).clone(), terms }).map(|e| e)
384                }
385            }
386        }
387    }
388}
389
390impl fmt::Display for Model {
391    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
392        let domain: Vec<String> = self.domain().into_iter().map(|e| e.to_string()).collect();
393        let elements: Vec<String> = self.domain().iter().sorted().iter().map(|e| {
394            let witnesses: Vec<String> = self.witness(e).iter().map(|w| w.to_string()).collect();
395            let witnesses = witnesses.into_iter().sorted();
396            format!("{} -> {}", witnesses.into_iter().sorted().join(", "), e)
397        }).collect();
398        let facts: Vec<String> = self.facts().into_iter().map(|e| e.to_string()).collect();
399        write!(f, "Domain: {{{}}}\nElements:{}\nFacts: {}\n",
400               domain.join(", "),
401               elements.join(", "),
402               facts.join(", "))
403    }
404}
405
406/// Represents atomic formulae in [`Sequent`].
407///
408/// [`Sequent`]: ./struct.Sequent.html
409#[derive(Clone)]
410pub enum Literal {
411    /// Represents an atomic literal, corresponding to an atomic [`Formula`] of variant [`Atom`].
412    ///
413    /// [`Formula`]: ../../../formula/syntax/enum.Formula.html
414    /// [`Atom`]: ../../../formula/syntax/enum.Formula.html#variant.Atom
415    Atm { predicate: Pred, terms: Vec<Term> },
416
417    /// Represents a equality literal, corresponding to an atomic [`Formula`] of variant [`Equals`].
418    ///
419    /// [`Equals`]: ../../../formula/syntax/enum.Formula.html#variant.Equals
420    Eql { left: Term, right: Term },
421}
422
423impl Literal {
424    /// Builds the [body] of a [`Sequent`] from a [`Formula`].
425    ///
426    /// [`Sequent`]: ./struct.Sequent.html
427    /// [body]: ./struct.Sequent.html#structfield.body_literals
428    /// [`Formula`]: ../../../formula/syntax/enum.Formula.html
429    fn build_body(formula: &Formula) -> Vec<Literal> {
430        match formula {
431            Formula::Top => vec![],
432            Formula::Atom { predicate, terms } =>
433                vec![Literal::Atm { predicate: predicate.clone(), terms: terms.to_vec() }],
434            Formula::Equals { left, right } =>
435                vec![Literal::Eql { left: left.clone(), right: right.clone() }],
436            Formula::And { left, right } => {
437                let mut left = Literal::build_body(left);
438                let mut right = Literal::build_body(right);
439                left.append(&mut right);
440                left
441            }
442            _ => panic!("Something is wrong: expecting a geometric sequent in standard form.")
443        }
444    }
445
446    /// Builds the [head] of a [`Sequent`] from a [`Formula`].
447    ///
448    /// [`Sequent`]: ./struct.Sequent.html
449    /// [head]: ./struct.Sequent.html#structfield.head_literals
450    /// [`Formula`]: ../../../formula/syntax/enum.Formula.html
451    fn build_head(formula: &Formula) -> Vec<Vec<Literal>> {
452        match formula {
453            Formula::Top => vec![vec![]],
454            Formula::Bottom => vec![],
455            Formula::Atom { predicate, terms } =>
456                vec![vec![Literal::Atm { predicate: predicate.clone(), terms: terms.to_vec() }]],
457            Formula::Equals { left, right } =>
458                vec![vec![Literal::Eql { left: left.clone(), right: right.clone() }]],
459            Formula::And { left, right } => {
460                let mut left = Literal::build_head(left);
461                let mut right = Literal::build_head(right);
462                if left.is_empty() {
463                    left
464                } else if right.is_empty() {
465                    right
466                } else if left.len() == 1 && right.len() == 1 {
467                    let mut left = left.remove(0);
468                    let mut right = right.remove(0);
469                    left.append(&mut right);
470                    vec![left]
471                } else {
472                    panic!("Something is wrong: expecting a geometric sequent in standard form.")
473                }
474            }
475            Formula::Or { left, right } => {
476                let mut left = Literal::build_head(left);
477                let mut right = Literal::build_head(right);
478                left.append(&mut right);
479                left
480            }
481            _ => panic!("Something is wrong: expecting a geometric sequent in standard form.")
482        }
483    }
484}
485
486impl<'t> fmt::Display for Literal {
487    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
488        match self {
489            Literal::Atm { predicate, terms } => {
490                let ts: Vec<String> = terms.iter().map(|t| t.to_string()).collect();
491                write!(f, "{}({})", predicate, ts.join(", "))
492            }
493            Literal::Eql { left, right } => write!(f, "{} = {}", left, right),
494        }
495    }
496}
497
498/// Is represented by a list of [`Literal`]s in the body and a list of list of `Literal`s in the
499/// head.
500///
501/// [`Literal`]: ./enum.Literal.html
502#[derive(Clone)]
503pub struct Sequent {
504    /// Is the list of free variables in the sequent and is used for memoization.
505    pub free_vars: Vec<V>,
506
507    /// Is the [`Formula`] from which the body of the sequent is built.
508    ///
509    /// [`Formula`]: ../../../formula/syntax/enum.Formula.html
510    body: Formula,
511
512    /// Is the [`Formula`] from which the head of the sequent is built.
513    ///
514    /// [`Formula`]: ../../../formula/syntax/enum.Formula.html
515    head: Formula,
516
517    /// Represents the body of the sequent as a list of [`Literal`]s. The literals in
518    /// `body_literals` are assumed to be conjoined.
519    ///
520    /// [`Literal`]: ./enum.Literal.html
521    ///
522    /// **Note**: See [here](../../index.html#background) for more information about the structure
523    /// of geometric sequents.
524    pub body_literals: Vec<Literal>,
525
526    /// Represents the head of the sequent as a list of list of [`Literal`]s. The literals in
527    /// each sublist of `head_literals` are assumed to be conjoined where the sublists are
528    /// disjointed with each other.
529    ///
530    /// [`Literal`]: ./enum.Literal.html
531    ///
532    /// **Note**: See [here](../../index.html#background) for more information about the structure
533    /// of geometric sequents.
534    pub head_literals: Vec<Vec<Literal>>,
535}
536
537impl From<&Formula> for Sequent {
538    fn from(formula: &Formula) -> Self {
539        match formula {
540            Formula::Implies { left, right } => {
541                let free_vars: Vec<V> = formula.free_vars().into_iter().map(|v| v.clone()).collect();
542                let body_literals = Literal::build_body(left);
543                let head_literals = Literal::build_head(right);
544                let body = *left.clone();
545                let head = *right.clone();
546                Sequent { free_vars, body, head, body_literals, head_literals }
547            }
548            _ => panic!("Something is wrong: expecting a geometric sequent in standard form.")
549        }
550    }
551}
552
553impl fmt::Display for Sequent {
554    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
555        let body: Vec<String> = self.body_literals.iter().map(|l| l.to_string()).collect();
556        let head: Vec<String> =
557            self.head_literals.iter().map(|ls| {
558                let ls: Vec<String> = ls.iter().map(|l| l.to_string()).collect();
559                format!("[{}]", ls.join(", "))
560            }).collect();
561        write!(f, "[{}] -> [{}]", body.join(", "), head.join(", "))
562    }
563}
564
565impl SequentTrait for Sequent {
566    fn body(&self) -> Formula {
567        self.body.clone()
568    }
569
570    fn head(&self) -> Formula {
571        self.head.clone()
572    }
573}
574
575/// Evaluates a [`Sequent`] in a [`Model`] within a [chase-step].
576///
577/// [`Sequent`]: ./struct.Sequent.html
578/// [`Model`]: ./struct.Model.html
579/// [chase-step]: ../../index.html#chase-step
580pub struct Evaluator {}
581
582impl<'s, Stg: StrategyTrait<Item=&'s Sequent>, B: BounderTrait> EvaluatorTrait<'s, Stg, B> for Evaluator {
583    type Sequent = Sequent;
584    type Model = Model;
585    fn evaluate(&self, initial_model: &Model, strategy: &mut Stg, bounder: Option<&B>) -> Option<EvaluateResult<Model>> {
586        let domain: Vec<&E> = initial_model.domain().clone();
587        let domain_size = domain.len();
588        for sequent in strategy {
589            let vars = &sequent.free_vars;
590            let vars_size = vars.len();
591            if domain_size == 0 && vars_size > 0 {
592                continue; // empty models can only be extended with sequents with no free variables.
593            }
594
595            // maintain a list of indices into the model elements to which variables are mapped
596            let mut assignment: Vec<usize> = iter::repeat(0).take(vars_size).collect();
597
598            // try all the variable assignments to the elements of the model
599            // (notice the do-while pattern)
600            while {
601                // construct a map from variables to elements
602                let mut assignment_map: HashMap<&V, E> = HashMap::new();
603                for i in 0..vars_size {
604                    assignment_map.insert(vars.get(i).unwrap(), (*domain.get(assignment[i]).unwrap()).clone());
605                }
606                // construct a "characteristic function" for the assignment map
607                let assignment_func = |v: &V| assignment_map.get(v).unwrap().clone();
608
609                // lift the variable assignments to literals (used to create observations)
610                let observe_literal = make_observe_literal(assignment_func);
611
612                // build body and head observations
613                let body: Vec<Observation<WitnessTerm>> = sequent.body_literals
614                    .iter()
615                    .map(&observe_literal)
616                    .collect();
617                let head: Vec<Vec<Observation<WitnessTerm>>> = sequent.head_literals
618                    .iter()
619                    .map(|l| l.iter().map(&observe_literal).collect())
620                    .collect();
621
622                // if all body observations are true in the model but not all the head observations
623                // are true, extend the model:
624                if body.iter().all(|o| initial_model.is_observed(o))
625                    && !head.iter().any(|os| os.iter().all(|o| initial_model.is_observed(o))) {
626                    if head.is_empty() {
627                        return None; // the chase fails if the head is empty (false)
628                    } else {
629                        // if there is a bounder, only extend models that are not out of the given bound:
630                        let models: Vec<Either<Model, Model>> = if let Some(bounder) = bounder {
631                            let extend = make_bounded_extend(bounder, initial_model);
632                            head.iter().map(extend).collect()
633                        } else {
634                            let extend = make_extend(initial_model);
635                            head.iter().map(extend).collect()
636                        };
637
638                        let result = EvaluateResult::from(models);
639                        if !result.empty() {
640                            // this evaluator instantiates the first matching sequent with the first
641                            // matching assignment (unlike impl::batch.rs)
642                            return Some(result);
643                        }
644                    }
645                }
646
647                // try the next variable assignment
648                domain_size > 0 && next_assignment(&mut assignment, domain_size - 1)
649            } {}
650        }
651        Some(EvaluateResult::new()) // if none of the assignments apply, the model is complete already
652    }
653}
654
655// Returns a closure that returns a cloned extension of the given model, extended by a given set of
656// observations.
657fn make_extend<'m>(
658    model: &'m Model
659) -> impl FnMut(&'m Vec<Observation<WitnessTerm>>) -> Either<Model, Model>
660{
661    move |os: &'m Vec<Observation<WitnessTerm>>| {
662        let mut model = model.clone();
663        os.iter().foreach(|o| model.observe(o));
664        Either::Left(model)
665    }
666}
667
668// Returns a closure that returns a cloned extension of the given model, extended by a given set of
669// observations. Unlike `make_extend`, `make_bounded_extend` extends the model with respect to a
670// bounder: a model wrapped in `Either::Right` has not reached the bounds while a model wrapped in
671// `Either::Left` has reached the bounds provided by `bounder`.
672fn make_bounded_extend<'m, B: BounderTrait>(
673    bounder: &'m B,
674    model: &'m Model,
675) -> impl FnMut(&'m Vec<Observation<WitnessTerm>>) -> Either<Model, Model>
676{
677    move |os: &Vec<Observation<WitnessTerm>>| {
678        let mut model = model.clone();
679        let mut modified = false;
680        os.iter().foreach(|o| {
681            if bounder.bound(&model, o) {
682                if !model.is_observed(o) {
683                    modified = true;
684                }
685            } else {
686                if !model.is_observed(o) {
687                    model.observe(o);
688                }
689            }
690        });
691        if modified {
692            Either::Right(model)
693        } else {
694            Either::Left(model)
695        }
696    }
697}
698
699// Given an function from variables to elements of a model, returns a closure that lift the variable
700// assignments to literals of a sequent, returning observations.
701fn make_observe_literal(assignment_func: impl Fn(&V) -> E)
702                        -> impl Fn(&Literal) -> Observation<WitnessTerm> {
703    move |lit: &Literal| {
704        match lit {
705            Literal::Atm { predicate, terms } => {
706                let terms = terms
707                    .into_iter()
708                    .map(|t| WitnessTerm::witness(t, &assignment_func))
709                    .collect();
710                Observation::Fact { relation: Rel(predicate.0.clone()), terms }
711            }
712            Literal::Eql { left, right } => {
713                let left = WitnessTerm::witness(left, &assignment_func);
714                let right = WitnessTerm::witness(right, &assignment_func);
715                Observation::Identity { left, right }
716            }
717        }
718    }
719}
720
721// Implements a counter to enumerate all the possible assignments of a domain of elements to free
722// variables of a sequent. It mutates the given a list of indices, corresponding to mapping of each
723// position to an element of a domain to the next assignment. Returns true if a next assignment
724// exists and false otherwise.
725fn next_assignment(vec: &mut Vec<usize>, last: usize) -> bool {
726    let len = vec.len();
727    for i in 0..len {
728        if vec[i] != last {
729            vec[i] += 1;
730            return true;
731        } else {
732            vec[i] = 0;
733        }
734    }
735    false
736}
737
738#[cfg(test)]
739mod test_basic {
740    use super::*;
741    use crate::test_prelude::*;
742    use std::iter::FromIterator;
743
744    // Witness Elements
745    pub fn _e_0() -> WitnessTerm { e_0().into() }
746
747    pub fn _e_1() -> WitnessTerm { e_1().into() }
748
749    pub fn _e_2() -> WitnessTerm { e_2().into() }
750
751    pub fn _e_3() -> WitnessTerm { e_3().into() }
752
753    pub fn _e_4() -> WitnessTerm { e_4().into() }
754
755    // Witness Constants
756    pub fn _a_() -> WitnessTerm { WitnessTerm::Const { constant: _a() } }
757
758    pub fn _b_() -> WitnessTerm { WitnessTerm::Const { constant: _b() } }
759
760    pub fn _c_() -> WitnessTerm { WitnessTerm::Const { constant: _c() } }
761
762    pub fn _d_() -> WitnessTerm { WitnessTerm::Const { constant: _d() } }
763
764    #[test]
765    fn test_witness_const() {
766        assert_eq!(_a_(), _a().into());
767        assert_eq!("'a", _a_().to_string());
768    }
769
770    #[test]
771    fn test_observation() {
772        assert_eq!("<R(e#0)>", _R_().app1(_e_0()).to_string());
773        assert_eq!("<R(e#0, e#1, e#2)>", _R_().app3(_e_0(), _e_1(), _e_2()).to_string());
774        assert_eq!("<e#0 = e#1>", _e_0().equals(_e_1()).to_string());
775    }
776
777    #[test]
778    fn test_empty_model() {
779        let model = Model::new();
780        let empty_domain: Vec<&E> = Vec::new();
781        let empty_facts: Vec<&Observation<WitnessTerm>> = Vec::new();
782        assert_eq!(empty_domain, model.domain());
783        assert_eq_sets(&empty_facts, &model.facts());
784    }
785
786    #[test]
787    fn test_witness_app() {
788        let f_0: WitnessTerm = f().app0();
789        assert_eq!("f[]", f_0.to_string());
790        assert_eq!("f['c]", f().app1(_c_()).to_string());
791        let g_0: WitnessTerm = g().app0();
792        assert_eq!("f[g[]]", f().app1(g_0).to_string());
793        assert_eq!("f['c, g['d]]", f().app2(_c_(), g().app1(_d_())).to_string());
794    }
795
796    #[test]
797    fn test_observe() {
798        {
799            let mut model = Model::new();
800            model.observe(&_R_().app0());
801            assert_eq_sets(&Vec::from_iter(vec![_R_().app0()].iter()), &model.facts());
802            assert!(model.is_observed(&_R_().app0()));
803        }
804        {
805            let mut model = Model::new();
806            model.observe(&_R_().app1(_c_()));
807            assert_eq_sets(&Vec::from_iter(vec![&e_0()]), &model.domain());
808            assert_eq_sets(&Vec::from_iter(vec![_R_().app1(_e_0())].iter()), &model.facts());
809            assert!(model.is_observed(&_R_().app1(_c_())));
810            assert!(model.is_observed(&_R_().app1(_e_0())));
811            assert!(!model.is_observed(&_R_().app1(_e_1())));
812            assert_eq_sets(&Vec::from_iter(vec![&_c_()]), &model.witness(&e_0()));
813        }
814        {
815            let mut model = Model::new();
816            model.observe(&_a_().equals(_b_()));
817            assert_eq_sets(&Vec::from_iter(vec![&e_0()]), &model.domain());
818            let empty_facts: Vec<&Observation<WitnessTerm>> = Vec::new();
819            assert_eq_sets(&empty_facts, &model.facts());
820            assert_eq_sets(&Vec::from_iter(vec![&_a_(), &_b_()]), &model.witness(&e_0()));
821        }
822        {
823            let mut model = Model::new();
824            model.observe(&_a_().equals(_a_()));
825            assert_eq_sets(&Vec::from_iter(vec![&e_0()]), &model.domain());
826            let empty_facts: Vec<&Observation<WitnessTerm>> = Vec::new();
827            assert_eq_sets(&empty_facts, &model.facts());
828            assert_eq_sets(&Vec::from_iter(vec![&_a_()]), &model.witness(&e_0()));
829        }
830        {
831            let mut model = Model::new();
832            model.observe(&_P_().app1(_a_()));
833            model.observe(&_Q_().app1(_b_()));
834            model.observe(&_a_().equals(_b_()));
835            assert_eq_sets(&Vec::from_iter(vec![&e_0()]), &model.domain());
836            assert_eq_sets(&Vec::from_iter(vec![_P_().app1(_e_0()), _Q_().app1(_e_0())].iter()), &model.facts());
837            assert!(model.is_observed(&_P_().app1(_e_0())));
838            assert!(model.is_observed(&_P_().app1(_a_())));
839            assert!(model.is_observed(&_P_().app1(_b_())));
840            assert!(model.is_observed(&_Q_().app1(_e_0())));
841            assert!(model.is_observed(&_Q_().app1(_a_())));
842            assert!(model.is_observed(&_Q_().app1(_b_())));
843            assert_eq_sets(&Vec::from_iter(vec![&_a_(), &_b_()]), &model.witness(&e_0()));
844        }
845        {
846            let mut model = Model::new();
847            model.observe(&_R_().app1(f().app1(_c_())));
848            assert_eq_sets(&Vec::from_iter(vec![&e_0(), &e_1()]), &model.domain());
849            assert_eq_sets(&Vec::from_iter(vec![_R_().app1(_e_1())].iter()), &model.facts());
850            assert!(model.is_observed(&_R_().app1(_e_1())));
851            assert!(model.is_observed(&_R_().app1(f().app1(_c_()))));
852            assert_eq_sets(&Vec::from_iter(vec![&_c_()]), &model.witness(&e_0()));
853            assert_eq_sets(&Vec::from_iter(vec![&f().app1(_e_0())]), &model.witness(&e_1()));
854        }
855        {
856            let mut model = Model::new();
857            model.observe(&_R_().app2(_a_(), _b_()));
858            assert_eq_sets(&Vec::from_iter(vec![&e_0(), &e_1()]), &model.domain());
859            assert_eq_sets(&Vec::from_iter(vec![_R_().app2(_e_0(), _e_1())].iter()), &model.facts());
860            assert!(model.is_observed(&_R_().app2(_e_0(), _e_1())));
861            assert!(!model.is_observed(&_R_().app2(_e_0(), _e_0())));
862            assert_eq_sets(&Vec::from_iter(vec![&_a_()]), &model.witness(&e_0()));
863            assert_eq_sets(&Vec::from_iter(vec![&_b_()]), &model.witness(&e_1()));
864        }
865        {
866            let mut model = Model::new();
867            model.observe(&_R_().app2(f().app1(_c_()), g().app1(f().app1(_c_()))));
868            assert_eq_sets(&Vec::from_iter(vec![&e_0(), &e_1(), &e_2()]), &model.domain());
869            assert_eq_sets(&Vec::from_iter(vec![_R_().app2(_e_1(), _e_2())].iter()), &model.facts());
870            assert!(model.is_observed(&_R_().app2(_e_1(), _e_2())));
871            assert!(model.is_observed(&_R_().app2(f().app1(_c_()), g().app1(f().app1(_c_())))));
872            assert!(model.is_observed(&_R_().app2(f().app1(_c_()), _e_2())));
873            assert_eq_sets(&Vec::from_iter(vec![&_c_()]), &model.witness(&e_0()));
874            assert_eq_sets(&Vec::from_iter(vec![&f().app1(_e_0())]), &model.witness(&e_1()));
875            assert_eq_sets(&Vec::from_iter(vec![&g().app1(_e_1())]), &model.witness(&e_2()));
876        }
877        {
878            let mut model = Model::new();
879            model.observe(&_R_().app2(_a_(), _b_()));
880            model.observe(&_S_().app2(_c_(), _d_()));
881            assert_eq_sets(&Vec::from_iter(vec![&e_0(), &e_1(), &e_2(), &e_3()]), &model.domain());
882            assert_eq_sets(&Vec::from_iter(vec![_R_().app2(_e_0(), _e_1())
883                                                , _S_().app2(_e_2(), _e_3())
884            ].iter()), &model.facts());
885        }
886        {
887            let mut model = Model::new();
888            model.observe(&_R_().app2(_a_(), f().app1(_a_())));
889            model.observe(&_S_().app1(_b_()));
890            model.observe(&_R_().app2(g().app1(f().app1(_a_())), _b_()));
891            model.observe(&_S_().app1(_c_()));
892            assert_eq_sets(&Vec::from_iter(vec![&e_0(), &e_1(), &e_2(), &e_3(), &e_4()]), &model.domain());
893            assert_eq_sets(&Vec::from_iter(vec![_R_().app2(_e_0(), _e_1())
894                                                , _S_().app1(_e_4())
895                                                , _S_().app1(_e_2())
896                                                , _R_().app2(_e_3(), _e_2())
897            ].iter()), &model.facts());
898        }
899    }
900
901    #[test]
902    #[should_panic]
903    fn test_observe_missing_element() {
904        let mut model = Model::new();
905        model.observe(&_R_().app1(_e_0()));
906    }
907
908    #[test]
909    fn test_build_sequent() {
910        assert_debug_string("[] -> [[]]",
911                            Sequent::from(&"true -> true".parse().unwrap()));
912        assert_debug_string("[] -> [[]]",
913                            Sequent::from(&"true -> true & true".parse().unwrap()));
914        assert_debug_string("[] -> [[], []]",
915                            Sequent::from(&"true -> true | true".parse().unwrap()));
916        assert_debug_string("[] -> []",
917                            Sequent::from(&"true -> false".parse().unwrap()));
918        assert_debug_string("[] -> []",
919                            Sequent::from(&"true -> false & true".parse().unwrap()));
920        assert_debug_string("[] -> []",
921                            Sequent::from(&"true -> true & false".parse().unwrap()));
922        assert_debug_string("[] -> [[]]",
923                            Sequent::from(&"true -> true | false".parse().unwrap()));
924        assert_debug_string("[] -> [[]]",
925                            Sequent::from(&"true -> false | true".parse().unwrap()));
926        assert_debug_string("[P(x)] -> [[Q(x)]]",
927                            Sequent::from(&"P(x) -> Q(x)".parse().unwrap()));
928        assert_debug_string("[P(x), Q(x)] -> [[Q(y)]]",
929                            Sequent::from(&"P(x) & Q(x) -> Q(y)".parse().unwrap()));
930        assert_debug_string("[P(x), Q(x)] -> [[Q(x)], [R(z), S(z)]]",
931                            Sequent::from(&"P(x) & Q(x) -> Q(x) | (R(z) & S(z))".parse().unwrap()));
932        assert_debug_string("[] -> [[P(x), Q(x)], [P(y), Q(y)], [P(z), Q(z)]]",
933                            Sequent::from(&"true -> (P(x) & Q(x)) | (P(y) & Q(y)) | (P(z) & Q(z))".parse().unwrap()));
934    }
935
936    #[test]
937    #[should_panic]
938    fn test_build_invalid_sequent_1() {
939        Sequent::from(&"true".parse().unwrap());
940    }
941
942    #[test]
943    #[should_panic]
944    fn test_build_invalid_sequent_2() {
945        Sequent::from(&"false".parse().unwrap());
946    }
947
948    #[test]
949    #[should_panic]
950    fn test_build_invalid_sequent_3() {
951        Sequent::from(&"false -> true".parse().unwrap());
952    }
953
954    #[test]
955    #[should_panic]
956    fn test_build_invalid_sequent_4() {
957        Sequent::from(&"(P(x) | Q(x)) -> R(x)".parse().unwrap());
958    }
959
960    #[test]
961    #[should_panic]
962    fn test_build_invalid_sequent_5() {
963        Sequent::from(&"P(x) -> R(x) & (Q(z) | R(z))".parse().unwrap());
964    }
965
966    #[test]
967    #[should_panic]
968    fn test_build_invalid_sequent_6() {
969        Sequent::from(&"P(x) -> ?x. Q(x)".parse().unwrap());
970    }
971
972    #[test]
973    #[should_panic]
974    fn test_build_invalid_sequent_7() {
975        Sequent::from(&"?x.Q(x) -> P(x)".parse().unwrap());
976    }
977
978    #[test]
979    #[should_panic]
980    fn test_build_invalid_sequent_8() {
981        Sequent::from(&"true -> ~false".parse().unwrap());
982    }
983
984    #[test]
985    #[should_panic]
986    fn test_build_invalid_sequent_9() {
987        Sequent::from(&"true -> ~true".parse().unwrap());
988    }
989
990    #[test]
991    #[should_panic]
992    fn test_build_invalid_sequent_10() {
993        Sequent::from(&"~P(x) -> ~Q(x)".parse().unwrap());
994    }
995
996    #[test]
997    fn test_core() {
998        assert_eq!("Domain: {e#0}\n\
999                      Facts: <P(e#0)>\n\
1000                      'a -> e#0",
1001                   print_basic_models(solve_basic(&&read_theory_from_file("../theories/core/thy0.raz"))));
1002        assert_eq!("Domain: {e#0, e#1}\n\
1003                       Facts: <P(e#0)>, <P(e#1)>\n\
1004                       'a -> e#0\n\
1005                       'b -> e#1",
1006                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy1.raz"))));
1007        assert_eq!("Domain: {e#0}\n\
1008                       Facts: <P(e#0)>, <Q(e#0)>\n\
1009                       'a -> e#0",
1010                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy2.raz"))));
1011        assert_eq!("Domain: {e#0, e#1}\n\
1012                       Facts: <R(e#0, e#1)>\n\
1013                       'sk#0 -> e#0\n\
1014                       'sk#1 -> e#1",
1015                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy3.raz"))));
1016        assert_eq!("Domain: {e#0}\n\
1017                Facts: \n\
1018                'a, 'b -> e#0",
1019                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy4.raz"))));
1020        assert_eq!("Domain: {e#0, e#1}\n\
1021                       Facts: <P(e#0, e#1)>\n\
1022                       'a -> e#0\n\
1023                       'b -> e#1",
1024                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy5.raz"))));
1025        assert_eq!("Domain: {e#0, e#1}\n\
1026                       Facts: <P(e#1)>\n\
1027                       'a -> e#0\n\
1028                       f[e#0] -> e#1",
1029                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy6.raz"))));
1030        assert_eq!("Domain: {e#0}\n\
1031                       Facts: <P(e#0)>, <Q(e#0)>, <R(e#0)>\n\
1032                       'a -> e#0",
1033                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy7.raz"))));
1034        assert_eq!("Domain: {e#0}\n\
1035                       Facts: <P(e#0)>\n\
1036                       'a -> e#0\n\
1037                       -- -- -- -- -- -- -- -- -- --\n\
1038                       Domain: {e#0}\n\
1039                       Facts: <Q(e#0)>\n\
1040                       'b -> e#0\n\
1041                       -- -- -- -- -- -- -- -- -- --\n\
1042                       Domain: {e#0}\n\
1043                       Facts: <R(e#0)>\n\
1044                       'c -> e#0",
1045                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy8.raz"))));
1046        assert_eq!("Domain: {e#0}\n\
1047                       Facts: <P(e#0)>, <Q(e#0)>\n\
1048                       'a, 'b -> e#0",
1049                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy9.raz"))));
1050        assert_eq!("Domain: {e#0}\n\
1051                       Facts: <P(e#0)>, <R(e#0)>\n\
1052                       'a -> e#0\n\
1053                       -- -- -- -- -- -- -- -- -- --\n\
1054                       Domain: {e#0}\n\
1055                       Facts: <Q(e#0)>, <S(e#0)>\n\
1056                       'b -> e#0",
1057                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy10.raz"))));
1058        assert_eq!("Domain: {}\n\
1059                       Facts: \n",
1060                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy11.raz"))));
1061        assert_eq!("Domain: {}\n\
1062                       Facts: \n",
1063                   print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy12.raz"))));
1064        assert_eq!("", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy13.raz"))));
1065        assert_eq!("Domain: {e#0}\n\
1066                       Facts: <Q(e#0)>\n\
1067                       'b -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy14.raz"))));
1068        assert_eq!("", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy15.raz"))));
1069        assert_eq!("Domain: {e#0}\n\
1070                       Facts: <P(e#0, e#0)>, <Q(e#0)>\n\
1071                       'c -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy16.raz"))));
1072        assert_eq!("Domain: {e#0, e#1, e#2}\n\
1073                       Facts: <P(e#0, e#0)>, <P(e#1, e#2)>, <Q(e#0)>\n\
1074                       'c -> e#0\n\
1075                       'a -> e#1\n\
1076                       'b -> e#2", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy17.raz"))));
1077        assert_eq!("Domain: {e#0, e#1, e#2}\n\
1078                       Facts: <P(e#0, e#1)>, <P(e#2, e#2)>, <Q(e#2)>\n\
1079                       'a -> e#0\n\
1080                       'b -> e#1\n\
1081                       'c -> e#2", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy18.raz"))));
1082        assert_eq!("Domain: {e#0, e#1, e#10, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1083                       Facts: \n\
1084                       'a -> e#0\n\
1085                       f[e#0] -> e#1\n\
1086                       f[e#1] -> e#2\n\
1087                       f[e#2] -> e#3\n\
1088                       f[e#3] -> e#4\n\
1089                       f[e#4] -> e#5\n\
1090                       f[e#5] -> e#6\n\
1091                       f[e#6] -> e#7\n\
1092                       f[e#7] -> e#8\n\
1093                       f[e#8] -> e#9\n\
1094                       'b, f[e#9] -> e#10", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy19.raz"))));
1095        assert_eq!("Domain: {e#0, e#1, e#10, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1096                       Facts: <P(e#0)>, <P(e#1)>, <P(e#2)>, <P(e#3)>, <P(e#4)>, <P(e#5)>, <P(e#6)>, <P(e#7)>, <P(e#8)>, <P(e#9)>\n\
1097                       'a -> e#0\n\
1098                       f[e#0] -> e#1\n\
1099                       f[e#1] -> e#2\n\
1100                       f[e#2] -> e#3\n\
1101                       f[e#3] -> e#4\n\
1102                       f[e#4] -> e#5\n\
1103                       f[e#5] -> e#6\n\
1104                       f[e#6] -> e#7\n\
1105                       f[e#7] -> e#8\n\
1106                       f[e#8] -> e#9\n\
1107                       'b, f[e#9] -> e#10", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy20.raz"))));
1108        assert_eq!("Domain: {e#0, e#1, e#10, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1109                       Facts: <P(e#0)>, <P(e#1)>, <P(e#2)>, <P(e#3)>, <P(e#4)>, <P(e#5)>, <P(e#6)>, <P(e#7)>, <P(e#8)>\n\
1110                       'a -> e#0\n\
1111                       f[e#0] -> e#1\n\
1112                       f[e#1] -> e#2\n\
1113                       f[e#2] -> e#3\n\
1114                       f[e#3] -> e#4\n\
1115                       f[e#4] -> e#5\n\
1116                       f[e#5] -> e#6\n\
1117                       f[e#6] -> e#7\n\
1118                       f[e#7] -> e#8\n\
1119                       f[e#8] -> e#9\n\
1120                       'b, f[e#9] -> e#10", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy21.raz"))));
1121        assert_eq!("Domain: {e#0}\n\
1122                Facts: <P(e#0)>, <Q(e#0)>, <R(e#0)>\n\
1123                'a -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy22.raz"))));
1124        assert_eq!("Domain: {e#0}\n\
1125                       Facts: <P(e#0)>, <Q(e#0)>, <R(e#0)>, <S(e#0)>\n\
1126                       'sk#0, 'sk#1, 'sk#2 -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy23.raz"))));
1127        assert_eq!("Domain: {e#0}\n\
1128                       Facts: <P(e#0)>, <Q(e#0)>, <R(e#0)>, <S(e#0)>, <T(e#0)>\n\
1129                       'sk#0, 'sk#1, 'sk#2, 'sk#3 -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy24.raz"))));
1130        assert_eq!("Domain: {e#0, e#1, e#2, e#3}\n\
1131                       Facts: <P(e#0)>, <Q(e#1)>, <R(e#2)>, <S(e#3)>\n\
1132                       'sk#0 -> e#0\n\
1133                       'sk#1 -> e#1\n\
1134                       'sk#2 -> e#2\n\
1135                       'sk#3 -> e#3", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy25.raz"))));
1136        assert_eq!("Domain: {e#0}\n\
1137                       Facts: <P(e#0)>\n\
1138                       'sk#0 -> e#0\n\
1139                       -- -- -- -- -- -- -- -- -- --\n\
1140                       Domain: {e#0}\n\
1141                       Facts: <P(e#0)>\n\
1142                       'sk#1 -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy26.raz"))));
1143        assert_eq!("", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy27.raz"))));
1144        assert_eq!("Domain: {}\n\
1145        Facts: <T()>, <V()>\n\n\
1146        -- -- -- -- -- -- -- -- -- --\n\
1147        Domain: {}\n\
1148        Facts: <U()>, <V()>\n", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy28.raz"))));
1149        assert_eq!("Domain: {}\n\
1150        Facts: <P()>\n\n\
1151        -- -- -- -- -- -- -- -- -- --\n\
1152        Domain: {}\n\
1153        Facts: <Q()>, <R()>, <T()>, <V()>\n\n\
1154        -- -- -- -- -- -- -- -- -- --\n\
1155        Domain: {}\n\
1156        Facts: <Q()>, <R()>, <U()>, <V()>\n\n\
1157        -- -- -- -- -- -- -- -- -- --\n\
1158        Domain: {}\n\
1159        Facts: <Q()>, <S()>, <W()>\n\n\
1160        -- -- -- -- -- -- -- -- -- --\n\
1161        Domain: {}\n\
1162        Facts: <Q()>, <S()>, <X()>\n\n\
1163        -- -- -- -- -- -- -- -- -- --\n\
1164        Domain: {}\n\
1165        Facts: <Q()>, <S()>, <Y()>\n", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy29.raz"))));
1166        assert_eq!("", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy30.raz"))));
1167        assert_eq!("Domain: {e#0}\n\
1168                       Facts: <Q(e#0, e#0)>, <R(e#0)>, <U(e#0)>\n\
1169                       'sk#0 -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy31.raz"))));
1170        assert_eq!("Domain: {e#0, e#1}\n\
1171        Facts: <Q(e#0, e#1)>, <R(e#0)>\n\
1172        'sk#0 -> e#0\n\
1173        sk#1[e#0] -> e#1", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy32.raz"))));
1174        assert_eq!("Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1175        Facts: <P(e#0)>, <P1(e#1)>, <P11(e#2)>, <P111(e#3)>, <P1111(e#4)>\n\
1176        'sk#0 -> e#0\n\
1177        sk#1[e#0] -> e#1\n\
1178        sk#3[e#1] -> e#2\n\
1179        sk#7[e#2] -> e#3\n\
1180        sk#15[e#3] -> e#4\n\
1181        -- -- -- -- -- -- -- -- -- --\n\
1182        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1183        Facts: <P(e#0)>, <P1(e#1)>, <P11(e#2)>, <P111(e#3)>, <P1112(e#4)>\n\
1184        'sk#0 -> e#0\n\
1185        sk#1[e#0] -> e#1\n\
1186        sk#3[e#1] -> e#2\n\
1187        sk#7[e#2] -> e#3\n\
1188        sk#15[e#3] -> e#4\n\
1189        -- -- -- -- -- -- -- -- -- --\n\
1190        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1191        Facts: <P(e#0)>, <P1(e#1)>, <P11(e#2)>, <P112(e#3)>, <P1121(e#4)>\n\
1192        'sk#0 -> e#0\n\
1193        sk#1[e#0] -> e#1\n\
1194        sk#3[e#1] -> e#2\n\
1195        sk#7[e#2] -> e#3\n\
1196        sk#17[e#3] -> e#4\n\
1197        -- -- -- -- -- -- -- -- -- --\n\
1198        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1199        Facts: <P(e#0)>, <P1(e#1)>, <P11(e#2)>, <P112(e#3)>, <P1122(e#4)>\n\
1200        'sk#0 -> e#0\n\
1201        sk#1[e#0] -> e#1\n\
1202        sk#3[e#1] -> e#2\n\
1203        sk#7[e#2] -> e#3\n\
1204        sk#17[e#3] -> e#4\n\
1205        -- -- -- -- -- -- -- -- -- --\n\
1206        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1207        Facts: <P(e#0)>, <P1(e#1)>, <P12(e#2)>, <P121(e#3)>, <P1211(e#4)>\n\
1208        'sk#0 -> e#0\n\
1209        sk#1[e#0] -> e#1\n\
1210        sk#3[e#1] -> e#2\n\
1211        sk#9[e#2] -> e#3\n\
1212        sk#19[e#3] -> e#4\n\
1213        -- -- -- -- -- -- -- -- -- --\n\
1214        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1215        Facts: <P(e#0)>, <P1(e#1)>, <P12(e#2)>, <P121(e#3)>, <P1212(e#4)>\n\
1216        'sk#0 -> e#0\n\
1217        sk#1[e#0] -> e#1\n\
1218        sk#3[e#1] -> e#2\n\
1219        sk#9[e#2] -> e#3\n\
1220        sk#19[e#3] -> e#4\n\
1221        -- -- -- -- -- -- -- -- -- --\n\
1222        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1223        Facts: <P(e#0)>, <P1(e#1)>, <P12(e#2)>, <P122(e#3)>, <P1221(e#4)>\n\
1224        'sk#0 -> e#0\n\
1225        sk#1[e#0] -> e#1\n\
1226        sk#3[e#1] -> e#2\n\
1227        sk#9[e#2] -> e#3\n\
1228        sk#21[e#3] -> e#4\n\
1229        -- -- -- -- -- -- -- -- -- --\n\
1230        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1231        Facts: <P(e#0)>, <P1(e#1)>, <P12(e#2)>, <P122(e#3)>, <P1222(e#4)>\n\
1232        'sk#0 -> e#0\n\
1233        sk#1[e#0] -> e#1\n\
1234        sk#3[e#1] -> e#2\n\
1235        sk#9[e#2] -> e#3\n\
1236        sk#21[e#3] -> e#4\n\
1237        -- -- -- -- -- -- -- -- -- --\n\
1238        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1239        Facts: <P(e#0)>, <P2(e#1)>, <P21(e#2)>, <P211(e#3)>, <P2111(e#4)>\n\
1240        'sk#0 -> e#0\n\
1241        sk#1[e#0] -> e#1\n\
1242        sk#5[e#1] -> e#2\n\
1243        sk#11[e#2] -> e#3\n\
1244        sk#23[e#3] -> e#4\n\
1245        -- -- -- -- -- -- -- -- -- --\n\
1246        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1247        Facts: <P(e#0)>, <P2(e#1)>, <P21(e#2)>, <P211(e#3)>, <P2112(e#4)>\n\
1248        'sk#0 -> e#0\n\
1249        sk#1[e#0] -> e#1\n\
1250        sk#5[e#1] -> e#2\n\
1251        sk#11[e#2] -> e#3\n\
1252        sk#23[e#3] -> e#4\n\
1253        -- -- -- -- -- -- -- -- -- --\n\
1254        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1255        Facts: <P(e#0)>, <P2(e#1)>, <P21(e#2)>, <P212(e#3)>, <P2121(e#4)>\n\
1256        'sk#0 -> e#0\n\
1257        sk#1[e#0] -> e#1\n\
1258        sk#5[e#1] -> e#2\n\
1259        sk#11[e#2] -> e#3\n\
1260        sk#25[e#3] -> e#4\n\
1261        -- -- -- -- -- -- -- -- -- --\n\
1262        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1263        Facts: <P(e#0)>, <P2(e#1)>, <P21(e#2)>, <P212(e#3)>, <P2122(e#4)>\n\
1264        'sk#0 -> e#0\n\
1265        sk#1[e#0] -> e#1\n\
1266        sk#5[e#1] -> e#2\n\
1267        sk#11[e#2] -> e#3\n\
1268        sk#25[e#3] -> e#4\n\
1269        -- -- -- -- -- -- -- -- -- --\n\
1270        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1271        Facts: <P(e#0)>, <P2(e#1)>, <P22(e#2)>, <P221(e#3)>, <P2211(e#4)>\n\
1272        'sk#0 -> e#0\n\
1273        sk#1[e#0] -> e#1\n\
1274        sk#5[e#1] -> e#2\n\
1275        sk#13[e#2] -> e#3\n\
1276        sk#27[e#3] -> e#4\n\
1277        -- -- -- -- -- -- -- -- -- --\n\
1278        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1279        Facts: <P(e#0)>, <P2(e#1)>, <P22(e#2)>, <P221(e#3)>, <P2212(e#4)>\n\
1280        'sk#0 -> e#0\n\
1281        sk#1[e#0] -> e#1\n\
1282        sk#5[e#1] -> e#2\n\
1283        sk#13[e#2] -> e#3\n\
1284        sk#27[e#3] -> e#4\n\
1285        -- -- -- -- -- -- -- -- -- --\n\
1286        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1287        Facts: <P(e#0)>, <P2(e#1)>, <P22(e#2)>, <P222(e#3)>, <P2221(e#4)>\n\
1288        'sk#0 -> e#0\n\
1289        sk#1[e#0] -> e#1\n\
1290        sk#5[e#1] -> e#2\n\
1291        sk#13[e#2] -> e#3\n\
1292        sk#29[e#3] -> e#4\n\
1293        -- -- -- -- -- -- -- -- -- --\n\
1294        Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1295        Facts: <P(e#0)>, <P2(e#1)>, <P22(e#2)>, <P222(e#3)>, <P2222(e#4)>\n\
1296        'sk#0 -> e#0\n\
1297        sk#1[e#0] -> e#1\n\
1298        sk#5[e#1] -> e#2\n\
1299        sk#13[e#2] -> e#3\n\
1300        sk#29[e#3] -> e#4", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy35.raz"))));
1301        assert_eq!("Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1302        Facts: <Q(e#0, e#1)>, <Q1(e#2, e#3)>, <Q11(e#4, e#5)>, <Q111(e#6, e#7)>, <Q1111(e#8, e#9)>\n\
1303        'sk#0 -> e#0\n\
1304        'sk#1 -> e#1\n\
1305        sk#2[e#0, e#1] -> e#2\n\
1306        sk#3[e#0, e#1] -> e#3\n\
1307        sk#6[e#2, e#3] -> e#4\n\
1308        sk#7[e#2, e#3] -> e#5\n\
1309        sk#14[e#4, e#5] -> e#6\n\
1310        sk#15[e#4, e#5] -> e#7\n\
1311        sk#30[e#6, e#7] -> e#8\n\
1312        sk#31[e#6, e#7] -> e#9\n\
1313        -- -- -- -- -- -- -- -- -- --\n\
1314        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1315        Facts: <Q(e#0, e#1)>, <Q1(e#2, e#3)>, <Q11(e#4, e#5)>, <Q111(e#6, e#7)>, <Q1112(e#8, e#9)>\n\
1316        'sk#0 -> e#0\n\
1317        'sk#1 -> e#1\n\
1318        sk#2[e#0, e#1] -> e#2\n\
1319        sk#3[e#0, e#1] -> e#3\n\
1320        sk#6[e#2, e#3] -> e#4\n\
1321        sk#7[e#2, e#3] -> e#5\n\
1322        sk#14[e#4, e#5] -> e#6\n\
1323        sk#15[e#4, e#5] -> e#7\n\
1324        sk#30[e#6, e#7] -> e#8\n\
1325        sk#31[e#6, e#7] -> e#9\n\
1326        -- -- -- -- -- -- -- -- -- --\n\
1327        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1328        Facts: <Q(e#0, e#1)>, <Q1(e#2, e#3)>, <Q11(e#4, e#5)>, <Q112(e#6, e#7)>, <Q1121(e#8, e#9)>\n\
1329        'sk#0 -> e#0\n\
1330        'sk#1 -> e#1\n\
1331        sk#2[e#0, e#1] -> e#2\n\
1332        sk#3[e#0, e#1] -> e#3\n\
1333        sk#6[e#2, e#3] -> e#4\n\
1334        sk#7[e#2, e#3] -> e#5\n\
1335        sk#14[e#4, e#5] -> e#6\n\
1336        sk#15[e#4, e#5] -> e#7\n\
1337        sk#34[e#6, e#7] -> e#8\n\
1338        sk#35[e#6, e#7] -> e#9\n\
1339        -- -- -- -- -- -- -- -- -- --\n\
1340        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1341        Facts: <Q(e#0, e#1)>, <Q1(e#2, e#3)>, <Q11(e#4, e#5)>, <Q112(e#6, e#7)>, <Q1122(e#8, e#9)>\n\
1342        'sk#0 -> e#0\n\
1343        'sk#1 -> e#1\n\
1344        sk#2[e#0, e#1] -> e#2\n\
1345        sk#3[e#0, e#1] -> e#3\n\
1346        sk#6[e#2, e#3] -> e#4\n\
1347        sk#7[e#2, e#3] -> e#5\n\
1348        sk#14[e#4, e#5] -> e#6\n\
1349        sk#15[e#4, e#5] -> e#7\n\
1350        sk#34[e#6, e#7] -> e#8\n\
1351        sk#35[e#6, e#7] -> e#9\n\
1352        -- -- -- -- -- -- -- -- -- --\n\
1353        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1354        Facts: <Q(e#0, e#1)>, <Q1(e#2, e#3)>, <Q12(e#4, e#5)>, <Q121(e#6, e#7)>, <Q1211(e#8, e#9)>\n\
1355        'sk#0 -> e#0\n\
1356        'sk#1 -> e#1\n\
1357        sk#2[e#0, e#1] -> e#2\n\
1358        sk#3[e#0, e#1] -> e#3\n\
1359        sk#6[e#2, e#3] -> e#4\n\
1360        sk#7[e#2, e#3] -> e#5\n\
1361        sk#18[e#4, e#5] -> e#6\n\
1362        sk#19[e#4, e#5] -> e#7\n\
1363        sk#38[e#6, e#7] -> e#8\n\
1364        sk#39[e#6, e#7] -> e#9\n\
1365        -- -- -- -- -- -- -- -- -- --\n\
1366        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1367        Facts: <Q(e#0, e#1)>, <Q1(e#2, e#3)>, <Q12(e#4, e#5)>, <Q121(e#6, e#7)>, <Q1212(e#8, e#9)>\n\
1368        'sk#0 -> e#0\n\
1369        'sk#1 -> e#1\n\
1370        sk#2[e#0, e#1] -> e#2\n\
1371        sk#3[e#0, e#1] -> e#3\n\
1372        sk#6[e#2, e#3] -> e#4\n\
1373        sk#7[e#2, e#3] -> e#5\n\
1374        sk#18[e#4, e#5] -> e#6\n\
1375        sk#19[e#4, e#5] -> e#7\n\
1376        sk#38[e#6, e#7] -> e#8\n\
1377        sk#39[e#6, e#7] -> e#9\n\
1378        -- -- -- -- -- -- -- -- -- --\n\
1379        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1380        Facts: <Q(e#0, e#1)>, <Q1(e#2, e#3)>, <Q12(e#4, e#5)>, <Q122(e#6, e#7)>, <Q1221(e#8, e#9)>\n\
1381        'sk#0 -> e#0\n\
1382        'sk#1 -> e#1\n\
1383        sk#2[e#0, e#1] -> e#2\n\
1384        sk#3[e#0, e#1] -> e#3\n\
1385        sk#6[e#2, e#3] -> e#4\n\
1386        sk#7[e#2, e#3] -> e#5\n\
1387        sk#18[e#4, e#5] -> e#6\n\
1388        sk#19[e#4, e#5] -> e#7\n\
1389        sk#42[e#6, e#7] -> e#8\n\
1390        sk#43[e#6, e#7] -> e#9\n\
1391        -- -- -- -- -- -- -- -- -- --\n\
1392        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1393        Facts: <Q(e#0, e#1)>, <Q1(e#2, e#3)>, <Q12(e#4, e#5)>, <Q122(e#6, e#7)>, <Q1222(e#8, e#9)>\n\
1394        'sk#0 -> e#0\n\
1395        'sk#1 -> e#1\n\
1396        sk#2[e#0, e#1] -> e#2\n\
1397        sk#3[e#0, e#1] -> e#3\n\
1398        sk#6[e#2, e#3] -> e#4\n\
1399        sk#7[e#2, e#3] -> e#5\n\
1400        sk#18[e#4, e#5] -> e#6\n\
1401        sk#19[e#4, e#5] -> e#7\n\
1402        sk#42[e#6, e#7] -> e#8\n\
1403        sk#43[e#6, e#7] -> e#9\n\
1404        -- -- -- -- -- -- -- -- -- --\n\
1405        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1406        Facts: <Q(e#0, e#1)>, <Q2(e#2, e#3)>, <Q21(e#4, e#5)>, <Q211(e#6, e#7)>, <Q2111(e#8, e#9)>\n\
1407        'sk#0 -> e#0\n\
1408        'sk#1 -> e#1\n\
1409        sk#2[e#0, e#1] -> e#2\n\
1410        sk#3[e#0, e#1] -> e#3\n\
1411        sk#10[e#2, e#3] -> e#4\n\
1412        sk#11[e#2, e#3] -> e#5\n\
1413        sk#22[e#4, e#5] -> e#6\n\
1414        sk#23[e#4, e#5] -> e#7\n\
1415        sk#46[e#6, e#7] -> e#8\n\
1416        sk#47[e#6, e#7] -> e#9\n\
1417        -- -- -- -- -- -- -- -- -- --\n\
1418        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1419        Facts: <Q(e#0, e#1)>, <Q2(e#2, e#3)>, <Q21(e#4, e#5)>, <Q211(e#6, e#7)>, <Q2112(e#8, e#9)>\n\
1420        'sk#0 -> e#0\n\
1421        'sk#1 -> e#1\n\
1422        sk#2[e#0, e#1] -> e#2\n\
1423        sk#3[e#0, e#1] -> e#3\n\
1424        sk#10[e#2, e#3] -> e#4\n\
1425        sk#11[e#2, e#3] -> e#5\n\
1426        sk#22[e#4, e#5] -> e#6\n\
1427        sk#23[e#4, e#5] -> e#7\n\
1428        sk#46[e#6, e#7] -> e#8\n\
1429        sk#47[e#6, e#7] -> e#9\n\
1430        -- -- -- -- -- -- -- -- -- --\n\
1431        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1432        Facts: <Q(e#0, e#1)>, <Q2(e#2, e#3)>, <Q21(e#4, e#5)>, <Q212(e#6, e#7)>, <Q2121(e#8, e#9)>\n\
1433        'sk#0 -> e#0\n\
1434        'sk#1 -> e#1\n\
1435        sk#2[e#0, e#1] -> e#2\n\
1436        sk#3[e#0, e#1] -> e#3\n\
1437        sk#10[e#2, e#3] -> e#4\n\
1438        sk#11[e#2, e#3] -> e#5\n\
1439        sk#22[e#4, e#5] -> e#6\n\
1440        sk#23[e#4, e#5] -> e#7\n\
1441        sk#50[e#6, e#7] -> e#8\n\
1442        sk#51[e#6, e#7] -> e#9\n\
1443        -- -- -- -- -- -- -- -- -- --\n\
1444        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1445        Facts: <Q(e#0, e#1)>, <Q2(e#2, e#3)>, <Q21(e#4, e#5)>, <Q212(e#6, e#7)>, <Q2122(e#8, e#9)>\n\
1446        'sk#0 -> e#0\n\
1447        'sk#1 -> e#1\n\
1448        sk#2[e#0, e#1] -> e#2\n\
1449        sk#3[e#0, e#1] -> e#3\n\
1450        sk#10[e#2, e#3] -> e#4\n\
1451        sk#11[e#2, e#3] -> e#5\n\
1452        sk#22[e#4, e#5] -> e#6\n\
1453        sk#23[e#4, e#5] -> e#7\n\
1454        sk#50[e#6, e#7] -> e#8\n\
1455        sk#51[e#6, e#7] -> e#9\n\
1456        -- -- -- -- -- -- -- -- -- --\n\
1457        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1458        Facts: <Q(e#0, e#1)>, <Q2(e#2, e#3)>, <Q22(e#4, e#5)>, <Q221(e#6, e#7)>, <Q2211(e#8, e#9)>\n\
1459        'sk#0 -> e#0\n\
1460        'sk#1 -> e#1\n\
1461        sk#2[e#0, e#1] -> e#2\n\
1462        sk#3[e#0, e#1] -> e#3\n\
1463        sk#10[e#2, e#3] -> e#4\n\
1464        sk#11[e#2, e#3] -> e#5\n\
1465        sk#26[e#4, e#5] -> e#6\n\
1466        sk#27[e#4, e#5] -> e#7\n\
1467        sk#54[e#6, e#7] -> e#8\n\
1468        sk#55[e#6, e#7] -> e#9\n\
1469        -- -- -- -- -- -- -- -- -- --\n\
1470        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1471        Facts: <Q(e#0, e#1)>, <Q2(e#2, e#3)>, <Q22(e#4, e#5)>, <Q221(e#6, e#7)>, <Q2212(e#8, e#9)>\n\
1472        'sk#0 -> e#0\n\
1473        'sk#1 -> e#1\n\
1474        sk#2[e#0, e#1] -> e#2\n\
1475        sk#3[e#0, e#1] -> e#3\n\
1476        sk#10[e#2, e#3] -> e#4\n\
1477        sk#11[e#2, e#3] -> e#5\n\
1478        sk#26[e#4, e#5] -> e#6\n\
1479        sk#27[e#4, e#5] -> e#7\n\
1480        sk#54[e#6, e#7] -> e#8\n\
1481        sk#55[e#6, e#7] -> e#9\n\
1482        -- -- -- -- -- -- -- -- -- --\n\
1483        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1484        Facts: <Q(e#0, e#1)>, <Q2(e#2, e#3)>, <Q22(e#4, e#5)>, <Q222(e#6, e#7)>, <Q2221(e#8, e#9)>\n\
1485        'sk#0 -> e#0\n\
1486        'sk#1 -> e#1\n\
1487        sk#2[e#0, e#1] -> e#2\n\
1488        sk#3[e#0, e#1] -> e#3\n\
1489        sk#10[e#2, e#3] -> e#4\n\
1490        sk#11[e#2, e#3] -> e#5\n\
1491        sk#26[e#4, e#5] -> e#6\n\
1492        sk#27[e#4, e#5] -> e#7\n\
1493        sk#58[e#6, e#7] -> e#8\n\
1494        sk#59[e#6, e#7] -> e#9\n\
1495        -- -- -- -- -- -- -- -- -- --\n\
1496        Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1497        Facts: <Q(e#0, e#1)>, <Q2(e#2, e#3)>, <Q22(e#4, e#5)>, <Q222(e#6, e#7)>, <Q2222(e#8, e#9)>\n\
1498        'sk#0 -> e#0\n\
1499        'sk#1 -> e#1\n\
1500        sk#2[e#0, e#1] -> e#2\n\
1501        sk#3[e#0, e#1] -> e#3\n\
1502        sk#10[e#2, e#3] -> e#4\n\
1503        sk#11[e#2, e#3] -> e#5\n\
1504        sk#26[e#4, e#5] -> e#6\n\
1505        sk#27[e#4, e#5] -> e#7\n\
1506        sk#58[e#6, e#7] -> e#8\n\
1507        sk#59[e#6, e#7] -> e#9", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy36.raz"))));
1508        assert_eq!("", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy37.raz"))));
1509        assert_eq!("Domain: {e#0}\n\
1510                       Facts: <R(e#0, e#0, e#0)>\n\
1511                       'sk#0, 'sk#1, 'sk#2 -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy38.raz"))));
1512        assert_eq!("Domain: {e#0, e#1, e#2, e#3, e#4, e#5, e#6}\n\
1513                       Facts: <Q(e#1)>, <R(e#1, e#6)>\n\
1514                       'sk#0 -> e#0\n\
1515                       f[e#0] -> e#1\n\
1516                       f[e#1] -> e#2\n\
1517                       f[e#2] -> e#3\n\
1518                       f[e#3] -> e#4\n\
1519                       f[e#4] -> e#5\n\
1520                       f[e#5] -> e#6", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy39.raz"))));
1521        assert_eq!("Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1522        Facts: <P(e#1)>, <Q(e#1)>, <R(e#0, e#1)>, <R(e#1, e#3)>, <S(e#4)>\n\
1523        'sk#0 -> e#0\n\
1524        f[e#0] -> e#1\n\
1525        f[e#1] -> e#2\n\
1526        f[e#2] -> e#3\n\
1527        sk#1[e#1] -> e#4", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy40.raz"))));
1528        assert_eq!("Domain: {}\n\
1529                       Facts: \n", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy41.raz"))));
1530        assert_eq!("Domain: {e#0}\n\
1531        Facts: \n\
1532        'e, 'sk#0, f[e#0, e#0], i[e#0] -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy42.raz"))));
1533        assert_eq!("Domain: {e#0, e#1}\n\
1534        Facts: <P(e#0)>, <P(e#1)>, <Q(e#0)>, <Q(e#1)>\n\
1535        'a -> e#0\n\
1536        'b -> e#1", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy43.raz"))));
1537        assert_eq!("Domain: {e#0}\n\
1538        Facts: <P(e#0)>, <Q(e#0)>\n\
1539        'a -> e#0\n\
1540        -- -- -- -- -- -- -- -- -- --\n\
1541        Domain: {e#0}\n\
1542        Facts: <P(e#0)>, <R(e#0)>\n\
1543        'a -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy44.raz"))));
1544        assert_eq!("Domain: {e#0}\n\
1545        Facts: <P(e#0)>, <Q(e#0)>\n\
1546        'a, \'b -> e#0\n\
1547        -- -- -- -- -- -- -- -- -- --\n\
1548        Domain: {e#0, e#1}\n\
1549        Facts: <P(e#0)>, <Q(e#1)>, <R(e#0, e#1)>\n\
1550        'a -> e#0\n\
1551        'b -> e#1", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy45.raz"))));
1552        assert_eq!("Domain: {e#0}\n\
1553        Facts: <P(e#0)>, <Q(e#0)>, <R(e#0, e#0)>\n\
1554        'sk#0, 'sk#1 -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy46.raz"))));
1555        assert_eq!("Domain: {e#0}\n\
1556        Facts: <O(e#0)>, <P(e#0)>, <Q(e#0)>, <R(e#0)>, <S(e#0, e#0, e#0, e#0)>\n\
1557        'sk#0, 'sk#1, 'sk#2, 'sk#3 -> e#0", print_basic_models(solve_basic(&read_theory_from_file("../theories/core/thy47.raz"))));
1558    }
1559
1560    #[test]
1561    fn test_bounded() {
1562//        assert_eq!("Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1563//        Facts: <P(e#0)>, <P(e#1)>, <P(e#2)>, <P(e#3)>, <P(e#4)>\n\
1564//        'a -> e#0\n\
1565//        f[e#0] -> e#1\n\
1566//        f[e#1] -> e#2\n\
1567//        f[e#2] -> e#3\n\
1568//        f[e#3] -> e#4", print_basic_models(solve_domain_bounded_basic(&read_theory_from_file("../theories/bounded/thy0.raz"), 5)));
1569//        assert_eq!("Domain: {e#0, e#1, e#10, e#11, e#12, e#13, e#14, e#15, e#16, e#17, e#18, e#19, e#2, e#3, e#4, e#5, e#6, e#7, e#8, e#9}\n\
1570//        Facts: <P(e#0)>, <P(e#1)>, <P(e#10)>, <P(e#11)>, <P(e#12)>, <P(e#13)>, <P(e#14)>, <P(e#15)>, <P(e#16)>, <P(e#17)>, <P(e#18)>, <P(e#19)>, <P(e#2)>, <P(e#3)>, <P(e#4)>, <P(e#5)>, <P(e#6)>, <P(e#7)>, <P(e#8)>, <P(e#9)>\n\
1571//        'a -> e#0\n\
1572//        f[e#0] -> e#1\n\
1573//        f[e#1] -> e#2\n\
1574//        f[e#2] -> e#3\n\
1575//        f[e#3] -> e#4\n\
1576//        f[e#4] -> e#5\n\
1577//        f[e#5] -> e#6\n\
1578//        f[e#6] -> e#7\n\
1579//        f[e#7] -> e#8\n\
1580//        f[e#8] -> e#9\n\
1581//        f[e#9] -> e#10\n\
1582//        f[e#10] -> e#11\n\
1583//        f[e#11] -> e#12\n\
1584//        f[e#12] -> e#13\n\
1585//        f[e#13] -> e#14\n\
1586//        f[e#14] -> e#15\n\
1587//        f[e#15] -> e#16\n\
1588//        f[e#16] -> e#17\n\
1589//        f[e#17] -> e#18\n\
1590//        f[e#18] -> e#19", print_basic_models(solve_domain_bounded_basic(&read_theory_from_file("../theories/bounded/thy0.raz"), 20)));
1591//        assert_eq!("Domain: {e#0, e#1, e#2, e#3, e#4}\n\
1592//        Facts: <P(e#0)>, <P(e#1)>, <P(e#2)>, <P(e#3)>, <P(e#4)>\n\
1593//        'a -> e#0\n\
1594//        f[e#0] -> e#1\n\
1595//        f[e#1] -> e#2\n\
1596//        f[e#2] -> e#3\n\
1597//        f[e#3] -> e#4", print_basic_models(solve_domain_bounded_basic(&read_theory_from_file("../theories/bounded/thy2.raz"), 5)));
1598        assert_eq!(
1599            r#"Domain: {e#0}
1600Facts: <P(e#0)>, <Q(e#0)>
1601'sk#0 -> e#0"#,
1602            print_basic_models(solve_domain_bounded_basic(&read_theory_from_file("../theories/bounded/thy3.raz"), 5)));
1603        assert_eq!(
1604            r#"Domain: {e#0}
1605Facts: <P(e#0)>, <Q(e#0)>
1606'a -> e#0
1607-- -- -- -- -- -- -- -- -- --
1608Domain: {e#0, e#1}
1609Facts: <P(e#0)>, <P(e#1)>, <Q(e#1)>
1610'a -> e#0
1611sk#0[e#0] -> e#1
1612-- -- -- -- -- -- -- -- -- --
1613Domain: {e#0, e#1, e#2}
1614Facts: <P(e#0)>, <P(e#1)>, <P(e#2)>, <Q(e#2)>
1615'a -> e#0
1616sk#0[e#0] -> e#1
1617sk#0[e#1] -> e#2
1618-- -- -- -- -- -- -- -- -- --
1619Domain: {e#0, e#1, e#2, e#3}
1620Facts: <P(e#0)>, <P(e#1)>, <P(e#2)>, <P(e#3)>, <Q(e#3)>
1621'a -> e#0
1622sk#0[e#0] -> e#1
1623sk#0[e#1] -> e#2
1624sk#0[e#2] -> e#3
1625-- -- -- -- -- -- -- -- -- --
1626Domain: {e#0, e#1, e#2, e#3, e#4}
1627Facts: <P(e#0)>, <P(e#1)>, <P(e#2)>, <P(e#3)>, <P(e#4)>, <Q(e#4)>
1628'a -> e#0
1629sk#0[e#0] -> e#1
1630sk#0[e#1] -> e#2
1631sk#0[e#2] -> e#3
1632sk#0[e#3] -> e#4"#,
1633            print_basic_models(solve_domain_bounded_basic(&read_theory_from_file("../theories/bounded/thy4.raz"), 5)));
1634    }
1635}