From 5432c5cf5c1a1499bf5ff99ed3dfbb28532667e7 Mon Sep 17 00:00:00 2001 From: Salman Saghafi Date: Sun, 4 Dec 2022 22:56:35 -0800 Subject: [PATCH 1/3] refactoring CNF and DNF implementations Now CNF and DNF formulas can contain quantifiers, followed by a matrix that is in a normal form. Any PNF can be converted to a CNF and DNF without Skolemization. CNFClauseSet and DNFClauseSet are replacing the old CNF and DNF for a quantifier-free representation, obtained after Skolemization. --- razor-fol/src/transform.rs | 4 +- razor-fol/src/transform/cnf.rs | 492 +++++++++++++++++++++++++++------ razor-fol/src/transform/dnf.rs | 352 ++++++++++++++++------- razor-fol/src/transform/gnf.rs | 17 +- 4 files changed, 659 insertions(+), 206 deletions(-) diff --git a/razor-fol/src/transform.rs b/razor-fol/src/transform.rs index ac22701..313ec12 100644 --- a/razor-fol/src/transform.rs +++ b/razor-fol/src/transform.rs @@ -10,8 +10,8 @@ mod relational; mod simplify; mod snf; -pub use cnf::{ToCNF, CNF}; -pub use dnf::{ToDNF, DNF}; +pub use cnf::{CNFClauseSet, ToCNF, ToCNFClauseSet, CNF}; +pub use dnf::{DNFClauseSet, ToDNF, ToDNFClauseSet, DNF}; pub use gnf::{PcfSet, ToGNF, GNF, PCF}; pub use nnf::{ToNNF, NNF}; pub use pnf::{ToPNF, PNF}; diff --git a/razor-fol/src/transform/cnf.rs b/razor-fol/src/transform/cnf.rs index 49af7ee..85e2668 100644 --- a/razor-fol/src/transform/cnf.rs +++ b/razor-fol/src/transform/cnf.rs @@ -4,32 +4,102 @@ transforming an [`SNF`] to a [`CNF`]. [`SNF`]: crate::transform::SNF */ -use super::{ToSNF, SNF}; +use std::ops::Deref; + +use super::{ToPNF, ToSNF, PNF, SNF}; use crate::syntax::{ formula::{ clause::{Clause, ClauseSet, Literal}, - *, + Exists, Forall, FormulaEx, *, }, term::Complex, Error, Sig, Var, FOF, }; use itertools::Itertools; -use std::{collections::BTreeSet, ops::Deref}; // CNF clauses and clause sets are constructed over complex terms. type CNFClause = Clause; -type CNFClauseSet = ClauseSet; -/// Represents a formula in Conjunctive Normal Form (CNF). +#[derive(Clone)] +pub struct CNFClauseSet(ClauseSet); + +impl Deref for CNFClauseSet { + type Target = ClauseSet; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From> for CNFClauseSet { + fn from(value: ClauseSet) -> Self { + Self(value) + } +} + +impl Default for CNFClauseSet { + fn default() -> Self { + ClauseSet::default().into() + } +} + +/// Represents a [`PNF`] with a matrix in Conjunctive Normal Form (CNF). /// /// **Hint**: A CNF is a firsts-order formula that is a conjunction of zero or /// more [`Clause`]s where each clause is a disjunction of [`Literal`]s. #[derive(Clone, Debug)] -pub struct CNF(CNFClauseSet); +pub enum CNF { + /// Is the quantifier-free portion of a [`PNF`]. + Clauses(ClauseSet), + + /// Is an existentially quantified PNF, wrapping an [`Exists`]. + Exists(Box>), + + /// Is a universally quantified PNF, wrapping a [`Forall`]. + Forall(Box>), +} + +impl CNF { + fn clause_to_fof(clause: CNFClause) -> FOF { + clause + .into_literals() + .into_iter() + .sorted() + .into_iter() + .map(|clause| match clause { + Literal::Pos(pos) => match pos { + Atomic::Atom(this) => this.into(), + Atomic::Equals(this) => this.into(), + }, + Literal::Neg(neg) => match neg { + Atomic::Atom(this) => FOF::not(this.into()), + Atomic::Equals(this) => FOF::not(this.into()), + }, + }) + .fold1(|item, acc| item.or(acc)) + .unwrap_or(FOF::Bottom) + } +} + +impl FormulaEx for CNF { + fn precedence(&self) -> u8 { + match self { + Self::Clauses(_) => PRECEDENCE_AND, + Self::Exists(this) => this.precedence(), + Self::Forall(this) => this.precedence(), + } + } +} + +impl From> for CNF { + fn from(value: ClauseSet) -> Self { + Self::Clauses(value) + } +} impl From for CNF { fn from(value: CNFClauseSet) -> Self { - Self(value) + value.0.into() } } @@ -49,20 +119,19 @@ pub trait ToCNF: Formula { fn cnf(&self) -> CNF; } -impl ToCNF for SNF { +impl ToCNF for PNF { fn cnf(&self) -> CNF { use super::ToNNF; - // Compromising type safety to avoid implementing a number of - // types arising from pairwise combinations of PNF, SNF and NNF: + // types arising from pairwise combinations of PNF, NNF and NNF: let nnf = FOF::from(self.clone()).nnf(); cnf(distribute_or(&nnf.into())) } } -impl ToCNF for T { +impl ToCNF for T { fn cnf(&self) -> CNF { - self.snf().cnf() + self.pnf().cnf() } } @@ -72,44 +141,47 @@ impl From for CNF { } } -impl CNF { - /// Returns the clauses of `self`. - #[inline(always)] - pub fn clauses(&self) -> &BTreeSet { - &self.0 - } +/// Is the trait of [`Formula`] types that can be transformed to [`CNFClauseSet`]. +/// Unlike a [`CNF`], a [`CNFClauseSet`] is quantifier-free; that is, assuming +/// free-variables are universally quantified, the input must be Skolemized (see [`SNF`]). +pub trait ToCNFClauseSet: Formula { + /// Transform `self` to a Conjunctive Normal Form (CNF) clause set. + /// + /// **Example**: + /// ```rust + /// # use razor_fol::syntax::FOF; + /// use razor_fol::transform::ToCNFClauseSet; + /// + /// let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + /// let clauses = formula.cnf_clause_set(); + /// assert_eq!("(P(x) ∨ ¬Q(y)) ∧ (Q(y) ∨ ¬P(x))", clauses.to_string()); + /// ``` + fn cnf_clause_set(&self) -> CNFClauseSet; +} - /// Consumes `self` and returns the underlying set of clauses. - pub fn into_clauses(self) -> BTreeSet { - self.0.into_clauses() +impl ToCNFClauseSet for SNF { + fn cnf_clause_set(&self) -> CNFClauseSet { + use super::ToNNF; + let nnf = FOF::from(self.clone()).nnf(); + cnf_clause_set(distribute_or(&nnf.into())) } +} - fn clause_to_fof(clause: CNFClause) -> FOF { - clause - .into_literals() - .into_iter() - .sorted() - .into_iter() - .map(|clause| match clause { - Literal::Pos(pos) => match pos { - Atomic::Atom(this) => this.into(), - Atomic::Equals(this) => this.into(), - }, - Literal::Neg(neg) => match neg { - Atomic::Atom(this) => FOF::not(this.into()), - Atomic::Equals(this) => FOF::not(this.into()), - }, - }) - .fold1(|item, acc| item.or(acc)) - .unwrap_or(FOF::Bottom) +impl ToCNFClauseSet for T { + fn cnf_clause_set(&self) -> CNFClauseSet { + self.snf().cnf_clause_set() } } -impl Deref for CNF { - type Target = CNFClauseSet; +impl From for CNFClauseSet { + fn from(value: T) -> Self { + value.cnf_clause_set() + } +} - fn deref(&self) -> &Self::Target { - &self.0 +impl std::fmt::Display for CNFClauseSet { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + FOF::from(self).fmt(f) } } @@ -129,28 +201,37 @@ impl Formula for CNF { type Term = Complex; fn signature(&self) -> Result { - self.0.signature() + match self { + Self::Clauses(this) => this.signature(), + Self::Exists(this) => this.signature(), + Self::Forall(this) => this.signature(), + } } fn free_vars(&self) -> Vec<&Var> { - self.0.free_vars() + match self { + Self::Clauses(this) => this.free_vars(), + Self::Exists(this) => this.free_vars(), + Self::Forall(this) => this.free_vars(), + } } fn transform_term(&self, f: &impl Fn(&Complex) -> Complex) -> Self { - Self(self.0.transform_term(f)) + match self { + Self::Clauses(this) => this.transform_term(f).into(), + Self::Exists(this) => Self::Exists(Box::new(this.transform_term(f))), + Self::Forall(this) => Self::Forall(Box::new(this.transform_term(f))), + } } } impl From for FOF { fn from(value: CNF) -> Self { - value - .into_clauses() - .into_iter() - .sorted() - .into_iter() - .map(CNF::clause_to_fof) - .fold1(|item, acc| item.and(acc)) - .unwrap_or(FOF::Top) + match value { + CNF::Clauses(this) => clause_set_to_fof(this), + CNF::Exists(this) => FOF::exists(this.variables, this.formula.into()), + CNF::Forall(this) => FOF::forall(this.variables, this.formula.into()), + } } } @@ -160,6 +241,28 @@ impl From<&CNF> for FOF { } } +fn clause_set_to_fof(value: ClauseSet) -> FOF { + value + .into_iter() + .sorted() + .into_iter() + .map(CNF::clause_to_fof) + .fold1(|item, acc| item.and(acc)) + .unwrap_or(FOF::Top) +} + +impl From for FOF { + fn from(value: CNFClauseSet) -> Self { + clause_set_to_fof(value.0) + } +} + +impl From<&CNFClauseSet> for FOF { + fn from(value: &CNFClauseSet) -> Self { + value.clone().into() + } +} + // Distributes conjunctions in the given formula. // The function assumes that its input is in NNF and SNF. fn distribute_or(formula: &FOF) -> FOF { @@ -184,48 +287,49 @@ fn distribute_or(formula: &FOF) -> FOF { } } FOF::Forall(this) => FOF::forall(this.variables.clone(), distribute_or(&this.formula)), + FOF::Exists(this) => FOF::exists(this.variables.clone(), distribute_or(&this.formula)), _ => unreachable!(), // `formula` is both in SNF and NNF } } -fn cnf(formula: FOF) -> CNF { +fn clause_set(formula: FOF) -> ClauseSet { match formula { - FOF::Top => CNF::default(), - FOF::Bottom => ClauseSet::from(Clause::default()).into(), + FOF::Top => ClauseSet::default(), + FOF::Bottom => ClauseSet::from(Clause::default()), FOF::Atom(this) => { let clause = Clause::from(Literal::from(this)); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } FOF::Equals(this) => { let clause = Clause::from(Literal::from(this)); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } FOF::Not(this) => match this.formula { FOF::Atom(atom) => { let lit: Literal<_> = Not { formula: atom }.into(); let clause = Clause::from(lit); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } FOF::Equals(eq) => { let lit: Literal<_> = Not { formula: eq }.into(); let clause = Clause::from(lit); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } _ => unreachable!(), // `formula` is in NNF }, FOF::And(this) => { - let left = cnf(this.left); - let right = cnf(this.right); - left.0.union(&right.0).into() + let left = clause_set(this.left); + let right = clause_set(this.right); + left.union(&right) } FOF::Or(this) => { - let left = cnf(this.left); - let right = cnf(this.right); - if left.0.is_empty() { - left - } else if right.0.is_empty() { - right - } else if left.0.len() == 1 && right.0.len() == 1 { + let left = clause_set(this.left); + let right = clause_set(this.right); + if left.is_empty() { + left.into() + } else if right.is_empty() { + right.into() + } else if left.len() == 1 && right.len() == 1 { let left = left.into_clauses().into_iter().next().unwrap(); let right = right.into_clauses().into_iter().next().unwrap(); let clause = left.union(&right); @@ -234,8 +338,29 @@ fn cnf(formula: FOF) -> CNF { unreachable!() // Disjunction is distributed over conjunction in `formula` } } - FOF::Forall(this) => cnf(this.formula), - _ => unreachable!(), // `formula` is in SNF + _ => unreachable!(), // `formula` is in PNF + } +} + +fn cnf_clause_set(formula: FOF) -> CNFClauseSet { + match formula { + FOF::Forall(this) => cnf_clause_set(this.formula), + FOF::Exists(this) => cnf_clause_set(this.formula), + _ => clause_set(formula).into(), + } +} + +fn cnf(formula: FOF) -> CNF { + match formula { + FOF::Forall(this) => CNF::Forall(Box::new(Forall { + variables: this.variables, + formula: cnf(this.formula), + })), + FOF::Exists(this) => CNF::Exists(Box::new(Exists { + variables: this.variables, + formula: cnf(this.formula), + })), + _ => CNF::Clauses(clause_set(formula)), } } @@ -252,7 +377,11 @@ mod tests { }; fn cnf(formula: &FOF) -> FOF { - formula.snf().cnf().into() + formula.pnf().cnf().into() + } + + fn cnf_clause_set(formula: &FOF) -> FOF { + formula.snf().cnf_clause_set().into() } #[test] @@ -295,11 +424,11 @@ mod tests { } { let formula: FOF = "!x. P(x)".parse().unwrap(); - assert_debug_string!("P(x)", cnf(&formula)); + assert_debug_string!("! x. P(x)", cnf(&formula)); } { let formula: FOF = "!x. P(f(), g(f(), x))".parse().unwrap(); - assert_debug_string!("P(f(), g(f(), x))", cnf(&formula)); + assert_debug_string!("! x. P(f(), g(f(), x))", cnf(&formula)); } // quantifier-free formulae { @@ -344,42 +473,45 @@ mod tests { //random formulae { let formula: FOF = "?x. P(x)".parse().unwrap(); - assert_debug_string!("P('c#0)", cnf(&formula)); + assert_debug_string!("? x. P(x)", cnf(&formula)); } { let formula: FOF = "?x. (P(x) & Q(f(), x))".parse().unwrap(); - assert_debug_string!("P('c#0) & Q(f(), 'c#0)", cnf(&formula)); + assert_debug_string!("? x. (P(x) & Q(f(), x))", cnf(&formula)); } { let formula: FOF = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); - assert_debug_string!("(R(x) | ~P(y)) | ~Q(x, y)", cnf(&formula)); + assert_debug_string!("! x. (! y. ((R(x) | ~P(y)) | ~Q(x, y)))", cnf(&formula)); } { let formula: FOF = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); - assert_debug_string!("(~P(x) | ~Q(y)) | ~R(x, y)", cnf(&formula)); + assert_debug_string!("! x. (! y. ((~P(x) | ~Q(y)) | ~R(x, y)))", cnf(&formula)); } { let formula: FOF = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); - assert_debug_string!("(Q(y) | ~P(y, x)) & (Q(y) | ~Q(x))", cnf(&formula)); + assert_debug_string!( + "! y. (! x. ((Q(y) | ~P(y, x)) & (Q(y) | ~Q(x))))", + cnf(&formula) + ); } { let formula: FOF = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); assert_debug_string!( - "(Q(y) | ~P(y, f#0(y))) & (Q(y) | ~Q(f#0(y)))", + "! y. (? x. ((Q(y) | ~P(y, x)) & (Q(y) | ~Q(x))))", cnf(&formula), ); } { let formula: FOF = "?x. ?y. P(x, y)".parse().unwrap(); - assert_debug_string!("P('c#0, 'c#1)", cnf(&formula)); + assert_debug_string!("? x. (? y. P(x, y))", cnf(&formula)); } { let formula: FOF = "?x, y. P(x, y)".parse().unwrap(); - assert_debug_string!("P('c#0, 'c#1)", cnf(&formula)); + assert_debug_string!("? x, y. P(x, y)", cnf(&formula)); } { let formula: FOF = "!x. ?y. P(x, y)".parse().unwrap(); - assert_debug_string!("P(x, f#0(x))", cnf(&formula)); + assert_debug_string!("! x. (? y. P(x, y))", cnf(&formula)); } { let formula: FOF = @@ -387,7 +519,7 @@ mod tests { .parse() .unwrap(); assert_debug_string!( - "((P(f#0(z), x) | ~R(z)) & (~Q(u`, x`, y) | ~R(z))) & (~R(z) | ~(w = f(u`)))", + "? u. (! x, y. (! u`, x`, w. (((P(u, x) | ~R(z)) & (~Q(u`, x`, y) | ~R(z))) & (~R(z) | ~(w = f(u`))))))", cnf(&formula) ); } @@ -396,7 +528,7 @@ mod tests { .parse() .unwrap(); assert_debug_string!( - "(P(y) | Q(f#0(x, y), x)) & (Q(f#0(x, y), x) | ~Q(x, y))", + "! x. (! y. (? y`. ((P(y) | Q(y`, x)) & (Q(y`, x) | ~Q(x, y)))))", cnf(&formula), ); } @@ -405,7 +537,7 @@ mod tests { .parse() .unwrap(); assert_debug_string!( - "(P(f#0(x)) | Q(f#1(x), x)) & (Q(f#1(x), x) | ~Q(x, f#0(x)))", + "! x. (? y. (? y`. ((P(y) | Q(y`, x)) & (Q(y`, x) | ~Q(x, y)))))", cnf(&formula), ); } @@ -414,7 +546,7 @@ mod tests { .parse() .unwrap(); assert_debug_string!( - "P(\'c#0) & ((y = z | ~Q(\'c#0, y)) | ~Q(\'c#0, z))", + "? x. (! y, z. (P(x) & ((y = z | ~Q(x, y)) | ~Q(x, z))))", cnf(&formula), ); } @@ -423,7 +555,187 @@ mod tests { .parse() .unwrap(); assert_debug_string!( - "(((P(f(x, y)) | ~P(x)) | ~P(y)) & (Q(x, f#0(x, y)) | ~P(x))) & (~P(x) | ~P(f#0(x, y)))", cnf(&formula)); + "! x. (! y. (? y`. ((((P(f(x, y)) | ~P(x)) | ~P(y)) & (Q(x, y`) | ~P(x))) & (~P(x) | ~P(y`)))))", + cnf(&formula)); + } + } + + #[test] + fn test_cnf_clause_set() { + { + let formula: FOF = "true".parse().unwrap(); + assert_debug_string!("true", cnf_clause_set(&formula)); + } + { + let formula: FOF = "false".parse().unwrap(); + assert_debug_string!("false", cnf_clause_set(&formula)); + } + { + let formula: FOF = "P(f(), g(f(), f()))".parse().unwrap(); + assert_debug_string!("P(f(), g(f(), f()))", cnf_clause_set(&formula)); + } + { + let formula: FOF = "P(x)".parse().unwrap(); + assert_debug_string!("P(x)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "x=y".parse().unwrap(); + assert_debug_string!("x = y", cnf_clause_set(&formula)); + } + { + let formula: FOF = "P(x) & Q(y)".parse().unwrap(); + assert_debug_string!("P(x) & Q(y)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "P(x) | Q(y)".parse().unwrap(); + assert_debug_string!("P(x) | Q(y)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "P(x) -> Q(y)".parse().unwrap(); + assert_debug_string!("Q(y) | ~P(x)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + assert_debug_string!("(P(x) | ~Q(y)) & (Q(y) | ~P(x))", cnf_clause_set(&formula)); + } + { + let formula: FOF = "!x. P(x)".parse().unwrap(); + assert_debug_string!("P(x)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "!x. P(f(), g(f(), x))".parse().unwrap(); + assert_debug_string!("P(f(), g(f(), x))", cnf_clause_set(&formula)); + } + // quantifier-free formulae + { + let formula: FOF = "~((P(x1) | P(x2)) and Q(y))".parse().unwrap(); + assert_debug_string!( + "(~P(x1) | ~Q(y)) & (~P(x2) | ~Q(y))", + cnf_clause_set(&formula) + ); + } + { + let formula: FOF = "P(x) | ~(Q(x) -> Q(y))".parse().unwrap(); + assert_debug_string!("(P(x) | Q(x)) & (P(x) | ~Q(y))", cnf_clause_set(&formula)); + } + { + let formula: FOF = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); + assert_debug_string!("(R(z) | ~P(x)) & (R(z) | ~Q(y))", cnf_clause_set(&formula)); + } + { + let formula: FOF = "P(x) | ~(Q(x) <=> Q(y))".parse().unwrap(); + assert_debug_string!( + "((((P(x) | Q(x)) | Q(y)) & ((P(x) | Q(x)) | ~Q(x))) & ((P(x) | Q(y)) | ~Q(y))) & ((P(x) | ~Q(x)) | ~Q(y))", + cnf_clause_set(&formula)); + } + { + let formula: FOF = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); + assert_debug_string!( + "(((P(x) | Q(y)) | ~R(z)) & (R(z) | ~P(x))) & (R(z) | ~Q(y))", + cnf_clause_set(&formula), + ); + } + { + let formula: FOF = "P(x) | (Q(x) | (R(y) & R(z)))".parse().unwrap(); + assert_debug_string!( + "((P(x) | Q(x)) | R(y)) & ((P(x) | Q(x)) | R(z))", + cnf_clause_set(&formula), + ); + } + { + let formula: FOF = "(P(x1) & P(x2)) | (Q(x1) & Q(x2))".parse().unwrap(); + assert_debug_string!( + "(((P(x1) | Q(x1)) & (P(x1) | Q(x2))) & (P(x2) | Q(x1))) & (P(x2) | Q(x2))", + cnf_clause_set(&formula), + ); + } + //random formulae + { + let formula: FOF = "?x. P(x)".parse().unwrap(); + assert_debug_string!("P('c#0)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "?x. (P(x) & Q(f(), x))".parse().unwrap(); + assert_debug_string!("P('c#0) & Q(f(), 'c#0)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); + assert_debug_string!("(R(x) | ~P(y)) | ~Q(x, y)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); + assert_debug_string!("(~P(x) | ~Q(y)) | ~R(x, y)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); + assert_debug_string!( + "(Q(y) | ~P(y, x)) & (Q(y) | ~Q(x))", + cnf_clause_set(&formula) + ); + } + { + let formula: FOF = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); + assert_debug_string!( + "(Q(y) | ~P(y, f#0(y))) & (Q(y) | ~Q(f#0(y)))", + cnf_clause_set(&formula), + ); + } + { + let formula: FOF = "?x. ?y. P(x, y)".parse().unwrap(); + assert_debug_string!("P('c#0, 'c#1)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "?x, y. P(x, y)".parse().unwrap(); + assert_debug_string!("P('c#0, 'c#1)", cnf_clause_set(&formula)); + } + { + let formula: FOF = "!x. ?y. P(x, y)".parse().unwrap(); + assert_debug_string!("P(x, f#0(x))", cnf_clause_set(&formula)); + } + { + let formula: FOF = + "R(z) -> ?u. (!x, y. (P(u, x) & ~? u, x, w. (Q(u, x, y) | (w = f(u)))))" + .parse() + .unwrap(); + assert_debug_string!( + "((P(f#0(z), x) | ~R(z)) & (~Q(u`, x`, y) | ~R(z))) & (~R(z) | ~(w = f(u`)))", + cnf_clause_set(&formula) + ); + } + { + let formula: FOF = "!x. (!y. (P(y) -> Q(x, y)) -> ?y. Q(y, x))" + .parse() + .unwrap(); + assert_debug_string!( + "(P(y) | Q(f#0(x, y), x)) & (Q(f#0(x, y), x) | ~Q(x, y))", + cnf_clause_set(&formula), + ); + } + { + let formula: FOF = "!x. ((!y. (P(y) -> Q(x, y))) -> ?y. Q(y, x))" + .parse() + .unwrap(); + assert_debug_string!( + "(P(f#0(x)) | Q(f#1(x), x)) & (Q(f#1(x), x) | ~Q(x, f#0(x)))", + cnf_clause_set(&formula), + ); + } + { + let formula: FOF = "?x. (!y, z. (P(x) & ((Q(x, y) & ~(y = z)) -> ~Q(x, z))))" + .parse() + .unwrap(); + assert_debug_string!( + "P('c#0) & ((y = z | ~Q('c#0, y)) | ~Q('c#0, z))", + cnf_clause_set(&formula), + ); + } + { + let formula: FOF = "!x. (P(x) -> (!y. (P(y) -> P(f(x, y))) & ~!y. (Q(x, y) -> P(y))))" + .parse() + .unwrap(); + assert_debug_string!( + "(((P(f(x, y)) | ~P(x)) | ~P(y)) & (Q(x, f#0(x, y)) | ~P(x))) & (~P(x) | ~P(f#0(x, y)))", + cnf_clause_set(&formula)); } } diff --git a/razor-fol/src/transform/dnf.rs b/razor-fol/src/transform/dnf.rs index 4d78d1c..ada8a61 100644 --- a/razor-fol/src/transform/dnf.rs +++ b/razor-fol/src/transform/dnf.rs @@ -4,32 +4,95 @@ transforming an [`SNF`] to a [`DNF`]. [`SNF`]: crate::transform::SNF */ -use super::{ToSNF, SNF}; +use std::ops::Deref; + +use super::{ToPNF, ToSNF, PNF, SNF}; use crate::syntax::{ formula::{ clause::{Clause, ClauseSet, Literal}, - *, + Exists, Forall, *, }, term::Complex, Error, Sig, Var, FOF, }; use itertools::Itertools; -use std::{collections::BTreeSet, ops::Deref}; // DNF clauses and clause sets are constructed over complex terms. type DNFClause = Clause; -type DNFClauseSet = ClauseSet; +#[derive(Clone)] +pub struct DNFClauseSet(ClauseSet); + +impl From> for DNFClauseSet { + fn from(value: ClauseSet) -> Self { + Self(value) + } +} + +impl Deref for DNFClauseSet { + type Target = ClauseSet; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} -/// Represents a formula in Disjunctive Normal Form (DNF). +/// Represents a [`PNF`] with a matrix in Disjunctive Normal Form (DNF). /// /// **Hint**: A DNF is a firsts-order formula that is a disjunction of zero or /// more [`Clause`]s where each clause is a conjunction of [`Literal`]s. #[derive(Clone)] -pub struct DNF(DNFClauseSet); +pub enum DNF { + /// Is the quantifier-free portion of a [`PNF`]. + Clauses(ClauseSet), + + /// Is an existentially quantified PNF, wrapping an [`Exists`]. + Exists(Box>), + + /// Is a universally quantified PNF, wrapping a [`Forall`]. + Forall(Box>), +} + +impl DNF { + fn clause_to_fof(clause: DNFClause) -> FOF { + clause + .into_literals() + .into_iter() + .sorted() + .into_iter() + .map(|clause| match clause { + Literal::Pos(pos) => match pos { + Atomic::Atom(this) => this.into(), + Atomic::Equals(this) => this.into(), + }, + Literal::Neg(neg) => match neg { + Atomic::Atom(this) => FOF::not(this.into()), + Atomic::Equals(this) => FOF::not(this.into()), + }, + }) + .fold1(|item, acc| item.and(acc)) + .unwrap_or(FOF::Top) + } +} + +impl FormulaEx for DNF { + fn precedence(&self) -> u8 { + match self { + DNF::Clauses(_) => PRECEDENCE_OR, + DNF::Exists(this) => this.precedence(), + DNF::Forall(this) => this.precedence(), + } + } +} + +impl From> for DNF { + fn from(value: ClauseSet) -> Self { + Self::Clauses(value) + } +} impl From for DNF { fn from(value: DNFClauseSet) -> Self { - DNF(value) + value.0.into() } } @@ -53,7 +116,7 @@ pub trait ToDNF: Formula { fn dnf(&self) -> DNF; } -impl ToDNF for SNF { +impl ToDNF for PNF { fn dnf(&self) -> DNF { use super::ToNNF; @@ -64,9 +127,9 @@ impl ToDNF for SNF { } } -impl ToDNF for T { +impl ToDNF for T { fn dnf(&self) -> DNF { - self.snf().dnf() + self.pnf().dnf() } } @@ -76,44 +139,51 @@ impl From for DNF { } } -impl DNF { - /// Returns the clauses of `self`. - #[inline(always)] - pub fn clauses(&self) -> &BTreeSet { - &self.0 - } +/// Is the trait of [`Formula`] types that can be transformed to [`DNFClauseSet`]. +/// Unlike a [`DNF`], a [`DNFClauseSet`] is quantifier-free; that is, assuming +/// free-variables are universally quantified, the input must be Skolemized (see [`SNF`]). +pub trait ToDNFClauseSet: Formula { + /// Transform `self` to a Conjunctive Normal Form (DNF) clause set. + /// + /// **Example**: + /// ```rust + /// # use razor_fol::syntax::FOF; + /// use razor_fol::transform::ToDNFClauseSet; + /// + /// let formula: FOF = "P(x) iff Q(y)".parse().unwrap(); + /// let clauses = formula.dnf_clause_set(); + /// + /// assert_eq!( + /// "(((P(x) ∧ Q(y)) ∨ (P(x) ∧ ¬P(x))) ∨ (Q(y) ∧ ¬Q(y))) ∨ (¬P(x) ∧ ¬Q(y))", + /// clauses.to_string() + /// ); + /// ``` + fn dnf_clause_set(&self) -> DNFClauseSet; +} - /// Consumes `self` and returns the underlying clauses. - pub fn into_clauses(self) -> BTreeSet { - self.0.into_clauses() +impl ToDNFClauseSet for SNF { + fn dnf_clause_set(&self) -> DNFClauseSet { + use super::ToNNF; + let nnf = FOF::from(self.clone()).nnf(); + dnf_clause_set(distribute_and(&nnf.into())) } +} - fn clause_to_fof(clause: DNFClause) -> FOF { - clause - .into_literals() - .into_iter() - .sorted() - .into_iter() - .map(|clause| match clause { - Literal::Pos(pos) => match pos { - Atomic::Atom(this) => this.into(), - Atomic::Equals(this) => this.into(), - }, - Literal::Neg(neg) => match neg { - Atomic::Atom(this) => FOF::not(this.into()), - Atomic::Equals(this) => FOF::not(this.into()), - }, - }) - .fold1(|item, acc| item.and(acc)) - .unwrap_or(FOF::Top) +impl ToDNFClauseSet for T { + fn dnf_clause_set(&self) -> DNFClauseSet { + self.snf().dnf_clause_set() } } -impl Deref for DNF { - type Target = DNFClauseSet; +impl From for DNFClauseSet { + fn from(value: T) -> Self { + value.dnf_clause_set() + } +} - fn deref(&self) -> &Self::Target { - &self.0 +impl std::fmt::Display for DNFClauseSet { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + FOF::from(self).fmt(f) } } @@ -125,7 +195,7 @@ impl std::fmt::Display for DNF { impl Default for DNF { fn default() -> Self { - DNF::from(ClauseSet::<_>::default()) + Self::Clauses(ClauseSet::<_>::default().into()) } } @@ -133,28 +203,37 @@ impl Formula for DNF { type Term = Complex; fn signature(&self) -> Result { - self.0.signature() + match self { + Self::Clauses(this) => this.signature(), + Self::Exists(this) => this.signature(), + Self::Forall(this) => this.signature(), + } } fn free_vars(&self) -> Vec<&Var> { - self.0.free_vars() + match self { + Self::Clauses(this) => this.free_vars(), + Self::Exists(this) => this.free_vars(), + Self::Forall(this) => this.free_vars(), + } } fn transform_term(&self, f: &impl Fn(&Complex) -> Complex) -> Self { - DNF(self.0.transform_term(f)) + match self { + Self::Clauses(this) => this.transform_term(f).into(), + Self::Exists(this) => Self::Exists(Box::new(this.transform_term(f))), + Self::Forall(this) => Self::Forall(Box::new(this.transform_term(f))), + } } } impl From for FOF { fn from(value: DNF) -> Self { - value - .into_clauses() - .into_iter() - .sorted() - .into_iter() - .map(DNF::clause_to_fof) - .fold1(|item, acc| item.or(acc)) - .unwrap_or(FOF::Bottom) + match value { + DNF::Clauses(this) => clause_set_to_fof(this), + DNF::Exists(this) => FOF::exists(this.variables, this.formula.into()), + DNF::Forall(this) => FOF::forall(this.variables, this.formula.into()), + } } } @@ -164,6 +243,28 @@ impl From<&DNF> for FOF { } } +fn clause_set_to_fof(value: ClauseSet) -> FOF { + value + .into_iter() + .sorted() + .into_iter() + .map(DNF::clause_to_fof) + .fold1(|item, acc| item.or(acc)) + .unwrap_or(FOF::Bottom) +} + +impl From for FOF { + fn from(value: DNFClauseSet) -> Self { + clause_set_to_fof(value.0) + } +} + +impl From<&DNFClauseSet> for FOF { + fn from(value: &DNFClauseSet) -> Self { + value.clone().into() + } +} + // Distributes disjunction in the given formula. The function assumes that its input is an NNF. fn distribute_and(formula: &FOF) -> FOF { match formula { @@ -186,61 +287,83 @@ fn distribute_and(formula: &FOF) -> FOF { } } FOF::Forall(this) => FOF::forall(this.variables.clone(), distribute_and(&this.formula)), - _ => unreachable!(), // NNF input + FOF::Exists(this) => FOF::exists(this.variables.clone(), distribute_and(&this.formula)), + _ => unreachable!(), // `formula` is both in SNF and NNF } } -fn dnf(formula: FOF) -> DNF { +fn clause_set(formula: FOF) -> ClauseSet { match formula { - FOF::Top => ClauseSet::from(Clause::default()).into(), - FOF::Bottom => DNF::default(), + FOF::Top => ClauseSet::from(Clause::default()), + FOF::Bottom => ClauseSet::default(), FOF::Atom(this) => { let clause = Clause::from(Literal::from(this)); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } FOF::Equals(this) => { let clause = Clause::from(Literal::from(this)); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } FOF::Not(this) => match this.formula { FOF::Atom(atom) => { let lit: Literal<_> = Not { formula: atom }.into(); let clause = Clause::from(lit); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } FOF::Equals(eq) => { let lit: Literal<_> = Not { formula: eq }.into(); let clause = Clause::from(lit); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } _ => unreachable!(), // `formula` is in NNF }, FOF::And(this) => { - let left = dnf(this.left); - let right = dnf(this.right); - if left.0.is_empty() { + let left = clause_set(this.left); + let right = clause_set(this.right); + if left.is_empty() { left - } else if right.0.is_empty() { + } else if right.is_empty() { right - } else if left.0.len() == 1 && right.0.len() == 1 { + } else if left.len() == 1 && right.len() == 1 { let left = left.into_clauses().into_iter().next().unwrap(); let right = right.into_clauses().into_iter().next().unwrap(); let clause = left.union(&right); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } else { unreachable!() // Conjunction is distributed over disjunction in `formula` } } FOF::Or(this) => { - let left = dnf(this.left); - let right = dnf(this.right); - left.0.union(&right.0).into() + let left = clause_set(this.left); + let right = clause_set(this.right); + left.union(&right) } - FOF::Forall(this) => dnf(this.formula), _ => unreachable!(), // `formula` is in SNF } } +fn dnf_clause_set(formula: FOF) -> DNFClauseSet { + match formula { + FOF::Exists(this) => dnf_clause_set(this.formula), + FOF::Forall(this) => dnf_clause_set(this.formula), + _ => clause_set(formula).into(), + } +} + +fn dnf(formula: FOF) -> DNF { + match formula { + FOF::Forall(this) => DNF::Forall(Box::new(Forall { + variables: this.variables, + formula: dnf(this.formula), + })), + FOF::Exists(this) => DNF::Exists(Box::new(Exists { + variables: this.variables, + formula: dnf(this.formula), + })), + _ => DNF::Clauses(clause_set(formula)), + } +} + #[cfg(test)] mod tests { use super::*; @@ -253,126 +376,135 @@ mod tests { term, v, }; - fn dnf(formula: &FOF) -> FOF { - formula.snf().dnf().into() + fn dnf_clause_set(formula: &FOF) -> FOF { + formula.snf().dnf_clause_set().into() } #[test] fn test_dnf() { { let formula: FOF = "true".parse().unwrap(); - assert_debug_string!("true", dnf(&formula)); + assert_debug_string!("true", dnf_clause_set(&formula)); } { let formula: FOF = "false".parse().unwrap(); - assert_debug_string!("false", dnf(&formula)); + assert_debug_string!("false", dnf_clause_set(&formula)); } { let formula: FOF = "P(f(), g(f(), f()))".parse().unwrap(); - assert_debug_string!("P(f(), g(f(), f()))", dnf(&formula)); + assert_debug_string!("P(f(), g(f(), f()))", dnf_clause_set(&formula)); } { let formula: FOF = "P(x)".parse().unwrap(); - assert_debug_string!("P(x)", dnf(&formula)); + assert_debug_string!("P(x)", dnf_clause_set(&formula)); } { let formula: FOF = "x=y".parse().unwrap(); - assert_debug_string!("x = y", dnf(&formula)); + assert_debug_string!("x = y", dnf_clause_set(&formula)); } { let formula: FOF = "P(x) & Q(y)".parse().unwrap(); - assert_debug_string!("P(x) & Q(y)", dnf(&formula)); + assert_debug_string!("P(x) & Q(y)", dnf_clause_set(&formula)); } { let formula: FOF = "P(x) | Q(y)".parse().unwrap(); - assert_debug_string!("P(x) | Q(y)", dnf(&formula)); + assert_debug_string!("P(x) | Q(y)", dnf_clause_set(&formula)); } { let formula: FOF = "P(x) -> Q(y)".parse().unwrap(); - assert_debug_string!("Q(y) | ~P(x)", dnf(&formula)); + assert_debug_string!("Q(y) | ~P(x)", dnf_clause_set(&formula)); } { let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); assert_debug_string!( "(((P(x) & Q(y)) | (P(x) & ~P(x))) | (Q(y) & ~Q(y))) | (~P(x) & ~Q(y))", - dnf(&formula), + dnf_clause_set(&formula), ); } { let formula: FOF = "!x. P(x)".parse().unwrap(); - assert_debug_string!("P(x)", dnf(&formula)); + assert_debug_string!("P(x)", dnf_clause_set(&formula)); } { let formula: FOF = "!x. P(f(), g(f(), x))".parse().unwrap(); - assert_debug_string!("P(f(), g(f(), x))", dnf(&formula)); + assert_debug_string!("P(f(), g(f(), x))", dnf_clause_set(&formula)); } // quantifier-free formulae { let formula: FOF = "~((P(x1) | P(x2)) and Q(y))".parse().unwrap(); - assert_debug_string!("(~P(x1) & ~P(x2)) | ~Q(y)", dnf(&formula)); + assert_debug_string!("(~P(x1) & ~P(x2)) | ~Q(y)", dnf_clause_set(&formula)); } { let formula: FOF = "P(x) | ~(Q(x) -> Q(y))".parse().unwrap(); - assert_debug_string!("P(x) | (Q(x) & ~Q(y))", dnf(&formula)); + assert_debug_string!("P(x) | (Q(x) & ~Q(y))", dnf_clause_set(&formula)); } { let formula: FOF = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); - assert_debug_string!("R(z) | (~P(x) & ~Q(y))", dnf(&formula)); + assert_debug_string!("R(z) | (~P(x) & ~Q(y))", dnf_clause_set(&formula)); } { let formula: FOF = "P(x) | ~(Q(x) <=> Q(y))".parse().unwrap(); - assert_debug_string!("(P(x) | (Q(x) & ~Q(y))) | (Q(y) & ~Q(x))", dnf(&formula),); + assert_debug_string!( + "(P(x) | (Q(x) & ~Q(y))) | (Q(y) & ~Q(x))", + dnf_clause_set(&formula), + ); } { let formula: FOF = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); assert_debug_string!("(((((P(x) & R(z)) | ((P(x) & ~P(x)) & ~Q(y))) | (Q(y) & R(z))) | ((Q(y) & ~P(x)) & ~Q(y))) | (R(z) & ~R(z))) | ((~P(x) & ~Q(y)) & ~R(z))", - dnf(&formula)); + dnf_clause_set(&formula)); } { let formula: FOF = "P(x) | (Q(x) | (R(y) & R(z)))".parse().unwrap(); - assert_debug_string!("(P(x) | Q(x)) | (R(y) & R(z))", dnf(&formula)); + assert_debug_string!("(P(x) | Q(x)) | (R(y) & R(z))", dnf_clause_set(&formula)); } { let formula: FOF = "(P(x1) & P(x2)) | (Q(x1) & Q(x2))".parse().unwrap(); - assert_debug_string!("(P(x1) & P(x2)) | (Q(x1) & Q(x2))", dnf(&formula)); + assert_debug_string!( + "(P(x1) & P(x2)) | (Q(x1) & Q(x2))", + dnf_clause_set(&formula) + ); } //random formulae { let formula: FOF = "?x. P(x)".parse().unwrap(); - assert_debug_string!("P('c#0)", dnf(&formula)); + assert_debug_string!("P('c#0)", dnf_clause_set(&formula)); } { let formula: FOF = "?x. (P(x) & Q(f(), x))".parse().unwrap(); - assert_debug_string!("P('c#0) & Q(f(), 'c#0)", dnf(&formula)); + assert_debug_string!("P('c#0) & Q(f(), 'c#0)", dnf_clause_set(&formula)); } { let formula: FOF = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); - assert_debug_string!("(R(x) | ~P(y)) | ~Q(x, y)", dnf(&formula)); + assert_debug_string!("(R(x) | ~P(y)) | ~Q(x, y)", dnf_clause_set(&formula)); } { let formula: FOF = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); - assert_debug_string!("(~P(x) | ~Q(y)) | ~R(x, y)", dnf(&formula)); + assert_debug_string!("(~P(x) | ~Q(y)) | ~R(x, y)", dnf_clause_set(&formula)); } { let formula: FOF = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); - assert_debug_string!("Q(y) | (~P(y, x) & ~Q(x))", dnf(&formula)); + assert_debug_string!("Q(y) | (~P(y, x) & ~Q(x))", dnf_clause_set(&formula)); } { let formula: FOF = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); - assert_debug_string!("Q(y) | (~P(y, f#0(y)) & ~Q(f#0(y)))", dnf(&formula)); + assert_debug_string!( + "Q(y) | (~P(y, f#0(y)) & ~Q(f#0(y)))", + dnf_clause_set(&formula) + ); } { let formula: FOF = "?x. ?y. P(x, y)".parse().unwrap(); - assert_debug_string!("P('c#0, 'c#1)", dnf(&formula)); + assert_debug_string!("P('c#0, 'c#1)", dnf_clause_set(&formula)); } { let formula: FOF = "?x, y. P(x, y)".parse().unwrap(); - assert_debug_string!("P('c#0, 'c#1)", dnf(&formula)); + assert_debug_string!("P('c#0, 'c#1)", dnf_clause_set(&formula)); } { let formula: FOF = "!x. ?y. P(x, y)".parse().unwrap(); - assert_debug_string!("P(x, f#0(x))", dnf(&formula)); + assert_debug_string!("P(x, f#0(x))", dnf_clause_set(&formula)); } { let formula: FOF = @@ -381,20 +513,26 @@ mod tests { .unwrap(); assert_debug_string!( "((P(f#0(z), x) & ~Q(u`, x`, y)) & ~(w = f(u`))) | ~R(z)", - dnf(&formula), + dnf_clause_set(&formula), ); } { let formula: FOF = "!x. (!y. (P(y) -> Q(x, y)) -> ?y. Q(y, x))" .parse() .unwrap(); - assert_debug_string!("(P(y) & ~Q(x, y)) | Q(f#0(x, y), x)", dnf(&formula)); + assert_debug_string!( + "(P(y) & ~Q(x, y)) | Q(f#0(x, y), x)", + dnf_clause_set(&formula) + ); } { let formula: FOF = "!x. ((!y. (P(y) -> Q(x, y))) -> ?y. Q(y, x))" .parse() .unwrap(); - assert_debug_string!("(P(f#0(x)) & ~Q(x, f#0(x))) | Q(f#1(x), x)", dnf(&formula),); + assert_debug_string!( + "(P(f#0(x)) & ~Q(x, f#0(x))) | Q(f#1(x), x)", + dnf_clause_set(&formula), + ); } { let formula: FOF = "?x. (!y, z. (P(x) & ((Q(x, y) & ~(y = z)) -> ~Q(x, z))))" @@ -402,14 +540,14 @@ mod tests { .unwrap(); assert_debug_string!( "((P(\'c#0) & y = z) | (P(\'c#0) & ~Q(\'c#0, y))) | (P(\'c#0) & ~Q(\'c#0, z))", - dnf(&formula) + dnf_clause_set(&formula) ); } { let formula: FOF = "!x. (P(x) -> (!y. (P(y) -> P(f(x, y))) & ~!y. (Q(x, y) -> P(y))))" .parse() .unwrap(); - assert_debug_string!("(((P(f(x, y)) & Q(x, f#0(x, y))) & ~P(f#0(x, y))) | ((Q(x, f#0(x, y)) & ~P(y)) & ~P(f#0(x, y)))) | ~P(x)", dnf(&formula)); + assert_debug_string!("(((P(f(x, y)) & Q(x, f#0(x, y))) & ~P(f#0(x, y))) | ((Q(x, f#0(x, y)) & ~P(y)) & ~P(f#0(x, y)))) | ~P(x)", dnf_clause_set(&formula)); } } @@ -474,8 +612,8 @@ mod tests { assert_eq!(sig, dnf.signature().unwrap()); } { - let cnf = fof!({ P(x, x) } | { P(x) }).dnf(); - assert!(cnf.signature().is_err()); + let dnf = fof!({ P(x, x) } | { P(x) }).dnf(); + assert!(dnf.signature().is_err()); } } } diff --git a/razor-fol/src/transform/gnf.rs b/razor-fol/src/transform/gnf.rs index dfb4036..9c87fce 100644 --- a/razor-fol/src/transform/gnf.rs +++ b/razor-fol/src/transform/gnf.rs @@ -1,9 +1,9 @@ /*! Defines formulae in Geometric Normal Form (GNF) and implements an algorithm for -transforming a [`CNF`] to a [`GNF`]. +transforming a [`CNFClauseSet`] to a [`GNF`]. -[`CNF`]: crate::transform::CNF +[`CNFClauseSet`]: crate::transform::CNFClauseSet */ -use super::{ToCNF, CNF}; +use super::{ToSNF, SNF}; use crate::syntax::{ formula::{ clause::{Clause, Literal}, @@ -368,15 +368,18 @@ pub trait ToGNF: Formula { fn gnf(&self) -> Vec; } -impl ToGNF for CNF { +impl ToGNF for SNF { fn gnf(&self) -> Vec { - self.iter().map(gnf).collect() + use super::ToCNFClauseSet; + + let clauses = self.cnf_clause_set(); + clauses.iter().map(gnf).collect() } } -impl ToGNF for T { +impl ToGNF for T { fn gnf(&self) -> Vec { - self.cnf().gnf() + self.snf().gnf() } } From 0437b00298ee45e99dba65a997024f140d022b8a Mon Sep 17 00:00:00 2001 From: Salman Saghafi Date: Mon, 5 Dec 2022 09:58:40 -0800 Subject: [PATCH 2/3] clippy --- razor-chase/src/chase.rs | 8 +++---- razor-chase/src/chase/bounder.rs | 14 +++++------- razor-chase/src/chase/impl/basic.rs | 8 +++---- razor-chase/src/chase/impl/batch.rs | 2 +- razor-chase/src/chase/impl/collapse.rs | 8 +++---- .../src/chase/impl/relational/model.rs | 4 +--- .../src/chase/impl/relational/symbol.rs | 6 ++--- razor-chase/src/chase/strategy.rs | 4 ++-- razor-fol/src/parser.rs | 22 +++++++++---------- razor-fol/src/syntax.rs | 2 +- razor-fol/src/syntax/formula.rs | 4 ++-- razor-fol/src/syntax/formula/clause.rs | 2 +- razor-fol/src/syntax/symbol.rs | 8 +++---- razor-fol/src/syntax/term.rs | 2 ++ razor-fol/src/syntax/theory.rs | 2 +- razor-fol/src/transform/cnf.rs | 6 ++--- razor-fol/src/transform/dnf.rs | 2 +- razor-fol/src/transform/gnf.rs | 16 ++------------ razor-fol/src/transform/relational.rs | 8 +------ razor/src/command.rs | 2 +- 20 files changed, 53 insertions(+), 77 deletions(-) diff --git a/razor-chase/src/chase.rs b/razor-chase/src/chase.rs index 311356a..aba0c9e 100644 --- a/razor-chase/src/chase.rs +++ b/razor-chase/src/chase.rs @@ -43,7 +43,7 @@ //! [the chase]: https://en.wikipedia.org/wiki/Chase_(algorithm) //! [geometric theories]: https://www.cs.bham.ac.uk/~sjv/GLiCS.pdf //! [run of the chase]: self#chase_all -//! [standard syntactic manipulation]: razor_fol::transform::CNF::gnf() +//! [standard syntactic manipulation]: razor_fol::transform::GNF //! [godel]: https://en.wikipedia.org/wiki/Gödel%27s_incompleteness_theorems //! //! ## The Chase @@ -149,7 +149,7 @@ impl fmt::Display for E { impl fmt::Debug for E { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self) } } @@ -261,7 +261,7 @@ impl fmt::Display for Rel { impl fmt::Debug for Rel { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self) } } @@ -293,7 +293,7 @@ impl fmt::Display for Observation { impl fmt::Debug for Observation { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self) } } diff --git a/razor-chase/src/chase/bounder.rs b/razor-chase/src/chase/bounder.rs index d8c63d7..ddb450d 100644 --- a/razor-chase/src/chase/bounder.rs +++ b/razor-chase/src/chase/bounder.rs @@ -3,7 +3,7 @@ //! The bounders are instances of [`Bounder`]. //! //! [`Bounder`]: crate::chase::Bounder -use crate::chase::{Bounder, Model, Observation, WitnessTerm}; +use crate::chase::{Bounder, Model, Observation}; /// Bounds the size of a [model] by the number of elements in its [domain]. /// @@ -29,13 +29,11 @@ impl Bounder for DomainSize { match observation { Observation::Fact { relation: _, terms } => { let model_size = model.domain().len(); - let terms: Vec::TermType as WitnessTerm>::ElementType>> = - terms - .iter() - .map(|t| model.element(t)) - .filter(|t| t.is_none()) - .collect(); - let size = terms.len(); + let size = terms + .iter() + .map(|t| model.element(t)) + .filter(|t| t.is_none()) + .count(); model_size + size > self.max_domain_size } Observation::Identity { left, right } => { diff --git a/razor-chase/src/chase/impl/basic.rs b/razor-chase/src/chase/impl/basic.rs index 14d2aa9..bb15ebe 100644 --- a/razor-chase/src/chase/impl/basic.rs +++ b/razor-chase/src/chase/impl/basic.rs @@ -89,7 +89,7 @@ impl fmt::Display for BasicWitnessTerm { impl fmt::Debug for BasicWitnessTerm { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self) } } @@ -465,9 +465,7 @@ impl fmt::Debug for BasicModel { .sorted() .iter() .map(|e| { - let witnesses: Vec = - self.witness(e).iter().map(|w| w.to_string()).collect(); - let witnesses = witnesses.into_iter().sorted(); + let witnesses = self.witness(e).iter().map(|w| w.to_string()).sorted(); format!("{} -> {}", witnesses.into_iter().sorted().join(", "), e) }) .collect(); @@ -751,7 +749,7 @@ fn make_observe_literal( // variables of a sequent. It mutates the given a list of indices, corresponding to mapping of each // position to an element of a domain to the next assignment. Returns true if a next assignment // exists and false otherwise. -fn next_assignment(vec: &mut Vec, last: usize) -> bool { +fn next_assignment(vec: &mut [usize], last: usize) -> bool { for item in vec.iter_mut() { if *item != last { *item += 1; diff --git a/razor-chase/src/chase/impl/batch.rs b/razor-chase/src/chase/impl/batch.rs index 8c5ef63..178a204 100644 --- a/razor-chase/src/chase/impl/batch.rs +++ b/razor-chase/src/chase/impl/batch.rs @@ -186,7 +186,7 @@ fn make_observe_literal( // variables of a sequent. It mutates the given a list of indices, corresponding to mapping of each // position to an element of a domain to the next assignment. Returns true if a next assignment // exists and false otherwise. -fn next_assignment(vec: &mut Vec, last: usize) -> bool { +fn next_assignment(vec: &mut [usize], last: usize) -> bool { for item in vec.iter_mut() { if *item != last { *item += 1; diff --git a/razor-chase/src/chase/impl/collapse.rs b/razor-chase/src/chase/impl/collapse.rs index 5a18eb1..87677a6 100644 --- a/razor-chase/src/chase/impl/collapse.rs +++ b/razor-chase/src/chase/impl/collapse.rs @@ -71,7 +71,7 @@ impl Deref for Element { impl fmt::Debug for Element { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.get().to_string()) + write!(f, "{}", self.get()) } } @@ -479,9 +479,7 @@ impl fmt::Debug for ColModel { .sorted() .iter() .map(|e| { - let witnesses: Vec = - self.witness(e).iter().map(|w| w.to_string()).collect(); - let witnesses = witnesses.into_iter().sorted(); + let witnesses = self.witness(e).iter().map(|w| w.to_string()).sorted(); format!( "{} -> {}", witnesses.into_iter().sorted().join(", "), @@ -695,7 +693,7 @@ fn make_observe_literal( // variables of a sequent. It mutates the given a list of indices, corresponding to mapping of each // position to an element of a domain to the next assignment. Returns true if a next assignment // exists and false otherwise. -fn next_assignment(vec: &mut Vec, last: usize) -> bool { +fn next_assignment(vec: &mut [usize], last: usize) -> bool { for item in vec.iter_mut() { if *item != last { *item += 1; diff --git a/razor-chase/src/chase/impl/relational/model.rs b/razor-chase/src/chase/impl/relational/model.rs index c5b2d50..41d0e91 100644 --- a/razor-chase/src/chase/impl/relational/model.rs +++ b/razor-chase/src/chase/impl/relational/model.rs @@ -305,9 +305,7 @@ impl fmt::Debug for RelModel { .sorted() .iter() .map(|e| { - let witnesses: Vec = - self.witness(e).iter().map(|w| w.to_string()).collect(); - let witnesses = witnesses.into_iter().sorted(); + let witnesses = self.witness(e).iter().map(|w| w.to_string()).sorted(); format!("{} -> {}", witnesses.into_iter().sorted().join(", "), e) }) .collect(); diff --git a/razor-chase/src/chase/impl/relational/symbol.rs b/razor-chase/src/chase/impl/relational/symbol.rs index d50acfa..30665ed 100644 --- a/razor-chase/src/chase/impl/relational/symbol.rs +++ b/razor-chase/src/chase/impl/relational/symbol.rs @@ -82,12 +82,12 @@ impl Symbol { impl std::fmt::Display for Symbol { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let display = match self { - Symbol::Const(c) => format!("constant {}", c.to_string()), + Symbol::Const(c) => format!("constant {}", c), Symbol::Func { symbol, arity } => { - format!("function {}, arity {}", symbol.to_string(), arity) + format!("function {}, arity {}", symbol, arity) } Symbol::Pred { symbol, arity } => { - format!("predicate {}, arity {}", symbol.to_string(), arity) + format!("predicate {}, arity {}", symbol, arity) } Symbol::Equality => "equality (=)".into(), Symbol::Domain => "domain".into(), diff --git a/razor-chase/src/chase/strategy.rs b/razor-chase/src/chase/strategy.rs index fbd6b79..fc9293a 100644 --- a/razor-chase/src/chase/strategy.rs +++ b/razor-chase/src/chase/strategy.rs @@ -21,7 +21,7 @@ pub struct Linear { index: usize, } -impl<'s, S: Sequent> Linear { +impl Linear { #[inline(always)] fn reset(&mut self) { self.index = 0; @@ -37,7 +37,7 @@ impl Iterator for Linear { } } -impl<'s, S: Sequent> Clone for Linear { +impl Clone for Linear { fn clone(&self) -> Self { Self { sequents: self.sequents.clone(), diff --git a/razor-fol/src/parser.rs b/razor-fol/src/parser.rs index 4e8e5d6..8e011f3 100644 --- a/razor-fol/src/parser.rs +++ b/razor-fol/src/parser.rs @@ -44,7 +44,7 @@ use thiserror::Error; lalrpop_mod!(#[allow(clippy::all)] pub grammar); // synthesized by LALRPOP -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Eq, Debug)] pub enum TokenType { Comma, Dot, @@ -121,24 +121,24 @@ impl ToString for TokenType { } /// Is the type of errors returned by the parser. -#[derive(Error, PartialEq, Debug)] +#[derive(Error, PartialEq, Eq, Debug)] pub enum Error { #[error("found `{found:?}` at line {}, column {}; expecting {}", - (*.position).line, - (*.position).column, - Error::pretty_expected_tokens(&*.expected), + (position).line, + (position).column, + Error::pretty_expected_tokens(expected), )] UnrecognizedToken { position: Position, expected: Vec, found: String, }, - #[error("invalid token at line {}, column {}", (*.position).line, (*.position).column)] + #[error("invalid token at line {}, column {}", (position).line, (position).column)] InvalidToken { position: Position }, #[error("unexpected end of input at line {}, column {}; expecting {}", - (*.position).line, - (*.position).column, - Error::pretty_expected_tokens(&*.expected) + (position).line, + (position).column, + Error::pretty_expected_tokens(expected) )] UnrecognizedEOF { position: Position, @@ -149,7 +149,7 @@ pub enum Error { #[from] source: crate::syntax::Error, }, - #[error("unexpected token `{found:?}` at line {}, column {}", (*.position).line, (*.position).column)] + #[error("unexpected token `{found:?}` at line {}, column {}", (position).line, (position).column)] ExtraToken { position: Position, found: String }, } @@ -165,7 +165,7 @@ impl Error { } } -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Eq, Debug)] pub struct Position { line: usize, column: usize, diff --git a/razor-fol/src/syntax.rs b/razor-fol/src/syntax.rs index 4d36159..2fd623f 100644 --- a/razor-fol/src/syntax.rs +++ b/razor-fol/src/syntax.rs @@ -14,7 +14,7 @@ pub use theory::Theory; use thiserror::Error; /// Is the type of errors arising from inconsistencies in the syntax of formulae. -#[derive(Error, PartialEq, Debug)] +#[derive(Error, PartialEq, Eq, Debug)] pub enum Error { /// Is returned when an unsupported operation is performed on an expression. #[error("inconsistent predicate in theory signature `{}` and `{}`", .this.to_string(), .other.to_string())] diff --git a/razor-fol/src/syntax/formula.rs b/razor-fol/src/syntax/formula.rs index ab120d7..541af77 100644 --- a/razor-fol/src/syntax/formula.rs +++ b/razor-fol/src/syntax/formula.rs @@ -149,14 +149,14 @@ impl FormulaEx for Atom { impl fmt::Display for Atom { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let ts = self.terms.iter().map(|t| t.to_string()).collect_vec(); - write!(f, "{}({})", self.predicate.to_string(), ts.join(", ")) + write!(f, "{}({})", self.predicate, ts.join(", ")) } } impl fmt::Debug for Atom { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let ts = self.terms.iter().map(|t| format!("{:?}", t)).collect_vec(); - write!(f, "{}({})", self.predicate.to_string(), ts.join(", ")) + write!(f, "{}({})", self.predicate, ts.join(", ")) } } diff --git a/razor-fol/src/syntax/formula/clause.rs b/razor-fol/src/syntax/formula/clause.rs index f52c493..1a9981b 100644 --- a/razor-fol/src/syntax/formula/clause.rs +++ b/razor-fol/src/syntax/formula/clause.rs @@ -192,7 +192,7 @@ impl Formula for Clause { /// /// [`CNF`]: crate::transform::CNF /// [`DNF`]: crate::transform::DNF -#[derive(PartialEq, Clone, Debug)] +#[derive(PartialEq, Eq, Clone, Debug)] pub struct ClauseSet(BTreeSet>); impl From> for ClauseSet { diff --git a/razor-fol/src/syntax/symbol.rs b/razor-fol/src/syntax/symbol.rs index 5d9c32f..d7b1f9c 100644 --- a/razor-fol/src/syntax/symbol.rs +++ b/razor-fol/src/syntax/symbol.rs @@ -50,7 +50,7 @@ impl fmt::Display for Func { impl fmt::Debug for Func { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self) } } @@ -80,7 +80,7 @@ impl fmt::Display for Var { impl fmt::Debug for Var { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self) } } @@ -113,7 +113,7 @@ impl fmt::Display for Const { impl fmt::Debug for Const { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self) } } @@ -157,7 +157,7 @@ impl fmt::Display for Pred { impl fmt::Debug for Pred { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_string()) + write!(f, "{}", self) } } diff --git a/razor-fol/src/syntax/term.rs b/razor-fol/src/syntax/term.rs index 9c86d74..36e5632 100644 --- a/razor-fol/src/syntax/term.rs +++ b/razor-fol/src/syntax/term.rs @@ -62,6 +62,7 @@ pub trait Term { /// let s = t.rename_var(&renaming); // s = f(a, z, g(a, b, a)) /// assert_eq!("f(a, z, g(a, b, a))", s.to_string()) /// ``` + #[allow(clippy::only_used_in_recursion)] fn rename_var(&self, renaming: &impl Renaming) -> Self where Self: Sized, @@ -99,6 +100,7 @@ pub trait Term { /// let s = t.substitute(&x_to_c); // s = f('c, g('c, y, 'c)) /// assert_eq!("f('c, g('c, y, 'c))", s.to_string()) /// ``` + #[allow(clippy::only_used_in_recursion)] fn substitute(&self, sub: &impl Substitution) -> Self where Self: Sized, diff --git a/razor-fol/src/syntax/theory.rs b/razor-fol/src/syntax/theory.rs index 2f80b5f..72ef459 100644 --- a/razor-fol/src/syntax/theory.rs +++ b/razor-fol/src/syntax/theory.rs @@ -4,7 +4,7 @@ use super::{Error, Formula, Sig}; use std::{fmt, iter::FromIterator, ops::Deref}; /// is a first-order theory, containing a set of first-order formulae. -#[derive(PartialEq, Clone, Debug)] +#[derive(PartialEq, Eq, Clone, Debug)] pub struct Theory(Vec); impl Theory { diff --git a/razor-fol/src/transform/cnf.rs b/razor-fol/src/transform/cnf.rs index 85e2668..2d67ef2 100644 --- a/razor-fol/src/transform/cnf.rs +++ b/razor-fol/src/transform/cnf.rs @@ -326,14 +326,14 @@ fn clause_set(formula: FOF) -> ClauseSet { let left = clause_set(this.left); let right = clause_set(this.right); if left.is_empty() { - left.into() + left } else if right.is_empty() { - right.into() + right } else if left.len() == 1 && right.len() == 1 { let left = left.into_clauses().into_iter().next().unwrap(); let right = right.into_clauses().into_iter().next().unwrap(); let clause = left.union(&right); - ClauseSet::from(clause).into() + ClauseSet::from(clause) } else { unreachable!() // Disjunction is distributed over conjunction in `formula` } diff --git a/razor-fol/src/transform/dnf.rs b/razor-fol/src/transform/dnf.rs index ada8a61..7a97017 100644 --- a/razor-fol/src/transform/dnf.rs +++ b/razor-fol/src/transform/dnf.rs @@ -195,7 +195,7 @@ impl std::fmt::Display for DNF { impl Default for DNF { fn default() -> Self { - Self::Clauses(ClauseSet::<_>::default().into()) + Self::Clauses(ClauseSet::<_>::default()) } } diff --git a/razor-fol/src/transform/gnf.rs b/razor-fol/src/transform/gnf.rs index 9c87fce..4d30127 100644 --- a/razor-fol/src/transform/gnf.rs +++ b/razor-fol/src/transform/gnf.rs @@ -20,7 +20,7 @@ type PosLiteral = Atomic; /// A Positive Conjunctive Formula (PCF) represents a collection of [`Atomic`]s, interpreted /// as a conjunction of positive literals. PCFs are the building blocks of [`GNF`]s. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)] pub struct PCF(BTreeSet); impl PCF { @@ -92,12 +92,6 @@ impl From> for PCF { } } -impl Default for PCF { - fn default() -> Self { - Self(BTreeSet::new()) - } -} - impl Formula for PCF { type Term = Complex; @@ -165,7 +159,7 @@ impl TryFrom for PCF { /// Is a set of [`PCF`]s in the head of a [`GNF`], interpreted as a disjunction of /// PCFs where each PCF is a conjunction of positive literals. -#[derive(PartialEq, Clone, Debug)] +#[derive(PartialEq, Eq, Clone, Default, Debug)] pub struct PcfSet(BTreeSet); impl PcfSet { @@ -234,12 +228,6 @@ impl Deref for PcfSet { } } -impl Default for PcfSet { - fn default() -> Self { - Self(BTreeSet::new()) - } -} - impl Formula for PcfSet { type Term = Complex; diff --git a/razor-fol/src/transform/relational.rs b/razor-fol/src/transform/relational.rs index 68c0ce3..11cb8e7 100644 --- a/razor-fol/src/transform/relational.rs +++ b/razor-fol/src/transform/relational.rs @@ -22,7 +22,7 @@ type FlatLiteral = Atomic; /// /// [`Clause`]: crate::syntax::formula::clause::Clause /// [`BTreeSet`]: std::collections::BTreeSet -#[derive(Clone, Debug)] +#[derive(Clone, Default, Debug)] pub struct FlatClause(Vec); impl FlatClause { @@ -73,12 +73,6 @@ impl From> for FlatClause { } } -impl Default for FlatClause { - fn default() -> Self { - Self(Vec::new()) - } -} - impl Formula for FlatClause { type Term = Variable; diff --git a/razor/src/command.rs b/razor/src/command.rs index 9919c5b..9423fb3 100644 --- a/razor/src/command.rs +++ b/razor/src/command.rs @@ -26,7 +26,7 @@ impl std::str::FromStr for BoundCommand { fn from_str(s: &str) -> Result { let domain_str: &'static str = "domain="; - if s.to_lowercase().starts_with(&domain_str) { + if s.to_lowercase().starts_with(domain_str) { let size_str = &s[domain_str.len()..]; if let Ok(size) = size_str.parse::() { Ok(BoundCommand::Domain { size }) From 0c6cf05dbafa553019dad1b7f9b9013a0550c8c5 Mon Sep 17 00:00:00 2001 From: Salman Saghafi Date: Mon, 5 Dec 2022 12:11:52 -0800 Subject: [PATCH 3/3] changing formula types to idiomatic rust names CNF -> Cnf DNF -> Dnf FOF -> Fof SNF -> Snf PNF -> Pnf PCF -> Pcf --- razor-chase/src/chase.rs | 20 +- razor-chase/src/chase/impl/basic.rs | 54 +- razor-chase/src/chase/impl/batch.rs | 4 +- razor-chase/src/chase/impl/collapse.rs | 12 +- razor-chase/src/chase/impl/relational.rs | 4 +- .../src/chase/impl/relational/expression.rs | 4 +- .../chase/impl/relational/pre_processor.rs | 20 +- .../src/chase/impl/relational/sequent.rs | 14 +- razor-chase/src/chase/scheduler.rs | 4 +- razor-chase/src/chase/strategy.rs | 18 +- razor-chase/src/test_prelude.rs | 4 +- razor-fol/src/grammar.lalrpop | 32 +- razor-fol/src/parser.rs | 82 +-- razor-fol/src/syntax.rs | 2 +- razor-fol/src/syntax/formula.rs | 14 +- razor-fol/src/syntax/formula/clause.rs | 16 +- razor-fol/src/syntax/formula/fof.rs | 164 +++--- razor-fol/src/syntax/formula/qff.rs | 248 ++++----- razor-fol/src/syntax/macros.rs | 28 +- razor-fol/src/syntax/signature.rs | 18 +- razor-fol/src/syntax/term.rs | 22 +- razor-fol/src/transform.rs | 18 +- razor-fol/src/transform/cnf.rs | 328 ++++++------ razor-fol/src/transform/dnf.rs | 264 +++++----- razor-fol/src/transform/gnf.rs | 332 ++++++------ razor-fol/src/transform/linear.rs | 26 +- razor-fol/src/transform/nnf.rs | 262 +++++----- razor-fol/src/transform/pnf.rs | 484 +++++++++--------- razor-fol/src/transform/range_restrict.rs | 16 +- razor-fol/src/transform/relational.rs | 90 ++-- razor-fol/src/transform/simplify.rs | 136 ++--- razor-fol/src/transform/snf.rs | 144 +++--- razor/src/utils.rs | 6 +- 33 files changed, 1445 insertions(+), 1445 deletions(-) diff --git a/razor-chase/src/chase.rs b/razor-chase/src/chase.rs index aba0c9e..9e82cf9 100644 --- a/razor-chase/src/chase.rs +++ b/razor-chase/src/chase.rs @@ -43,7 +43,7 @@ //! [the chase]: https://en.wikipedia.org/wiki/Chase_(algorithm) //! [geometric theories]: https://www.cs.bham.ac.uk/~sjv/GLiCS.pdf //! [run of the chase]: self#chase_all -//! [standard syntactic manipulation]: razor_fol::transform::GNF +//! [standard syntactic manipulation]: razor_fol::transform::Gnf //! [godel]: https://en.wikipedia.org/wiki/Gödel%27s_incompleteness_theorems //! //! ## The Chase @@ -340,18 +340,18 @@ pub trait Model: Clone { /// [bg]: self#background pub trait Sequent: Clone { /// Returns the *body* (premise) of the sequent as a formula. - fn body(&self) -> FOF; + fn body(&self) -> Fof; /// Returns the *head* (consequence) of the sequent as a formula. - fn head(&self) -> FOF; + fn head(&self) -> Fof; } impl Sequent for &S { - fn body(&self) -> FOF { + fn body(&self) -> Fof { (*self).body() } - fn head(&self) -> FOF { + fn head(&self) -> Fof { (*self).head() } } @@ -367,7 +367,7 @@ pub trait PreProcessor { /// Given a theory, returns an iterator of [sequents][Sequent] and an initial /// [model][Model] by applying the necessary pre-processing. - fn pre_process(&self, theory: &Theory) -> (Vec, Self::Model); + fn pre_process(&self, theory: &Theory) -> (Vec, Self::Model); } /// Strategy is the trait of algorithms for choosing sequents in the context of an @@ -527,7 +527,7 @@ pub trait Scheduler> { /// [the chase]: self#the-chase /// /// ```rust -/// use razor_fol::syntax::{FOF, Theory}; +/// use razor_fol::syntax::{Fof, Theory}; /// use razor_chase::chase::{ /// PreProcessor, Scheduler, Strategy, chase_all, /// r#impl::basic, @@ -537,7 +537,7 @@ pub trait Scheduler> { /// }; /// /// // parse the theory: -/// let theory: Theory = r#" +/// let theory: Theory = r#" /// exists x . P(x); /// P(x) implies Q(x) | R(x); /// R(x) -> exists y . S(x, y); @@ -596,7 +596,7 @@ where /// [chase-step]: self#chase-step /// /// ```rust -/// use razor_fol::syntax::{FOF, Theory}; +/// use razor_fol::syntax::{Fof, Theory}; /// use razor_chase::chase::{ /// PreProcessor, Scheduler, Strategy, chase_step, /// r#impl::basic, @@ -607,7 +607,7 @@ where /// use std::convert::TryInto; /// /// // parse the theory: -/// let theory: Theory = r#" +/// let theory: Theory = r#" /// exists x . P(x); /// P(x) implies Q(x) | R(x); /// R(x) -> exists y . S(x, y); diff --git a/razor-chase/src/chase/impl/basic.rs b/razor-chase/src/chase/impl/basic.rs index bb15ebe..ff42061 100644 --- a/razor-chase/src/chase/impl/basic.rs +++ b/razor-chase/src/chase/impl/basic.rs @@ -11,8 +11,8 @@ use crate::chase::*; use either::Either; use itertools::Itertools; use razor_fol::{ - syntax::{formula::Atomic, term::Complex, Formula, FOF}, - transform::GNF, + syntax::{formula::Atomic, term::Complex, Fof, Formula}, + transform::Gnf, }; use std::{ collections::{HashMap, HashSet}, @@ -503,12 +503,12 @@ pub struct BasicSequent { pub head: Vec>, // other fields: - body_fof: FOF, - head_fof: FOF, + body_fof: Fof, + head_fof: Fof, } -impl From for BasicSequent { - fn from(gnf: GNF) -> Self { +impl From for BasicSequent { + fn from(gnf: Gnf) -> Self { let gnf_body = gnf.body(); let gnf_head = gnf.head(); let free_vars = gnf.free_vars().into_iter().cloned().collect(); @@ -545,11 +545,11 @@ impl fmt::Display for BasicSequent { } impl Sequent for BasicSequent { - fn body(&self) -> FOF { + fn body(&self) -> Fof { self.body_fof.clone() } - fn head(&self) -> FOF { + fn head(&self) -> Fof { self.head_fof.clone() } } @@ -564,9 +564,9 @@ impl PreProcessor for BasicPreProcessor { type Sequent = BasicSequent; type Model = BasicModel; - fn pre_process(&self, theory: &Theory) -> (Vec, Self::Model) { - use razor_fol::transform::ToGNF; - use razor_fol::transform::ToSNF; + fn pre_process(&self, theory: &Theory) -> (Vec, Self::Model) { + use razor_fol::transform::ToGnf; + use razor_fol::transform::ToSnf; let mut c_counter: u32 = 0; let mut f_counter: u32 = 0; @@ -768,7 +768,7 @@ mod test_basic { bounder::DomainSize, chase_all, scheduler::FIFO, strategy::Linear, Scheduler, }; use crate::test_prelude::*; - use razor_fol::transform::ToGNF; + use razor_fol::transform::ToGnf; use std::iter::FromIterator; // Witness Elements @@ -1020,55 +1020,55 @@ mod test_basic { } // Assumes that `fof` is in GNF, so it converts to a single GNF - fn sequents(gnfs: Vec) -> Vec { + fn sequents(gnfs: Vec) -> Vec { gnfs.into_iter().map(BasicSequent::from).collect() } #[test] fn test_build_sequent() { - assert_debug_string("[]", sequents("true -> true".parse::().unwrap().gnf())); + assert_debug_string("[]", sequents("true -> true".parse::().unwrap().gnf())); assert_debug_string( "[]", - sequents("true -> true & true".parse::().unwrap().gnf()), + sequents("true -> true & true".parse::().unwrap().gnf()), ); assert_debug_string( "[]", - sequents("true -> true | true".parse::().unwrap().gnf()), + sequents("true -> true | true".parse::().unwrap().gnf()), ); assert_debug_string( "[[] -> []]", - sequents("true -> false".parse::().unwrap().gnf()), + sequents("true -> false".parse::().unwrap().gnf()), ); assert_debug_string( "[[] -> []]", - sequents("true -> false & true".parse::().unwrap().gnf()), + sequents("true -> false & true".parse::().unwrap().gnf()), ); assert_debug_string( "[[] -> []]", - sequents("true -> true & false".parse::().unwrap().gnf()), + sequents("true -> true & false".parse::().unwrap().gnf()), ); assert_debug_string( "[]", - sequents("true -> true | false".parse::().unwrap().gnf()), + sequents("true -> true | false".parse::().unwrap().gnf()), ); assert_debug_string( "[]", - sequents("true -> false | true".parse::().unwrap().gnf()), + sequents("true -> false | true".parse::().unwrap().gnf()), ); assert_debug_string( "[[P(x)] -> [[Q(x)]]]", - sequents("P(x) -> Q(x)".parse::().unwrap().gnf()), + sequents("P(x) -> Q(x)".parse::().unwrap().gnf()), ); assert_debug_string( // Note: only range restricted geometric formulae get contracted "[[P(x), Q(x)] -> [[Q(y)]]]", - sequents("P(x) & Q(x) -> Q(y)".parse::().unwrap().gnf()), + sequents("P(x) & Q(x) -> Q(y)".parse::().unwrap().gnf()), ); assert_debug_string( "[[P(x, z), Q(x)] -> [[Q(x)], [R(z)]], [P(x, z), Q(x)] -> [[Q(x)], [S(z)]]]", sequents( "P(x, z) & Q(x) -> Q(x) | (R(z) & S(z))" - .parse::() + .parse::() .unwrap() .gnf(), ), @@ -1077,14 +1077,14 @@ mod test_basic { "[[D(x, y, z)] -> [[P(x)], [P(y)], [P(z)]], [D(x, y, z)] -> [[P(x)], [P(y)], [Q(z)]], [D(x, y, z)] -> [[P(x)], [P(z)], [Q(y)]], [D(x, y, z)] -> [[P(x)], [Q(y)], [Q(z)]], [D(x, y, z)] -> [[P(y)], [P(z)], [Q(x)]], [D(x, y, z)] -> [[P(y)], [Q(x)], [Q(z)]], [D(x, y, z)] -> [[P(z)], [Q(x)], [Q(y)]], [D(x, y, z)] -> [[Q(x)], [Q(y)], [Q(z)]]]", sequents( "D(x, y, z) -> (P(x) & Q(x)) | (P(y) & Q(y)) | (P(z) & Q(z))" - .parse::() + .parse::() .unwrap() .gnf(), ), ); } - fn run(theory: &Theory) -> Vec { + fn run(theory: &Theory) -> Vec { let pre_processor = BasicPreProcessor; let (sequents, init_model) = pre_processor.pre_process(theory); @@ -1097,7 +1097,7 @@ mod test_basic { chase_all(&mut scheduler, &evaluator, bounder) } - fn run_domain_bounded(theory: &Theory, bound: usize) -> Vec { + fn run_domain_bounded(theory: &Theory, bound: usize) -> Vec { let pre_processor = BasicPreProcessor; let (sequents, init_model) = pre_processor.pre_process(theory); let evaluator = BasicEvaluator; diff --git a/razor-chase/src/chase/impl/batch.rs b/razor-chase/src/chase/impl/batch.rs index 178a204..930dd6d 100644 --- a/razor-chase/src/chase/impl/batch.rs +++ b/razor-chase/src/chase/impl/batch.rs @@ -211,7 +211,7 @@ mod test_batch { bounder::DomainSize, chase_all, scheduler::FIFO, strategy::Linear, Scheduler, }; use crate::test_prelude::*; - use razor_fol::syntax::{Theory, FOF}; + use razor_fol::syntax::{Fof, Theory}; use std::collections::HashSet; static IGNORE_TEST: [&'static str; 1] = ["thy24.raz"]; @@ -263,7 +263,7 @@ mod test_batch { } } - fn run(theory: &Theory) -> Vec { + fn run(theory: &Theory) -> Vec { use crate::chase::r#impl::collapse::ColPreProcessor; use crate::chase::PreProcessor; diff --git a/razor-chase/src/chase/impl/collapse.rs b/razor-chase/src/chase/impl/collapse.rs index 87677a6..d9e3626 100644 --- a/razor-chase/src/chase/impl/collapse.rs +++ b/razor-chase/src/chase/impl/collapse.rs @@ -15,7 +15,7 @@ use crate::chase::{ }; use either::Either; use itertools::Itertools; -use razor_fol::syntax::{formula::Atomic, term::Complex, Const, Func, Theory, Var, FOF}; +use razor_fol::syntax::{formula::Atomic, term::Complex, Const, Fof, Func, Theory, Var}; use std::{ cell::Cell, collections::{HashMap, HashSet}, @@ -507,9 +507,9 @@ impl PreProcessor for ColPreProcessor { type Sequent = ColSequent; type Model = ColModel; - fn pre_process(&self, theory: &Theory) -> (Vec, Self::Model) { - use razor_fol::transform::ToGNF; - use razor_fol::transform::ToSNF; + fn pre_process(&self, theory: &Theory) -> (Vec, Self::Model) { + use razor_fol::transform::ToGnf; + use razor_fol::transform::ToSnf; let mut c_counter: u32 = 0; let mut f_counter: u32 = 0; @@ -730,7 +730,7 @@ mod test_collapse { bounder::DomainSize, chase_all, scheduler::FIFO, strategy::Linear, Scheduler, }; use crate::test_prelude::*; - use razor_fol::syntax::{Theory, FOF}; + use razor_fol::syntax::{Fof, Theory}; use std::collections::HashSet; static IGNORE_TEST: [&'static str; 1] = ["thy24.raz"]; @@ -782,7 +782,7 @@ mod test_collapse { } } - fn run(theory: &Theory) -> Vec { + fn run(theory: &Theory) -> Vec { use crate::chase::PreProcessor; let pre_processor = super::ColPreProcessor; diff --git a/razor-chase/src/chase/impl/relational.rs b/razor-chase/src/chase/impl/relational.rs index 680ff7b..e73c61b 100644 --- a/razor-chase/src/chase/impl/relational.rs +++ b/razor-chase/src/chase/impl/relational.rs @@ -74,9 +74,9 @@ mod tests { }, test_prelude::*, }; - use razor_fol::syntax::{Theory, FOF}; + use razor_fol::syntax::{Fof, Theory}; - fn run(theory: &Theory, pre_processor: &RelPreProcessor) -> Vec { + fn run(theory: &Theory, pre_processor: &RelPreProcessor) -> Vec { let (sequents, init_model) = pre_processor.pre_process(theory); let evaluator = RelEvaluator; diff --git a/razor-chase/src/chase/impl/relational/expression.rs b/razor-chase/src/chase/impl/relational/expression.rs index 3594ab9..0d99a32 100644 --- a/razor-chase/src/chase/impl/relational/expression.rs +++ b/razor-chase/src/chase/impl/relational/expression.rs @@ -474,7 +474,7 @@ mod tests { use crate::chase::E; use codd::{query, Database, Tuples}; use itertools::Itertools; - use razor_fol::{fof, syntax::FOF, v}; + use razor_fol::{fof, syntax::Fof, v}; use std::convert::TryFrom; macro_rules! atts { @@ -525,7 +525,7 @@ mod tests { } // Assumes the input in GNF - fn relational(fof: FOF) -> Relational { + fn relational(fof: Fof) -> Relational { use razor_fol::transform::{PcfSet, ToRelational}; PcfSet::try_from(fof).unwrap().relational() diff --git a/razor-chase/src/chase/impl/relational/pre_processor.rs b/razor-chase/src/chase/impl/relational/pre_processor.rs index 677a2cd..adea67c 100644 --- a/razor-chase/src/chase/impl/relational/pre_processor.rs +++ b/razor-chase/src/chase/impl/relational/pre_processor.rs @@ -2,8 +2,8 @@ use super::{constants::*, expression::Convertor, model::RelModel, sequent::RelSe use crate::chase::PreProcessor; use itertools::Itertools; use razor_fol::{ - syntax::{formula::*, term::Complex, Sig, Theory, Var, FOF}, - transform::{PcfSet, GNF, PCF}, + syntax::{formula::*, term::Complex, Fof, Sig, Theory, Var}, + transform::{Gnf, Pcf, PcfSet}, }; /// Is a [`PreProcessor`] instance that converts the input theory to a vector of [`Sequent`]. @@ -27,9 +27,9 @@ impl PreProcessor for RelPreProcessor { type Sequent = RelSequent; type Model = RelModel; - fn pre_process(&self, theory: &Theory) -> (Vec, Self::Model) { - use razor_fol::transform::ToGNF; - use razor_fol::transform::ToSNF; + fn pre_process(&self, theory: &Theory) -> (Vec, Self::Model) { + use razor_fol::transform::ToGnf; + use razor_fol::transform::ToSnf; let mut c_counter: u32 = 0; let mut f_counter: u32 = 0; @@ -70,8 +70,8 @@ impl PreProcessor for RelPreProcessor { } } -fn equality_axioms() -> Vec { - use razor_fol::{fof, transform::ToGNF}; +fn equality_axioms() -> Vec { + use razor_fol::{fof, transform::ToGnf}; // reflexive (not needed - automatically added for new elements): // fof!(['|'] -> [(x) = (x)]), @@ -84,7 +84,7 @@ fn equality_axioms() -> Vec { // Function integrity axioms in the form of: // 1) 'c = x & 'c = y -> x = y // 2) (f(x1, ..., xn) = x) & (f(y1, ..., yn) = y) & x1 = y1 & ... & xn = yn -> x = y -fn integrity_axioms(sig: &Sig) -> Vec { +fn integrity_axioms(sig: &Sig) -> Vec { use razor_fol::term; let mut result = Vec::new(); @@ -105,7 +105,7 @@ fn integrity_axioms(sig: &Sig) -> Vec { } .into(); - let gnf: GNF = (PCF::from(vec![c_x, c_y]), PcfSet::from(PCF::from(x_y))).into(); + let gnf: Gnf = (Pcf::from(vec![c_x, c_y]), PcfSet::from(Pcf::from(x_y))).into(); result.push(gnf); } @@ -144,7 +144,7 @@ fn integrity_axioms(sig: &Sig) -> Vec { } .into(); - let gnf: GNF = (PCF::from(left), PcfSet::from(PCF::from(right))).into(); + let gnf: Gnf = (Pcf::from(left), PcfSet::from(Pcf::from(right))).into(); result.push(gnf); } diff --git a/razor-chase/src/chase/impl/relational/sequent.rs b/razor-chase/src/chase/impl/relational/sequent.rs index 602b2c4..4c8d9ab 100644 --- a/razor-chase/src/chase/impl/relational/sequent.rs +++ b/razor-chase/src/chase/impl/relational/sequent.rs @@ -12,9 +12,9 @@ use razor_fol::{ syntax::{ formula::{Atom, Atomic, Equals}, term::Variable, - Const, Func, Pred, Var, FOF, + Const, Fof, Func, Pred, Var, }, - transform::{FlatClause, Relational, ToRelational, GNF}, + transform::{FlatClause, Gnf, Relational, ToRelational}, }; use std::convert::TryFrom; @@ -69,10 +69,10 @@ pub struct RelSequent { pub expression: rel_exp::Mono, /// The body of the implication from which the sequent was made. - body_formula: FOF, + body_formula: Fof, /// The head of the implication from which the sequent was made. - head_formula: FOF, + head_formula: Fof, } impl RelSequent { @@ -94,7 +94,7 @@ impl RelSequent { &self.attributes } - pub(super) fn new(gnf: &GNF, convertor: &mut Convertor) -> Result { + pub(super) fn new(gnf: &Gnf, convertor: &mut Convertor) -> Result { let body_linear = optimize_relational(gnf.body())?.linear_with(&mut linear_generator()); let head_relational = optimize_relational(gnf.head())?; @@ -134,11 +134,11 @@ impl RelSequent { } impl Sequent for RelSequent { - fn body(&self) -> FOF { + fn body(&self) -> Fof { self.body_formula.clone() } - fn head(&self) -> FOF { + fn head(&self) -> Fof { self.head_formula.clone() } } diff --git a/razor-chase/src/chase/scheduler.rs b/razor-chase/src/chase/scheduler.rs index cd04987..f1abdd2 100644 --- a/razor-chase/src/chase/scheduler.rs +++ b/razor-chase/src/chase/scheduler.rs @@ -200,10 +200,10 @@ mod test_lifo { PreProcessor, Scheduler, }; use crate::test_prelude::*; - use razor_fol::syntax::{Theory, FOF}; + use razor_fol::syntax::{Fof, Theory}; use std::collections::HashSet; - pub fn run(theory: &Theory) -> Vec { + pub fn run(theory: &Theory) -> Vec { let pre_processor = BasicPreProcessor; let (sequents, init_model) = pre_processor.pre_process(theory); let evaluator = BasicEvaluator; diff --git a/razor-chase/src/chase/strategy.rs b/razor-chase/src/chase/strategy.rs index fc9293a..a88b9e1 100644 --- a/razor-chase/src/chase/strategy.rs +++ b/razor-chase/src/chase/strategy.rs @@ -4,7 +4,7 @@ //! //! [`Strategy`]: crate::chase::Strategy use crate::chase::{Sequent, Strategy}; -use razor_fol::syntax::{Formula, FOF}; +use razor_fol::syntax::{Fof, Formula}; use std::iter::FromIterator; /// Starting from the first [sequent] returns the next sequent every time `Iterator::next()` is @@ -134,7 +134,7 @@ impl> FromIterator for Bootstrap { fn from_iter>(iter: T) -> Self { let (initial_sequents, rest) = iter .into_iter() - .partition(|s| s.body() == FOF::Top && s.head().free_vars().is_empty()); + .partition(|s| s.body() == Fof::Top && s.head().free_vars().is_empty()); Bootstrap { initial_sequents, @@ -177,7 +177,7 @@ pub struct FailFast> { impl> FromIterator for FailFast { fn from_iter>(iter: T) -> Self { let (fail_sequents, rest): (Vec<_>, _) = - iter.into_iter().partition(|s| s.head() == FOF::Bottom); + iter.into_iter().partition(|s| s.head() == Fof::Bottom); Self { fail_strategy: fail_sequents.into_iter().collect(), @@ -208,10 +208,10 @@ mod test_fair { PreProcessor, Scheduler, }; use crate::test_prelude::{print_basic_model, read_file, read_theory_from_file}; - use razor_fol::syntax::{Theory, FOF}; + use razor_fol::syntax::{Fof, Theory}; use std::collections::HashSet; - fn run(theory: &Theory) -> Vec { + fn run(theory: &Theory) -> Vec { let preprocessor = BasicPreProcessor; let (sequents, init_model) = preprocessor.pre_process(theory); let evaluator = BasicEvaluator; @@ -261,10 +261,10 @@ mod test_bootstrap { PreProcessor, Scheduler, }; use crate::test_prelude::*; - use razor_fol::syntax::{Theory, FOF}; + use razor_fol::syntax::{Fof, Theory}; use std::collections::HashSet; - fn run(theory: &Theory) -> Vec { + fn run(theory: &Theory) -> Vec { let pre_processor = BasicPreProcessor; let (sequents, init_model) = pre_processor.pre_process(theory); let evaluator = BasicEvaluator; @@ -314,10 +314,10 @@ mod test_fail_fast { PreProcessor, Scheduler, }; use crate::test_prelude::*; - use razor_fol::syntax::{Theory, FOF}; + use razor_fol::syntax::{Fof, Theory}; use std::collections::HashSet; - fn run(theory: &Theory) -> Vec { + fn run(theory: &Theory) -> Vec { let pre_processor = BasicPreProcessor; let (sequents, init_model) = pre_processor.pre_process(theory); let evaluator = BasicEvaluator; diff --git a/razor-chase/src/test_prelude.rs b/razor-chase/src/test_prelude.rs index 015eb25..300f727 100644 --- a/razor-chase/src/test_prelude.rs +++ b/razor-chase/src/test_prelude.rs @@ -1,6 +1,6 @@ use crate::chase::{r#impl::basic, r#impl::collapse, *}; use itertools::Itertools; -use razor_fol::syntax::{term::Complex, Const, Func, Pred, Theory, Var, FOF}; +use razor_fol::syntax::{term::Complex, Const, Fof, Func, Pred, Theory, Var}; use std::{fmt, fs::File, io::Read}; pub fn equal_sets(first: &[T], second: &[T]) -> bool { @@ -211,7 +211,7 @@ pub fn read_file(filename: &str) -> String { content } -pub fn read_theory_from_file(filename: &str) -> Theory { +pub fn read_theory_from_file(filename: &str) -> Theory { let content = read_file(filename); content.parse().unwrap() } diff --git a/razor-fol/src/grammar.lalrpop b/razor-fol/src/grammar.lalrpop index 639c069..547bd77 100644 --- a/razor-fol/src/grammar.lalrpop +++ b/razor-fol/src/grammar.lalrpop @@ -1,4 +1,4 @@ -use crate::syntax::{*, term::Complex, FOF::*, Theory}; +use crate::syntax::{*, term::Complex, Fof::*, Theory}; use lalrpop_util::ParseError; use super::Error; @@ -76,13 +76,13 @@ pub Term: Complex = { => <>.into(), }; -pub Equal: FOF = +pub Equal: Fof = _EQUAL_ => l.equals(r); pub Pred: Pred = => <>.into(); -pub Atom: FOF = { +pub Atom: Fof = { _TRUE_ => Top, _FALSE_ => Bottom, , @@ -99,48 +99,48 @@ Unitary = { Unit, }; -Not: FOF = { - _NOT_ => FOF::not(<>), +Not: Fof = { + _NOT_ => Fof::not(<>), Unitary, }; -UnitNot: FOF = { - _NOT_ => FOF::not(<>), +UnitNot: Fof = { + _NOT_ => Fof::not(<>), Unit, }; -And: FOF = { +And: Fof = { _AND_ => l.and(r), Not, }; -UnitAnd: FOF = { +UnitAnd: Fof = { _AND_ => l.and(r), UnitNot, }; -Or: FOF = { +Or: Fof = { _OR_ => l.or(r), And, }; -UnitOr: FOF = { +UnitOr: Fof = { _OR_ => l.or(r), UnitAnd, }; -Quant: FOF = { - _FORALL_ _DOT_ => FOF::forall(<>), - _EXISTS_ _DOT_ => FOF::exists(<>), +Quant: Fof = { + _FORALL_ _DOT_ => Fof::forall(<>), + _EXISTS_ _DOT_ => Fof::exists(<>), }; -pub Formula: FOF = { +pub Formula: Fof = { _IMPLIES_ => l.implies(r), _IFF_ => l.iff(r), Or, }; -pub Theory: Theory = +pub Theory: Theory = ( _SEMICOLON_)* =>? { let theory: Theory<_> = <>.into_iter().collect(); theory.signature().map_err(|e| ParseError::User { diff --git a/razor-fol/src/parser.rs b/razor-fol/src/parser.rs index 8e011f3..2bf102c 100644 --- a/razor-fol/src/parser.rs +++ b/razor-fol/src/parser.rs @@ -1,25 +1,25 @@ //! Implements a parser for first-order formulae and theories in Razor's syntax. //! //! The module provides a parser for first-order formulae by implementing [`FromStr`] for -//! [`FOF`] and [`Theory`]. The parser is often used implicitly through [`parse`] method. +//! [`Fof`] and [`Theory`]. The parser is often used implicitly through [`parse`] method. //! //! **Example**: -//! The following example parses a string into a [`FOF`]: +//! The following example parses a string into a [`Fof`]: //! ```rust -//! use razor_fol::syntax::FOF; +//! use razor_fol::syntax::Fof; //! -//! // parse a string into `FOF`: -//! let formula: FOF = "exists x. P(x) & Q(x)".parse().unwrap(); +//! // parse a string into `Fof`: +//! let formula: Fof = "exists x. P(x) & Q(x)".parse().unwrap(); //! //! assert_eq!("∃ x. (P(x) ∧ Q(x))", formula.to_string()); //! ``` //! //! Similarly, a [`Theory`] can be parsed from a string: //! ```rust -//! use razor_fol::syntax::{FOF, Theory}; +//! use razor_fol::syntax::{Fof, Theory}; //! //! // parse a string into `Theory` (formulae are separated by `;`) -//! let theory: Theory = r#" +//! let theory: Theory = r#" //! // mathematical notation: //! ∀ x. Eq(x, x); //! // verbose notation: @@ -33,11 +33,11 @@ //! ∃ x, y, z. ((Eq(x, y) ∧ Eq(y, z)) → Eq(x, z))", theory.to_string()); //! ``` //! -//! [`FOF`]: crate::syntax::FOF +//! [`Fof`]: crate::syntax::Fof //! [`Theory`]: crate::syntax::Theory //! [`FromStr`]: std::str::FromStr //! [`parse`]: ::std::str#parse -use super::syntax::{Theory, FOF}; +use super::syntax::{Fof, Theory}; use lalrpop_util::ParseError; use std::str::FromStr; use thiserror::Error; @@ -250,7 +250,7 @@ impl<'s> SourceInfo<'s> { } } -impl FromStr for FOF { +impl FromStr for Fof { type Err = Error; fn from_str(s: &str) -> Result { @@ -261,7 +261,7 @@ impl FromStr for FOF { } } -impl FromStr for Theory { +impl FromStr for Theory { type Err = Error; fn from_str(s: &str) -> Result { @@ -1094,7 +1094,7 @@ mod tests { use TokenType::*; { - let parsed: Result, Error> = "P(X)".parse(); + let parsed: Result, Error> = "P(X)".parse(); assert_eq!( Error::UnrecognizedToken { position: Position { line: 1, column: 3 }, @@ -1105,7 +1105,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P('A)".parse(); + let parsed: Result, Error> = "P('A)".parse(); assert_eq!( Error::InvalidToken { position: Position { line: 1, column: 3 } @@ -1114,7 +1114,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x)".parse(); + let parsed: Result, Error> = "P(x)".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 5 }, @@ -1124,7 +1124,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x".parse(); + let parsed: Result, Error> = "P(x".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 4 }, @@ -1136,7 +1136,7 @@ mod tests { ); } { - let parsed: Result, Error> = "~P(x".parse(); + let parsed: Result, Error> = "~P(x".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 5 }, @@ -1148,7 +1148,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) and ".parse(); + let parsed: Result, Error> = "P(x) and ".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 9 }, @@ -1158,7 +1158,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) and X".parse(); + let parsed: Result, Error> = "P(x) and X".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { @@ -1171,7 +1171,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) or ".parse(); + let parsed: Result, Error> = "P(x) or ".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 8 }, @@ -1181,7 +1181,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) or X".parse(); + let parsed: Result, Error> = "P(x) or X".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { @@ -1194,7 +1194,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) -> ".parse(); + let parsed: Result, Error> = "P(x) -> ".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 8 }, @@ -1204,7 +1204,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) -> X".parse(); + let parsed: Result, Error> = "P(x) -> X".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { @@ -1217,7 +1217,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) <=> ".parse(); + let parsed: Result, Error> = "P(x) <=> ".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 9 }, @@ -1227,7 +1227,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) <=> X".parse(); + let parsed: Result, Error> = "P(x) <=> X".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { @@ -1240,7 +1240,7 @@ mod tests { ); } { - let parsed: Result, Error> = "!x P(x".parse(); + let parsed: Result, Error> = "!x P(x".parse(); assert_eq!( Error::UnrecognizedToken { position: Position { line: 1, column: 4 }, @@ -1253,7 +1253,7 @@ mod tests { ); } { - let parsed: Result, Error> = "! P(x".parse(); + let parsed: Result, Error> = "! P(x".parse(); assert_eq!( Error::UnrecognizedToken { position: Position { line: 1, column: 3 }, @@ -1264,7 +1264,7 @@ mod tests { ); } { - let parsed: Result, Error> = "!x . ".parse(); + let parsed: Result, Error> = "!x . ".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 5 }, @@ -1274,7 +1274,7 @@ mod tests { ); } { - let parsed: Result, Error> = "!x . X".parse(); + let parsed: Result, Error> = "!x . X".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 7 }, @@ -1284,7 +1284,7 @@ mod tests { ); } { - let parsed: Result, Error> = "∀x . X".parse(); + let parsed: Result, Error> = "∀x . X".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 7 }, @@ -1294,7 +1294,7 @@ mod tests { ); } { - let parsed: Result, Error> = "?x P(x".parse(); + let parsed: Result, Error> = "?x P(x".parse(); assert_eq!( Error::UnrecognizedToken { position: Position { line: 1, column: 4 }, @@ -1307,7 +1307,7 @@ mod tests { ); } { - let parsed: Result, Error> = "? P(x".parse(); + let parsed: Result, Error> = "? P(x".parse(); assert_eq!( Error::UnrecognizedToken { position: Position { line: 1, column: 3 }, @@ -1318,7 +1318,7 @@ mod tests { ); } { - let parsed: Result, Error> = "?x . ".parse(); + let parsed: Result, Error> = "?x . ".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 5 }, @@ -1328,7 +1328,7 @@ mod tests { ); } { - let parsed: Result, Error> = "?x . X".parse(); + let parsed: Result, Error> = "?x . X".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 7 }, @@ -1338,7 +1338,7 @@ mod tests { ); } { - let parsed: Result, Error> = "x".parse(); + let parsed: Result, Error> = "x".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 2 }, @@ -1350,7 +1350,7 @@ mod tests { ); } { - let parsed: Result, Error> = "(X)".parse(); + let parsed: Result, Error> = "(X)".parse(); assert_eq!( Error::UnrecognizedToken { position: Position { line: 1, column: 3 }, @@ -1361,7 +1361,7 @@ mod tests { ); } { - let parsed: Result, Error> = "(P(x)".parse(); + let parsed: Result, Error> = "(P(x)".parse(); assert_eq!( Error::UnrecognizedEOF { position: Position { line: 1, column: 6 }, @@ -1371,7 +1371,7 @@ mod tests { ); } { - let parsed: Result, Error> = "P(x) + let parsed: Result, Error> = "P(x) Q(x) <=> R(x);" .parse(); assert_eq!( @@ -1384,7 +1384,7 @@ Q(x) <=> R(x);" ); } { - let parsed: Result, Error> = "P(x); + let parsed: Result, Error> = "P(x); Q(x) => R(x); S(x) <=> Q(x);" .parse(); @@ -1398,7 +1398,7 @@ S(x) <=> Q(x);" ); } { - let parsed: Result, Error> = "P(x); + let parsed: Result, Error> = "P(x); Q(x) <=> R(x); S(x) and " .parse(); @@ -1411,7 +1411,7 @@ S(x) and " ); } { - let parsed: Result, Error> = "f(x) = 'a; + let parsed: Result, Error> = "f(x) = 'a; // Testing error location with unicode characters: ∀x . /* comment 🪒 ♖♞♗♚♕♝♘♜ */ X" .parse(); @@ -1428,7 +1428,7 @@ S(x) and " } { use crate::syntax::signature::PredSig; - let parsed: Result, Error> = "P(x); + let parsed: Result, Error> = "P(x); P(x,y);" .parse(); assert_eq!( diff --git a/razor-fol/src/syntax.rs b/razor-fol/src/syntax.rs index 2fd623f..602a982 100644 --- a/razor-fol/src/syntax.rs +++ b/razor-fol/src/syntax.rs @@ -6,7 +6,7 @@ pub mod symbol; pub mod term; mod theory; -pub use formula::{fof::FOF, Formula}; +pub use formula::{fof::Fof, Formula}; pub use signature::Sig; pub use symbol::{Const, Func, Pred, Var, EQ_SYM}; pub use term::Term; diff --git a/razor-fol/src/syntax/formula.rs b/razor-fol/src/syntax/formula.rs index 541af77..9654148 100644 --- a/razor-fol/src/syntax/formula.rs +++ b/razor-fol/src/syntax/formula.rs @@ -33,17 +33,17 @@ pub trait Formula { /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::{Var, FOF, Func}; + /// # use razor_fol::syntax::{Var, Fof, Func}; /// # use std::{collections::HashSet, iter::FromIterator}; /// use razor_fol::syntax::Formula; /// - /// let fof: FOF = "(P(x) ∧ Q(x, f(g(x), y))) ∨ 'c = g(z)".parse().unwrap(); + /// let fof: Fof = "(P(x) ∧ Q(x, f(g(x), y))) ∨ 'c = g(z)".parse().unwrap(); /// let signature = fof.signature().unwrap(); /// assert_eq!(&HashSet::from_iter(vec!["c".into()]), signature.constants()); /// assert_eq!(Func::from("f"), signature.functions().get("f").unwrap().symbol); /// assert_eq!(2, signature.predicates().get("Q").unwrap().arity); /// - /// let fof: FOF = "P(x) ∧ P(g(x), y)".parse().unwrap(); + /// let fof: Fof = "P(x) ∧ P(g(x), y)".parse().unwrap(); /// let signature = fof.signature().is_err(); // inconsistent arity for `P` /// ``` fn signature(&self) -> Result; @@ -55,7 +55,7 @@ pub trait Formula { /// /// **Example**: /// ```rust - /// # use razor_fol::{v, syntax::FOF}; + /// # use razor_fol::{v, syntax::Fof}; /// # use itertools::Itertools; /// use razor_fol::syntax::Formula; /// @@ -64,13 +64,13 @@ pub trait Formula { /// let y = v!(y); /// let z = v!(z); /// - /// let formula: FOF = "(P(x) & Q(x, f(g(x), y))) | 'c = g(z)".parse().unwrap(); + /// let formula: Fof = "(P(x) & Q(x, f(g(x), y))) | 'c = g(z)".parse().unwrap(); /// assert_eq!(vec![&x, &y, &z].iter().sorted(), formula.free_vars().iter().sorted()); /// - /// let formula: FOF = "forall x. P(x, y)".parse().unwrap(); + /// let formula: Fof = "forall x. P(x, y)".parse().unwrap(); /// assert_eq!(vec![&y], formula.free_vars()); /// - /// let formula: FOF = "exists x. P(x, y)".parse().unwrap(); + /// let formula: Fof = "exists x. P(x, y)".parse().unwrap(); /// assert_eq!(vec![&y], formula.free_vars()); /// ``` fn free_vars(&self) -> Vec<&Var>; diff --git a/razor-fol/src/syntax/formula/clause.rs b/razor-fol/src/syntax/formula/clause.rs index 1a9981b..bc5195c 100644 --- a/razor-fol/src/syntax/formula/clause.rs +++ b/razor-fol/src/syntax/formula/clause.rs @@ -84,11 +84,11 @@ impl FormulaEx for Literal { /// /// **Note:** /// The interpretation of a clause depends on its syntactic context. -/// For example, a [`CNF`] clause is interpreted as disjunction of literals whereas -/// a [`DNF`] clause corresponds to a conjunction of literals. +/// For example, a [`Cnf`] clause is interpreted as disjunction of literals whereas +/// a [`Dnf`] clause corresponds to a conjunction of literals. /// -/// [`CNF`]: crate::transform::CNF -/// [`DNF`]: crate::transform::DNF +/// [`Cnf`]: crate::transform::Cnf +/// [`Dnf`]: crate::transform::Dnf #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)] pub struct Clause(BTreeSet>); @@ -186,12 +186,12 @@ impl Formula for Clause { /// /// **Note:** /// The interpretation of a clause set depends on its syntactic context. For example, -/// a [`CNF`] is a clause set that is interpreted as a conjunction of clauses where each -/// clause is a disjunction of literals. In contrast, a [`DNF`] is a clause set that +/// a [`Cnf`] is a clause set that is interpreted as a conjunction of clauses where each +/// clause is a disjunction of literals. In contrast, a [`Dnf`] is a clause set that /// corresponds to a disjunction of clauses where each clause is a conjunction of literals. /// -/// [`CNF`]: crate::transform::CNF -/// [`DNF`]: crate::transform::DNF +/// [`Cnf`]: crate::transform::Cnf +/// [`Dnf`]: crate::transform::Dnf #[derive(PartialEq, Eq, Clone, Debug)] pub struct ClauseSet(BTreeSet>); diff --git a/razor-fol/src/syntax/formula/fof.rs b/razor-fol/src/syntax/formula/fof.rs index 8b8cfae..a724713 100644 --- a/razor-fol/src/syntax/formula/fof.rs +++ b/razor-fol/src/syntax/formula/fof.rs @@ -1,11 +1,11 @@ /*! Defines the syntax of first-order formulae with equality.*/ -use super::{qff::QFF, Sig, Var, *}; +use super::{qff::Qff, Sig, Var, *}; use crate::syntax::term::Complex; use std::fmt; /// Is an abstract syntax tree (AST) for first-order formulae. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum FOF { +pub enum Fof { /// Is logical top (⊤) or truth. Top, @@ -21,114 +21,114 @@ pub enum FOF { Equals(Equals), /// Is the negation of a first-order formula, wrapping a [`Not`]. - Not(Box>), + Not(Box>), /// Is a conjunction of two first-order formulae, wrapping an [`And`]. - And(Box>), + And(Box>), /// Is a disjunction of two first-order formulae, wrapping an [`Or`]. - Or(Box>), + Or(Box>), /// Is an implication between two first-order formulae, wrapping an [`Implies`]. - Implies(Box>), + Implies(Box>), /// Is an bi-implication between two first-order formulae, wrapping an [`Iff`]. - Iff(Box>), + Iff(Box>), /// Is an existentially quantified first-order formula, wrapping an [`Exists`]. - Exists(Box>), + Exists(Box>), /// Is a universally quantified first-order formula, wrapping a [`Forall`]. - Forall(Box>), + Forall(Box>), } -impl From> for FOF { +impl From> for Fof { fn from(value: Atom) -> Self { Self::Atom(value) } } -impl From> for FOF { +impl From> for Fof { fn from(value: Equals) -> Self { Self::Equals(value) } } -impl From> for FOF { - fn from(value: Not) -> Self { +impl From> for Fof { + fn from(value: Not) -> Self { Self::Not(Box::new(value)) } } -impl From> for FOF { - fn from(value: And) -> Self { +impl From> for Fof { + fn from(value: And) -> Self { Self::And(Box::new(value)) } } -impl From> for FOF { - fn from(value: Or) -> Self { +impl From> for Fof { + fn from(value: Or) -> Self { Self::Or(Box::new(value)) } } -impl From> for FOF { - fn from(value: Implies) -> Self { +impl From> for Fof { + fn from(value: Implies) -> Self { Self::Implies(Box::new(value)) } } -impl From> for FOF { - fn from(value: Iff) -> Self { +impl From> for Fof { + fn from(value: Iff) -> Self { Self::Iff(Box::new(value)) } } -impl From> for FOF { - fn from(value: Exists) -> Self { +impl From> for Fof { + fn from(value: Exists) -> Self { Self::Exists(Box::new(value)) } } -impl From> for FOF { - fn from(value: Forall) -> Self { +impl From> for Fof { + fn from(value: Forall) -> Self { Self::Forall(Box::new(value)) } } -impl From for FOF { - fn from(value: QFF) -> Self { +impl From for Fof { + fn from(value: Qff) -> Self { match value { - QFF::Top => Self::Top, - QFF::Bottom => Self::Bottom, - QFF::Atom(this) => Self::Atom(this), - QFF::Equals(this) => Self::Equals(this), - QFF::Not(this) => FOF::not(this.formula.into()), - QFF::And(this) => { - let left: FOF = this.left.into(); - let right: FOF = this.right.into(); + Qff::Top => Self::Top, + Qff::Bottom => Self::Bottom, + Qff::Atom(this) => Self::Atom(this), + Qff::Equals(this) => Self::Equals(this), + Qff::Not(this) => Fof::not(this.formula.into()), + Qff::And(this) => { + let left: Fof = this.left.into(); + let right: Fof = this.right.into(); left.and(right) } - QFF::Or(this) => { - let left: FOF = this.left.into(); - let right: FOF = this.right.into(); + Qff::Or(this) => { + let left: Fof = this.left.into(); + let right: Fof = this.right.into(); left.or(right) } - QFF::Implies(this) => { - let pre: FOF = this.premise.into(); - let cons: FOF = this.consequence.into(); + Qff::Implies(this) => { + let pre: Fof = this.premise.into(); + let cons: Fof = this.consequence.into(); pre.implies(cons) } - QFF::Iff(this) => { - let left: FOF = this.left.into(); - let right: FOF = this.right.into(); + Qff::Iff(this) => { + let left: Fof = this.left.into(); + let right: Fof = this.right.into(); left.iff(right) } } } } -impl FOF { +impl Fof { /// Returns the negation of `formula`. #[allow(clippy::should_implement_trait)] // Disallow `formula.not()` intentionally: @@ -192,22 +192,22 @@ impl FOF { } } -impl Formula for FOF { +impl Formula for Fof { type Term = Complex; fn signature(&self) -> Result { match self { - FOF::Top => Ok(Sig::new()), - FOF::Bottom => Ok(Sig::new()), - FOF::Atom(this) => this.signature(), - FOF::Equals(this) => this.signature(), - FOF::Not(this) => this.signature(), - FOF::And(this) => this.signature(), - FOF::Or(this) => this.signature(), - FOF::Implies(this) => this.signature(), - FOF::Iff(this) => this.signature(), - FOF::Exists(this) => this.signature(), - FOF::Forall(this) => this.signature(), + Fof::Top => Ok(Sig::new()), + Fof::Bottom => Ok(Sig::new()), + Fof::Atom(this) => this.signature(), + Fof::Equals(this) => this.signature(), + Fof::Not(this) => this.signature(), + Fof::And(this) => this.signature(), + Fof::Or(this) => this.signature(), + Fof::Implies(this) => this.signature(), + Fof::Iff(this) => this.signature(), + Fof::Exists(this) => this.signature(), + Fof::Forall(this) => this.signature(), } } @@ -229,39 +229,39 @@ impl Formula for FOF { fn transform_term(&self, f: &impl Fn(&Complex) -> Complex) -> Self { match self { - FOF::Top | FOF::Bottom => self.clone(), - FOF::Atom(this) => this.transform_term(f).into(), - FOF::Equals(this) => this.transform_term(f).into(), - FOF::Not(this) => this.transform_term(f).into(), - FOF::And(this) => this.transform_term(f).into(), - FOF::Or(this) => this.transform_term(f).into(), - FOF::Implies(this) => this.transform_term(f).into(), - FOF::Iff(this) => this.transform_term(f).into(), - FOF::Exists(this) => this.transform_term(f).into(), - FOF::Forall(this) => this.transform_term(f).into(), + Fof::Top | Fof::Bottom => self.clone(), + Fof::Atom(this) => this.transform_term(f).into(), + Fof::Equals(this) => this.transform_term(f).into(), + Fof::Not(this) => this.transform_term(f).into(), + Fof::And(this) => this.transform_term(f).into(), + Fof::Or(this) => this.transform_term(f).into(), + Fof::Implies(this) => this.transform_term(f).into(), + Fof::Iff(this) => this.transform_term(f).into(), + Fof::Exists(this) => this.transform_term(f).into(), + Fof::Forall(this) => this.transform_term(f).into(), } } } -impl FormulaEx for FOF { +impl FormulaEx for Fof { fn precedence(&self) -> u8 { match self { - FOF::Top => PRECEDENCE_ATOM, - FOF::Bottom => PRECEDENCE_ATOM, - FOF::Atom(this) => this.precedence(), - FOF::Equals(this) => this.precedence(), - FOF::Not(this) => this.precedence(), - FOF::And(this) => this.precedence(), - FOF::Or(this) => this.precedence(), - FOF::Implies(this) => this.precedence(), - FOF::Iff(this) => this.precedence(), - FOF::Exists(this) => this.precedence(), - FOF::Forall(this) => this.precedence(), + Fof::Top => PRECEDENCE_ATOM, + Fof::Bottom => PRECEDENCE_ATOM, + Fof::Atom(this) => this.precedence(), + Fof::Equals(this) => this.precedence(), + Fof::Not(this) => this.precedence(), + Fof::And(this) => this.precedence(), + Fof::Or(this) => this.precedence(), + Fof::Implies(this) => this.precedence(), + Fof::Iff(this) => this.precedence(), + Fof::Exists(this) => this.precedence(), + Fof::Forall(this) => this.precedence(), } } } -impl fmt::Display for FOF { +impl fmt::Display for Fof { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { Self::Top => write!(f, "⊤"), @@ -279,7 +279,7 @@ impl fmt::Display for FOF { } } -impl fmt::Debug for FOF { +impl fmt::Debug for Fof { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { Self::Top => write!(f, "true"), @@ -299,7 +299,7 @@ impl fmt::Debug for FOF { #[cfg(test)] mod tests { - use super::{FOF::*, *}; + use super::{Fof::*, *}; use crate::{ assert_eq_sorted_vecs, fof, syntax::{ diff --git a/razor-fol/src/syntax/formula/qff.rs b/razor-fol/src/syntax/formula/qff.rs index 8fc9340..00e627b 100644 --- a/razor-fol/src/syntax/formula/qff.rs +++ b/razor-fol/src/syntax/formula/qff.rs @@ -1,15 +1,15 @@ -/// Defines a quantifier-free first-order formula of type [`QFF`]. +/// Defines a quantifier-free first-order formula of type [`Qff`]. use super::{Error, Sig, Var, *}; use crate::syntax::term::Complex; use std::fmt; -/// Is the type of the quantifier-free part of formulae types such as [`PNF`] -/// and [`SNF`]. +/// Is the type of the quantifier-free part of formulae types such as [`Pnf`] +/// and [`Snf`]. /// -/// [`PNF`]: crate::transform::PNF -/// [`SNF`]: crate::transform::SNF +/// [`Pnf`]: crate::transform::Pnf +/// [`Snf`]: crate::transform::Snf #[derive(PartialEq, Clone)] -pub enum QFF { +pub enum Qff { /// Is logical top (⊤) or truth. Top, @@ -23,77 +23,77 @@ pub enum QFF { Equals(Equals), /// Is the negation of a formula, wrapping a [`Not`]. - Not(Box>), + Not(Box>), /// Is a conjunction of two formulae, wrapping an [`And`]. - And(Box>), + And(Box>), /// Is a disjunction of two formulae, wrapping an [`Or`]. - Or(Box>), + Or(Box>), /// Is an implication between two formulae, wrapping an [`Implies`]. - Implies(Box>), + Implies(Box>), /// Is an bi-implication between two formulae, wrapping an [`Iff`]. - Iff(Box>), + Iff(Box>), } -impl From> for QFF { +impl From> for Qff { fn from(value: Atom) -> Self { - QFF::Atom(value) + Qff::Atom(value) } } -impl From> for QFF { +impl From> for Qff { fn from(value: Equals) -> Self { - QFF::Equals(value) + Qff::Equals(value) } } -impl From> for QFF { - fn from(value: Not) -> Self { - QFF::Not(Box::new(value)) +impl From> for Qff { + fn from(value: Not) -> Self { + Qff::Not(Box::new(value)) } } -impl From> for QFF { - fn from(value: And) -> Self { - QFF::And(Box::new(value)) +impl From> for Qff { + fn from(value: And) -> Self { + Qff::And(Box::new(value)) } } -impl From> for QFF { - fn from(value: Or) -> Self { - QFF::Or(Box::new(value)) +impl From> for Qff { + fn from(value: Or) -> Self { + Qff::Or(Box::new(value)) } } -impl From> for QFF { - fn from(value: Implies) -> Self { - QFF::Implies(Box::new(value)) +impl From> for Qff { + fn from(value: Implies) -> Self { + Qff::Implies(Box::new(value)) } } -impl From> for QFF { - fn from(value: Iff) -> Self { - QFF::Iff(Box::new(value)) +impl From> for Qff { + fn from(value: Iff) -> Self { + Qff::Iff(Box::new(value)) } } -impl Formula for QFF { +impl Formula for Qff { type Term = Complex; fn signature(&self) -> Result { match self { - QFF::Top => Ok(Sig::new()), - QFF::Bottom => Ok(Sig::new()), - QFF::Atom(this) => this.signature(), - QFF::Equals(this) => this.signature(), - QFF::Not(this) => this.signature(), - QFF::And(this) => this.signature(), - QFF::Or(this) => this.signature(), - QFF::Implies(this) => this.signature(), - QFF::Iff(this) => this.signature(), + Qff::Top => Ok(Sig::new()), + Qff::Bottom => Ok(Sig::new()), + Qff::Atom(this) => this.signature(), + Qff::Equals(this) => this.signature(), + Qff::Not(this) => this.signature(), + Qff::And(this) => this.signature(), + Qff::Or(this) => this.signature(), + Qff::Implies(this) => this.signature(), + Qff::Iff(this) => this.signature(), } } @@ -113,35 +113,35 @@ impl Formula for QFF { fn transform_term(&self, f: &impl Fn(&Complex) -> Complex) -> Self { match self { - QFF::Top | QFF::Bottom => self.clone(), - QFF::Atom(this) => this.transform_term(f).into(), - QFF::Equals(this) => this.transform_term(f).into(), - QFF::Not(this) => this.transform_term(f).into(), - QFF::And(this) => this.transform_term(f).into(), - QFF::Or(this) => this.transform_term(f).into(), - QFF::Implies(this) => this.transform_term(f).into(), - QFF::Iff(this) => this.transform_term(f).into(), + Qff::Top | Qff::Bottom => self.clone(), + Qff::Atom(this) => this.transform_term(f).into(), + Qff::Equals(this) => this.transform_term(f).into(), + Qff::Not(this) => this.transform_term(f).into(), + Qff::And(this) => this.transform_term(f).into(), + Qff::Or(this) => this.transform_term(f).into(), + Qff::Implies(this) => this.transform_term(f).into(), + Qff::Iff(this) => this.transform_term(f).into(), } } } -impl FormulaEx for QFF { +impl FormulaEx for Qff { fn precedence(&self) -> u8 { match self { - QFF::Top => PRECEDENCE_ATOM, - QFF::Bottom => PRECEDENCE_ATOM, - QFF::Atom(this) => this.precedence(), - QFF::Equals(this) => this.precedence(), - QFF::Not(this) => this.precedence(), - QFF::And(this) => this.precedence(), - QFF::Or(this) => this.precedence(), - QFF::Implies(this) => this.precedence(), - QFF::Iff(this) => this.precedence(), + Qff::Top => PRECEDENCE_ATOM, + Qff::Bottom => PRECEDENCE_ATOM, + Qff::Atom(this) => this.precedence(), + Qff::Equals(this) => this.precedence(), + Qff::Not(this) => this.precedence(), + Qff::And(this) => this.precedence(), + Qff::Or(this) => this.precedence(), + Qff::Implies(this) => this.precedence(), + Qff::Iff(this) => this.precedence(), } } } -impl fmt::Display for QFF { +impl fmt::Display for Qff { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { Self::Top => write!(f, "⊤"), @@ -157,7 +157,7 @@ impl fmt::Display for QFF { } } -impl fmt::Debug for QFF { +impl fmt::Debug for Qff { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { Self::Top => write!(f, "⊤"), @@ -189,7 +189,7 @@ mod tests { fn atom_to_string() { assert_eq!( "R()", - QFF::from(Atom { + Qff::from(Atom { predicate: "R".into(), terms: vec![], }) @@ -197,7 +197,7 @@ mod tests { ); assert_eq!( "R(x, y)", - QFF::from(Atom { + Qff::from(Atom { predicate: "R".into(), terms: vec![term!(x), term!(y)], }) @@ -211,7 +211,7 @@ mod tests { let expected: Vec<&Var> = vec![]; assert_eq_sorted_vecs!( expected, - QFF::from(Atom { + Qff::from(Atom { predicate: "R".into(), terms: vec![], }) @@ -222,7 +222,7 @@ mod tests { let expected = vec![v!(x), v!(y)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Atom { + Qff::from(Atom { predicate: "R".into(), terms: vec![term!(x), term!(y)], }) @@ -233,7 +233,7 @@ mod tests { let expected = vec![v!(x), v!(y), v!(z)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Atom { + Qff::from(Atom { predicate: "R".into(), terms: vec![term!(y), term!(g(x, z))], }) @@ -244,7 +244,7 @@ mod tests { let expected = vec![v!(x), v!(z)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Atom { + Qff::from(Atom { predicate: "R".into(), terms: vec![term!(z), term!(f(f(f(f(f(f(x)))))))], }) @@ -255,7 +255,7 @@ mod tests { #[test] fn atom_transform() { - let formula: QFF = Atom { + let formula: Qff = Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(y)], } @@ -268,7 +268,7 @@ mod tests { } }; assert_eq!( - QFF::from(Atom { + Qff::from(Atom { predicate: "P".into(), terms: vec![term!(z), term!(y)], }), @@ -286,7 +286,7 @@ mod tests { }) .unwrap(); sig.add_constant(Const::from("c")); - let formula: QFF = Atom { + let formula: Qff = Atom { predicate: "P".into(), terms: vec![term!(@c)], } @@ -306,7 +306,7 @@ mod tests { }) .unwrap(); sig.add_constant(Const::from("c")); - let formula: QFF = Atom { + let formula: Qff = Atom { predicate: "P".into(), terms: vec![term!(f(x, @c))], } @@ -332,7 +332,7 @@ mod tests { .unwrap(); sig.add_constant(Const::from("c")); sig.add_constant(Const::from("d")); - let formula: QFF = Atom { + let formula: Qff = Atom { predicate: "P".into(), terms: vec![term!(f(x, @c)), term!(@d), term!(f(g(x), y))], } @@ -340,7 +340,7 @@ mod tests { assert_eq!(sig, formula.signature().unwrap()); } { - let formula: QFF = Atom { + let formula: Qff = Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(f(x, y))], } @@ -348,7 +348,7 @@ mod tests { assert!(formula.signature().is_err()); } { - let formula: QFF = Atom { + let formula: Qff = Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(f(y))], } @@ -361,7 +361,7 @@ mod tests { fn equals_to_string() { assert_eq!( "x = y", - QFF::from(Equals { + Qff::from(Equals { left: term!(x), right: term!(y), }) @@ -375,7 +375,7 @@ mod tests { let expected = vec![v!(x), v!(y)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Equals { + Qff::from(Equals { left: term!(x), right: term!(y), }) @@ -386,7 +386,7 @@ mod tests { let expected = vec![v!(x)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Equals { + Qff::from(Equals { left: term!(x), right: term!(g()), }) @@ -397,7 +397,7 @@ mod tests { #[test] fn equals_transform() { - let formula: QFF = Equals { + let formula: Qff = Equals { left: term!(f(x)), right: term!(y), } @@ -410,7 +410,7 @@ mod tests { } }; assert_eq!( - QFF::from(Equals { + Qff::from(Equals { left: term!(z), right: term!(y), }), @@ -428,7 +428,7 @@ mod tests { }) .unwrap(); sig.add_constant(Const::from("c")); - let formula: QFF = Equals { + let formula: Qff = Equals { left: term!(@c), right: term!(@c), } @@ -436,7 +436,7 @@ mod tests { assert_eq!(sig, formula.signature().unwrap()); } { - let formula: QFF = Equals { + let formula: Qff = Equals { left: term!(f(x)), right: term!(f(y)), } @@ -444,7 +444,7 @@ mod tests { assert!(formula.signature().is_ok()); } { - let formula: QFF = Equals { + let formula: Qff = Equals { left: term!(f(x)), right: term!(f(x, y)), } @@ -457,7 +457,7 @@ mod tests { fn not_to_string() { assert_eq!( "¬R(x, y)", - QFF::from(Not { + Qff::from(Not { formula: Atom { predicate: "R".into(), terms: vec![term!(x), term!(y)] @@ -474,7 +474,7 @@ mod tests { let expected: Vec<&Var> = vec![]; assert_eq_sorted_vecs!( expected, - QFF::from(Not { + Qff::from(Not { formula: Atom { predicate: "R".into(), terms: vec![] @@ -488,7 +488,7 @@ mod tests { let expected = vec![v!(x), v!(y)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Not { + Qff::from(Not { formula: Equals { left: term!(x), right: term!(y), @@ -502,7 +502,7 @@ mod tests { let expected = vec![v!(x), v!(y)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Not { + Qff::from(Not { formula: Atom { predicate: "R".into(), terms: vec![term!(x), term!(y)] @@ -516,7 +516,7 @@ mod tests { #[test] fn not_transform() { - let formula: QFF = Not { + let formula: Qff = Not { formula: Atom { predicate: "R".into(), terms: vec![term!(f(x)), term!(y)], @@ -532,7 +532,7 @@ mod tests { } }; assert_eq!( - QFF::from(Not { + Qff::from(Not { formula: Atom { predicate: "R".into(), terms: vec![term!(z), term!(y)], @@ -557,7 +557,7 @@ mod tests { }) .unwrap(); sig.add_constant(Const::from("c")); - let formula: QFF = Not { + let formula: Qff = Not { formula: Atom { predicate: "P".into(), terms: vec![term!(f(@c)), term!(y)], @@ -572,7 +572,7 @@ mod tests { fn and_to_string() { assert_eq!( "P() ∧ Q()", - QFF::from(And { + Qff::from(And { left: Atom { predicate: "P".into(), terms: vec![] @@ -594,7 +594,7 @@ mod tests { let expected: Vec<&Var> = vec![]; assert_eq_sorted_vecs!( expected, - QFF::from(And { + Qff::from(And { left: Atom { predicate: "P".into(), terms: vec![] @@ -613,7 +613,7 @@ mod tests { let expected = vec![v!(x), v!(y), v!(z)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(And { + Qff::from(And { left: Atom { predicate: "P".into(), terms: vec![term!(z), term!(y)] @@ -632,7 +632,7 @@ mod tests { #[test] fn and_transform() { - let formula: QFF = And { + let formula: Qff = And { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -653,7 +653,7 @@ mod tests { } }; assert_eq!( - QFF::from(And { + Qff::from(And { left: Atom { predicate: "P".into(), terms: vec![term!(z)], @@ -689,7 +689,7 @@ mod tests { }) .unwrap(); sig.add_constant(Const::from("c")); - let formula: QFF = And { + let formula: Qff = And { left: Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(y)], @@ -705,7 +705,7 @@ mod tests { assert_eq!(sig, formula.signature().unwrap()); } { - let formula: QFF = And { + let formula: Qff = And { left: Atom { predicate: "P".into(), terms: vec![term!(x)], @@ -721,7 +721,7 @@ mod tests { assert!(formula.signature().is_err()); } { - let formula: QFF = And { + let formula: Qff = And { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -737,7 +737,7 @@ mod tests { assert!(formula.signature().is_ok()); } { - let formula: QFF = And { + let formula: Qff = And { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -758,7 +758,7 @@ mod tests { fn or_to_string() { assert_eq!( "P() ∨ Q()", - QFF::from(Or { + Qff::from(Or { left: Atom { predicate: "P".into(), terms: vec![], @@ -780,7 +780,7 @@ mod tests { let expected: Vec<&Var> = vec![]; assert_eq_sorted_vecs!( expected, - QFF::from(Or { + Qff::from(Or { left: Atom { predicate: "P".into(), terms: vec![] @@ -799,7 +799,7 @@ mod tests { let expected = vec![v!(x), v!(y), v!(z)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Or { + Qff::from(Or { left: Atom { predicate: "P".into(), terms: vec![term!(z), term!(y)] @@ -818,7 +818,7 @@ mod tests { #[test] fn or_transform() { - let formula: QFF = Or { + let formula: Qff = Or { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -839,7 +839,7 @@ mod tests { } }; assert_eq!( - QFF::from(Or { + Qff::from(Or { left: Atom { predicate: "P".into(), terms: vec![term!(z)], @@ -875,7 +875,7 @@ mod tests { }) .unwrap(); sig.add_constant(Const::from("c")); - let formula: QFF = Or { + let formula: Qff = Or { left: Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(y)], @@ -891,7 +891,7 @@ mod tests { assert_eq!(sig, formula.signature().unwrap()); } { - let formula: QFF = Or { + let formula: Qff = Or { left: Atom { predicate: "P".into(), terms: vec![term!(x)], @@ -907,7 +907,7 @@ mod tests { assert!(formula.signature().is_err()); } { - let formula: QFF = Or { + let formula: Qff = Or { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -923,7 +923,7 @@ mod tests { assert!(formula.signature().is_err()); } { - let formula: QFF = Or { + let formula: Qff = Or { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -944,7 +944,7 @@ mod tests { fn implies_to_string() { assert_eq!( "P() → Q()", - QFF::from(Implies { + Qff::from(Implies { premise: Atom { predicate: "P".into(), terms: vec![], @@ -966,7 +966,7 @@ mod tests { let expected: Vec<&Var> = vec![]; assert_eq_sorted_vecs!( expected, - QFF::from(Implies { + Qff::from(Implies { premise: Atom { predicate: "P".into(), terms: vec![], @@ -985,7 +985,7 @@ mod tests { let expected = vec![v!(x), v!(y), v!(z)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Implies { + Qff::from(Implies { premise: Atom { predicate: "P".into(), terms: vec![term!(z), term!(y)], @@ -1004,7 +1004,7 @@ mod tests { #[test] fn implies_transform() { - let formula: QFF = Implies { + let formula: Qff = Implies { premise: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -1025,7 +1025,7 @@ mod tests { } }; assert_eq!( - QFF::from(Implies { + Qff::from(Implies { premise: Atom { predicate: "P".into(), terms: vec![term!(z)], @@ -1061,7 +1061,7 @@ mod tests { }) .unwrap(); sig.add_constant(Const::from("c")); - let formula: QFF = Implies { + let formula: Qff = Implies { premise: Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(y)], @@ -1077,7 +1077,7 @@ mod tests { assert_eq!(sig, formula.signature().unwrap()); } { - let formula: QFF = Implies { + let formula: Qff = Implies { premise: Atom { predicate: "P".into(), terms: vec![term!(x)], @@ -1093,7 +1093,7 @@ mod tests { assert!(formula.signature().is_err()); } { - let formula: QFF = Implies { + let formula: Qff = Implies { premise: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -1109,7 +1109,7 @@ mod tests { assert!(formula.signature().is_err()); } { - let formula: QFF = Implies { + let formula: Qff = Implies { premise: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -1130,7 +1130,7 @@ mod tests { fn iff_to_string() { assert_eq!( "P() ⇔ Q()", - QFF::from(Iff { + Qff::from(Iff { left: Atom { predicate: "P".into(), terms: vec![], @@ -1152,7 +1152,7 @@ mod tests { let expected: Vec<&Var> = vec![]; assert_eq_sorted_vecs!( expected, - QFF::from(Iff { + Qff::from(Iff { left: Atom { predicate: "P".into(), terms: vec![], @@ -1171,7 +1171,7 @@ mod tests { let expected = vec![v!(x), v!(y), v!(z)]; assert_eq_sorted_vecs!( expected.iter().collect::>(), - QFF::from(Iff { + Qff::from(Iff { left: Atom { predicate: "P".into(), terms: vec![term!(z), term!(y)], @@ -1190,7 +1190,7 @@ mod tests { #[test] fn iff_transform() { - let formula: QFF = Iff { + let formula: Qff = Iff { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -1211,7 +1211,7 @@ mod tests { } }; assert_eq!( - QFF::from(Iff { + Qff::from(Iff { left: Atom { predicate: "P".into(), terms: vec![term!(z)], @@ -1247,7 +1247,7 @@ mod tests { }) .unwrap(); sig.add_constant(Const::from("c")); - let formula: QFF = Iff { + let formula: Qff = Iff { left: Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(y)], @@ -1263,7 +1263,7 @@ mod tests { assert_eq!(sig, formula.signature().unwrap()); } { - let formula: QFF = Iff { + let formula: Qff = Iff { left: Atom { predicate: "P".into(), terms: vec![term!(x)], @@ -1279,7 +1279,7 @@ mod tests { assert!(formula.signature().is_err()); } { - let formula: QFF = Iff { + let formula: Qff = Iff { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], @@ -1295,7 +1295,7 @@ mod tests { assert!(formula.signature().is_err()); } { - let formula: QFF = Iff { + let formula: Qff = Iff { left: Atom { predicate: "P".into(), terms: vec![term!(f(x))], diff --git a/razor-fol/src/syntax/macros.rs b/razor-fol/src/syntax/macros.rs index 1c0c521..2687182 100644 --- a/razor-fol/src/syntax/macros.rs +++ b/razor-fol/src/syntax/macros.rs @@ -162,7 +162,7 @@ macro_rules! terms { }; } -/// Parses the input tokens as an [`FOF`]. +/// Parses the input tokens as an [`Fof`]. /// /// **Note:** /// The syntax of the input to this macro resembles the [compact] variation of Razor's texual @@ -177,7 +177,7 @@ macro_rules! terms { /// 2. Unlike the textual form where constants are preceded by `'`, in the macro input, /// constants are preceded by `@`. /// -/// [`FOF`]: crate::syntax::FOF +/// [`Fof`]: crate::syntax::Fof /// [compact]: https://salmans.github.io/rusty-razor/syntax/variations.html /// **Example**: /// ```rust @@ -235,17 +235,17 @@ macro_rules! terms { macro_rules! fof { // Top ('|') => { - $crate::syntax::FOF::Top + $crate::syntax::Fof::Top }; // Bottom (_|_) => { - $crate::syntax::FOF::Bottom + $crate::syntax::Fof::Bottom }; // Atom ($pred:ident ($($t:tt)*)) => { { let ts = $crate::terms!($($t)*); - $crate::syntax::FOF::from( + $crate::syntax::Fof::from( $crate::syntax::Pred::from(stringify!($pred)).app(ts) ) } @@ -335,14 +335,14 @@ macro_rules! fof { { let left = $crate::term!($($left)*); let right = $crate::term!($($right)*); - $crate::syntax::FOF::from($crate::syntax::formula::Equals{left, right}) + $crate::syntax::Fof::from($crate::syntax::formula::Equals{left, right}) } }; (@not ($($fmla:tt)*)) => { - $crate::syntax::FOF::from($crate::syntax::formula::Not{ formula: fof!($($fmla)*) }) + $crate::syntax::Fof::from($crate::syntax::formula::Not{ formula: fof!($($fmla)*) }) }; (@and ($($left:tt)*) ($($right:tt)*)) => { - $crate::syntax::FOF::from( + $crate::syntax::Fof::from( $crate::syntax::formula::And { left: fof!($($left)*), right: fof!($($right)*), @@ -350,7 +350,7 @@ macro_rules! fof { ) }; (@or ($($left:tt)*) ($($right:tt)*)) => { - $crate::syntax::FOF::from( + $crate::syntax::Fof::from( $crate::syntax::formula::Or { left: fof!($($left)*), right: fof!($($right)*), @@ -358,7 +358,7 @@ macro_rules! fof { ) }; (@implies ($($premise:tt)*) ($($consequence:tt)*)) => { - $crate::syntax::FOF::from( + $crate::syntax::Fof::from( $crate::syntax::formula::Implies { premise: fof!($($premise)*), consequence: fof!($($consequence)*), @@ -366,7 +366,7 @@ macro_rules! fof { ) }; (@iff ($($left:tt)*) ($($right:tt)*)) => { - $crate::syntax::FOF::from( + $crate::syntax::Fof::from( $crate::syntax::formula::Iff { left: fof!($($left)*), right: fof!($($right)*), @@ -376,7 +376,7 @@ macro_rules! fof { (@forall ($($v:ident),+) ($($fmla:tt)*)) => { { let vs = vec![$($crate::syntax::Var::from(stringify!($v)),)+]; - $crate::syntax::FOF::from( + $crate::syntax::Fof::from( $crate::syntax::formula::Forall { variables: vs, formula: fof!($($fmla)*), @@ -387,7 +387,7 @@ macro_rules! fof { (@exists ($($v:ident),+) ($($fmla:tt)*)) => { { let vs = vec![$($crate::syntax::Var::from(stringify!($v)),)+]; - $crate::syntax::FOF::from( + $crate::syntax::Fof::from( $crate::syntax::formula::Exists { variables: vs, formula: fof!($($fmla)*), @@ -402,7 +402,7 @@ mod tests { #[test] fn test_macro() { assert_eq!("⊤", fof!('|').to_string()); - assert_eq!("⟘", fof!(_|_).to_string()); + assert_eq!("⟘", fof!(_ | _).to_string()); assert_eq!("P()", fof!(P()).to_string()); assert_eq!("P(x)", fof!(P(x)).to_string()); diff --git a/razor-fol/src/syntax/signature.rs b/razor-fol/src/syntax/signature.rs index d73895b..de787f2 100644 --- a/razor-fol/src/syntax/signature.rs +++ b/razor-fol/src/syntax/signature.rs @@ -156,7 +156,7 @@ impl Default for Sig { #[cfg(test)] mod tests { use super::*; - use crate::syntax::{Formula, FOF}; + use crate::syntax::{Fof, Formula}; #[test] fn test_merge() { @@ -335,8 +335,8 @@ mod tests { sig.add_constant(Const::from("c")); sig.add_constant(Const::from("d")); let formulae = vec![ - "P(f('c), y)".parse::().unwrap(), - "Q(g('d), z)".parse::().unwrap(), + "P(f('c), y)".parse::().unwrap(), + "Q(g('d), z)".parse::().unwrap(), ]; assert_eq!( sig, @@ -364,8 +364,8 @@ mod tests { .unwrap(); sig.add_constant(Const::from("c")); let formulae = vec![ - "P(f('c), y)".parse::().unwrap(), - "P(f('c), y)".parse::().unwrap(), + "P(f('c), y)".parse::().unwrap(), + "P(f('c), y)".parse::().unwrap(), ]; assert_eq!( sig, @@ -393,8 +393,8 @@ mod tests { .unwrap(); sig.add_constant(Const::from("c")); let formulae = vec![ - "P(f('c), y)".parse::().unwrap(), - "P(f('c, d), y)".parse::().unwrap(), + "P(f('c), y)".parse::().unwrap(), + "P(f('c, d), y)".parse::().unwrap(), ]; assert!(Sig::from_signatures( formulae @@ -419,8 +419,8 @@ mod tests { .unwrap(); sig.add_constant(Const::from("c")); let formulae = vec![ - "P(f('c), y)".parse::().unwrap(), - "P(f('c), y, z)".parse::().unwrap(), + "P(f('c), y)".parse::().unwrap(), + "P(f('c), y, z)".parse::().unwrap(), ]; assert!(Sig::from_signatures( formulae diff --git a/razor-fol/src/syntax/term.rs b/razor-fol/src/syntax/term.rs index 36e5632..0db6f40 100644 --- a/razor-fol/src/syntax/term.rs +++ b/razor-fol/src/syntax/term.rs @@ -1,5 +1,5 @@ /*! Defines the syntax for first-order terms. */ -use super::{formula::Equals, signature::FuncSig, Const, Error, Func, Sig, Var, FOF}; +use super::{formula::Equals, signature::FuncSig, Const, Error, Fof, Func, Sig, Var}; use std::{collections::HashMap, fmt, ops::Deref}; /// Is the trait of types that act as terms. @@ -185,8 +185,8 @@ pub enum Complex { impl Complex { /// Returns an [equation] (formula) between `self` and `term`. /// - /// [equation]: crate::syntax::FOF::Equals - pub fn equals(self, term: Self) -> FOF { + /// [equation]: crate::syntax::Fof::Equals + pub fn equals(self, term: Self) -> Fof { Equals { left: self, right: term, @@ -684,8 +684,8 @@ mod tests { #[test] fn test_rename_formula() { assert_eq!( - FOF::Top, - FOF::Top.rename_var(&|v: &Var| { + Fof::Top, + Fof::Top.rename_var(&|v: &Var| { if *v == v!(x) { v!(y) } else { @@ -694,8 +694,8 @@ mod tests { }) ); assert_eq!( - FOF::Bottom, - FOF::Bottom.rename_var(&|v: &Var| { + Fof::Bottom, + Fof::Bottom.rename_var(&|v: &Var| { if *v == v!(x) { v!(y) } else { @@ -850,8 +850,8 @@ mod tests { #[test] fn test_substitute_formula() { assert_eq!( - FOF::Top, - FOF::Top.substitute(&|v: &Var| { + Fof::Top, + Fof::Top.substitute(&|v: &Var| { if *v == v!(x) { term!(y) } else { @@ -860,8 +860,8 @@ mod tests { }) ); assert_eq!( - FOF::Bottom, - FOF::Bottom.substitute(&|v: &Var| { + Fof::Bottom, + Fof::Bottom.substitute(&|v: &Var| { if *v == v!(x) { term!(y) } else { diff --git a/razor-fol/src/transform.rs b/razor-fol/src/transform.rs index 313ec12..db7f0a0 100644 --- a/razor-fol/src/transform.rs +++ b/razor-fol/src/transform.rs @@ -10,21 +10,21 @@ mod relational; mod simplify; mod snf; -pub use cnf::{CNFClauseSet, ToCNF, ToCNFClauseSet, CNF}; -pub use dnf::{DNFClauseSet, ToDNF, ToDNFClauseSet, DNF}; -pub use gnf::{PcfSet, ToGNF, GNF, PCF}; -pub use nnf::{ToNNF, NNF}; -pub use pnf::{ToPNF, PNF}; +pub use cnf::{Cnf, CnfClauseSet, ToCnf, ToCnfClauseSet}; +pub use dnf::{Dnf, DnfClauseSet, ToDnf, ToDnfClauseSet}; +pub use gnf::{Gnf, Pcf, PcfSet, ToGnf}; +pub use nnf::{Nnf, ToNnf}; +pub use pnf::{Pnf, ToPnf}; pub use relational::{FlatClause, Relational, ToRelational}; -pub use snf::{ToSNF, SNF}; +pub use snf::{Snf, ToSnf}; -use crate::syntax::FOF; +use crate::syntax::Fof; use thiserror::Error; /// Is the type of errors arising from inconsistencies when transforming formula types. #[derive(Error, Debug)] pub enum Error { - /// Is returned when a [`FOF`] cannot be forced into a [`GNF`]. + /// Is returned when a [`Fof`] cannot be forced into a [`Gnf`]. #[error("formula `{}` cannot be forced into a GNF", .formula.to_string())] - FofToGnf { formula: FOF }, + FofToGnf { formula: Fof }, } diff --git a/razor-fol/src/transform/cnf.rs b/razor-fol/src/transform/cnf.rs index 2d67ef2..8843d4b 100644 --- a/razor-fol/src/transform/cnf.rs +++ b/razor-fol/src/transform/cnf.rs @@ -1,29 +1,29 @@ -/*! Defines formulae in Conjunctive Normal Form (CNF) and implements an algorithm for -transforming an [`SNF`] to a [`CNF`]. +/*! Defines formulae in Conjunctive Normal Form (CNF) and implements algorithms for +transforming a [`Pnf`] to a [`Cnf`]. -[`SNF`]: crate::transform::SNF +[`Pnf`]: crate::transform::Pnf */ use std::ops::Deref; -use super::{ToPNF, ToSNF, PNF, SNF}; +use super::{Pnf, Snf, ToPnf, ToSnf}; use crate::syntax::{ formula::{ clause::{Clause, ClauseSet, Literal}, Exists, Forall, FormulaEx, *, }, term::Complex, - Error, Sig, Var, FOF, + Error, Fof, Sig, Var, }; use itertools::Itertools; // CNF clauses and clause sets are constructed over complex terms. -type CNFClause = Clause; +type CnfClause = Clause; #[derive(Clone)] -pub struct CNFClauseSet(ClauseSet); +pub struct CnfClauseSet(ClauseSet); -impl Deref for CNFClauseSet { +impl Deref for CnfClauseSet { type Target = ClauseSet; fn deref(&self) -> &Self::Target { @@ -31,36 +31,36 @@ impl Deref for CNFClauseSet { } } -impl From> for CNFClauseSet { +impl From> for CnfClauseSet { fn from(value: ClauseSet) -> Self { Self(value) } } -impl Default for CNFClauseSet { +impl Default for CnfClauseSet { fn default() -> Self { ClauseSet::default().into() } } -/// Represents a [`PNF`] with a matrix in Conjunctive Normal Form (CNF). +/// Represents a [`Pnf`] with a matrix in Conjunctive Normal Form (CNF). /// /// **Hint**: A CNF is a firsts-order formula that is a conjunction of zero or /// more [`Clause`]s where each clause is a disjunction of [`Literal`]s. #[derive(Clone, Debug)] -pub enum CNF { - /// Is the quantifier-free portion of a [`PNF`]. +pub enum Cnf { + /// Is the quantifier-free portion of a [`Pnf`]. Clauses(ClauseSet), /// Is an existentially quantified PNF, wrapping an [`Exists`]. - Exists(Box>), + Exists(Box>), /// Is a universally quantified PNF, wrapping a [`Forall`]. - Forall(Box>), + Forall(Box>), } -impl CNF { - fn clause_to_fof(clause: CNFClause) -> FOF { +impl Cnf { + fn clause_to_fof(clause: CnfClause) -> Fof { clause .into_literals() .into_iter() @@ -72,16 +72,16 @@ impl CNF { Atomic::Equals(this) => this.into(), }, Literal::Neg(neg) => match neg { - Atomic::Atom(this) => FOF::not(this.into()), - Atomic::Equals(this) => FOF::not(this.into()), + Atomic::Atom(this) => Fof::not(this.into()), + Atomic::Equals(this) => Fof::not(this.into()), }, }) .fold1(|item, acc| item.or(acc)) - .unwrap_or(FOF::Bottom) + .unwrap_or(Fof::Bottom) } } -impl FormulaEx for CNF { +impl FormulaEx for Cnf { fn precedence(&self) -> u8 { match self { Self::Clauses(_) => PRECEDENCE_AND, @@ -91,113 +91,113 @@ impl FormulaEx for CNF { } } -impl From> for CNF { +impl From> for Cnf { fn from(value: ClauseSet) -> Self { Self::Clauses(value) } } -impl From for CNF { - fn from(value: CNFClauseSet) -> Self { +impl From for Cnf { + fn from(value: CnfClauseSet) -> Self { value.0.into() } } -/// Is the trait of [`Formula`] types that can be transformed to [`CNF`]. -pub trait ToCNF: Formula { +/// Is the trait of [`Formula`] types that can be transformed to [`Cnf`]. +pub trait ToCnf: Formula { /// Transform `self` to a Conjunctive Normal Form (CNF). /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToCNF; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToCnf; /// - /// let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + /// let formula: Fof = "P(x) <=> Q(y)".parse().unwrap(); /// let cnf = formula.cnf(); /// assert_eq!("(P(x) ∨ ¬Q(y)) ∧ (Q(y) ∨ ¬P(x))", cnf.to_string()); /// ``` - fn cnf(&self) -> CNF; + fn cnf(&self) -> Cnf; } -impl ToCNF for PNF { - fn cnf(&self) -> CNF { - use super::ToNNF; +impl ToCnf for Pnf { + fn cnf(&self) -> Cnf { + use super::ToNnf; // Compromising type safety to avoid implementing a number of // types arising from pairwise combinations of PNF, NNF and NNF: - let nnf = FOF::from(self.clone()).nnf(); + let nnf = Fof::from(self.clone()).nnf(); cnf(distribute_or(&nnf.into())) } } -impl ToCNF for T { - fn cnf(&self) -> CNF { +impl ToCnf for T { + fn cnf(&self) -> Cnf { self.pnf().cnf() } } -impl From for CNF { +impl From for Cnf { fn from(value: T) -> Self { value.cnf() } } -/// Is the trait of [`Formula`] types that can be transformed to [`CNFClauseSet`]. -/// Unlike a [`CNF`], a [`CNFClauseSet`] is quantifier-free; that is, assuming -/// free-variables are universally quantified, the input must be Skolemized (see [`SNF`]). -pub trait ToCNFClauseSet: Formula { +/// Is the trait of [`Formula`] types that can be transformed to [`CnfClauseSet`]. +/// Unlike a [`Cnf`], a [`CnfClauseSet`] is quantifier-free; that is, assuming +/// free-variables are universally quantified, the input must be Skolemized (see [`Snf`]). +pub trait ToCnfClauseSet: Formula { /// Transform `self` to a Conjunctive Normal Form (CNF) clause set. /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToCNFClauseSet; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToCnfClauseSet; /// - /// let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + /// let formula: Fof = "P(x) <=> Q(y)".parse().unwrap(); /// let clauses = formula.cnf_clause_set(); /// assert_eq!("(P(x) ∨ ¬Q(y)) ∧ (Q(y) ∨ ¬P(x))", clauses.to_string()); /// ``` - fn cnf_clause_set(&self) -> CNFClauseSet; + fn cnf_clause_set(&self) -> CnfClauseSet; } -impl ToCNFClauseSet for SNF { - fn cnf_clause_set(&self) -> CNFClauseSet { - use super::ToNNF; - let nnf = FOF::from(self.clone()).nnf(); +impl ToCnfClauseSet for Snf { + fn cnf_clause_set(&self) -> CnfClauseSet { + use super::ToNnf; + let nnf = Fof::from(self.clone()).nnf(); cnf_clause_set(distribute_or(&nnf.into())) } } -impl ToCNFClauseSet for T { - fn cnf_clause_set(&self) -> CNFClauseSet { +impl ToCnfClauseSet for T { + fn cnf_clause_set(&self) -> CnfClauseSet { self.snf().cnf_clause_set() } } -impl From for CNFClauseSet { +impl From for CnfClauseSet { fn from(value: T) -> Self { value.cnf_clause_set() } } -impl std::fmt::Display for CNFClauseSet { +impl std::fmt::Display for CnfClauseSet { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } -impl std::fmt::Display for CNF { +impl std::fmt::Display for Cnf { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } -impl Default for CNF { +impl Default for Cnf { fn default() -> Self { Self::from(ClauseSet::<_>::default()) } } -impl Formula for CNF { +impl Formula for Cnf { type Term = Complex; fn signature(&self) -> Result { @@ -225,60 +225,60 @@ impl Formula for CNF { } } -impl From for FOF { - fn from(value: CNF) -> Self { +impl From for Fof { + fn from(value: Cnf) -> Self { match value { - CNF::Clauses(this) => clause_set_to_fof(this), - CNF::Exists(this) => FOF::exists(this.variables, this.formula.into()), - CNF::Forall(this) => FOF::forall(this.variables, this.formula.into()), + Cnf::Clauses(this) => clause_set_to_fof(this), + Cnf::Exists(this) => Fof::exists(this.variables, this.formula.into()), + Cnf::Forall(this) => Fof::forall(this.variables, this.formula.into()), } } } -impl From<&CNF> for FOF { - fn from(value: &CNF) -> Self { +impl From<&Cnf> for Fof { + fn from(value: &Cnf) -> Self { value.clone().into() } } -fn clause_set_to_fof(value: ClauseSet) -> FOF { +fn clause_set_to_fof(value: ClauseSet) -> Fof { value .into_iter() .sorted() .into_iter() - .map(CNF::clause_to_fof) + .map(Cnf::clause_to_fof) .fold1(|item, acc| item.and(acc)) - .unwrap_or(FOF::Top) + .unwrap_or(Fof::Top) } -impl From for FOF { - fn from(value: CNFClauseSet) -> Self { +impl From for Fof { + fn from(value: CnfClauseSet) -> Self { clause_set_to_fof(value.0) } } -impl From<&CNFClauseSet> for FOF { - fn from(value: &CNFClauseSet) -> Self { +impl From<&CnfClauseSet> for Fof { + fn from(value: &CnfClauseSet) -> Self { value.clone().into() } } // Distributes conjunctions in the given formula. // The function assumes that its input is in NNF and SNF. -fn distribute_or(formula: &FOF) -> FOF { +fn distribute_or(formula: &Fof) -> Fof { match formula { - FOF::Top | FOF::Bottom | FOF::Atom { .. } | FOF::Equals { .. } | FOF::Not { .. } => { + Fof::Top | Fof::Bottom | Fof::Atom { .. } | Fof::Equals { .. } | Fof::Not { .. } => { formula.clone() } - FOF::And(this) => distribute_or(&this.left).and(distribute_or(&this.right)), - FOF::Or(this) => { + Fof::And(this) => distribute_or(&this.left).and(distribute_or(&this.right)), + Fof::Or(this) => { let left = distribute_or(&this.left); let right = distribute_or(&this.right); - if let FOF::And(left) = left { + if let Fof::And(left) = left { let first = left.left.or(right.clone()); let second = left.right.or(right); distribute_or(&first).and(distribute_or(&second)) - } else if let FOF::And(right) = right { + } else if let Fof::And(right) = right { let first = left.clone().or(right.left); let second = left.or(right.right); distribute_or(&first).and(distribute_or(&second)) @@ -286,43 +286,43 @@ fn distribute_or(formula: &FOF) -> FOF { left.or(right) } } - FOF::Forall(this) => FOF::forall(this.variables.clone(), distribute_or(&this.formula)), - FOF::Exists(this) => FOF::exists(this.variables.clone(), distribute_or(&this.formula)), + Fof::Forall(this) => Fof::forall(this.variables.clone(), distribute_or(&this.formula)), + Fof::Exists(this) => Fof::exists(this.variables.clone(), distribute_or(&this.formula)), _ => unreachable!(), // `formula` is both in SNF and NNF } } -fn clause_set(formula: FOF) -> ClauseSet { +fn clause_set(formula: Fof) -> ClauseSet { match formula { - FOF::Top => ClauseSet::default(), - FOF::Bottom => ClauseSet::from(Clause::default()), - FOF::Atom(this) => { + Fof::Top => ClauseSet::default(), + Fof::Bottom => ClauseSet::from(Clause::default()), + Fof::Atom(this) => { let clause = Clause::from(Literal::from(this)); ClauseSet::from(clause) } - FOF::Equals(this) => { + Fof::Equals(this) => { let clause = Clause::from(Literal::from(this)); ClauseSet::from(clause) } - FOF::Not(this) => match this.formula { - FOF::Atom(atom) => { + Fof::Not(this) => match this.formula { + Fof::Atom(atom) => { let lit: Literal<_> = Not { formula: atom }.into(); let clause = Clause::from(lit); ClauseSet::from(clause) } - FOF::Equals(eq) => { + Fof::Equals(eq) => { let lit: Literal<_> = Not { formula: eq }.into(); let clause = Clause::from(lit); ClauseSet::from(clause) } _ => unreachable!(), // `formula` is in NNF }, - FOF::And(this) => { + Fof::And(this) => { let left = clause_set(this.left); let right = clause_set(this.right); left.union(&right) } - FOF::Or(this) => { + Fof::Or(this) => { let left = clause_set(this.left); let right = clause_set(this.right); if left.is_empty() { @@ -342,25 +342,25 @@ fn clause_set(formula: FOF) -> ClauseSet { } } -fn cnf_clause_set(formula: FOF) -> CNFClauseSet { +fn cnf_clause_set(formula: Fof) -> CnfClauseSet { match formula { - FOF::Forall(this) => cnf_clause_set(this.formula), - FOF::Exists(this) => cnf_clause_set(this.formula), + Fof::Forall(this) => cnf_clause_set(this.formula), + Fof::Exists(this) => cnf_clause_set(this.formula), _ => clause_set(formula).into(), } } -fn cnf(formula: FOF) -> CNF { +fn cnf(formula: Fof) -> Cnf { match formula { - FOF::Forall(this) => CNF::Forall(Box::new(Forall { + Fof::Forall(this) => Cnf::Forall(Box::new(Forall { variables: this.variables, formula: cnf(this.formula), })), - FOF::Exists(this) => CNF::Exists(Box::new(Exists { + Fof::Exists(this) => Cnf::Exists(Box::new(Exists { variables: this.variables, formula: cnf(this.formula), })), - _ => CNF::Clauses(clause_set(formula)), + _ => Cnf::Clauses(clause_set(formula)), } } @@ -376,95 +376,95 @@ mod tests { term, v, }; - fn cnf(formula: &FOF) -> FOF { + fn cnf(formula: &Fof) -> Fof { formula.pnf().cnf().into() } - fn cnf_clause_set(formula: &FOF) -> FOF { + fn cnf_clause_set(formula: &Fof) -> Fof { formula.snf().cnf_clause_set().into() } #[test] fn test_cnf() { { - let formula: FOF = "true".parse().unwrap(); + let formula: Fof = "true".parse().unwrap(); assert_debug_string!("true", cnf(&formula)); } { - let formula: FOF = "false".parse().unwrap(); + let formula: Fof = "false".parse().unwrap(); assert_debug_string!("false", cnf(&formula)); } { - let formula: FOF = "P(f(), g(f(), f()))".parse().unwrap(); + let formula: Fof = "P(f(), g(f(), f()))".parse().unwrap(); assert_debug_string!("P(f(), g(f(), f()))", cnf(&formula)); } { - let formula: FOF = "P(x)".parse().unwrap(); + let formula: Fof = "P(x)".parse().unwrap(); assert_debug_string!("P(x)", cnf(&formula)); } { - let formula: FOF = "x=y".parse().unwrap(); + let formula: Fof = "x=y".parse().unwrap(); assert_debug_string!("x = y", cnf(&formula)); } { - let formula: FOF = "P(x) & Q(y)".parse().unwrap(); + let formula: Fof = "P(x) & Q(y)".parse().unwrap(); assert_debug_string!("P(x) & Q(y)", cnf(&formula)); } { - let formula: FOF = "P(x) | Q(y)".parse().unwrap(); + let formula: Fof = "P(x) | Q(y)".parse().unwrap(); assert_debug_string!("P(x) | Q(y)", cnf(&formula)); } { - let formula: FOF = "P(x) -> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) -> Q(y)".parse().unwrap(); assert_debug_string!("Q(y) | ~P(x)", cnf(&formula)); } { - let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) <=> Q(y)".parse().unwrap(); assert_debug_string!("(P(x) | ~Q(y)) & (Q(y) | ~P(x))", cnf(&formula)); } { - let formula: FOF = "!x. P(x)".parse().unwrap(); + let formula: Fof = "!x. P(x)".parse().unwrap(); assert_debug_string!("! x. P(x)", cnf(&formula)); } { - let formula: FOF = "!x. P(f(), g(f(), x))".parse().unwrap(); + let formula: Fof = "!x. P(f(), g(f(), x))".parse().unwrap(); assert_debug_string!("! x. P(f(), g(f(), x))", cnf(&formula)); } // quantifier-free formulae { - let formula: FOF = "~((P(x1) | P(x2)) and Q(y))".parse().unwrap(); + let formula: Fof = "~((P(x1) | P(x2)) and Q(y))".parse().unwrap(); assert_debug_string!("(~P(x1) | ~Q(y)) & (~P(x2) | ~Q(y))", cnf(&formula)); } { - let formula: FOF = "P(x) | ~(Q(x) -> Q(y))".parse().unwrap(); + let formula: Fof = "P(x) | ~(Q(x) -> Q(y))".parse().unwrap(); assert_debug_string!("(P(x) | Q(x)) & (P(x) | ~Q(y))", cnf(&formula)); } { - let formula: FOF = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); + let formula: Fof = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); assert_debug_string!("(R(z) | ~P(x)) & (R(z) | ~Q(y))", cnf(&formula)); } { - let formula: FOF = "P(x) | ~(Q(x) <=> Q(y))".parse().unwrap(); + let formula: Fof = "P(x) | ~(Q(x) <=> Q(y))".parse().unwrap(); assert_debug_string!( "((((P(x) | Q(x)) | Q(y)) & ((P(x) | Q(x)) | ~Q(x))) & ((P(x) | Q(y)) | ~Q(y))) & ((P(x) | ~Q(x)) | ~Q(y))", cnf(&formula)); } { - let formula: FOF = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); + let formula: Fof = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); assert_debug_string!( "(((P(x) | Q(y)) | ~R(z)) & (R(z) | ~P(x))) & (R(z) | ~Q(y))", cnf(&formula), ); } { - let formula: FOF = "P(x) | (Q(x) | (R(y) & R(z)))".parse().unwrap(); + let formula: Fof = "P(x) | (Q(x) | (R(y) & R(z)))".parse().unwrap(); assert_debug_string!( "((P(x) | Q(x)) | R(y)) & ((P(x) | Q(x)) | R(z))", cnf(&formula), ); } { - let formula: FOF = "(P(x1) & P(x2)) | (Q(x1) & Q(x2))".parse().unwrap(); + let formula: Fof = "(P(x1) & P(x2)) | (Q(x1) & Q(x2))".parse().unwrap(); assert_debug_string!( "(((P(x1) | Q(x1)) & (P(x1) | Q(x2))) & (P(x2) | Q(x1))) & (P(x2) | Q(x2))", cnf(&formula), @@ -472,49 +472,49 @@ mod tests { } //random formulae { - let formula: FOF = "?x. P(x)".parse().unwrap(); + let formula: Fof = "?x. P(x)".parse().unwrap(); assert_debug_string!("? x. P(x)", cnf(&formula)); } { - let formula: FOF = "?x. (P(x) & Q(f(), x))".parse().unwrap(); + let formula: Fof = "?x. (P(x) & Q(f(), x))".parse().unwrap(); assert_debug_string!("? x. (P(x) & Q(f(), x))", cnf(&formula)); } { - let formula: FOF = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); + let formula: Fof = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); assert_debug_string!("! x. (! y. ((R(x) | ~P(y)) | ~Q(x, y)))", cnf(&formula)); } { - let formula: FOF = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); + let formula: Fof = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); assert_debug_string!("! x. (! y. ((~P(x) | ~Q(y)) | ~R(x, y)))", cnf(&formula)); } { - let formula: FOF = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); + let formula: Fof = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); assert_debug_string!( "! y. (! x. ((Q(y) | ~P(y, x)) & (Q(y) | ~Q(x))))", cnf(&formula) ); } { - let formula: FOF = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); + let formula: Fof = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); assert_debug_string!( "! y. (? x. ((Q(y) | ~P(y, x)) & (Q(y) | ~Q(x))))", cnf(&formula), ); } { - let formula: FOF = "?x. ?y. P(x, y)".parse().unwrap(); + let formula: Fof = "?x. ?y. P(x, y)".parse().unwrap(); assert_debug_string!("? x. (? y. P(x, y))", cnf(&formula)); } { - let formula: FOF = "?x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "?x, y. P(x, y)".parse().unwrap(); assert_debug_string!("? x, y. P(x, y)", cnf(&formula)); } { - let formula: FOF = "!x. ?y. P(x, y)".parse().unwrap(); + let formula: Fof = "!x. ?y. P(x, y)".parse().unwrap(); assert_debug_string!("! x. (? y. P(x, y))", cnf(&formula)); } { - let formula: FOF = + let formula: Fof = "R(z) -> ?u. (!x, y. (P(u, x) & ~? u, x, w. (Q(u, x, y) | (w = f(u)))))" .parse() .unwrap(); @@ -524,7 +524,7 @@ mod tests { ); } { - let formula: FOF = "!x. (!y. (P(y) -> Q(x, y)) -> ?y. Q(y, x))" + let formula: Fof = "!x. (!y. (P(y) -> Q(x, y)) -> ?y. Q(y, x))" .parse() .unwrap(); assert_debug_string!( @@ -533,7 +533,7 @@ mod tests { ); } { - let formula: FOF = "!x. ((!y. (P(y) -> Q(x, y))) -> ?y. Q(y, x))" + let formula: Fof = "!x. ((!y. (P(y) -> Q(x, y))) -> ?y. Q(y, x))" .parse() .unwrap(); assert_debug_string!( @@ -542,7 +542,7 @@ mod tests { ); } { - let formula: FOF = "?x. (!y, z. (P(x) & ((Q(x, y) & ~(y = z)) -> ~Q(x, z))))" + let formula: Fof = "?x. (!y, z. (P(x) & ((Q(x, y) & ~(y = z)) -> ~Q(x, z))))" .parse() .unwrap(); assert_debug_string!( @@ -551,7 +551,7 @@ mod tests { ); } { - let formula: FOF = "!x. (P(x) -> (!y. (P(y) -> P(f(x, y))) & ~!y. (Q(x, y) -> P(y))))" + let formula: Fof = "!x. (P(x) -> (!y. (P(y) -> P(f(x, y))) & ~!y. (Q(x, y) -> P(y))))" .parse() .unwrap(); assert_debug_string!( @@ -563,87 +563,87 @@ mod tests { #[test] fn test_cnf_clause_set() { { - let formula: FOF = "true".parse().unwrap(); + let formula: Fof = "true".parse().unwrap(); assert_debug_string!("true", cnf_clause_set(&formula)); } { - let formula: FOF = "false".parse().unwrap(); + let formula: Fof = "false".parse().unwrap(); assert_debug_string!("false", cnf_clause_set(&formula)); } { - let formula: FOF = "P(f(), g(f(), f()))".parse().unwrap(); + let formula: Fof = "P(f(), g(f(), f()))".parse().unwrap(); assert_debug_string!("P(f(), g(f(), f()))", cnf_clause_set(&formula)); } { - let formula: FOF = "P(x)".parse().unwrap(); + let formula: Fof = "P(x)".parse().unwrap(); assert_debug_string!("P(x)", cnf_clause_set(&formula)); } { - let formula: FOF = "x=y".parse().unwrap(); + let formula: Fof = "x=y".parse().unwrap(); assert_debug_string!("x = y", cnf_clause_set(&formula)); } { - let formula: FOF = "P(x) & Q(y)".parse().unwrap(); + let formula: Fof = "P(x) & Q(y)".parse().unwrap(); assert_debug_string!("P(x) & Q(y)", cnf_clause_set(&formula)); } { - let formula: FOF = "P(x) | Q(y)".parse().unwrap(); + let formula: Fof = "P(x) | Q(y)".parse().unwrap(); assert_debug_string!("P(x) | Q(y)", cnf_clause_set(&formula)); } { - let formula: FOF = "P(x) -> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) -> Q(y)".parse().unwrap(); assert_debug_string!("Q(y) | ~P(x)", cnf_clause_set(&formula)); } { - let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) <=> Q(y)".parse().unwrap(); assert_debug_string!("(P(x) | ~Q(y)) & (Q(y) | ~P(x))", cnf_clause_set(&formula)); } { - let formula: FOF = "!x. P(x)".parse().unwrap(); + let formula: Fof = "!x. P(x)".parse().unwrap(); assert_debug_string!("P(x)", cnf_clause_set(&formula)); } { - let formula: FOF = "!x. P(f(), g(f(), x))".parse().unwrap(); + let formula: Fof = "!x. P(f(), g(f(), x))".parse().unwrap(); assert_debug_string!("P(f(), g(f(), x))", cnf_clause_set(&formula)); } // quantifier-free formulae { - let formula: FOF = "~((P(x1) | P(x2)) and Q(y))".parse().unwrap(); + let formula: Fof = "~((P(x1) | P(x2)) and Q(y))".parse().unwrap(); assert_debug_string!( "(~P(x1) | ~Q(y)) & (~P(x2) | ~Q(y))", cnf_clause_set(&formula) ); } { - let formula: FOF = "P(x) | ~(Q(x) -> Q(y))".parse().unwrap(); + let formula: Fof = "P(x) | ~(Q(x) -> Q(y))".parse().unwrap(); assert_debug_string!("(P(x) | Q(x)) & (P(x) | ~Q(y))", cnf_clause_set(&formula)); } { - let formula: FOF = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); + let formula: Fof = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); assert_debug_string!("(R(z) | ~P(x)) & (R(z) | ~Q(y))", cnf_clause_set(&formula)); } { - let formula: FOF = "P(x) | ~(Q(x) <=> Q(y))".parse().unwrap(); + let formula: Fof = "P(x) | ~(Q(x) <=> Q(y))".parse().unwrap(); assert_debug_string!( "((((P(x) | Q(x)) | Q(y)) & ((P(x) | Q(x)) | ~Q(x))) & ((P(x) | Q(y)) | ~Q(y))) & ((P(x) | ~Q(x)) | ~Q(y))", cnf_clause_set(&formula)); } { - let formula: FOF = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); + let formula: Fof = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); assert_debug_string!( "(((P(x) | Q(y)) | ~R(z)) & (R(z) | ~P(x))) & (R(z) | ~Q(y))", cnf_clause_set(&formula), ); } { - let formula: FOF = "P(x) | (Q(x) | (R(y) & R(z)))".parse().unwrap(); + let formula: Fof = "P(x) | (Q(x) | (R(y) & R(z)))".parse().unwrap(); assert_debug_string!( "((P(x) | Q(x)) | R(y)) & ((P(x) | Q(x)) | R(z))", cnf_clause_set(&formula), ); } { - let formula: FOF = "(P(x1) & P(x2)) | (Q(x1) & Q(x2))".parse().unwrap(); + let formula: Fof = "(P(x1) & P(x2)) | (Q(x1) & Q(x2))".parse().unwrap(); assert_debug_string!( "(((P(x1) | Q(x1)) & (P(x1) | Q(x2))) & (P(x2) | Q(x1))) & (P(x2) | Q(x2))", cnf_clause_set(&formula), @@ -651,49 +651,49 @@ mod tests { } //random formulae { - let formula: FOF = "?x. P(x)".parse().unwrap(); + let formula: Fof = "?x. P(x)".parse().unwrap(); assert_debug_string!("P('c#0)", cnf_clause_set(&formula)); } { - let formula: FOF = "?x. (P(x) & Q(f(), x))".parse().unwrap(); + let formula: Fof = "?x. (P(x) & Q(f(), x))".parse().unwrap(); assert_debug_string!("P('c#0) & Q(f(), 'c#0)", cnf_clause_set(&formula)); } { - let formula: FOF = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); + let formula: Fof = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); assert_debug_string!("(R(x) | ~P(y)) | ~Q(x, y)", cnf_clause_set(&formula)); } { - let formula: FOF = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); + let formula: Fof = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); assert_debug_string!("(~P(x) | ~Q(y)) | ~R(x, y)", cnf_clause_set(&formula)); } { - let formula: FOF = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); + let formula: Fof = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); assert_debug_string!( "(Q(y) | ~P(y, x)) & (Q(y) | ~Q(x))", cnf_clause_set(&formula) ); } { - let formula: FOF = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); + let formula: Fof = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); assert_debug_string!( "(Q(y) | ~P(y, f#0(y))) & (Q(y) | ~Q(f#0(y)))", cnf_clause_set(&formula), ); } { - let formula: FOF = "?x. ?y. P(x, y)".parse().unwrap(); + let formula: Fof = "?x. ?y. P(x, y)".parse().unwrap(); assert_debug_string!("P('c#0, 'c#1)", cnf_clause_set(&formula)); } { - let formula: FOF = "?x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "?x, y. P(x, y)".parse().unwrap(); assert_debug_string!("P('c#0, 'c#1)", cnf_clause_set(&formula)); } { - let formula: FOF = "!x. ?y. P(x, y)".parse().unwrap(); + let formula: Fof = "!x. ?y. P(x, y)".parse().unwrap(); assert_debug_string!("P(x, f#0(x))", cnf_clause_set(&formula)); } { - let formula: FOF = + let formula: Fof = "R(z) -> ?u. (!x, y. (P(u, x) & ~? u, x, w. (Q(u, x, y) | (w = f(u)))))" .parse() .unwrap(); @@ -703,7 +703,7 @@ mod tests { ); } { - let formula: FOF = "!x. (!y. (P(y) -> Q(x, y)) -> ?y. Q(y, x))" + let formula: Fof = "!x. (!y. (P(y) -> Q(x, y)) -> ?y. Q(y, x))" .parse() .unwrap(); assert_debug_string!( @@ -712,7 +712,7 @@ mod tests { ); } { - let formula: FOF = "!x. ((!y. (P(y) -> Q(x, y))) -> ?y. Q(y, x))" + let formula: Fof = "!x. ((!y. (P(y) -> Q(x, y))) -> ?y. Q(y, x))" .parse() .unwrap(); assert_debug_string!( @@ -721,7 +721,7 @@ mod tests { ); } { - let formula: FOF = "?x. (!y, z. (P(x) & ((Q(x, y) & ~(y = z)) -> ~Q(x, z))))" + let formula: Fof = "?x. (!y, z. (P(x) & ((Q(x, y) & ~(y = z)) -> ~Q(x, z))))" .parse() .unwrap(); assert_debug_string!( @@ -730,7 +730,7 @@ mod tests { ); } { - let formula: FOF = "!x. (P(x) -> (!y. (P(y) -> P(f(x, y))) & ~!y. (Q(x, y) -> P(y))))" + let formula: Fof = "!x. (P(x) -> (!y. (P(y) -> P(f(x, y))) & ~!y. (Q(x, y) -> P(y))))" .parse() .unwrap(); assert_debug_string!( @@ -766,7 +766,7 @@ mod tests { }; assert_eq!( fof!({ [P(y, z)] & [Q(z)] } & { [R(y)] | [R(z)] }), - FOF::from(cnf.transform_term(&f)) + Fof::from(cnf.transform_term(&f)) ); } diff --git a/razor-fol/src/transform/dnf.rs b/razor-fol/src/transform/dnf.rs index 7a97017..8c13ea2 100644 --- a/razor-fol/src/transform/dnf.rs +++ b/razor-fol/src/transform/dnf.rs @@ -1,34 +1,34 @@ /*! Defines formulae in Disjunctive Normal Form (DNF) and implements an algorithm for -transforming an [`SNF`] to a [`DNF`]. +transforming a [`Pnf`] to a [`Dnf`]. -[`SNF`]: crate::transform::SNF +[`Pnf`]: crate::transform::Pnf */ use std::ops::Deref; -use super::{ToPNF, ToSNF, PNF, SNF}; +use super::{Pnf, Snf, ToPnf, ToSnf}; use crate::syntax::{ formula::{ clause::{Clause, ClauseSet, Literal}, Exists, Forall, *, }, term::Complex, - Error, Sig, Var, FOF, + Error, Fof, Sig, Var, }; use itertools::Itertools; // DNF clauses and clause sets are constructed over complex terms. -type DNFClause = Clause; +type DnfClause = Clause; #[derive(Clone)] -pub struct DNFClauseSet(ClauseSet); +pub struct DnfClauseSet(ClauseSet); -impl From> for DNFClauseSet { +impl From> for DnfClauseSet { fn from(value: ClauseSet) -> Self { Self(value) } } -impl Deref for DNFClauseSet { +impl Deref for DnfClauseSet { type Target = ClauseSet; fn deref(&self) -> &Self::Target { @@ -36,24 +36,24 @@ impl Deref for DNFClauseSet { } } -/// Represents a [`PNF`] with a matrix in Disjunctive Normal Form (DNF). +/// Represents a [`Pnf`] with a matrix in Disjunctive Normal Form (DNF). /// /// **Hint**: A DNF is a firsts-order formula that is a disjunction of zero or /// more [`Clause`]s where each clause is a conjunction of [`Literal`]s. #[derive(Clone)] -pub enum DNF { - /// Is the quantifier-free portion of a [`PNF`]. +pub enum Dnf { + /// Is the quantifier-free portion of a [`Pnf`]. Clauses(ClauseSet), /// Is an existentially quantified PNF, wrapping an [`Exists`]. - Exists(Box>), + Exists(Box>), /// Is a universally quantified PNF, wrapping a [`Forall`]. - Forall(Box>), + Forall(Box>), } -impl DNF { - fn clause_to_fof(clause: DNFClause) -> FOF { +impl Dnf { + fn clause_to_fof(clause: DnfClause) -> Fof { clause .into_literals() .into_iter() @@ -65,47 +65,47 @@ impl DNF { Atomic::Equals(this) => this.into(), }, Literal::Neg(neg) => match neg { - Atomic::Atom(this) => FOF::not(this.into()), - Atomic::Equals(this) => FOF::not(this.into()), + Atomic::Atom(this) => Fof::not(this.into()), + Atomic::Equals(this) => Fof::not(this.into()), }, }) .fold1(|item, acc| item.and(acc)) - .unwrap_or(FOF::Top) + .unwrap_or(Fof::Top) } } -impl FormulaEx for DNF { +impl FormulaEx for Dnf { fn precedence(&self) -> u8 { match self { - DNF::Clauses(_) => PRECEDENCE_OR, - DNF::Exists(this) => this.precedence(), - DNF::Forall(this) => this.precedence(), + Dnf::Clauses(_) => PRECEDENCE_OR, + Dnf::Exists(this) => this.precedence(), + Dnf::Forall(this) => this.precedence(), } } } -impl From> for DNF { +impl From> for Dnf { fn from(value: ClauseSet) -> Self { Self::Clauses(value) } } -impl From for DNF { - fn from(value: DNFClauseSet) -> Self { +impl From for Dnf { + fn from(value: DnfClauseSet) -> Self { value.0.into() } } -/// Is the trait of [`Formula`] types that can be transformed to [`DNF`]. -pub trait ToDNF: Formula { +/// Is the trait of [`Formula`] types that can be transformed to [`Dnf`]. +pub trait ToDnf: Formula { /// Transform `self` to a Disjunctive Normal Form (DNF). /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToDNF; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToDnf; /// - /// let formula: FOF = "P(x) iff Q(y)".parse().unwrap(); + /// let formula: Fof = "P(x) iff Q(y)".parse().unwrap(); /// let dnf = formula.dnf(); /// /// assert_eq!( @@ -113,44 +113,44 @@ pub trait ToDNF: Formula { /// dnf.to_string() /// ); /// ``` - fn dnf(&self) -> DNF; + fn dnf(&self) -> Dnf; } -impl ToDNF for PNF { - fn dnf(&self) -> DNF { - use super::ToNNF; +impl ToDnf for Pnf { + fn dnf(&self) -> Dnf { + use super::ToNnf; // Compromising type safety to avoid implementing a number of // types arising from pairwise combinations of PNF, SNF and NNF: - let nnf = FOF::from(self.clone()).nnf(); + let nnf = Fof::from(self.clone()).nnf(); dnf(distribute_and(&nnf.into())) } } -impl ToDNF for T { - fn dnf(&self) -> DNF { +impl ToDnf for T { + fn dnf(&self) -> Dnf { self.pnf().dnf() } } -impl From for DNF { +impl From for Dnf { fn from(value: T) -> Self { value.dnf() } } -/// Is the trait of [`Formula`] types that can be transformed to [`DNFClauseSet`]. -/// Unlike a [`DNF`], a [`DNFClauseSet`] is quantifier-free; that is, assuming -/// free-variables are universally quantified, the input must be Skolemized (see [`SNF`]). -pub trait ToDNFClauseSet: Formula { +/// Is the trait of [`Formula`] types that can be transformed to [`DnfClauseSet`]. +/// Unlike a [`Dnf`], a [`DnfClauseSet`] is quantifier-free; that is, assuming +/// free-variables are universally quantified, the input must be Skolemized (see [`Snf`]). +pub trait ToDnfClauseSet: Formula { /// Transform `self` to a Conjunctive Normal Form (DNF) clause set. /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToDNFClauseSet; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToDnfClauseSet; /// - /// let formula: FOF = "P(x) iff Q(y)".parse().unwrap(); + /// let formula: Fof = "P(x) iff Q(y)".parse().unwrap(); /// let clauses = formula.dnf_clause_set(); /// /// assert_eq!( @@ -158,48 +158,48 @@ pub trait ToDNFClauseSet: Formula { /// clauses.to_string() /// ); /// ``` - fn dnf_clause_set(&self) -> DNFClauseSet; + fn dnf_clause_set(&self) -> DnfClauseSet; } -impl ToDNFClauseSet for SNF { - fn dnf_clause_set(&self) -> DNFClauseSet { - use super::ToNNF; - let nnf = FOF::from(self.clone()).nnf(); +impl ToDnfClauseSet for Snf { + fn dnf_clause_set(&self) -> DnfClauseSet { + use super::ToNnf; + let nnf = Fof::from(self.clone()).nnf(); dnf_clause_set(distribute_and(&nnf.into())) } } -impl ToDNFClauseSet for T { - fn dnf_clause_set(&self) -> DNFClauseSet { +impl ToDnfClauseSet for T { + fn dnf_clause_set(&self) -> DnfClauseSet { self.snf().dnf_clause_set() } } -impl From for DNFClauseSet { +impl From for DnfClauseSet { fn from(value: T) -> Self { value.dnf_clause_set() } } -impl std::fmt::Display for DNFClauseSet { +impl std::fmt::Display for DnfClauseSet { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } -impl std::fmt::Display for DNF { +impl std::fmt::Display for Dnf { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } -impl Default for DNF { +impl Default for Dnf { fn default() -> Self { Self::Clauses(ClauseSet::<_>::default()) } } -impl Formula for DNF { +impl Formula for Dnf { type Term = Complex; fn signature(&self) -> Result { @@ -227,97 +227,97 @@ impl Formula for DNF { } } -impl From for FOF { - fn from(value: DNF) -> Self { +impl From for Fof { + fn from(value: Dnf) -> Self { match value { - DNF::Clauses(this) => clause_set_to_fof(this), - DNF::Exists(this) => FOF::exists(this.variables, this.formula.into()), - DNF::Forall(this) => FOF::forall(this.variables, this.formula.into()), + Dnf::Clauses(this) => clause_set_to_fof(this), + Dnf::Exists(this) => Fof::exists(this.variables, this.formula.into()), + Dnf::Forall(this) => Fof::forall(this.variables, this.formula.into()), } } } -impl From<&DNF> for FOF { - fn from(value: &DNF) -> Self { +impl From<&Dnf> for Fof { + fn from(value: &Dnf) -> Self { value.clone().into() } } -fn clause_set_to_fof(value: ClauseSet) -> FOF { +fn clause_set_to_fof(value: ClauseSet) -> Fof { value .into_iter() .sorted() .into_iter() - .map(DNF::clause_to_fof) + .map(Dnf::clause_to_fof) .fold1(|item, acc| item.or(acc)) - .unwrap_or(FOF::Bottom) + .unwrap_or(Fof::Bottom) } -impl From for FOF { - fn from(value: DNFClauseSet) -> Self { +impl From for Fof { + fn from(value: DnfClauseSet) -> Self { clause_set_to_fof(value.0) } } -impl From<&DNFClauseSet> for FOF { - fn from(value: &DNFClauseSet) -> Self { +impl From<&DnfClauseSet> for Fof { + fn from(value: &DnfClauseSet) -> Self { value.clone().into() } } // Distributes disjunction in the given formula. The function assumes that its input is an NNF. -fn distribute_and(formula: &FOF) -> FOF { +fn distribute_and(formula: &Fof) -> Fof { match formula { - FOF::Top | FOF::Bottom | FOF::Atom { .. } | FOF::Equals { .. } | FOF::Not { .. } => { + Fof::Top | Fof::Bottom | Fof::Atom { .. } | Fof::Equals { .. } | Fof::Not { .. } => { formula.clone() } - FOF::Or(this) => distribute_and(&this.left).or(distribute_and(&this.right)), - FOF::And(this) => { + Fof::Or(this) => distribute_and(&this.left).or(distribute_and(&this.right)), + Fof::And(this) => { let left = distribute_and(&this.left); let right = distribute_and(&this.right); - if let FOF::Or(left) = left { + if let Fof::Or(left) = left { let first = left.left.and(right.clone()); let second = left.right.and(right); distribute_and(&first).or(distribute_and(&second)) - } else if let FOF::Or(right) = right { + } else if let Fof::Or(right) = right { distribute_and(&left.clone().and(right.left)) .or(distribute_and(&left.and(right.right))) } else { left.and(right) } } - FOF::Forall(this) => FOF::forall(this.variables.clone(), distribute_and(&this.formula)), - FOF::Exists(this) => FOF::exists(this.variables.clone(), distribute_and(&this.formula)), + Fof::Forall(this) => Fof::forall(this.variables.clone(), distribute_and(&this.formula)), + Fof::Exists(this) => Fof::exists(this.variables.clone(), distribute_and(&this.formula)), _ => unreachable!(), // `formula` is both in SNF and NNF } } -fn clause_set(formula: FOF) -> ClauseSet { +fn clause_set(formula: Fof) -> ClauseSet { match formula { - FOF::Top => ClauseSet::from(Clause::default()), - FOF::Bottom => ClauseSet::default(), - FOF::Atom(this) => { + Fof::Top => ClauseSet::from(Clause::default()), + Fof::Bottom => ClauseSet::default(), + Fof::Atom(this) => { let clause = Clause::from(Literal::from(this)); ClauseSet::from(clause) } - FOF::Equals(this) => { + Fof::Equals(this) => { let clause = Clause::from(Literal::from(this)); ClauseSet::from(clause) } - FOF::Not(this) => match this.formula { - FOF::Atom(atom) => { + Fof::Not(this) => match this.formula { + Fof::Atom(atom) => { let lit: Literal<_> = Not { formula: atom }.into(); let clause = Clause::from(lit); ClauseSet::from(clause) } - FOF::Equals(eq) => { + Fof::Equals(eq) => { let lit: Literal<_> = Not { formula: eq }.into(); let clause = Clause::from(lit); ClauseSet::from(clause) } _ => unreachable!(), // `formula` is in NNF }, - FOF::And(this) => { + Fof::And(this) => { let left = clause_set(this.left); let right = clause_set(this.right); if left.is_empty() { @@ -333,7 +333,7 @@ fn clause_set(formula: FOF) -> ClauseSet { unreachable!() // Conjunction is distributed over disjunction in `formula` } } - FOF::Or(this) => { + Fof::Or(this) => { let left = clause_set(this.left); let right = clause_set(this.right); left.union(&right) @@ -342,25 +342,25 @@ fn clause_set(formula: FOF) -> ClauseSet { } } -fn dnf_clause_set(formula: FOF) -> DNFClauseSet { +fn dnf_clause_set(formula: Fof) -> DnfClauseSet { match formula { - FOF::Exists(this) => dnf_clause_set(this.formula), - FOF::Forall(this) => dnf_clause_set(this.formula), + Fof::Exists(this) => dnf_clause_set(this.formula), + Fof::Forall(this) => dnf_clause_set(this.formula), _ => clause_set(formula).into(), } } -fn dnf(formula: FOF) -> DNF { +fn dnf(formula: Fof) -> Dnf { match formula { - FOF::Forall(this) => DNF::Forall(Box::new(Forall { + Fof::Forall(this) => Dnf::Forall(Box::new(Forall { variables: this.variables, formula: dnf(this.formula), })), - FOF::Exists(this) => DNF::Exists(Box::new(Exists { + Fof::Exists(this) => Dnf::Exists(Box::new(Exists { variables: this.variables, formula: dnf(this.formula), })), - _ => DNF::Clauses(clause_set(formula)), + _ => Dnf::Clauses(clause_set(formula)), } } @@ -376,90 +376,90 @@ mod tests { term, v, }; - fn dnf_clause_set(formula: &FOF) -> FOF { + fn dnf_clause_set(formula: &Fof) -> Fof { formula.snf().dnf_clause_set().into() } #[test] fn test_dnf() { { - let formula: FOF = "true".parse().unwrap(); + let formula: Fof = "true".parse().unwrap(); assert_debug_string!("true", dnf_clause_set(&formula)); } { - let formula: FOF = "false".parse().unwrap(); + let formula: Fof = "false".parse().unwrap(); assert_debug_string!("false", dnf_clause_set(&formula)); } { - let formula: FOF = "P(f(), g(f(), f()))".parse().unwrap(); + let formula: Fof = "P(f(), g(f(), f()))".parse().unwrap(); assert_debug_string!("P(f(), g(f(), f()))", dnf_clause_set(&formula)); } { - let formula: FOF = "P(x)".parse().unwrap(); + let formula: Fof = "P(x)".parse().unwrap(); assert_debug_string!("P(x)", dnf_clause_set(&formula)); } { - let formula: FOF = "x=y".parse().unwrap(); + let formula: Fof = "x=y".parse().unwrap(); assert_debug_string!("x = y", dnf_clause_set(&formula)); } { - let formula: FOF = "P(x) & Q(y)".parse().unwrap(); + let formula: Fof = "P(x) & Q(y)".parse().unwrap(); assert_debug_string!("P(x) & Q(y)", dnf_clause_set(&formula)); } { - let formula: FOF = "P(x) | Q(y)".parse().unwrap(); + let formula: Fof = "P(x) | Q(y)".parse().unwrap(); assert_debug_string!("P(x) | Q(y)", dnf_clause_set(&formula)); } { - let formula: FOF = "P(x) -> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) -> Q(y)".parse().unwrap(); assert_debug_string!("Q(y) | ~P(x)", dnf_clause_set(&formula)); } { - let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) <=> Q(y)".parse().unwrap(); assert_debug_string!( "(((P(x) & Q(y)) | (P(x) & ~P(x))) | (Q(y) & ~Q(y))) | (~P(x) & ~Q(y))", dnf_clause_set(&formula), ); } { - let formula: FOF = "!x. P(x)".parse().unwrap(); + let formula: Fof = "!x. P(x)".parse().unwrap(); assert_debug_string!("P(x)", dnf_clause_set(&formula)); } { - let formula: FOF = "!x. P(f(), g(f(), x))".parse().unwrap(); + let formula: Fof = "!x. P(f(), g(f(), x))".parse().unwrap(); assert_debug_string!("P(f(), g(f(), x))", dnf_clause_set(&formula)); } // quantifier-free formulae { - let formula: FOF = "~((P(x1) | P(x2)) and Q(y))".parse().unwrap(); + let formula: Fof = "~((P(x1) | P(x2)) and Q(y))".parse().unwrap(); assert_debug_string!("(~P(x1) & ~P(x2)) | ~Q(y)", dnf_clause_set(&formula)); } { - let formula: FOF = "P(x) | ~(Q(x) -> Q(y))".parse().unwrap(); + let formula: Fof = "P(x) | ~(Q(x) -> Q(y))".parse().unwrap(); assert_debug_string!("P(x) | (Q(x) & ~Q(y))", dnf_clause_set(&formula)); } { - let formula: FOF = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); + let formula: Fof = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); assert_debug_string!("R(z) | (~P(x) & ~Q(y))", dnf_clause_set(&formula)); } { - let formula: FOF = "P(x) | ~(Q(x) <=> Q(y))".parse().unwrap(); + let formula: Fof = "P(x) | ~(Q(x) <=> Q(y))".parse().unwrap(); assert_debug_string!( "(P(x) | (Q(x) & ~Q(y))) | (Q(y) & ~Q(x))", dnf_clause_set(&formula), ); } { - let formula: FOF = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); + let formula: Fof = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); assert_debug_string!("(((((P(x) & R(z)) | ((P(x) & ~P(x)) & ~Q(y))) | (Q(y) & R(z))) | ((Q(y) & ~P(x)) & ~Q(y))) | (R(z) & ~R(z))) | ((~P(x) & ~Q(y)) & ~R(z))", dnf_clause_set(&formula)); } { - let formula: FOF = "P(x) | (Q(x) | (R(y) & R(z)))".parse().unwrap(); + let formula: Fof = "P(x) | (Q(x) | (R(y) & R(z)))".parse().unwrap(); assert_debug_string!("(P(x) | Q(x)) | (R(y) & R(z))", dnf_clause_set(&formula)); } { - let formula: FOF = "(P(x1) & P(x2)) | (Q(x1) & Q(x2))".parse().unwrap(); + let formula: Fof = "(P(x1) & P(x2)) | (Q(x1) & Q(x2))".parse().unwrap(); assert_debug_string!( "(P(x1) & P(x2)) | (Q(x1) & Q(x2))", dnf_clause_set(&formula) @@ -468,46 +468,46 @@ mod tests { //random formulae { - let formula: FOF = "?x. P(x)".parse().unwrap(); + let formula: Fof = "?x. P(x)".parse().unwrap(); assert_debug_string!("P('c#0)", dnf_clause_set(&formula)); } { - let formula: FOF = "?x. (P(x) & Q(f(), x))".parse().unwrap(); + let formula: Fof = "?x. (P(x) & Q(f(), x))".parse().unwrap(); assert_debug_string!("P('c#0) & Q(f(), 'c#0)", dnf_clause_set(&formula)); } { - let formula: FOF = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); + let formula: Fof = "!x. ((? y. P(y) & Q(x, y)) -> R(x))".parse().unwrap(); assert_debug_string!("(R(x) | ~P(y)) | ~Q(x, y)", dnf_clause_set(&formula)); } { - let formula: FOF = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); + let formula: Fof = "!x. (P(x) -> !y. (Q(y) -> ~R(x, y)))".parse().unwrap(); assert_debug_string!("(~P(x) | ~Q(y)) | ~R(x, y)", dnf_clause_set(&formula)); } { - let formula: FOF = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); + let formula: Fof = "!y. (!x. (P(y, x) | Q(x)) -> Q(y))".parse().unwrap(); assert_debug_string!("Q(y) | (~P(y, x) & ~Q(x))", dnf_clause_set(&formula)); } { - let formula: FOF = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); + let formula: Fof = "!y. ((!x. (P(y, x) | Q(x))) -> Q(y))".parse().unwrap(); assert_debug_string!( "Q(y) | (~P(y, f#0(y)) & ~Q(f#0(y)))", dnf_clause_set(&formula) ); } { - let formula: FOF = "?x. ?y. P(x, y)".parse().unwrap(); + let formula: Fof = "?x. ?y. P(x, y)".parse().unwrap(); assert_debug_string!("P('c#0, 'c#1)", dnf_clause_set(&formula)); } { - let formula: FOF = "?x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "?x, y. P(x, y)".parse().unwrap(); assert_debug_string!("P('c#0, 'c#1)", dnf_clause_set(&formula)); } { - let formula: FOF = "!x. ?y. P(x, y)".parse().unwrap(); + let formula: Fof = "!x. ?y. P(x, y)".parse().unwrap(); assert_debug_string!("P(x, f#0(x))", dnf_clause_set(&formula)); } { - let formula: FOF = + let formula: Fof = "R(z) -> ?u. (!x, y. (P(u, x) & ~? u, x, w. (Q(u, x, y) | (w = f(u)))))" .parse() .unwrap(); @@ -517,7 +517,7 @@ mod tests { ); } { - let formula: FOF = "!x. (!y. (P(y) -> Q(x, y)) -> ?y. Q(y, x))" + let formula: Fof = "!x. (!y. (P(y) -> Q(x, y)) -> ?y. Q(y, x))" .parse() .unwrap(); assert_debug_string!( @@ -526,7 +526,7 @@ mod tests { ); } { - let formula: FOF = "!x. ((!y. (P(y) -> Q(x, y))) -> ?y. Q(y, x))" + let formula: Fof = "!x. ((!y. (P(y) -> Q(x, y))) -> ?y. Q(y, x))" .parse() .unwrap(); assert_debug_string!( @@ -535,7 +535,7 @@ mod tests { ); } { - let formula: FOF = "?x. (!y, z. (P(x) & ((Q(x, y) & ~(y = z)) -> ~Q(x, z))))" + let formula: Fof = "?x. (!y, z. (P(x) & ((Q(x, y) & ~(y = z)) -> ~Q(x, z))))" .parse() .unwrap(); assert_debug_string!( @@ -544,7 +544,7 @@ mod tests { ); } { - let formula: FOF = "!x. (P(x) -> (!y. (P(y) -> P(f(x, y))) & ~!y. (Q(x, y) -> P(y))))" + let formula: Fof = "!x. (P(x) -> (!y. (P(y) -> P(f(x, y))) & ~!y. (Q(x, y) -> P(y))))" .parse() .unwrap(); assert_debug_string!("(((P(f(x, y)) & Q(x, f#0(x, y))) & ~P(f#0(x, y))) | ((Q(x, f#0(x, y)) & ~P(y)) & ~P(f#0(x, y)))) | ~P(x)", dnf_clause_set(&formula)); @@ -578,7 +578,7 @@ mod tests { }; assert_eq!( fof!({ [P(y, z)] | [Q(z)] } | { [R(y)] & [R(z)] }), - FOF::from(dnf.transform_term(&f)) + Fof::from(dnf.transform_term(&f)) ); } diff --git a/razor-fol/src/transform/gnf.rs b/razor-fol/src/transform/gnf.rs index 4d30127..ea86644 100644 --- a/razor-fol/src/transform/gnf.rs +++ b/razor-fol/src/transform/gnf.rs @@ -1,16 +1,16 @@ /*! Defines formulae in Geometric Normal Form (GNF) and implements an algorithm for -transforming a [`CNFClauseSet`] to a [`GNF`]. +transforming a [`CnfClauseSet`] to a [`Gnf`]. -[`CNFClauseSet`]: crate::transform::CNFClauseSet +[`CnfClauseSet`]: crate::transform::CnfClauseSet */ -use super::{ToSNF, SNF}; +use super::{Snf, ToSnf}; use crate::syntax::{ formula::{ clause::{Clause, Literal}, *, }, term::Complex, - Error, Sig, Var, FOF, + Error, Fof, Sig, Var, }; use itertools::Itertools; use std::{collections::BTreeSet, convert::TryFrom, iter::FromIterator, ops::Deref}; @@ -19,11 +19,11 @@ use std::{collections::BTreeSet, convert::TryFrom, iter::FromIterator, ops::Dere type PosLiteral = Atomic; /// A Positive Conjunctive Formula (PCF) represents a collection of [`Atomic`]s, interpreted -/// as a conjunction of positive literals. PCFs are the building blocks of [`GNF`]s. +/// as a conjunction of positive literals. PCFs are the building blocks of [`Gnf`]s. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)] -pub struct PCF(BTreeSet); +pub struct Pcf(BTreeSet); -impl PCF { +impl Pcf { /// Returns the positive literals of `self`. #[inline(always)] pub fn literals(&self) -> &BTreeSet { @@ -42,7 +42,7 @@ impl PCF { } } -impl Deref for PCF { +impl Deref for Pcf { type Target = BTreeSet; fn deref(&self) -> &Self::Target { @@ -50,33 +50,33 @@ impl Deref for PCF { } } -impl From for PCF { +impl From for Pcf { fn from(value: PosLiteral) -> Self { vec![value].into_iter().collect() } } -impl From> for PCF { +impl From> for Pcf { fn from(value: Atom) -> Self { let literal = Atomic::from(value); vec![literal].into_iter().collect() } } -impl From> for PCF { +impl From> for Pcf { fn from(value: Equals) -> Self { let literal = Atomic::from(value); vec![literal].into_iter().collect() } } -impl FromIterator for PCF { +impl FromIterator for Pcf { fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect()) } } -impl IntoIterator for PCF { +impl IntoIterator for Pcf { type Item = PosLiteral; type IntoIter = std::collections::btree_set::IntoIter; @@ -86,13 +86,13 @@ impl IntoIterator for PCF { } } -impl From> for PCF { +impl From> for Pcf { fn from(value: Vec) -> Self { Self(value.into_iter().collect()) } } -impl Formula for PCF { +impl Formula for Pcf { type Term = Complex; fn signature(&self) -> Result { @@ -115,37 +115,37 @@ impl Formula for PCF { } } -impl From for FOF { - fn from(value: PCF) -> Self { +impl From for Fof { + fn from(value: Pcf) -> Self { value .into_literals() .into_iter() .sorted() .into_iter() .map(|atomic| match atomic { - Atomic::Atom(this) => FOF::from(this), + Atomic::Atom(this) => Fof::from(this), Atomic::Equals(this) => this.into(), }) .fold1(|item, acc| item.and(acc)) - .unwrap_or(FOF::Top) + .unwrap_or(Fof::Top) } } -impl From<&PCF> for FOF { - fn from(value: &PCF) -> Self { +impl From<&Pcf> for Fof { + fn from(value: &Pcf) -> Self { value.clone().into() } } -impl TryFrom for PCF { +impl TryFrom for Pcf { type Error = super::Error; - fn try_from(value: FOF) -> Result { + fn try_from(value: Fof) -> Result { match value { - FOF::Top => Ok(Self::default()), - FOF::Atom(atom) => Ok(Self::from(atom)), - FOF::Equals(equals) => Ok(Self::from(equals)), - FOF::And(and) => { + Fof::Top => Ok(Self::default()), + Fof::Atom(atom) => Ok(Self::from(atom)), + Fof::Equals(equals) => Ok(Self::from(equals)), + Fof::And(and) => { let mut result = Self::try_from(and.left)?.into_literals(); result.extend(Self::try_from(and.right)?.into_literals()); Ok(result.into_iter().collect()) @@ -157,20 +157,20 @@ impl TryFrom for PCF { } } -/// Is a set of [`PCF`]s in the head of a [`GNF`], interpreted as a disjunction of +/// Is a set of [`Pcf`]s in the head of a [`Gnf`], interpreted as a disjunction of /// PCFs where each PCF is a conjunction of positive literals. #[derive(PartialEq, Eq, Clone, Default, Debug)] -pub struct PcfSet(BTreeSet); +pub struct PcfSet(BTreeSet); impl PcfSet { /// Returns the clauses of `self`. #[inline(always)] - pub fn clauses(&self) -> &BTreeSet { + pub fn clauses(&self) -> &BTreeSet { &self.0 } /// Consumes `self` and returns its underlying set of clauses. - pub fn into_clauses(self) -> BTreeSet { + pub fn into_clauses(self) -> BTreeSet { self.0 } @@ -192,20 +192,20 @@ impl PcfSet { } } -impl From for PcfSet { - fn from(value: PCF) -> Self { +impl From for PcfSet { + fn from(value: Pcf) -> Self { vec![value].into_iter().collect() } } -impl FromIterator for PcfSet { - fn from_iter>(iter: T) -> Self { +impl FromIterator for PcfSet { + fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect()) } } impl IntoIterator for PcfSet { - type Item = PCF; + type Item = Pcf; type IntoIter = std::collections::btree_set::IntoIter; @@ -214,14 +214,14 @@ impl IntoIterator for PcfSet { } } -impl From> for PcfSet { - fn from(value: Vec) -> Self { +impl From> for PcfSet { + fn from(value: Vec) -> Self { Self(value.into_iter().collect()) } } impl Deref for PcfSet { - type Target = BTreeSet; + type Target = BTreeSet; fn deref(&self) -> &Self::Target { &self.0 @@ -251,46 +251,46 @@ impl Formula for PcfSet { } } -impl From for FOF { +impl From for Fof { fn from(value: PcfSet) -> Self { value .into_clauses() .into_iter() .sorted() .into_iter() - .map(FOF::from) + .map(Fof::from) .fold1(|item, acc| item.or(acc)) - .unwrap_or(FOF::Bottom) + .unwrap_or(Fof::Bottom) } } -impl From<&PcfSet> for FOF { +impl From<&PcfSet> for Fof { fn from(value: &PcfSet) -> Self { value.clone().into() } } -/// Represents a formula in Geometric Normal Form (GNF), consisting of a [`PCF`] in the body +/// Represents a formula in Geometric Normal Form (GNF), consisting of a [`Pcf`] in the body /// (premise) and a [`PcfSet`] in the head (consequence). /// /// **Hint**: For mor information about GNF, see [Geometric Logic in Computer Science][glics] /// by Steve Vickers. /// /// [glics]: https://www.cs.bham.ac.uk/~sjv/GLiCS.pdf -/// [`FOF`]: crate::syntax::FOF +/// [`Fof`]: crate::syntax::Fof #[derive(Clone, Debug)] -pub struct GNF { +pub struct Gnf { /// Is the body of a GNF, comprised of a positive clause. - body: PCF, + body: Pcf, /// Is the head of a GNF, consisting of a positive clause set. head: PcfSet, } -impl GNF { +impl Gnf { /// Returns the body of `self`. #[inline(always)] - pub fn body(&self) -> &PCF { + pub fn body(&self) -> &Pcf { &self.body } @@ -301,28 +301,28 @@ impl GNF { } /// Consumes `self` and returns its body and head. - pub fn into_body_and_head(self) -> (PCF, PcfSet) { + pub fn into_body_and_head(self) -> (Pcf, PcfSet) { (self.body, self.head) } } -impl From<(PCF, PcfSet)> for GNF { - fn from(value: (PCF, PcfSet)) -> Self { +impl From<(Pcf, PcfSet)> for Gnf { + fn from(value: (Pcf, PcfSet)) -> Self { let (body, head) = value; Self { body, head } } } -impl TryFrom for PcfSet { +impl TryFrom for PcfSet { type Error = super::Error; - fn try_from(value: FOF) -> Result { + fn try_from(value: Fof) -> Result { match value { - FOF::Top | FOF::Atom(_) | FOF::Equals(_) | FOF::And(_) => { - PCF::try_from(value).map(Self::from) + Fof::Top | Fof::Atom(_) | Fof::Equals(_) | Fof::And(_) => { + Pcf::try_from(value).map(Self::from) } - FOF::Bottom => Ok(Self::default()), - FOF::Or(or) => { + Fof::Bottom => Ok(Self::default()), + Fof::Or(or) => { let mut result = Self::try_from(or.left)?.into_clauses(); result.extend(Self::try_from(or.right)?.into_clauses()); Ok(result.into_iter().collect()) @@ -334,17 +334,17 @@ impl TryFrom for PcfSet { } } -/// Is the trait of [`Formula`] types that can be transformed to a list of [`GNF`]s. -pub trait ToGNF: Formula { +/// Is the trait of [`Formula`] types that can be transformed to a list of [`Gnf`]s. +pub trait ToGnf: Formula { /// Transforms `self` to a list of formulae in Geometric Normal /// Form (GNF). /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToGNF; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToGnf; /// - /// let formula: FOF = "P(x) & (Q(x) | R(x))".parse().unwrap(); + /// let formula: Fof = "P(x) & (Q(x) | R(x))".parse().unwrap(); /// let gnfs = formula.gnf(); /// /// let gnf_to_string: Vec = gnfs @@ -353,25 +353,25 @@ pub trait ToGNF: Formula { /// .collect(); /// assert_eq!(vec!["⊤ → P(x)", "⊤ → (Q(x) ∨ R(x))"], gnf_to_string); /// ``` - fn gnf(&self) -> Vec; + fn gnf(&self) -> Vec; } -impl ToGNF for SNF { - fn gnf(&self) -> Vec { - use super::ToCNFClauseSet; +impl ToGnf for Snf { + fn gnf(&self) -> Vec { + use super::ToCnfClauseSet; let clauses = self.cnf_clause_set(); clauses.iter().map(gnf).collect() } } -impl ToGNF for T { - fn gnf(&self) -> Vec { +impl ToGnf for T { + fn gnf(&self) -> Vec { self.snf().gnf() } } -impl Formula for GNF { +impl Formula for Gnf { type Term = Complex; fn signature(&self) -> Result { @@ -393,47 +393,47 @@ impl Formula for GNF { } } -impl std::fmt::Display for GNF { +impl std::fmt::Display for Gnf { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } -impl From for FOF { - fn from(value: GNF) -> Self { - let body = FOF::from(value.body); - let head = FOF::from(value.head); +impl From for Fof { + fn from(value: Gnf) -> Self { + let body = Fof::from(value.body); + let head = Fof::from(value.head); body.implies(head) } } -impl From<&GNF> for FOF { - fn from(value: &GNF) -> Self { +impl From<&Gnf> for Fof { + fn from(value: &Gnf) -> Self { value.clone().into() } } -impl TryFrom for GNF { +impl TryFrom for Gnf { type Error = super::Error; - fn try_from(value: FOF) -> Result { + fn try_from(value: Fof) -> Result { match value { - FOF::Top => { - let body = PCF::default(); - let head = PcfSet::from(PCF::default()); + Fof::Top => { + let body = Pcf::default(); + let head = PcfSet::from(Pcf::default()); Ok((body, head).into()) } - FOF::Bottom => { - let body = PCF::default(); + Fof::Bottom => { + let body = Pcf::default(); let head = PcfSet::default(); Ok((body, head).into()) } - FOF::Atom(_) | FOF::Equals(_) | FOF::And(_) | FOF::Or(_) => { + Fof::Atom(_) | Fof::Equals(_) | Fof::And(_) | Fof::Or(_) => { let head = PcfSet::try_from(value)?; - Ok((PCF::default(), head).into()) + Ok((Pcf::default(), head).into()) } - FOF::Implies(implies) => { - let body = PCF::try_from(implies.premise)?; + Fof::Implies(implies) => { + let body = Pcf::try_from(implies.premise)?; let head = PcfSet::try_from(implies.consequence)?; Ok((body, head).into()) } @@ -445,15 +445,15 @@ impl TryFrom for GNF { } // Convert the disjuncts of the CNF to an implication. These implications are geometric sequents. -fn gnf(clause: &Clause) -> GNF { - let mut head: Vec = Vec::new(); +fn gnf(clause: &Clause) -> Gnf { + let mut head: Vec = Vec::new(); let mut body: Vec> = Vec::new(); clause.iter().for_each(|lit| match lit { Literal::Pos(this) => head.push(this.clone().into()), Literal::Neg(this) => body.push(this.clone()), }); - let body = PCF::from(body); + let body = Pcf::from(body); let head = PcfSet::from(head); (body, head).into() } @@ -471,27 +471,27 @@ mod tests { }; use itertools::Itertools; - fn gnf(formula: &FOF) -> Vec { + fn gnf(formula: &Fof) -> Vec { formula.gnf().into_iter().map(|gnf| gnf.into()).collect() } #[test] fn pcf_union() { { - let first = PCF::from(Atom { + let first = Pcf::from(Atom { predicate: "P".into(), terms: vec![], }); - let second = PCF::default(); + let second = Pcf::default(); assert_eq!(first, first.union(&second)); assert_eq!(first, second.union(&first)); } { - let first = PCF::from(Atom { + let first = Pcf::from(Atom { predicate: "P".into(), terms: vec![], }); - let second = PCF::from(vec![ + let second = Pcf::from(vec![ Atom { predicate: "Q".into(), terms: vec![], @@ -503,7 +503,7 @@ mod tests { } .into(), ]); - let expected = PCF::from(vec![ + let expected = Pcf::from(vec![ Atom { predicate: "P".into(), terms: vec![], @@ -528,11 +528,11 @@ mod tests { #[test] fn pcf_free_vars() { { - let pcf = PCF::default(); + let pcf = Pcf::default(); assert_eq!(Vec::<&Var>::new(), pcf.free_vars()); } { - let pcf = PCF::from(vec![ + let pcf = Pcf::from(vec![ Atom { predicate: "Q".into(), terms: vec![term!(x)], @@ -556,7 +556,7 @@ mod tests { #[test] fn pcf_transform() { { - let pcf: PCF = Atomic::from(Atom { + let pcf: Pcf = Atomic::from(Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(y)], }) @@ -572,7 +572,7 @@ mod tests { .into() }; assert_eq!( - PCF::from(Atom { + Pcf::from(Atom { predicate: "P".into(), terms: vec![term!(z), term!(y)], }), @@ -580,7 +580,7 @@ mod tests { ); } { - let pcf: PCF = Equals { + let pcf: Pcf = Equals { left: term!(f(x)), right: term!(y), } @@ -593,7 +593,7 @@ mod tests { } }; assert_eq!( - PCF::from(Equals { + Pcf::from(Equals { left: term!(z), right: term!(y), }), @@ -628,7 +628,7 @@ mod tests { .unwrap(); sig.add_constant("c".into()); - let pcf = PCF::from(vec![ + let pcf = Pcf::from(vec![ Atom { predicate: "P".into(), terms: vec![term!(x)], @@ -648,7 +648,7 @@ mod tests { assert_eq!(sig, pcf.signature().unwrap()); } { - let pcf = PCF::from(vec![ + let pcf = Pcf::from(vec![ Atom { predicate: "P".into(), terms: vec![term!(x)], @@ -672,7 +672,7 @@ mod tests { assert_eq!(PcfSet::default(), first.cross_union(&second)); } { - let first = PcfSet::from(vec![PCF::from(Atom { + let first = PcfSet::from(vec![Pcf::from(Atom { predicate: "P".into(), terms: vec![], })]); @@ -681,26 +681,26 @@ mod tests { assert_eq!(PcfSet::default(), second.cross_union(&first)); } { - let first = PcfSet::from(vec![PCF::from(Atom { + let first = PcfSet::from(vec![Pcf::from(Atom { predicate: "P".into(), terms: vec![], })]); - let second = PcfSet::from(vec![PCF::from(Atom { + let second = PcfSet::from(vec![Pcf::from(Atom { predicate: "P".into(), terms: vec![], })]); assert_eq!(first, first.cross_union(&second)); } { - let first = PcfSet::from(vec![PCF::from(Atom { + let first = PcfSet::from(vec![Pcf::from(Atom { predicate: "P".into(), terms: vec![], })]); - let second = PcfSet::from(vec![PCF::from(Atom { + let second = PcfSet::from(vec![Pcf::from(Atom { predicate: "Q".into(), terms: vec![], })]); - let expected = PcfSet::from(vec![PCF::from(vec![ + let expected = PcfSet::from(vec![Pcf::from(vec![ Atom { predicate: "P".into(), terms: vec![], @@ -716,11 +716,11 @@ mod tests { assert_eq!(expected, second.cross_union(&first)); } { - let first = PcfSet::from(vec![PCF::from(Atom { + let first = PcfSet::from(vec![Pcf::from(Atom { predicate: "P".into(), terms: vec![], })]); - let second = PcfSet::from(vec![PCF::from(vec![ + let second = PcfSet::from(vec![Pcf::from(vec![ Atom { predicate: "Q".into(), terms: vec![], @@ -732,7 +732,7 @@ mod tests { } .into(), ])]); - let expected = PcfSet::from(vec![PCF::from(vec![ + let expected = PcfSet::from(vec![Pcf::from(vec![ Atom { predicate: "P".into(), terms: vec![], @@ -754,27 +754,27 @@ mod tests { } { let first = PcfSet::from(vec![ - PCF::from(Atomic::from(Atom { + Pcf::from(Atomic::from(Atom { predicate: "P".into(), terms: vec![], })), - PCF::from(Atomic::from(Atom { + Pcf::from(Atomic::from(Atom { predicate: "Q".into(), terms: vec![], })), ]); let second = PcfSet::from(vec![ - PCF::from(Atomic::from(Atom { + Pcf::from(Atomic::from(Atom { predicate: "R".into(), terms: vec![], })), - PCF::from(Atomic::from(Atom { + Pcf::from(Atomic::from(Atom { predicate: "S".into(), terms: vec![], })), ]); let expected = PcfSet::from(vec![ - PCF::from(vec![ + Pcf::from(vec![ Atomic::from(Atom { predicate: "P".into(), terms: vec![], @@ -785,7 +785,7 @@ mod tests { } .into(), ]), - PCF::from(vec![ + Pcf::from(vec![ Atomic::from(Atom { predicate: "P".into(), terms: vec![], @@ -796,7 +796,7 @@ mod tests { } .into(), ]), - PCF::from(vec![ + Pcf::from(vec![ Atomic::from(Atom { predicate: "Q".into(), terms: vec![], @@ -807,7 +807,7 @@ mod tests { } .into(), ]), - PCF::from(vec![ + Pcf::from(vec![ Atomic::from(Atom { predicate: "Q".into(), terms: vec![], @@ -831,7 +831,7 @@ mod tests { assert_eq!(pcf_set, pcf_set.simplify()); } { - let pcf_set: PcfSet = vec![PCF::from(vec![Atomic::from(Atom { + let pcf_set: PcfSet = vec![Pcf::from(vec![Atomic::from(Atom { predicate: "P".into(), terms: vec![term!(x)], })])] @@ -840,7 +840,7 @@ mod tests { } { let pcf_set: PcfSet = vec![ - PCF::from(vec![ + Pcf::from(vec![ Atomic::from(Atom { predicate: "P".into(), terms: vec![term!(x)], @@ -851,30 +851,30 @@ mod tests { } .into(), ]), - PCF::from(vec![Atomic::from(Atom { + Pcf::from(vec![Atomic::from(Atom { predicate: "P".into(), terms: vec![term!(x)], })]), - PCF::from(vec![Atomic::from(Atom { + Pcf::from(vec![Atomic::from(Atom { predicate: "R".into(), terms: vec![term!(x)], })]), - PCF::from(vec![Atomic::from(Atom { + Pcf::from(vec![Atomic::from(Atom { predicate: "Q".into(), terms: vec![term!(x)], })]), ] .into(); let expected: PcfSet = vec![ - PCF::from(vec![Atomic::from(Atom { + Pcf::from(vec![Atomic::from(Atom { predicate: "P".into(), terms: vec![term!(x)], })]), - PCF::from(vec![Atomic::from(Atom { + Pcf::from(vec![Atomic::from(Atom { predicate: "Q".into(), terms: vec![term!(x)], })]), - PCF::from(vec![Atomic::from(Atom { + Pcf::from(vec![Atomic::from(Atom { predicate: "R".into(), terms: vec![term!(x)], })]), @@ -892,15 +892,15 @@ mod tests { } { let pcf_set = PcfSet::from(vec![ - PCF::from(Atom { + Pcf::from(Atom { predicate: "Q".into(), terms: vec![term!(x)], }), - PCF::from(Atom { + Pcf::from(Atom { predicate: "R".into(), terms: vec![term!(@c), term!(y)], }), - PCF::from(Atom { + Pcf::from(Atom { predicate: "R".into(), terms: vec![term!(x)], }), @@ -912,7 +912,7 @@ mod tests { #[test] fn pcf_set_transform() { { - let pcf_set: PcfSet = PCF::from(Atom { + let pcf_set: PcfSet = Pcf::from(Atom { predicate: "P".into(), terms: vec![term!(f(x)), term!(y)], }) @@ -928,7 +928,7 @@ mod tests { .into() }; assert_eq!( - PcfSet::from(PCF::from(Atom { + PcfSet::from(Pcf::from(Atom { predicate: "P".into(), terms: vec![term!(z), term!(y)], })), @@ -936,7 +936,7 @@ mod tests { ); } { - let pcf_set: PcfSet = PCF::from(Equals { + let pcf_set: PcfSet = Pcf::from(Equals { left: term!(f(x)), right: term!(y), }) @@ -949,7 +949,7 @@ mod tests { } }; assert_eq!( - PcfSet::from(PCF::from(Equals { + PcfSet::from(Pcf::from(Equals { left: term!(z), right: term!(y), })), @@ -985,7 +985,7 @@ mod tests { sig.add_constant("c".into()); let pcf_set = PcfSet::from(vec![ - PCF::from(Atom { + Pcf::from(Atom { predicate: "P".into(), terms: vec![term!(x)], }), @@ -1004,7 +1004,7 @@ mod tests { } { let pcf_set = PcfSet::from(vec![ - PCF::from(Atom { + Pcf::from(Atom { predicate: "P".into(), terms: vec![term!(x)], }), @@ -1021,69 +1021,69 @@ mod tests { #[test] fn test_gnf() { { - let formula: FOF = "true".parse().unwrap(); + let formula: Fof = "true".parse().unwrap(); assert_debug_strings!("", gnf(&formula)); } { - let formula: FOF = "false".parse().unwrap(); + let formula: Fof = "false".parse().unwrap(); assert_debug_strings!("true -> false", gnf(&formula)); } { - let formula: FOF = "P(x)".parse().unwrap(); + let formula: Fof = "P(x)".parse().unwrap(); assert_debug_strings!("true -> P(x)", gnf(&formula)); } { - let formula: FOF = "x = y".parse().unwrap(); + let formula: Fof = "x = y".parse().unwrap(); assert_debug_strings!("true -> x = y", gnf(&formula)); } { - let formula: FOF = "~P(x)".parse().unwrap(); + let formula: Fof = "~P(x)".parse().unwrap(); assert_debug_strings!("P(x) -> false", gnf(&formula)); } { - let formula: FOF = "P(x) -> Q(x)".parse().unwrap(); + let formula: Fof = "P(x) -> Q(x)".parse().unwrap(); assert_debug_strings!("P(x) -> Q(x)", gnf(&formula)); } { - let formula: FOF = "P(x) & Q(x)".parse().unwrap(); + let formula: Fof = "P(x) & Q(x)".parse().unwrap(); assert_debug_strings!("true -> P(x)\ntrue -> Q(x)", gnf(&formula)); } { - let formula: FOF = "P(x) | Q(x)".parse().unwrap(); + let formula: Fof = "P(x) | Q(x)".parse().unwrap(); assert_debug_strings!("true -> (P(x) | Q(x))", gnf(&formula)); } { - let formula: FOF = "! x. P(x)".parse().unwrap(); + let formula: Fof = "! x. P(x)".parse().unwrap(); assert_debug_strings!("true -> P(x)", gnf(&formula)); } { - let formula: FOF = "? x. P(x)".parse().unwrap(); + let formula: Fof = "? x. P(x)".parse().unwrap(); assert_debug_strings!("true -> P('c#0)", gnf(&formula)); } { - let formula: FOF = "P(x) & Q(x) -> P(y) | Q(y)".parse().unwrap(); + let formula: Fof = "P(x) & Q(x) -> P(y) | Q(y)".parse().unwrap(); assert_debug_strings!("(P(x) & Q(x)) -> (P(y) | Q(y))", gnf(&formula)); } { - let formula: FOF = "P(x) | Q(x) -> P(y) & Q(y)".parse().unwrap(); + let formula: Fof = "P(x) | Q(x) -> P(y) & Q(y)".parse().unwrap(); assert_debug_strings!( "P(x) -> P(y)\nQ(x) -> P(y)\nP(x) -> Q(y)\nQ(x) -> Q(y)", gnf(&formula), ); } { - let formula: FOF = "P(x) | Q(x) <=> P(y) & Q(y)".parse().unwrap(); + let formula: Fof = "P(x) | Q(x) <=> P(y) & Q(y)".parse().unwrap(); assert_debug_strings!( "(P(y) & Q(y)) -> (P(x) | Q(x))\nP(x) -> P(y)\nQ(x) -> P(y)\nP(x) -> Q(y)\nQ(x) -> Q(y)", gnf(&formula), ); } { - let formula: FOF = "!x. (P(x) -> ?y. Q(x,y))".parse().unwrap(); + let formula: Fof = "!x. (P(x) -> ?y. Q(x,y))".parse().unwrap(); assert_debug_strings!("P(x) -> Q(x, f#0(x))", gnf(&formula)); } { - let formula: FOF = "!x. (P(x) -> (?y. (Q(y) & R(x, y)) | ?y. (P(y) & S(x, y))))" + let formula: Fof = "!x. (P(x) -> (?y. (Q(y) & R(x, y)) | ?y. (P(y) & S(x, y))))" .parse() .unwrap(); assert_debug_strings!( @@ -1092,13 +1092,13 @@ mod tests { ); } { - let formula: FOF = "!x, y. ((P(x) & Q(y)) -> (R(x, y) -> S(x, y)))" + let formula: Fof = "!x, y. ((P(x) & Q(y)) -> (R(x, y) -> S(x, y)))" .parse() .unwrap(); assert_debug_strings!("((P(x) & Q(y)) & R(x, y)) -> S(x, y)", gnf(&formula)); } { - let formula: FOF = "!x, y. ((P(x) & Q(y)) <=> (R(x, y) <=> S(x, y)))" + let formula: Fof = "!x, y. ((P(x) & Q(y)) <=> (R(x, y) <=> S(x, y)))" .parse() .unwrap(); assert_debug_strings!("true -> ((P(x) | R(x, y)) | S(x, y))\nR(x, y) -> (P(x) | R(x, y))\nS(x, y) -> (P(x) | S(x, y))\n(R(x, y) & S(x, y)) -> P(x)\ntrue -> ((Q(y) | R(x, y)) | S(x, y))\nR(x, y) -> (Q(y) | R(x, y))\nS(x, y) -> (Q(y) | S(x, y))\n(R(x, y) & S(x, y)) -> Q(y)\n((P(x) & Q(y)) & S(x, y)) -> R(x, y)\n((P(x) & Q(y)) & R(x, y)) -> S(x, y)", @@ -1106,19 +1106,19 @@ mod tests { ); } { - let formula: FOF = "? x. P(x) -> Q(x)".parse().unwrap(); + let formula: Fof = "? x. P(x) -> Q(x)".parse().unwrap(); assert_debug_strings!("P('c#0) -> Q('c#0)", gnf(&formula)); } { - let formula: FOF = "(? x. P(x)) -> Q(x)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) -> Q(x)".parse().unwrap(); assert_debug_strings!("P(x`) -> Q(x)", gnf(&formula)); } { - let formula: FOF = "? x. (P(x) -> Q(x))".parse().unwrap(); + let formula: Fof = "? x. (P(x) -> Q(x))".parse().unwrap(); assert_debug_strings!("P('c#0) -> Q('c#0)", gnf(&formula)); } { - let formula: FOF = "false -> P(x)".parse().unwrap(); + let formula: Fof = "false -> P(x)".parse().unwrap(); assert_debug_strings!("", gnf(&formula)); } } @@ -1131,7 +1131,7 @@ mod tests { assert_eq!(Vec::<&Var>::new(), gnf[0].free_vars()); } { - let gnf = GNF::try_from(fof!({[P(x, @c)] & [Q(y)]} -> {[Q(x)] | [ [Q(y)] & [R()] ]})) + let gnf = Gnf::try_from(fof!({[P(x, @c)] & [Q(y)]} -> {[Q(x)] | [ [Q(y)] & [R()] ]})) .unwrap(); assert_eq_sorted_vecs!(vec![v!(x), v!(y)].iter().collect_vec(), gnf.free_vars()); } @@ -1140,7 +1140,7 @@ mod tests { #[test] fn gnf_transform() { let gnf = - GNF::try_from(fof!({[P(y, f(x))] & [Q(x)]} -> {[Q(f(x))] | [[R(f(x))] & [R(y)]]})) + Gnf::try_from(fof!({[P(y, f(x))] & [Q(x)]} -> {[Q(f(x))] | [[R(f(x))] & [R(y)]]})) .unwrap(); let f = |t: &Complex| { { @@ -1154,7 +1154,7 @@ mod tests { }; assert_eq!( fof!({[P(y, z)] & [Q(x)]} -> {[Q(z)] | [[R(y)] & [R(z)]]}), - FOF::from(gnf.transform_term(&f)) + Fof::from(gnf.transform_term(&f)) ); } @@ -1184,14 +1184,14 @@ mod tests { .unwrap(); sig.add_constant("c".into()); - let gnf = GNF::try_from( + let gnf = Gnf::try_from( fof!({[P(f(x, @c))] & [P(y)]} -> {[P(y)] | [[Q(x, x)] & [(x) = (y)]]}), ) .unwrap(); assert_eq!(sig, gnf.signature().unwrap()); } { - let gnf = GNF::try_from(fof!({P(x, x)} -> {P(x)})).unwrap(); + let gnf = Gnf::try_from(fof!({P(x, x)} -> {P(x)})).unwrap(); assert!(gnf.signature().is_err()); } } diff --git a/razor-fol/src/transform/linear.rs b/razor-fol/src/transform/linear.rs index 437ca75..3972902 100644 --- a/razor-fol/src/transform/linear.rs +++ b/razor-fol/src/transform/linear.rs @@ -10,12 +10,12 @@ impl Relational { /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; + /// # use razor_fol::syntax::Fof; /// # use std::convert::TryFrom; - /// use razor_fol::transform::{GNF, ToRelational}; + /// use razor_fol::transform::{Gnf, ToRelational}; /// - /// let fof = "P(x) -> P(f(x)) & Q('c)".parse::().unwrap(); - /// let gnf = GNF::try_from(fof).unwrap(); + /// let fof = "P(x) -> P(f(x)) & Q('c)".parse::().unwrap(); + /// let gnf = Gnf::try_from(fof).unwrap(); /// let gnf_head = gnf.head(); /// let relational = gnf_head.relational(); /// let mut generator = |name: &str, count| format!("V:{}:{}", name, count).into(); @@ -55,12 +55,12 @@ impl Relational { /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; + /// # use razor_fol::syntax::Fof; /// # use std::convert::TryFrom; - /// use razor_fol::transform::{GNF, ToRelational}; + /// use razor_fol::transform::{Gnf, ToRelational}; /// - /// let fof = "P(x) -> P(f(x)) & Q('c)".parse::().unwrap(); - /// let gnf = GNF::try_from(fof).unwrap(); + /// let fof = "P(x) -> P(f(x)) & Q('c)".parse::().unwrap(); + /// let gnf = Gnf::try_from(fof).unwrap(); /// let gnf_head = gnf.head(); /// let relational = gnf_head.relational(); /// let linear = relational.linear(); @@ -154,22 +154,22 @@ where #[cfg(test)] mod tests { - use crate::{fof, syntax::FOF, transform::PcfSet}; + use crate::{fof, syntax::Fof, transform::PcfSet}; // Assumes the input in GNF - fn clause_set(fof: FOF) -> PcfSet { + fn clause_set(fof: Fof) -> PcfSet { use std::convert::TryFrom; PcfSet::try_from(fof).unwrap() } - fn linear(fof: FOF) -> String { + fn linear(fof: Fof) -> String { use crate::transform::ToRelational; let rels = clause_set(fof) .iter() .map(|f| f.relational().linear()) - .map(FOF::from) + .map(Fof::from) .collect::>(); format!("{:?}", rels) } @@ -177,7 +177,7 @@ mod tests { #[test] fn test_linear() { assert_eq!("[true]", linear(fof!('|'))); - assert_eq!("[]", linear(fof!(_|_))); + assert_eq!("[]", linear(fof!(_ | _))); assert_eq!("[P()]", linear(fof!(P()))); assert_eq!("[P(x, y)]", linear(fof!(P(x, y)))); assert_eq!("[x = ~x:0 & P(x, ~x:0)]", linear(fof!(P(x, x)))); diff --git a/razor-fol/src/transform/nnf.rs b/razor-fol/src/transform/nnf.rs index 7e2ad46..84757a8 100644 --- a/razor-fol/src/transform/nnf.rs +++ b/razor-fol/src/transform/nnf.rs @@ -1,12 +1,12 @@ /*! Defines formulae in Negation Normal Form (NNF) and implements an algorithm for -transforming an [`FOF`] to an [`NNF`]. +transforming an [`Fof`] to an [`Nnf`]. -[`FOF`]: crate::syntax::FOF +[`Fof`]: crate::syntax::Fof */ use crate::syntax::{ formula::{clause::Literal, *}, term::Complex, - Error, Sig, Var, FOF, + Error, Fof, Sig, Var, }; /// Represents a formula in Negation Normal Form (NNF). @@ -14,7 +14,7 @@ use crate::syntax::{ /// **Hint**: An NNF is a formula where negation is applied only to its atomic (including /// equations) sub-formulae. #[derive(PartialEq, Clone)] -pub enum NNF { +pub enum Nnf { /// Is the logical top (⊤) or truth. Top, @@ -25,102 +25,102 @@ pub enum NNF { Literal(Literal), /// Is a conjunction of two formulae, wrapping an [`And`]. - And(Box>), + And(Box>), /// Is a disjunction of two formulae, wrapping an [`Or`]. - Or(Box>), + Or(Box>), /// Is an existentially quantified NNF, wrapping an [`Exists`]. - Exists(Box>), + Exists(Box>), /// Is a universally quantified NNF, wrapping a [`Forall`]. - Forall(Box>), + Forall(Box>), } -impl From> for NNF { +impl From> for Nnf { fn from(value: Atom) -> Self { Self::Literal(value.into()) } } -impl From> for NNF { +impl From> for Nnf { fn from(value: Equals) -> Self { Self::Literal(value.into()) } } -impl From>> for NNF { +impl From>> for Nnf { fn from(value: Not>) -> Self { Self::Literal(value.into()) } } -impl From>> for NNF { +impl From>> for Nnf { fn from(value: Not>) -> Self { Self::Literal(value.into()) } } -impl From> for NNF { - fn from(value: And) -> Self { +impl From> for Nnf { + fn from(value: And) -> Self { Self::And(value.into()) } } -impl From> for NNF { - fn from(value: Or) -> Self { +impl From> for Nnf { + fn from(value: Or) -> Self { Self::Or(value.into()) } } -impl From> for NNF { - fn from(value: Exists) -> Self { +impl From> for Nnf { + fn from(value: Exists) -> Self { Self::Exists(Box::new(value)) } } -impl From> for NNF { - fn from(value: Forall) -> Self { +impl From> for Nnf { + fn from(value: Forall) -> Self { Self::Forall(Box::new(value)) } } -impl From> for NNF { +impl From> for Nnf { fn from(value: Literal) -> Self { Self::Literal(value) } } -/// Is the trait of [`Formula`] types that can be transformed to [`NNF`]. -pub trait ToNNF: Formula { +/// Is the trait of [`Formula`] types that can be transformed to [`Nnf`]. +pub trait ToNnf: Formula { /// Transforms `self` to a Negation Normal Form (NNF). /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToNNF; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToNnf; /// - /// let formula: FOF = "not (P(x) iff Q(y))".parse().unwrap(); + /// let formula: Fof = "not (P(x) iff Q(y))".parse().unwrap(); /// let nnf = formula.nnf(); /// /// assert_eq!("(P(x) ∧ ¬Q(y)) ∨ (¬P(x) ∧ Q(y))", nnf.to_string()); /// ``` - fn nnf(&self) -> NNF; + fn nnf(&self) -> Nnf; } -impl ToNNF for FOF { - fn nnf(&self) -> NNF { +impl ToNnf for Fof { + fn nnf(&self) -> Nnf { nnf(self) } } -impl From for NNF { +impl From for Nnf { fn from(value: T) -> Self { value.nnf() } } -impl NNF { +impl Nnf { #[inline(always)] fn neg(atom: Atomic) -> Self { Literal::Neg(atom).into() @@ -155,17 +155,17 @@ impl NNF { } } -impl Formula for NNF { +impl Formula for Nnf { type Term = Complex; fn signature(&self) -> Result { match self { - NNF::Top | NNF::Bottom => Ok(Sig::default()), - NNF::Literal(this) => this.signature(), - NNF::And(this) => this.signature(), - NNF::Or(this) => this.signature(), - NNF::Exists(this) => this.signature(), - NNF::Forall(this) => this.signature(), + Nnf::Top | Nnf::Bottom => Ok(Sig::default()), + Nnf::Literal(this) => this.signature(), + Nnf::And(this) => this.signature(), + Nnf::Or(this) => this.signature(), + Nnf::Exists(this) => this.signature(), + Nnf::Forall(this) => this.signature(), } } @@ -193,31 +193,31 @@ impl Formula for NNF { } } -impl std::fmt::Display for NNF { +impl std::fmt::Display for Nnf { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } -impl FormulaEx for NNF { +impl FormulaEx for Nnf { fn precedence(&self) -> u8 { match self { - NNF::Top | NNF::Bottom => PRECEDENCE_ATOM, - NNF::Literal(this) => this.precedence(), - NNF::And(this) => this.precedence(), - NNF::Or(this) => this.precedence(), - NNF::Exists(this) => this.precedence(), - NNF::Forall(this) => this.precedence(), + Nnf::Top | Nnf::Bottom => PRECEDENCE_ATOM, + Nnf::Literal(this) => this.precedence(), + Nnf::And(this) => this.precedence(), + Nnf::Or(this) => this.precedence(), + Nnf::Exists(this) => this.precedence(), + Nnf::Forall(this) => this.precedence(), } } } -impl From for FOF { - fn from(value: NNF) -> Self { +impl From for Fof { + fn from(value: Nnf) -> Self { match value { - NNF::Top => Self::Top, - NNF::Bottom => Self::Bottom, - NNF::Literal(lit) => match lit { + Nnf::Top => Self::Top, + Nnf::Bottom => Self::Bottom, + Nnf::Literal(lit) => match lit { Literal::Pos(pos) => match pos { Atomic::Atom(this) => this.into(), Atomic::Equals(this) => this.into(), @@ -227,63 +227,63 @@ impl From for FOF { Atomic::Equals(this) => Self::not(this.into()), }, }, - NNF::And(this) => Self::from(this.left).and(this.right.into()), - NNF::Or(this) => Self::from(this.left).or(this.right.into()), - NNF::Exists(this) => Self::exists(this.variables, this.formula.into()), - NNF::Forall(this) => Self::forall(this.variables, this.formula.into()), + Nnf::And(this) => Self::from(this.left).and(this.right.into()), + Nnf::Or(this) => Self::from(this.left).or(this.right.into()), + Nnf::Exists(this) => Self::exists(this.variables, this.formula.into()), + Nnf::Forall(this) => Self::forall(this.variables, this.formula.into()), } } } -impl From<&NNF> for FOF { - fn from(value: &NNF) -> Self { +impl From<&Nnf> for Fof { + fn from(value: &Nnf) -> Self { value.clone().into() } } // Recursively pushes negation in the formula. #[inline] -fn push_not(formula: &FOF) -> NNF { +fn push_not(formula: &Fof) -> Nnf { match formula { - FOF::Top => NNF::Bottom, - FOF::Bottom => NNF::Top, - FOF::Atom(this) => NNF::neg(this.clone().into()), - FOF::Equals(this) => NNF::neg(this.clone().into()), - FOF::Not(this) => nnf(&this.formula), - FOF::And(this) => nnf(&FOF::not(this.left.clone())).or(nnf(&FOF::not(this.right.clone()))), - FOF::Or(this) => nnf(&FOF::not(this.left.clone())).and(nnf(&FOF::not(this.right.clone()))), - FOF::Implies(this) => nnf(&this.premise).and(nnf(&FOF::not(this.consequence.clone()))), - FOF::Iff(this) => { - let left_and_not_right = nnf(&this.left).and(nnf(&FOF::not(this.right.clone()))); - let not_left_and_right = nnf(&FOF::not(this.left.clone())).and(nnf(&this.right)); + Fof::Top => Nnf::Bottom, + Fof::Bottom => Nnf::Top, + Fof::Atom(this) => Nnf::neg(this.clone().into()), + Fof::Equals(this) => Nnf::neg(this.clone().into()), + Fof::Not(this) => nnf(&this.formula), + Fof::And(this) => nnf(&Fof::not(this.left.clone())).or(nnf(&Fof::not(this.right.clone()))), + Fof::Or(this) => nnf(&Fof::not(this.left.clone())).and(nnf(&Fof::not(this.right.clone()))), + Fof::Implies(this) => nnf(&this.premise).and(nnf(&Fof::not(this.consequence.clone()))), + Fof::Iff(this) => { + let left_and_not_right = nnf(&this.left).and(nnf(&Fof::not(this.right.clone()))); + let not_left_and_right = nnf(&Fof::not(this.left.clone())).and(nnf(&this.right)); left_and_not_right.or(not_left_and_right) } - FOF::Exists(this) => { - NNF::forall(this.variables.clone(), nnf(&FOF::not(this.formula.clone()))) + Fof::Exists(this) => { + Nnf::forall(this.variables.clone(), nnf(&Fof::not(this.formula.clone()))) } - FOF::Forall(this) => { - NNF::exists(this.variables.clone(), nnf(&FOF::not(this.formula.clone()))) + Fof::Forall(this) => { + Nnf::exists(this.variables.clone(), nnf(&Fof::not(this.formula.clone()))) } } } -fn nnf(fmla: &FOF) -> NNF { +fn nnf(fmla: &Fof) -> Nnf { match fmla { - FOF::Top => NNF::Top, - FOF::Bottom => NNF::Bottom, - FOF::Atom(this) => this.clone().into(), - FOF::Equals(this) => this.clone().into(), - FOF::Not(this) => push_not(&this.formula), - FOF::And(this) => nnf(&this.left).and(nnf(&this.right)), - FOF::Or(this) => nnf(&this.left).or(nnf(&this.right)), - FOF::Implies(this) => nnf(&FOF::not(this.premise.clone())).or(nnf(&this.consequence)), - FOF::Iff(this) => { - let not_left_or_right = nnf(&FOF::not(this.left.clone())).or(nnf(&this.right)); - let left_or_not_right = nnf(&this.left).or(nnf(&FOF::not(this.right.clone()))); + Fof::Top => Nnf::Top, + Fof::Bottom => Nnf::Bottom, + Fof::Atom(this) => this.clone().into(), + Fof::Equals(this) => this.clone().into(), + Fof::Not(this) => push_not(&this.formula), + Fof::And(this) => nnf(&this.left).and(nnf(&this.right)), + Fof::Or(this) => nnf(&this.left).or(nnf(&this.right)), + Fof::Implies(this) => nnf(&Fof::not(this.premise.clone())).or(nnf(&this.consequence)), + Fof::Iff(this) => { + let not_left_or_right = nnf(&Fof::not(this.left.clone())).or(nnf(&this.right)); + let left_or_not_right = nnf(&this.left).or(nnf(&Fof::not(this.right.clone()))); not_left_or_right.and(left_or_not_right) } - FOF::Exists(this) => NNF::exists(this.variables.clone(), nnf(&this.formula)), - FOF::Forall(this) => NNF::forall(this.variables.clone(), nnf(&this.formula)), + Fof::Exists(this) => Nnf::exists(this.variables.clone(), nnf(&this.formula)), + Fof::Forall(this) => Nnf::forall(this.variables.clone(), nnf(&this.formula)), } } @@ -299,182 +299,182 @@ mod tests { term, v, }; - fn nnf(formula: &FOF) -> FOF { + fn nnf(formula: &Fof) -> Fof { formula.nnf().into() } #[test] fn test_nnf() { { - let formula: FOF = "true".parse().unwrap(); + let formula: Fof = "true".parse().unwrap(); assert_debug_string!("true", nnf(&formula)); } { - let formula: FOF = "false".parse().unwrap(); + let formula: Fof = "false".parse().unwrap(); assert_debug_string!("false", nnf(&formula)); } { - let formula: FOF = "P(x)".parse().unwrap(); + let formula: Fof = "P(x)".parse().unwrap(); assert_debug_string!("P(x)", nnf(&formula)); } { - let formula: FOF = "x = y".parse().unwrap(); + let formula: Fof = "x = y".parse().unwrap(); assert_debug_string!("x = y", nnf(&formula)); } { - let formula: FOF = "~P(x)".parse().unwrap(); + let formula: Fof = "~P(x)".parse().unwrap(); assert_debug_string!("~P(x)", nnf(&formula)); } { - let formula: FOF = "P(x) & Q(y)".parse().unwrap(); + let formula: Fof = "P(x) & Q(y)".parse().unwrap(); assert_debug_string!("P(x) & Q(y)", nnf(&formula)); } { - let formula: FOF = "P(x) | Q(y)".parse().unwrap(); + let formula: Fof = "P(x) | Q(y)".parse().unwrap(); assert_debug_string!("P(x) | Q(y)", nnf(&formula)); } { - let formula: FOF = "P(x) -> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) -> Q(y)".parse().unwrap(); assert_debug_string!("~P(x) | Q(y)", nnf(&formula)); } { - let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) <=> Q(y)".parse().unwrap(); assert_debug_string!("(~P(x) | Q(y)) & (P(x) | ~Q(y))", nnf(&formula)); } { - let formula: FOF = "?x. P(x)".parse().unwrap(); + let formula: Fof = "?x. P(x)".parse().unwrap(); assert_debug_string!("? x. P(x)", nnf(&formula)); } { - let formula: FOF = "!x. P(x)".parse().unwrap(); + let formula: Fof = "!x. P(x)".parse().unwrap(); assert_debug_string!("! x. P(x)", nnf(&formula)); } // sanity checking { - let formula: FOF = "~true".parse().unwrap(); + let formula: Fof = "~true".parse().unwrap(); assert_debug_string!("false", nnf(&formula)); } { - let formula: FOF = "~false".parse().unwrap(); + let formula: Fof = "~false".parse().unwrap(); assert_debug_string!("true", nnf(&formula)); } { - let formula: FOF = "~~P(x)".parse().unwrap(); + let formula: Fof = "~~P(x)".parse().unwrap(); assert_debug_string!("P(x)", nnf(&formula)); } { - let formula: FOF = "~~~P(x)".parse().unwrap(); + let formula: Fof = "~~~P(x)".parse().unwrap(); assert_debug_string!("~P(x)", nnf(&formula)); } { - let formula: FOF = "~~~~P(x)".parse().unwrap(); + let formula: Fof = "~~~~P(x)".parse().unwrap(); assert_debug_string!("P(x)", nnf(&formula)); } { - let formula: FOF = "~~x = y".parse().unwrap(); + let formula: Fof = "~~x = y".parse().unwrap(); assert_debug_string!("x = y", nnf(&formula)); } { - let formula: FOF = "~(P(x) & Q(y))".parse().unwrap(); + let formula: Fof = "~(P(x) & Q(y))".parse().unwrap(); assert_debug_string!("~P(x) | ~Q(y)", nnf(&formula)); } { - let formula: FOF = "~(P(x) | Q(y))".parse().unwrap(); + let formula: Fof = "~(P(x) | Q(y))".parse().unwrap(); assert_debug_string!("~P(x) & ~Q(y)", nnf(&formula)); } { - let formula: FOF = "~(P(x) -> Q(y))".parse().unwrap(); + let formula: Fof = "~(P(x) -> Q(y))".parse().unwrap(); assert_debug_string!("P(x) & ~Q(y)", nnf(&formula)); } { - let formula: FOF = "~(P(x) <=> Q(y))".parse().unwrap(); + let formula: Fof = "~(P(x) <=> Q(y))".parse().unwrap(); assert_debug_string!("(P(x) & ~Q(y)) | (~P(x) & Q(y))", nnf(&formula)); } { - let formula: FOF = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); + let formula: Fof = "(P(x) | Q(y)) -> R(z)".parse().unwrap(); assert_debug_string!("(~P(x) & ~Q(y)) | R(z)", nnf(&formula)); } { - let formula: FOF = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); + let formula: Fof = "(P(x) | Q(y)) <=> R(z)".parse().unwrap(); assert_debug_string!( "((~P(x) & ~Q(y)) | R(z)) & ((P(x) | Q(y)) | ~R(z))", nnf(&formula), ); } { - let formula: FOF = "~?x. P(x)".parse().unwrap(); + let formula: Fof = "~?x. P(x)".parse().unwrap(); assert_debug_string!("! x. ~P(x)", nnf(&formula)); } { - let formula: FOF = "~!x. P(x)".parse().unwrap(); + let formula: Fof = "~!x. P(x)".parse().unwrap(); assert_debug_string!("? x. ~P(x)", nnf(&formula)); } // recursive application { - let formula: FOF = "~~P(x) & ~~Q(y)".parse().unwrap(); + let formula: Fof = "~~P(x) & ~~Q(y)".parse().unwrap(); assert_debug_string!("P(x) & Q(y)", nnf(&formula)); } { - let formula: FOF = "~~P(x) | ~~Q(y)".parse().unwrap(); + let formula: Fof = "~~P(x) | ~~Q(y)".parse().unwrap(); assert_debug_string!("P(x) | Q(y)", nnf(&formula)); } { - let formula: FOF = "~~P(x) -> ~~Q(y)".parse().unwrap(); + let formula: Fof = "~~P(x) -> ~~Q(y)".parse().unwrap(); assert_debug_string!("~P(x) | Q(y)", nnf(&formula)); } { - let formula: FOF = "~~P(x) <=> ~~Q(y)".parse().unwrap(); + let formula: Fof = "~~P(x) <=> ~~Q(y)".parse().unwrap(); assert_debug_string!("(~P(x) | Q(y)) & (P(x) | ~Q(y))", nnf(&formula)); } { - let formula: FOF = "?x. ~~P(x)".parse().unwrap(); + let formula: Fof = "?x. ~~P(x)".parse().unwrap(); assert_debug_string!("? x. P(x)", nnf(&formula)); } { - let formula: FOF = "!x. ~~P(x)".parse().unwrap(); + let formula: Fof = "!x. ~~P(x)".parse().unwrap(); assert_debug_string!("! x. P(x)", nnf(&formula)); } { - let formula: FOF = "~~~P(x)".parse().unwrap(); + let formula: Fof = "~~~P(x)".parse().unwrap(); assert_debug_string!("~P(x)", nnf(&formula)); } { - let formula: FOF = "~(~P(x) & ~Q(y))".parse().unwrap(); + let formula: Fof = "~(~P(x) & ~Q(y))".parse().unwrap(); assert_debug_string!("P(x) | Q(y)", nnf(&formula)); } { - let formula: FOF = "~(~P(x) | ~Q(y))".parse().unwrap(); + let formula: Fof = "~(~P(x) | ~Q(y))".parse().unwrap(); assert_debug_string!("P(x) & Q(y)", nnf(&formula)); } { - let formula: FOF = "~(~P(x) -> ~Q(y))".parse().unwrap(); + let formula: Fof = "~(~P(x) -> ~Q(y))".parse().unwrap(); assert_debug_string!("~P(x) & Q(y)", nnf(&formula)); } { - let formula: FOF = "~(~(P(x) & Q(x)) & ~(P(y) & Q(y)))".parse().unwrap(); + let formula: Fof = "~(~(P(x) & Q(x)) & ~(P(y) & Q(y)))".parse().unwrap(); assert_debug_string!("(P(x) & Q(x)) | (P(y) & Q(y))", nnf(&formula)); } { - let formula: FOF = "~(~(P(x) & Q(x)) | ~(P(y) & Q(y)))".parse().unwrap(); + let formula: Fof = "~(~(P(x) & Q(x)) | ~(P(y) & Q(y)))".parse().unwrap(); assert_debug_string!("(P(x) & Q(x)) & (P(y) & Q(y))", nnf(&formula)); } { - let formula: FOF = "~(~(P(x) & Q(x)) -> ~(P(y) & Q(y)))".parse().unwrap(); + let formula: Fof = "~(~(P(x) & Q(x)) -> ~(P(y) & Q(y)))".parse().unwrap(); assert_debug_string!("(~P(x) | ~Q(x)) & (P(y) & Q(y))", nnf(&formula)); } { - let formula: FOF = "~(~(P(x) & Q(x)) <=> ~(P(y) & Q(y)))".parse().unwrap(); + let formula: Fof = "~(~(P(x) & Q(x)) <=> ~(P(y) & Q(y)))".parse().unwrap(); assert_debug_string!( "((~P(x) | ~Q(x)) & (P(y) & Q(y))) | ((P(x) & Q(x)) & (~P(y) | ~Q(y)))", nnf(&formula), ); } { - let formula: FOF = "~?x. !y. (P(x) -> Q(y))".parse().unwrap(); + let formula: Fof = "~?x. !y. (P(x) -> Q(y))".parse().unwrap(); assert_debug_string!("! x. (? y. (P(x) & ~Q(y)))", nnf(&formula)); } { - let formula: FOF = "~((?x. P(x)) & (!y. Q(y)))".parse().unwrap(); + let formula: Fof = "~((?x. P(x)) & (!y. Q(y)))".parse().unwrap(); assert_debug_string!("(! x. ~P(x)) | (? y. ~Q(y))", nnf(&formula)); } } @@ -509,7 +509,7 @@ mod tests { }; assert_eq!( fof!({!x. {? y. {[P(z, y)] | [~(Q(z))]}}} & {[~(R(z, z))] | [R(@c)]}), - FOF::from(nnf.transform_term(&f)) + Fof::from(nnf.transform_term(&f)) ); } diff --git a/razor-fol/src/transform/pnf.rs b/razor-fol/src/transform/pnf.rs index 29a3925..8d79089 100644 --- a/razor-fol/src/transform/pnf.rs +++ b/razor-fol/src/transform/pnf.rs @@ -1,118 +1,118 @@ /*! Defines formulae in Prenex Normal Form (PNF) and implements an algorithm for transforming -an [`FOF`] to a [`PNF`]. +an [`Fof`] to a [`Pnf`]. -[`FOF`]: crate::syntax::FOF +[`Fof`]: crate::syntax::Fof */ -use crate::syntax::{formula::qff::QFF, formula::*, term::Complex, Var, FOF}; +use crate::syntax::{formula::qff::Qff, formula::*, term::Complex, Fof, Var}; /// Represents a formula in Prenex Normal Form (PNF). /// /// **Hint**: A PNF is a first-order formula with all quantifiers (existential and /// universal) and bound variables at the front, followed by a quantifier-free part. #[derive(Clone)] -pub enum PNF { - /// Is the quantifier-free portion of a [`PNF`]. - QFF(QFF), +pub enum Pnf { + /// Is the quantifier-free portion of a [`Pnf`]. + QFF(Qff), /// Is an existentially quantified PNF, wrapping an [`Exists`]. - Exists(Box>), + Exists(Box>), /// Is a universally quantified PNF, wrapping a [`Forall`]. - Forall(Box>), + Forall(Box>), } -impl From> for PNF { +impl From> for Pnf { fn from(value: Atom) -> Self { Self::QFF(value.into()) } } -impl From> for PNF { +impl From> for Pnf { fn from(value: Equals) -> Self { Self::QFF(value.into()) } } -impl From> for PNF { - fn from(value: Not) -> Self { +impl From> for Pnf { + fn from(value: Not) -> Self { Self::QFF(value.into()) } } -impl From> for PNF { - fn from(value: And) -> Self { +impl From> for Pnf { + fn from(value: And) -> Self { Self::QFF(value.into()) } } -impl From> for PNF { - fn from(value: Or) -> Self { +impl From> for Pnf { + fn from(value: Or) -> Self { Self::QFF(value.into()) } } -impl From> for PNF { - fn from(value: Implies) -> Self { +impl From> for Pnf { + fn from(value: Implies) -> Self { Self::QFF(value.into()) } } -impl From> for PNF { - fn from(value: Iff) -> Self { +impl From> for Pnf { + fn from(value: Iff) -> Self { Self::QFF(value.into()) } } -impl From> for PNF { - fn from(value: Exists) -> Self { +impl From> for Pnf { + fn from(value: Exists) -> Self { Self::Exists(Box::new(value)) } } -impl From> for PNF { - fn from(value: Forall) -> Self { +impl From> for Pnf { + fn from(value: Forall) -> Self { Self::Forall(Box::new(value)) } } -impl From for PNF { - fn from(value: QFF) -> Self { +impl From for Pnf { + fn from(value: Qff) -> Self { Self::QFF(value) } } -/// Is the trait of [`Formula`] types that can be transformed to [`PNF`]. -pub trait ToPNF: Formula { +/// Is the trait of [`Formula`] types that can be transformed to [`Pnf`]. +pub trait ToPnf: Formula { /// Transforms `self` to a Prenex Normal Form (PNF). /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToPNF; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToPnf; /// - /// let formula: FOF = "Q(x, y) → ∃ x, y. P(x, y)".parse().unwrap(); + /// let formula: Fof = "Q(x, y) → ∃ x, y. P(x, y)".parse().unwrap(); /// let pnf = formula.pnf(); /// /// assert_eq!("∃ x`, y`. (Q(x, y) → P(x`, y`))", pnf.to_string()); /// ``` - fn pnf(&self) -> PNF; + fn pnf(&self) -> Pnf; } -impl ToPNF for FOF { - fn pnf(&self) -> PNF { +impl ToPnf for Fof { + fn pnf(&self) -> Pnf { pnf(self) } } -impl From for PNF { +impl From for Pnf { fn from(value: T) -> Self { value.pnf() } } -impl PNF { +impl Pnf { #[inline(always)] - fn not(formula: QFF) -> Self { + fn not(formula: Qff) -> Self { Not { formula }.into() } @@ -127,34 +127,34 @@ impl PNF { } } -impl Formula for PNF { +impl Formula for Pnf { type Term = Complex; fn signature(&self) -> Result { match self { - PNF::QFF(this) => this.signature(), - PNF::Exists(this) => this.signature(), - PNF::Forall(this) => this.signature(), + Pnf::QFF(this) => this.signature(), + Pnf::Exists(this) => this.signature(), + Pnf::Forall(this) => this.signature(), } } fn free_vars(&self) -> Vec<&Var> { match self { - PNF::QFF(this) => this.free_vars(), - PNF::Exists(this) => this.free_vars(), - PNF::Forall(this) => this.free_vars(), + Pnf::QFF(this) => this.free_vars(), + Pnf::Exists(this) => this.free_vars(), + Pnf::Forall(this) => this.free_vars(), } } fn transform_term(&self, f: &impl Fn(&Complex) -> Complex) -> Self { match self { - PNF::QFF(this) => this.transform_term(f).into(), - PNF::Exists(this) => Exists { + Pnf::QFF(this) => this.transform_term(f).into(), + Pnf::Exists(this) => Exists { variables: this.variables.clone(), formula: this.formula.transform_term(f), } .into(), - PNF::Forall(this) => Forall { + Pnf::Forall(this) => Forall { variables: this.variables.clone(), formula: this.formula.transform_term(f), } @@ -163,34 +163,34 @@ impl Formula for PNF { } } -impl FormulaEx for PNF { +impl FormulaEx for Pnf { fn precedence(&self) -> u8 { match self { - PNF::QFF(this) => this.precedence(), - PNF::Exists(this) => this.precedence(), - PNF::Forall(this) => this.precedence(), + Pnf::QFF(this) => this.precedence(), + Pnf::Exists(this) => this.precedence(), + Pnf::Forall(this) => this.precedence(), } } } -impl std::fmt::Display for PNF { +impl std::fmt::Display for Pnf { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } -impl From for FOF { - fn from(value: PNF) -> Self { +impl From for Fof { + fn from(value: Pnf) -> Self { match value { - PNF::QFF(this) => this.into(), - PNF::Exists(this) => FOF::exists(this.variables, this.formula.into()), - PNF::Forall(this) => FOF::forall(this.variables, this.formula.into()), + Pnf::QFF(this) => this.into(), + Pnf::Exists(this) => Fof::exists(this.variables, this.formula.into()), + Pnf::Forall(this) => Fof::forall(this.variables, this.formula.into()), } } } -impl From<&PNF> for FOF { - fn from(value: &PNF) -> Self { +impl From<&Pnf> for Fof { + fn from(value: &Pnf) -> Self { value.clone().into() } } @@ -208,7 +208,7 @@ fn rename(variable: &Var, no_collision_variables: &[&Var]) -> Var { // helper for transforming formulae with binary operands #[inline] -fn binary_helper(vars: &[Var], formula: &PNF, other: &PNF) -> (Vec, PNF) { +fn binary_helper(vars: &[Var], formula: &Pnf, other: &Pnf) -> (Vec, Pnf) { let formula_vars = formula.free_vars(); let other_vars = other.free_vars(); @@ -236,45 +236,45 @@ fn binary_helper(vars: &[Var], formula: &PNF, other: &PNF) -> (Vec, PNF) { // The transforming function as a helper #[inline] -fn pnf(formula: &FOF) -> PNF { +fn pnf(formula: &Fof) -> Pnf { match formula { - FOF::Top => PNF::QFF(QFF::Top), - FOF::Bottom => PNF::QFF(QFF::Bottom), - FOF::Atom(this) => this.clone().into(), - FOF::Equals(this) => this.clone().into(), + Fof::Top => Pnf::QFF(Qff::Top), + Fof::Bottom => Pnf::QFF(Qff::Bottom), + Fof::Atom(this) => this.clone().into(), + Fof::Equals(this) => this.clone().into(), // e.g. ~(Qx. P(x)) -> Q' x. ~P(x) - FOF::Not(this) => match pnf(&this.formula) { - PNF::Forall(forall) => { - PNF::exists(forall.variables, pnf(&FOF::not(forall.formula.into()))) + Fof::Not(this) => match pnf(&this.formula) { + Pnf::Forall(forall) => { + Pnf::exists(forall.variables, pnf(&Fof::not(forall.formula.into()))) } - PNF::Exists(exists) => { - PNF::forall(exists.variables, pnf(&FOF::not(exists.formula.into()))) + Pnf::Exists(exists) => { + Pnf::forall(exists.variables, pnf(&Fof::not(exists.formula.into()))) } - PNF::QFF(this) => PNF::not(this), + Pnf::QFF(this) => Pnf::not(this), }, // e.g. (Q x. F(x)) & G(y) => Q x'. F(x') & G(y) or F(x) & (Q y. G(y)) => Q y'. F(x) & G(y') - FOF::And(this) => { + Fof::And(this) => { let left = pnf(&this.left); let right = pnf(&this.right); match (&left, &right) { - (PNF::Forall(f), _) => { + (Pnf::Forall(f), _) => { let (vars, fmla) = binary_helper(&f.variables, &f.formula, &right); - pnf(&FOF::forall(vars, FOF::from(fmla).and(right.into()))) + pnf(&Fof::forall(vars, Fof::from(fmla).and(right.into()))) } - (PNF::Exists(e), _) => { + (Pnf::Exists(e), _) => { let (vars, fmla) = binary_helper(&e.variables, &e.formula, &right); - pnf(&FOF::exists(vars, FOF::from(fmla).and(right.into()))) + pnf(&Fof::exists(vars, Fof::from(fmla).and(right.into()))) } - (_, PNF::Forall(f)) => { + (_, Pnf::Forall(f)) => { let (vars, fmla) = binary_helper(&f.variables, &f.formula, &left); - pnf(&FOF::forall(vars, FOF::from(left).and(fmla.into()))) + pnf(&Fof::forall(vars, Fof::from(left).and(fmla.into()))) } - (_, PNF::Exists(e)) => { + (_, Pnf::Exists(e)) => { let (vars, fmla) = binary_helper(&e.variables, &e.formula, &left); - pnf(&FOF::exists(vars, FOF::from(left).and(fmla.into()))) + pnf(&Fof::exists(vars, Fof::from(left).and(fmla.into()))) } - (PNF::QFF(left), PNF::QFF(right)) => And { + (Pnf::QFF(left), Pnf::QFF(right)) => And { left: left.clone(), right: right.clone(), } @@ -282,28 +282,28 @@ fn pnf(formula: &FOF) -> PNF { } } // e.g. (Q x. F(x)) | G(y) => Q x'. F(x') | G(y) or F(x) | (Q y. G(y)) => Q y'. F(x) | G(y') - FOF::Or(this) => { + Fof::Or(this) => { let left = pnf(&this.left); let right = pnf(&this.right); match (&left, &right) { - (PNF::Forall(f), _) => { + (Pnf::Forall(f), _) => { let (vars, fmla) = binary_helper(&f.variables, &f.formula, &right); - pnf(&FOF::forall(vars, FOF::from(fmla).or(right.into()))) + pnf(&Fof::forall(vars, Fof::from(fmla).or(right.into()))) } - (PNF::Exists(e), _) => { + (Pnf::Exists(e), _) => { let (vars, fmla) = binary_helper(&e.variables, &e.formula, &right); - pnf(&FOF::exists(vars, FOF::from(fmla).or(right.into()))) + pnf(&Fof::exists(vars, Fof::from(fmla).or(right.into()))) } - (_, PNF::Forall(f)) => { + (_, Pnf::Forall(f)) => { let (vars, fmla) = binary_helper(&f.variables, &f.formula, &left); - pnf(&FOF::forall(vars, FOF::from(left).or(fmla.into()))) + pnf(&Fof::forall(vars, Fof::from(left).or(fmla.into()))) } - (_, PNF::Exists(e)) => { + (_, Pnf::Exists(e)) => { let (vars, fmla) = binary_helper(&e.variables, &e.formula, &left); - pnf(&FOF::exists(vars, FOF::from(left).or(fmla.into()))) + pnf(&Fof::exists(vars, Fof::from(left).or(fmla.into()))) } - (PNF::QFF(left), PNF::QFF(right)) => Or { + (Pnf::QFF(left), Pnf::QFF(right)) => Or { left: left.clone(), right: right.clone(), } @@ -311,49 +311,49 @@ fn pnf(formula: &FOF) -> PNF { } } // e.g. (Q x. F(x)) -> G(y) => Q' x'. F(x') -> G(y) or F(x) -> (Q y. G(y)) => Q' y'. F(x) -> G(y') - FOF::Implies(this) => { + Fof::Implies(this) => { let premise = pnf(&this.premise); let consequence = pnf(&this.consequence); match (&premise, &consequence) { - (PNF::Forall(f), _) => { + (Pnf::Forall(f), _) => { let (vars, fmla) = binary_helper(&f.variables, &f.formula, &consequence); - pnf(&FOF::exists( + pnf(&Fof::exists( vars, - FOF::from(fmla).implies(consequence.into()), + Fof::from(fmla).implies(consequence.into()), )) } - (PNF::Exists(e), _) => { + (Pnf::Exists(e), _) => { let (vars, fmla) = binary_helper(&e.variables, &e.formula, &consequence); - pnf(&FOF::forall( + pnf(&Fof::forall( vars, - FOF::from(fmla).implies(consequence.into()), + Fof::from(fmla).implies(consequence.into()), )) } - (_, PNF::Forall(f)) => { + (_, Pnf::Forall(f)) => { let (vars, fmla) = binary_helper(&f.variables, &f.formula, &premise); - pnf(&FOF::forall(vars, FOF::from(premise).implies(fmla.into()))) + pnf(&Fof::forall(vars, Fof::from(premise).implies(fmla.into()))) } - (_, PNF::Exists(e)) => { + (_, Pnf::Exists(e)) => { let (vars, fmla) = binary_helper(&e.variables, &e.formula, &premise); - pnf(&FOF::exists(vars, FOF::from(premise).implies(fmla.into()))) + pnf(&Fof::exists(vars, Fof::from(premise).implies(fmla.into()))) } - (PNF::QFF(premise), PNF::QFF(consequence)) => Implies { + (Pnf::QFF(premise), Pnf::QFF(consequence)) => Implies { premise: premise.clone(), consequence: consequence.clone(), } .into(), } } - FOF::Iff(this) => { + Fof::Iff(this) => { let left = &this.left; let right = &this.right; let left_to_right = left.clone().implies(right.clone()); let right_to_left = right.clone().implies(left.clone()); pnf(&left_to_right.and(right_to_left)) } - FOF::Exists(this) => PNF::exists(this.variables.clone(), pnf(&this.formula)), - FOF::Forall(this) => PNF::forall(this.variables.clone(), pnf(&this.formula)), + Fof::Exists(this) => Pnf::exists(this.variables.clone(), pnf(&this.formula)), + Fof::Forall(this) => Pnf::forall(this.variables.clone(), pnf(&this.formula)), } } @@ -369,286 +369,286 @@ mod tests { term, v, v_1, }; - fn pnf(formula: &FOF) -> FOF { + fn pnf(formula: &Fof) -> Fof { formula.pnf().into() } #[test] fn test_pnf() { { - let formula: FOF = "true".parse().unwrap(); + let formula: Fof = "true".parse().unwrap(); assert_debug_string!("true", pnf(&formula)); } { - let formula: FOF = "false".parse().unwrap(); + let formula: Fof = "false".parse().unwrap(); assert_debug_string!("false", pnf(&formula)); } { - let formula: FOF = "P(x)".parse().unwrap(); + let formula: Fof = "P(x)".parse().unwrap(); assert_debug_string!("P(x)", pnf(&formula)); } { - let formula: FOF = "x = y".parse().unwrap(); + let formula: Fof = "x = y".parse().unwrap(); assert_debug_string!("x = y", pnf(&formula)); } { - let formula: FOF = "~P(x)".parse().unwrap(); + let formula: Fof = "~P(x)".parse().unwrap(); assert_debug_string!("~P(x)", pnf(&formula)); } { - let formula: FOF = "P(x) & Q(y)".parse().unwrap(); + let formula: Fof = "P(x) & Q(y)".parse().unwrap(); assert_debug_string!("P(x) & Q(y)", pnf(&formula)); } { - let formula: FOF = "P(x) | Q(y)".parse().unwrap(); + let formula: Fof = "P(x) | Q(y)".parse().unwrap(); assert_debug_string!("P(x) | Q(y)", pnf(&formula)); } { - let formula: FOF = "P(x) -> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) -> Q(y)".parse().unwrap(); assert_debug_string!("P(x) -> Q(y)", pnf(&formula)); } { - let formula: FOF = "P(x) <=> Q(y)".parse().unwrap(); + let formula: Fof = "P(x) <=> Q(y)".parse().unwrap(); assert_debug_string!("(P(x) -> Q(y)) & (Q(y) -> P(x))", pnf(&formula)); } { - let formula: FOF = "? x. P(x) & ~Q(y) | R(z)".parse().unwrap(); + let formula: Fof = "? x. P(x) & ~Q(y) | R(z)".parse().unwrap(); assert_debug_string!("? x. ((P(x) & ~Q(y)) | R(z))", pnf(&formula)); } { - let formula: FOF = "! x. P(x) & ~Q(y) | R(z)".parse().unwrap(); + let formula: Fof = "! x. P(x) & ~Q(y) | R(z)".parse().unwrap(); assert_debug_string!("! x. ((P(x) & ~Q(y)) | R(z))", pnf(&formula)); } // sanity checking: { - let formula: FOF = "~? x. P(x)".parse().unwrap(); + let formula: Fof = "~? x. P(x)".parse().unwrap(); assert_debug_string!("! x. ~P(x)", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) & Q(y)".parse().unwrap(); + let formula: Fof = "(! x. P(x)) & Q(y)".parse().unwrap(); assert_debug_string!("! x. (P(x) & Q(y))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) & Q(y)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) & Q(y)".parse().unwrap(); assert_debug_string!("? x. (P(x) & Q(y))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) & Q(x)".parse().unwrap(); + let formula: Fof = "(! x. P(x)) & Q(x)".parse().unwrap(); assert_debug_string!("! x`. (P(x`) & Q(x))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) & Q(x)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) & Q(x)".parse().unwrap(); assert_debug_string!("? x`. (P(x`) & Q(x))", pnf(&formula)); } { - let formula: FOF = "(! x, y. P(x, y)) & Q(x, y)".parse().unwrap(); + let formula: Fof = "(! x, y. P(x, y)) & Q(x, y)".parse().unwrap(); assert_debug_string!("! x`, y`. (P(x`, y`) & Q(x, y))", pnf(&formula)); } { - let formula: FOF = "(? x, y. P(x, y)) & Q(x, y)".parse().unwrap(); + let formula: Fof = "(? x, y. P(x, y)) & Q(x, y)".parse().unwrap(); assert_debug_string!("? x`, y`. (P(x`, y`) & Q(x, y))", pnf(&formula)); } { - let formula: FOF = "Q(y) & ! x. P(x)".parse().unwrap(); + let formula: Fof = "Q(y) & ! x. P(x)".parse().unwrap(); assert_debug_string!("! x. (Q(y) & P(x))", pnf(&formula)); } { - let formula: FOF = "Q(y) & ? x. P(x)".parse().unwrap(); + let formula: Fof = "Q(y) & ? x. P(x)".parse().unwrap(); assert_debug_string!("? x. (Q(y) & P(x))", pnf(&formula)); } { - let formula: FOF = "Q(x) & ! x. P(x)".parse().unwrap(); + let formula: Fof = "Q(x) & ! x. P(x)".parse().unwrap(); assert_debug_string!("! x`. (Q(x) & P(x`))", pnf(&formula)); } { - let formula: FOF = "Q(x) & ? x. P(x)".parse().unwrap(); + let formula: Fof = "Q(x) & ? x. P(x)".parse().unwrap(); assert_debug_string!("? x`. (Q(x) & P(x`))", pnf(&formula)); } { - let formula: FOF = "Q(x, y) & ! x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "Q(x, y) & ! x, y. P(x, y)".parse().unwrap(); assert_debug_string!("! x`, y`. (Q(x, y) & P(x`, y`))", pnf(&formula)); } { - let formula: FOF = "Q(x, y) & ? x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "Q(x, y) & ? x, y. P(x, y)".parse().unwrap(); assert_debug_string!("? x`, y`. (Q(x, y) & P(x`, y`))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) | Q(y)".parse().unwrap(); + let formula: Fof = "(! x. P(x)) | Q(y)".parse().unwrap(); assert_debug_string!("! x. (P(x) | Q(y))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) | Q(y)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) | Q(y)".parse().unwrap(); assert_debug_string!("? x. (P(x) | Q(y))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) | Q(x)".parse().unwrap(); + let formula: Fof = "(! x. P(x)) | Q(x)".parse().unwrap(); assert_debug_string!("! x`. (P(x`) | Q(x))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) | Q(x)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) | Q(x)".parse().unwrap(); assert_debug_string!("? x`. (P(x`) | Q(x))", pnf(&formula)); } { - let formula: FOF = "(! x, y. P(x, y)) | Q(x, y)".parse().unwrap(); + let formula: Fof = "(! x, y. P(x, y)) | Q(x, y)".parse().unwrap(); assert_debug_string!("! x`, y`. (P(x`, y`) | Q(x, y))", pnf(&formula)); } { - let formula: FOF = "(? x, y. P(x, y)) | Q(x, y)".parse().unwrap(); + let formula: Fof = "(? x, y. P(x, y)) | Q(x, y)".parse().unwrap(); assert_debug_string!("? x`, y`. (P(x`, y`) | Q(x, y))", pnf(&formula)); } { - let formula: FOF = "Q(y) | ! x. P(x)".parse().unwrap(); + let formula: Fof = "Q(y) | ! x. P(x)".parse().unwrap(); assert_debug_string!("! x. (Q(y) | P(x))", pnf(&formula)); } { - let formula: FOF = "Q(y) | ? x. P(x)".parse().unwrap(); + let formula: Fof = "Q(y) | ? x. P(x)".parse().unwrap(); assert_debug_string!("? x. (Q(y) | P(x))", pnf(&formula)); } { - let formula: FOF = "Q(x) | ! x. P(x)".parse().unwrap(); + let formula: Fof = "Q(x) | ! x. P(x)".parse().unwrap(); assert_debug_string!("! x`. (Q(x) | P(x`))", pnf(&formula)); } { - let formula: FOF = "Q(x) | ? x. P(x)".parse().unwrap(); + let formula: Fof = "Q(x) | ? x. P(x)".parse().unwrap(); assert_debug_string!("? x`. (Q(x) | P(x`))", pnf(&formula)); } { - let formula: FOF = "Q(x, y) | ! x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "Q(x, y) | ! x, y. P(x, y)".parse().unwrap(); assert_debug_string!("! x`, y`. (Q(x, y) | P(x`, y`))", pnf(&formula)); } { - let formula: FOF = "Q(x, y) | ? x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "Q(x, y) | ? x, y. P(x, y)".parse().unwrap(); assert_debug_string!("? x`, y`. (Q(x, y) | P(x`, y`))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) -> Q(y)".parse().unwrap(); + let formula: Fof = "(! x. P(x)) -> Q(y)".parse().unwrap(); assert_debug_string!("? x. (P(x) -> Q(y))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) -> Q(y)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) -> Q(y)".parse().unwrap(); assert_debug_string!("! x. (P(x) -> Q(y))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) -> Q(x)".parse().unwrap(); + let formula: Fof = "(! x. P(x)) -> Q(x)".parse().unwrap(); assert_debug_string!("? x`. (P(x`) -> Q(x))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) -> Q(x)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) -> Q(x)".parse().unwrap(); assert_debug_string!("! x`. (P(x`) -> Q(x))", pnf(&formula)); } { - let formula: FOF = "(! x, y. P(x, y)) -> Q(x, y)".parse().unwrap(); + let formula: Fof = "(! x, y. P(x, y)) -> Q(x, y)".parse().unwrap(); assert_debug_string!("? x`, y`. (P(x`, y`) -> Q(x, y))", pnf(&formula)); } { - let formula: FOF = "(? x, y. P(x, y)) -> Q(x, y)".parse().unwrap(); + let formula: Fof = "(? x, y. P(x, y)) -> Q(x, y)".parse().unwrap(); assert_debug_string!("! x`, y`. (P(x`, y`) -> Q(x, y))", pnf(&formula)); } { - let formula: FOF = "Q(y) -> ! x. P(x)".parse().unwrap(); + let formula: Fof = "Q(y) -> ! x. P(x)".parse().unwrap(); assert_debug_string!("! x. (Q(y) -> P(x))", pnf(&formula)); } { - let formula: FOF = "Q(y) -> ? x. P(x)".parse().unwrap(); + let formula: Fof = "Q(y) -> ? x. P(x)".parse().unwrap(); assert_debug_string!("? x. (Q(y) -> P(x))", pnf(&formula)); } { - let formula: FOF = "Q(x) -> ! x. P(x)".parse().unwrap(); + let formula: Fof = "Q(x) -> ! x. P(x)".parse().unwrap(); assert_debug_string!("! x`. (Q(x) -> P(x`))", pnf(&formula)); } { - let formula: FOF = "Q(x) -> ? x. P(x)".parse().unwrap(); + let formula: Fof = "Q(x) -> ? x. P(x)".parse().unwrap(); assert_debug_string!("? x`. (Q(x) -> P(x`))", pnf(&formula)); } { - let formula: FOF = "Q(x, y) -> ! x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "Q(x, y) -> ! x, y. P(x, y)".parse().unwrap(); assert_debug_string!("! x`, y`. (Q(x, y) -> P(x`, y`))", pnf(&formula)); } { - let formula: FOF = "Q(x, y) -> ? x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "Q(x, y) -> ? x, y. P(x, y)".parse().unwrap(); assert_debug_string!("? x`, y`. (Q(x, y) -> P(x`, y`))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) <=> Q(y)".parse().unwrap(); + let formula: Fof = "(! x. P(x)) <=> Q(y)".parse().unwrap(); assert_debug_string!( "? x. (! x`. ((P(x) -> Q(y)) & (Q(y) -> P(x`))))", pnf(&formula), ); } { - let formula: FOF = "(? x. P(x)) <=> Q(y)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) <=> Q(y)".parse().unwrap(); assert_debug_string!( "! x. (? x`. ((P(x) -> Q(y)) & (Q(y) -> P(x`))))", pnf(&formula), ); } { - let formula: FOF = "(! x. P(x)) <=> Q(x)".parse().unwrap(); + let formula: Fof = "(! x. P(x)) <=> Q(x)".parse().unwrap(); assert_debug_string!( "? x`. (! x``. ((P(x`) -> Q(x)) & (Q(x) -> P(x``))))", pnf(&formula), ); } { - let formula: FOF = "(? x. P(x)) <=> Q(x)".parse().unwrap(); + let formula: Fof = "(? x. P(x)) <=> Q(x)".parse().unwrap(); assert_debug_string!( "! x`. (? x``. ((P(x`) -> Q(x)) & (Q(x) -> P(x``))))", pnf(&formula), ); } { - let formula: FOF = "(! x, y. P(x, y)) <=> Q(x, y)".parse().unwrap(); + let formula: Fof = "(! x, y. P(x, y)) <=> Q(x, y)".parse().unwrap(); assert_debug_string!( "? x`, y`. (! x``, y``. ((P(x`, y`) -> Q(x, y)) & (Q(x, y) -> P(x``, y``))))", pnf(&formula), ); } { - let formula: FOF = "(? x, y. P(x, y)) <=> Q(x, y)".parse().unwrap(); + let formula: Fof = "(? x, y. P(x, y)) <=> Q(x, y)".parse().unwrap(); assert_debug_string!( "! x`, y`. (? x``, y``. ((P(x`, y`) -> Q(x, y)) & (Q(x, y) -> P(x``, y``))))", pnf(&formula), ); } { - let formula: FOF = "Q(y) <=> ! x. P(x)".parse().unwrap(); + let formula: Fof = "Q(y) <=> ! x. P(x)".parse().unwrap(); assert_debug_string!( "! x. (? x`. ((Q(y) -> P(x)) & (P(x`) -> Q(y))))", pnf(&formula), ); } { - let formula: FOF = "Q(y) <=> ? x. P(x)".parse().unwrap(); + let formula: Fof = "Q(y) <=> ? x. P(x)".parse().unwrap(); assert_debug_string!( "? x. (! x`. ((Q(y) -> P(x)) & (P(x`) -> Q(y))))", pnf(&formula), ); } { - let formula: FOF = "Q(x) <=> ! x. P(x)".parse().unwrap(); + let formula: Fof = "Q(x) <=> ! x. P(x)".parse().unwrap(); assert_debug_string!( "! x`. (? x``. ((Q(x) -> P(x`)) & (P(x``) -> Q(x))))", pnf(&formula), ); } { - let formula: FOF = "Q(x) <=> ? x. P(x)".parse().unwrap(); + let formula: Fof = "Q(x) <=> ? x. P(x)".parse().unwrap(); assert_debug_string!( "? x`. (! x``. ((Q(x) -> P(x`)) & (P(x``) -> Q(x))))", pnf(&formula), ); } { - let formula: FOF = "Q(x, y) <=> ! x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "Q(x, y) <=> ! x, y. P(x, y)".parse().unwrap(); assert_debug_string!( "! x`, y`. (? x``, y``. ((Q(x, y) -> P(x`, y`)) & (P(x``, y``) -> Q(x, y))))", pnf(&formula), ); } { - let formula: FOF = "Q(x, y) <=> ? x, y. P(x, y)".parse().unwrap(); + let formula: Fof = "Q(x, y) <=> ? x, y. P(x, y)".parse().unwrap(); assert_debug_string!( "? x`, y`. (! x``, y``. ((Q(x, y) -> P(x`, y`)) & (P(x``, y``) -> Q(x, y))))", pnf(&formula), @@ -658,26 +658,26 @@ mod tests { assert_debug_string!( "! x``, x`. (P(x``) & Q(x))", pnf( - &FOF::forall(vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into()) + &Fof::forall(vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into()) .and(pred!(Q).app(vec![term!(x)]).into()) ), ); assert_debug_string!( "? x``, x`. (P(x``) & Q(x))", pnf( - &FOF::exists(vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into()) + &Fof::exists(vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into()) .and(pred!(Q).app(vec![term!(x)]).into()) ), ); assert_debug_string!( "? x``. (P(x``) & Q(x, x`))", - pnf(&FOF::exists(vec![v!(x)], fof!(P(x))) + pnf(&Fof::exists(vec![v!(x)], fof!(P(x))) .and(pred!(Q).app(vec![term!(x), v_1!(x).into()]).into()) .into()), ); assert_debug_string!( "? x``. (P(x``, x`) & Q(x))", - pnf(&FOF::exists( + pnf(&Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x), v_1!(x).into()]).into() ) @@ -685,14 +685,14 @@ mod tests { ); assert_debug_string!( "! x``, x`. (Q(x) & P(x``))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])).and(FOF::forall( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])).and(Fof::forall( vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into() ))), ); assert_debug_string!( "? x``, x`. (Q(x) & P(x``))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])).and(FOF::exists( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])).and(Fof::exists( vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into() ))), @@ -700,7 +700,7 @@ mod tests { assert_debug_string!( "? x``. (Q(x, x`) & P(x``))", pnf( - &FOF::from(pred!(Q).app(vec![term!(x), v_1!(x).into()])).and(FOF::exists( + &Fof::from(pred!(Q).app(vec![term!(x), v_1!(x).into()])).and(Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x)]).into() )) @@ -708,7 +708,7 @@ mod tests { ); assert_debug_string!( "? x``. (Q(x) & P(x``, x`))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])).and(FOF::exists( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])).and(Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x), v_1!(x).into()]).into(), ))), @@ -717,7 +717,7 @@ mod tests { assert_debug_string!( "! x``, x`. (P(x``) | Q(x))", pnf( - &FOF::forall(vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into()).or(pred!( + &Fof::forall(vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into()).or(pred!( Q ) .app(vec![term!(x)]) @@ -727,7 +727,7 @@ mod tests { assert_debug_string!( "? x``, x`. (P(x``) | Q(x))", pnf( - &FOF::exists(vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into()).or(pred!( + &Fof::exists(vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into()).or(pred!( Q ) .app(vec![term!(x)]) @@ -737,13 +737,13 @@ mod tests { assert_debug_string!( "? x``. (P(x``) | Q(x, x`))", pnf( - &FOF::exists(vec![v!(x)], pred!(P).app(vec![term!(x)]).into()) + &Fof::exists(vec![v!(x)], pred!(P).app(vec![term!(x)]).into()) .or(pred!(Q).app(vec![term!(x), v_1!(x).into()]).into()) ) ); assert_debug_string!( "? x``. (P(x``, x`) | Q(x))", - pnf(&FOF::exists( + pnf(&Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x), v_1!(x).into()]).into() ) @@ -752,14 +752,14 @@ mod tests { ); assert_debug_string!( "! x``, x`. (Q(x) | P(x``))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])).or(FOF::forall( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])).or(Fof::forall( vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into() ))) ); assert_debug_string!( "? x``, x`. (Q(x) | P(x``))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])).or(FOF::exists( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])).or(Fof::exists( vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into() ))) @@ -767,7 +767,7 @@ mod tests { assert_debug_string!( "? x``. (Q(x, x`) | P(x``))", pnf( - &FOF::from(pred!(Q).app(vec![term!(x), v_1!(x).into()])).or(FOF::exists( + &Fof::from(pred!(Q).app(vec![term!(x), v_1!(x).into()])).or(Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x)]).into() )) @@ -775,7 +775,7 @@ mod tests { ); assert_debug_string!( "? x``. (Q(x) | P(x``, x`))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])).or(FOF::exists( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])).or(Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x), v_1!(x).into()]).into(), ))) @@ -783,17 +783,17 @@ mod tests { assert_debug_string!( "? x``, x`. (P(x``) -> Q(x))", - pnf(&FOF::forall( + pnf(&Fof::forall( vec![v!(x), v_1!(x)], - FOF::from(pred!(P).app(vec![term!(x)])) + Fof::from(pred!(P).app(vec![term!(x)])) ) .implies(pred!(Q).app(vec![term!(x)]).into())) ); assert_debug_string!( "! x``, x`. (P(x``) -> Q(x))", - pnf(&FOF::exists( + pnf(&Fof::exists( vec![v!(x), v_1!(x)], - FOF::from(pred!(P).app(vec![term!(x)])) + Fof::from(pred!(P).app(vec![term!(x)])) ) .implies(pred!(Q).app(vec![term!(x)]).into()) .into()) @@ -801,22 +801,22 @@ mod tests { assert_debug_string!( "! x``. (P(x``) -> Q(x, x`))", pnf( - &FOF::exists(vec![v!(x)], FOF::from(pred!(P).app(vec![term!(x)]))) + &Fof::exists(vec![v!(x)], Fof::from(pred!(P).app(vec![term!(x)]))) .implies(pred!(Q).app(vec![term!(x), v_1!(x).into()]).into()) ) ); assert_debug_string!( "! x``. (P(x``, x`) -> Q(x))", - pnf(&FOF::exists( + pnf(&Fof::exists( vec![v!(x)], - FOF::from(pred!(P).app(vec![term!(x), v_1!(x).into()])) + Fof::from(pred!(P).app(vec![term!(x), v_1!(x).into()])) ) .implies(pred!(Q).app(vec![term!(x)]).into())) ); assert_debug_string!( "! x``, x`. (Q(x) -> P(x``))", pnf( - &FOF::from(pred!(Q).app(vec![term!(x)])).implies(FOF::forall( + &Fof::from(pred!(Q).app(vec![term!(x)])).implies(Fof::forall( vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into() )) @@ -825,7 +825,7 @@ mod tests { assert_debug_string!( "? x``, x`. (Q(x) -> P(x``))", pnf( - &FOF::from(pred!(Q).app(vec![term!(x)])).implies(FOF::exists( + &Fof::from(pred!(Q).app(vec![term!(x)])).implies(Fof::exists( vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into() )) @@ -834,7 +834,7 @@ mod tests { assert_debug_string!( "? x``. (Q(x, x`) -> P(x``))", pnf( - &FOF::from(pred!(Q).app(vec![term!(x), v_1!(x).into()])).implies(FOF::exists( + &Fof::from(pred!(Q).app(vec![term!(x), v_1!(x).into()])).implies(Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x)]).into() )) @@ -843,7 +843,7 @@ mod tests { assert_debug_string!( "? x``. (Q(x) -> P(x``, x`))", pnf( - &FOF::from(pred!(Q).app(vec![term!(x)])).implies(FOF::exists( + &Fof::from(pred!(Q).app(vec![term!(x)])).implies(Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x), v_1!(x).into()]).into(), )) @@ -852,40 +852,40 @@ mod tests { assert_debug_string!( "? x``, x`. (! x```, x`. ((P(x``) -> Q(x)) & (Q(x) -> P(x```))))", - pnf(&FOF::forall( + pnf(&Fof::forall( vec![v!(x), v_1!(x)], - FOF::from(pred!(P).app(vec![term!(x)])) + Fof::from(pred!(P).app(vec![term!(x)])) ) .iff(pred!(Q).app(vec![term!(x)]).into())) ); assert_debug_string!( "! x``, x`. (? x```, x`. ((P(x``) -> Q(x)) & (Q(x) -> P(x```))))", - pnf(&FOF::exists( + pnf(&Fof::exists( vec![v!(x), v_1!(x)], - FOF::from(pred!(P).app(vec![term!(x)])) + Fof::from(pred!(P).app(vec![term!(x)])) ) .iff(pred!(Q).app(vec![term!(x)]).into())) ); assert_debug_string!( "! x``. (? x```. ((P(x``) -> Q(x, x`)) & (Q(x, x`) -> P(x```))))", pnf( - &FOF::exists(vec![v!(x)], FOF::from(pred!(P).app(vec![term!(x)]))) - .iff(FOF::from(pred!(Q).app(vec![term!(x), v_1!(x).into()]))) + &Fof::exists(vec![v!(x)], Fof::from(pred!(P).app(vec![term!(x)]))) + .iff(Fof::from(pred!(Q).app(vec![term!(x), v_1!(x).into()]))) .into() ) ); assert_debug_string!( "! x``. (? x```. ((P(x``, x`) -> Q(x)) & (Q(x) -> P(x```, x`))))", - pnf(&FOF::exists( + pnf(&Fof::exists( vec![v!(x)], - FOF::from(pred!(P).app(vec![term!(x), v_1!(x).into()])) + Fof::from(pred!(P).app(vec![term!(x), v_1!(x).into()])) ) .iff(pred!(Q).app(vec![term!(x)]).into())) ); assert_debug_string!( "! x``, x`. (? x```, x`. ((Q(x) -> P(x``)) & (P(x```) -> Q(x))))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])) - .iff(FOF::forall( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])) + .iff(Fof::forall( vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into() )) @@ -893,7 +893,7 @@ mod tests { ); assert_debug_string!( "? x``, x`. (! x```, x`. ((Q(x) -> P(x``)) & (P(x```) -> Q(x))))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])).iff(FOF::exists( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])).iff(Fof::exists( vec![v!(x), v_1!(x)], pred!(P).app(vec![term!(x)]).into() ))) @@ -901,7 +901,7 @@ mod tests { assert_debug_string!( "? x``. (! x```. ((Q(x, x`) -> P(x``)) & (P(x```) -> Q(x, x`))))", pnf( - &FOF::from(pred!(Q).app(vec![term!(x), v_1!(x).into()])).iff(FOF::exists( + &Fof::from(pred!(Q).app(vec![term!(x), v_1!(x).into()])).iff(Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x)]).into() )) @@ -909,83 +909,83 @@ mod tests { ); assert_debug_string!( "? x``. (! x```. ((Q(x) -> P(x``, x`)) & (P(x```, x`) -> Q(x))))", - pnf(&FOF::from(pred!(Q).app(vec![term!(x)])).iff(FOF::exists( + pnf(&Fof::from(pred!(Q).app(vec![term!(x)])).iff(Fof::exists( vec![v!(x)], pred!(P).app(vec![term!(x), v_1!(x).into()]).into(), ))) ); // both sides of binary formulae { - let formula: FOF = "(! x. P(x)) & (! x. Q(x))".parse().unwrap(); + let formula: Fof = "(! x. P(x)) & (! x. Q(x))".parse().unwrap(); assert_debug_string!("! x. (! x`. (P(x) & Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) & (? x. Q(x))".parse().unwrap(); + let formula: Fof = "(! x. P(x)) & (? x. Q(x))".parse().unwrap(); assert_debug_string!("! x. (? x`. (P(x) & Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) & (! x. Q(x))".parse().unwrap(); + let formula: Fof = "(? x. P(x)) & (! x. Q(x))".parse().unwrap(); assert_debug_string!("? x. (! x`. (P(x) & Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) & (? x. Q(x))".parse().unwrap(); + let formula: Fof = "(? x. P(x)) & (? x. Q(x))".parse().unwrap(); assert_debug_string!("? x. (? x`. (P(x) & Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) | (! x. Q(x))".parse().unwrap(); + let formula: Fof = "(! x. P(x)) | (! x. Q(x))".parse().unwrap(); assert_debug_string!("! x. (! x`. (P(x) | Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) | (? x. Q(x))".parse().unwrap(); + let formula: Fof = "(! x. P(x)) | (? x. Q(x))".parse().unwrap(); assert_debug_string!("! x. (? x`. (P(x) | Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) | (! x. Q(x))".parse().unwrap(); + let formula: Fof = "(? x. P(x)) | (! x. Q(x))".parse().unwrap(); assert_debug_string!("? x. (! x`. (P(x) | Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) | (? x. Q(x))".parse().unwrap(); + let formula: Fof = "(? x. P(x)) | (? x. Q(x))".parse().unwrap(); assert_debug_string!("? x. (? x`. (P(x) | Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) -> (! x. Q(x))".parse().unwrap(); + let formula: Fof = "(! x. P(x)) -> (! x. Q(x))".parse().unwrap(); assert_debug_string!("? x. (! x`. (P(x) -> Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) -> (? x. Q(x))".parse().unwrap(); + let formula: Fof = "(! x. P(x)) -> (? x. Q(x))".parse().unwrap(); assert_debug_string!("? x. (? x`. (P(x) -> Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) -> (! x. Q(x))".parse().unwrap(); + let formula: Fof = "(? x. P(x)) -> (! x. Q(x))".parse().unwrap(); assert_debug_string!("! x. (! x`. (P(x) -> Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(? x. P(x)) -> (? x. Q(x))".parse().unwrap(); + let formula: Fof = "(? x. P(x)) -> (? x. Q(x))".parse().unwrap(); assert_debug_string!("! x. (? x`. (P(x) -> Q(x`)))", pnf(&formula)); } { - let formula: FOF = "(! x. P(x)) <=> (! x. Q(x))".parse().unwrap(); + let formula: Fof = "(! x. P(x)) <=> (! x. Q(x))".parse().unwrap(); assert_debug_string!( "? x. (! x`. (? x``. (! x```. ((P(x) -> Q(x`)) & (Q(x``) -> P(x```))))))", pnf(&formula), ); } { - let formula: FOF = "(! x. P(x)) <=> (? x. Q(x))".parse().unwrap(); + let formula: Fof = "(! x. P(x)) <=> (? x. Q(x))".parse().unwrap(); assert_debug_string!( "? x. (? x`. (! x``. (! x```. ((P(x) -> Q(x`)) & (Q(x``) -> P(x```))))))", pnf(&formula), ); } { - let formula: FOF = "(? x. P(x)) <=> (! x. Q(x))".parse().unwrap(); + let formula: Fof = "(? x. P(x)) <=> (! x. Q(x))".parse().unwrap(); assert_debug_string!( "! x. (! x`. (? x``. (? x```. ((P(x) -> Q(x`)) & (Q(x``) -> P(x```))))))", pnf(&formula), ); } { - let formula: FOF = "(? x. P(x)) <=> (? x. Q(x))".parse().unwrap(); + let formula: Fof = "(? x. P(x)) <=> (? x. Q(x))".parse().unwrap(); assert_debug_string!( "! x. (? x`. (! x``. (? x```. ((P(x) -> Q(x`)) & (Q(x``) -> P(x```))))))", pnf(&formula), @@ -993,64 +993,64 @@ mod tests { } // multiple steps { - let formula: FOF = "~~?x.P(x)".parse().unwrap(); + let formula: Fof = "~~?x.P(x)".parse().unwrap(); assert_debug_string!("? x. ~(~P(x))", pnf(&formula)); } { - let formula: FOF = "~~!x.P(x)".parse().unwrap(); + let formula: Fof = "~~!x.P(x)".parse().unwrap(); assert_debug_string!("! x. ~(~P(x))", pnf(&formula)); } { - let formula: FOF = "P(x) & ((! x. Q(x)) & R(x))".parse().unwrap(); + let formula: Fof = "P(x) & ((! x. Q(x)) & R(x))".parse().unwrap(); assert_debug_string!("! x`. (P(x) & (Q(x`) & R(x)))", pnf(&formula)); } { - let formula: FOF = "P(x) & ((? x. Q(x)) & R(x))".parse().unwrap(); + let formula: Fof = "P(x) & ((? x. Q(x)) & R(x))".parse().unwrap(); assert_debug_string!("? x`. (P(x) & (Q(x`) & R(x)))", pnf(&formula)); } { - let formula: FOF = "P(x) | ((! x. Q(x)) | R(x))".parse().unwrap(); + let formula: Fof = "P(x) | ((! x. Q(x)) | R(x))".parse().unwrap(); assert_debug_string!("! x`. (P(x) | (Q(x`) | R(x)))", pnf(&formula)); } { - let formula: FOF = "P(x) | ((? x. Q(x)) | R(x))".parse().unwrap(); + let formula: Fof = "P(x) | ((? x. Q(x)) | R(x))".parse().unwrap(); assert_debug_string!("? x`. (P(x) | (Q(x`) | R(x)))", pnf(&formula)); } { - let formula: FOF = "P(x) -> ((! x. Q(x)) -> R(x))".parse().unwrap(); + let formula: Fof = "P(x) -> ((! x. Q(x)) -> R(x))".parse().unwrap(); assert_debug_string!("? x`. (P(x) -> (Q(x`) -> R(x)))", pnf(&formula)); } { - let formula: FOF = "P(x) -> ((? x. Q(x)) -> R(x))".parse().unwrap(); + let formula: Fof = "P(x) -> ((? x. Q(x)) -> R(x))".parse().unwrap(); assert_debug_string!("! x`. (P(x) -> (Q(x`) -> R(x)))", pnf(&formula)); } { - let formula: FOF = "P(x) <=> ((! x. Q(x)) <=> R(x))".parse().unwrap(); + let formula: Fof = "P(x) <=> ((! x. Q(x)) <=> R(x))".parse().unwrap(); assert_debug_string!("? x`. (! x``. (! x```. (? x````. ((P(x) -> ((Q(x`) -> R(x)) & (R(x) -> Q(x``)))) & (((Q(x```) -> R(x)) & (R(x) -> Q(x````))) -> P(x))))))", pnf(&formula)); } { - let formula: FOF = "P(x) <=> ((? x. Q(x)) <=> R(x))".parse().unwrap(); + let formula: Fof = "P(x) <=> ((? x. Q(x)) <=> R(x))".parse().unwrap(); assert_debug_string!("! x`. (? x``. (? x```. (! x````. ((P(x) -> ((Q(x`) -> R(x)) & (R(x) -> Q(x``)))) & (((Q(x```) -> R(x)) & (R(x) -> Q(x````))) -> P(x))))))", pnf(&formula)); } // random formulae { - let formula: FOF = "!x . (P(x) -> ?y . (P(y) & Q(x, y)))".parse().unwrap(); + let formula: Fof = "!x . (P(x) -> ?y . (P(y) & Q(x, y)))".parse().unwrap(); assert_debug_string!("! x. (? y. (P(x) -> (P(y) & Q(x, y))))", pnf(&formula)); } { - let formula: FOF = "?x . (P(x) & !y . (P(y) -> Q(x, y)))".parse().unwrap(); + let formula: Fof = "?x . (P(x) & !y . (P(y) -> Q(x, y)))".parse().unwrap(); assert_debug_string!("? x. (! y. (P(x) & (P(y) -> Q(x, y))))", pnf(&formula)); } { - let formula: FOF = "!x. (P(x) -> ~(!y . (P(y) -> Q(x, y))))".parse().unwrap(); + let formula: Fof = "!x. (P(x) -> ~(!y . (P(y) -> Q(x, y))))".parse().unwrap(); assert_debug_string!("! x. (? y. (P(x) -> ~(P(y) -> Q(x, y))))", pnf(&formula)); } { - let formula: FOF = "(P() | ? x. Q(x)) -> !z. R(z)".parse().unwrap(); + let formula: Fof = "(P() | ? x. Q(x)) -> !z. R(z)".parse().unwrap(); assert_debug_string!("! x. (! z. ((P() | Q(x)) -> R(z)))", pnf(&formula)); } { - let formula: FOF = "!x.?y.(!z.Q(x) & ~?x.R(x)) | (~Q(y) -> !w. R(y))" + let formula: Fof = "!x.?y.(!z.Q(x) & ~?x.R(x)) | (~Q(y) -> !w. R(y))" .parse() .unwrap(); assert_debug_string!( @@ -1059,11 +1059,11 @@ mod tests { ); } { - let formula: FOF = "!x. (!y. P(x, y) -> ?y. Q(x, y))".parse().unwrap(); + let formula: Fof = "!x. (!y. P(x, y) -> ?y. Q(x, y))".parse().unwrap(); assert_debug_string!("! x. (! y. (? y`. (P(x, y) -> Q(x, y`))))", pnf(&formula)); } { - let formula: FOF = "!x. ((!y. P(x, y)) -> ?y. Q(x, y))".parse().unwrap(); + let formula: Fof = "!x. ((!y. P(x, y)) -> ?y. Q(x, y))".parse().unwrap(); assert_debug_string!("! x. (? y. (? y`. (P(x, y) -> Q(x, y`))))", pnf(&formula)); } } @@ -1104,7 +1104,7 @@ mod tests { }; assert_eq!( fof!(!x . {? y . {[[P(z, y)] & [Q(w)]] -> [[(x) = (z)] | [~{R(z, z)}]]}}), - FOF::from(pnf.transform_term(&f)) + Fof::from(pnf.transform_term(&f)) ); } diff --git a/razor-fol/src/transform/range_restrict.rs b/razor-fol/src/transform/range_restrict.rs index a4b99ab..b42a02c 100644 --- a/razor-fol/src/transform/range_restrict.rs +++ b/razor-fol/src/transform/range_restrict.rs @@ -14,10 +14,10 @@ impl Relational { /// **Example**: /// ```rust /// # use std::convert::TryFrom; - /// use razor_fol::{syntax::FOF, transform::{GNF, ToRelational}, v}; + /// use razor_fol::{syntax::Fof, transform::{Gnf, ToRelational}, v}; /// - /// let fof = "R(x, y) -> P(x) & Q(y)".parse::().unwrap(); - /// let gnf = GNF::try_from(fof).unwrap(); + /// let fof = "R(x, y) -> P(x) & Q(y)".parse::().unwrap(); + /// let gnf = Gnf::try_from(fof).unwrap(); /// let gnf_head = gnf.head(); /// let relational = gnf_head.relational(); /// let range_restricted = relational.range_restrict(&vec![v!(x), v!(z)], "RR"); @@ -59,25 +59,25 @@ fn restrict(range: &[Var], symbol: &str) -> FlatClause { mod test { use crate::{ fof, - syntax::{Var, FOF}, + syntax::{Fof, Var}, transform::PcfSet, v, }; // Assumes the input in GNF - fn clause_set(fof: FOF) -> PcfSet { + fn clause_set(fof: Fof) -> PcfSet { use std::convert::TryFrom; PcfSet::try_from(fof).unwrap() } - fn rr(fof: FOF, range: &[Var]) -> String { + fn rr(fof: Fof, range: &[Var]) -> String { use crate::transform::ToRelational; let rels = clause_set(fof) .iter() .map(|f| f.relational().range_restrict(range, "RR")) - .map(FOF::from) + .map(Fof::from) .collect::>(); format!("{:?}", rels) } @@ -86,7 +86,7 @@ mod test { fn test_range_restrict() { assert_eq!("[true]", rr(fof!('|'), &vec![])); assert_eq!("[RR(x) & RR(y)]", rr(fof!('|'), &vec![v!(x), v!(y)])); - assert_eq!("[]", rr(fof!(_|_), &vec![])); + assert_eq!("[]", rr(fof!(_ | _), &vec![])); assert_eq!("[P(x)]", rr(fof!(P(x)), &vec![])); assert_eq!( diff --git a/razor-fol/src/transform/relational.rs b/razor-fol/src/transform/relational.rs index 11cb8e7..0100c19 100644 --- a/razor-fol/src/transform/relational.rs +++ b/razor-fol/src/transform/relational.rs @@ -1,10 +1,10 @@ /*! Defines a relational formula and implements an algorithm for transforming compatible formula types to [`Relational`].*/ -use super::{PcfSet, PCF}; +use super::{Pcf, PcfSet}; use crate::syntax::{ formula::*, term::{Complex, Variable}, - Const, Error, Formula, Func, Pred, Sig, Var, FOF, + Const, Error, Fof, Formula, Func, Pred, Sig, Var, }; use itertools::Itertools; use std::{collections::HashMap, iter::FromIterator, ops::Deref}; @@ -93,7 +93,7 @@ impl Formula for FlatClause { } } -impl From for FOF { +impl From for Fof { fn from(value: FlatLiteral) -> Self { match value { Atomic::Atom(this) => Atom:: { @@ -110,26 +110,26 @@ impl From for FOF { } } -impl From for FOF { +impl From for Fof { fn from(value: FlatClause) -> Self { value .into_literals() .into_iter() - .map(FOF::from) + .map(Fof::from) .fold1(|item, acc| item.and(acc)) - .unwrap_or(FOF::Top) + .unwrap_or(Fof::Top) } } /// Represents a relational formula as a Disjunctive Normal Form (DNF) over positive /// literals with flat terms. The primary use-case of this type is to transform -/// positive formulae in the head and body of a [`GNF`] to relational expressions +/// positive formulae in the head and body of a [`Gnf`] to relational expressions /// as database queries. /// /// **Hint**: A relational formula contains only (flat) variable terms with /// no functions nor constants. /// -/// [`GNF`]: crate::transform::GNF +/// [`Gnf`]: crate::transform::Gnf #[derive(Clone, Debug)] pub struct Relational(Vec); @@ -238,12 +238,12 @@ pub trait ToRelational: Formula { /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::{FOF, Const, Var, Func}; + /// # use razor_fol::syntax::{Fof, Const, Var, Func}; /// # use std::convert::TryFrom; - /// use razor_fol::transform::{GNF, ToRelational}; + /// use razor_fol::transform::{Gnf, ToRelational}; /// - /// let fof = "P(x) & Q(g(x)) -> (P(f(x)) & Q('c)) | R(x)".parse::().unwrap(); - /// let gnf = GNF::try_from(fof).unwrap(); + /// let fof = "P(x) & Q(g(x)) -> (P(f(x)) & Q('c)) | R(x)".parse::().unwrap(); + /// let gnf = Gnf::try_from(fof).unwrap(); /// /// // The body and head of a GNF can be relationalized: /// let gnf_body = gnf.body(); @@ -307,12 +307,12 @@ pub trait ToRelational: Formula { /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; + /// # use razor_fol::syntax::Fof; /// # use std::convert::TryFrom; - /// use razor_fol::transform::{GNF, ToRelational}; + /// use razor_fol::transform::{Gnf, ToRelational}; /// - /// let fof = "P(x) -> P(f(x)) & Q('c)".parse::().unwrap(); - /// let gnf = GNF::try_from(fof).unwrap(); + /// let fof = "P(x) -> P(f(x)) & Q('c)".parse::().unwrap(); + /// let gnf = Gnf::try_from(fof).unwrap(); /// let gnf_head = gnf.head(); /// let transformed = gnf_head.relational(); /// assert_eq!( @@ -333,7 +333,7 @@ pub trait ToRelational: Formula { } } -impl ToRelational for PCF { +impl ToRelational for Pcf { fn relational_with( &self, var_generator: &mut VG, @@ -411,18 +411,18 @@ impl Formula for Relational { } } -impl From for FOF { +impl From for Fof { fn from(value: Relational) -> Self { value .into_clauses() .into_iter() - .map(FOF::from) + .map(Fof::from) .fold1(|item, acc| item.or(acc)) - .unwrap_or(FOF::Bottom) + .unwrap_or(Fof::Bottom) } } -impl From<&Relational> for FOF { +impl From<&Relational> for Fof { fn from(value: &Relational) -> Self { value.clone().into() } @@ -430,7 +430,7 @@ impl From<&Relational> for FOF { impl std::fmt::Display for Relational { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } @@ -522,7 +522,7 @@ where // Applies top level flattening on the input clause set. fn flatten_clause( - clause: &PCF, + clause: &Pcf, context: &mut FlatteningContext, ) -> FlatClause where @@ -638,26 +638,26 @@ fn simplify_equations(clause_set: &Relational, generated_variables: &mut [Var]) #[cfg(test)] mod tests { use super::*; - use crate::transform::GNF; + use crate::transform::Gnf; use std::convert::TryFrom; use crate::{ assert_eq_sorted_vecs, fof, syntax::{signature::PredSig, Sig, EQ_SYM}, term, - transform::{ToGNF, PCF}, + transform::{Pcf, ToGnf}, v, }; // Assumes the input in GNF - fn clause_set(fof: FOF) -> Vec { + fn clause_set(fof: Fof) -> Vec { fof.gnf() .into_iter() .map(|f| f.into_body_and_head().1) .collect() } - fn flatten(fof: FOF) -> String { + fn flatten(fof: Fof) -> String { let mut var_counter = 0; let mut var_generator = || { let name = format!("?{}", var_counter); @@ -679,7 +679,7 @@ mod tests { ), ) }) - .map(FOF::from) + .map(Fof::from) .collect::>(); format!("{:?}", rels) } @@ -763,14 +763,14 @@ mod tests { fn test_relationalize() { use crate::{syntax::formula::*, term}; { - let clause_set = PcfSet::from(vec![PCF::from(Equals { + let clause_set = PcfSet::from(vec![Pcf::from(Equals { left: term!(f(x)), right: term!(y), })]); assert_eq!("$f(x, y)", clause_set.relational().to_string()); } { - let clause_set = PcfSet::from(vec![PCF::from(Equals { + let clause_set = PcfSet::from(vec![Pcf::from(Equals { left: term!(f(x)), right: term!(g(y)), })]); @@ -778,11 +778,11 @@ mod tests { } { let clause_set = PcfSet::from(vec![ - PCF::from(Equals { + Pcf::from(Equals { left: term!(f(x)), right: term!(g(y)), }), - PCF::from(Equals { + Pcf::from(Equals { left: term!(f(x)), right: term!(y), }), @@ -793,28 +793,28 @@ mod tests { ); } { - let clause_set = PcfSet::from(vec![PCF::from(Atom { + let clause_set = PcfSet::from(vec![Pcf::from(Atom { predicate: Pred::from("P"), terms: vec![term!(x), term!(f(y))], })]); assert_eq!("$f(y, ?0) ∧ P(x, ?0)", clause_set.relational().to_string()); } { - let clause_set = PcfSet::from(vec![PCF::from(Atom { + let clause_set = PcfSet::from(vec![Pcf::from(Atom { predicate: Pred::from("P"), terms: vec![term!(x), term!(f(x))], })]); assert_eq!("$f(x, ?0) ∧ P(x, ?0)", clause_set.relational().to_string()); } { - let clause_set = PcfSet::from(vec![PCF::from(Equals { + let clause_set = PcfSet::from(vec![Pcf::from(Equals { left: term!(f(x)), right: term!(f(x)), })]); assert_eq!("$f(x, ?1) ∧ $f(x, ?1)", clause_set.relational().to_string()); } { - let clause_set = PcfSet::from(vec![PCF::from(vec![ + let clause_set = PcfSet::from(vec![Pcf::from(vec![ Atom { predicate: Pred::from("P"), terms: vec![term!(f(x, y))], @@ -833,11 +833,11 @@ mod tests { } { let clause_set = PcfSet::from(vec![ - PCF::from(Atom { + Pcf::from(Atom { predicate: Pred::from("P"), terms: vec![term!(f(x, y))], }), - PCF::from(Atom { + Pcf::from(Atom { predicate: Pred::from("Q"), terms: vec![term!(f(x, y))], }), @@ -852,7 +852,7 @@ mod tests { #[test] fn relational_free_vars() { { - let gnf = GNF::try_from(fof!({'|'} -> {_|_})).unwrap(); + let gnf = Gnf::try_from(fof!({'|'} -> {_|_})).unwrap(); let (body, head) = gnf.into_body_and_head(); let body = body.relational(); let head = head.relational(); @@ -861,7 +861,7 @@ mod tests { } { // !! make sure the test gnf is not getting simplified by the conversion algorithm. - let gnf = GNF::try_from( + let gnf = Gnf::try_from( fof!({[[P(x)] & [Q(x, y)]] & [P(z)]} -> {[(P(x)) & ([z] = [y])] | [Q(x, y)]}), ) .unwrap(); @@ -881,7 +881,7 @@ mod tests { #[test] fn relational_transform() { - let gnf = GNF::try_from( + let gnf = Gnf::try_from( fof!({[[P(x)] & [Q(x, y)]] & [P(z)]} -> {[(P(x)) & ([z] = [y])] | [Q(x, y)]}), ) .unwrap(); @@ -901,11 +901,11 @@ mod tests { let head = head.relational(); assert_eq!( fof!([[P(z)] & [P(z)]] & [Q(z, y)]), - FOF::from(body.transform_term(&f)) + Fof::from(body.transform_term(&f)) ); assert_eq!( fof!([(P(z)) & ([z] = [y])] | [Q(z, y)]), - FOF::from(head.transform_term(&f)) + Fof::from(head.transform_term(&f)) ); } @@ -933,7 +933,7 @@ mod tests { }) .unwrap(); - let gnf = GNF::try_from( + let gnf = Gnf::try_from( fof!({[[P(x)] & [Q(x, y)]] & [P(z)]} -> {[(P(x)) & ([z] = [y])] | [Q(x, y)]}), ) .unwrap(); @@ -944,7 +944,7 @@ mod tests { assert_eq!(sig_head, head.signature().unwrap()); } { - let gnf = GNF::try_from( + let gnf = Gnf::try_from( fof!({[[P(x)] & [Q(x, y)]] & [P(z, z)]} -> {[(P(x)) & ([z] = [y])] | [P(x, y)]}), ) .unwrap(); diff --git a/razor-fol/src/transform/simplify.rs b/razor-fol/src/transform/simplify.rs index 4699c1c..2c5768e 100644 --- a/razor-fol/src/transform/simplify.rs +++ b/razor-fol/src/transform/simplify.rs @@ -1,20 +1,20 @@ /*! Implementas a basic syntactic simplification for formula. */ -use crate::syntax::{FOF::*, *}; +use crate::syntax::{Fof::*, *}; -impl FOF { +impl Fof { /// Applies a number of syntactic transformations to simplify `self`. /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; + /// # use razor_fol::syntax::Fof; /// - /// let formula: FOF = "not (not P())".parse().unwrap(); + /// let formula: Fof = "not (not P())".parse().unwrap(); /// assert_eq!("P()", formula.simplify().to_string()); /// - /// let formula: FOF = "forall x. (P() and true) | (Q(x) or false)".parse().unwrap(); + /// let formula: Fof = "forall x. (P() and true) | (Q(x) or false)".parse().unwrap(); /// assert_eq!("∀ x. (P() ∨ Q(x))", formula.simplify().to_string()); /// ``` - pub fn simplify(&self) -> FOF { + pub fn simplify(&self) -> Fof { match self { Top | Bottom | Atom { .. } | Equals { .. } => self.clone(), Not(this) => { @@ -23,7 +23,7 @@ impl FOF { Top => Bottom, Bottom => Top, Not(this) => this.formula.simplify(), - _ => FOF::not(formula), + _ => Fof::not(formula), } } And(this) => { @@ -66,7 +66,7 @@ impl FOF { } else if let Top = left { right } else if let Bottom = right { - FOF::not(left).simplify() + Fof::not(left).simplify() } else { left.implies(right) } @@ -79,9 +79,9 @@ impl FOF { } else if let Top = right { left } else if let Bottom = left { - FOF::not(right).simplify() + Fof::not(right).simplify() } else if let Bottom = right { - FOF::not(left).simplify() + Fof::not(left).simplify() } else { left.iff(right) } @@ -97,7 +97,7 @@ impl FOF { if vs.is_empty() { formula } else { - FOF::exists(vs, formula) + Fof::exists(vs, formula) } } Forall(this) => { @@ -111,7 +111,7 @@ impl FOF { if vs.is_empty() { formula } else { - FOF::forall(vs, formula) + Fof::forall(vs, formula) } } } @@ -126,230 +126,230 @@ mod tests { #[test] fn test_simplify() { { - let formula: FOF = "~true".parse().unwrap(); + let formula: Fof = "~true".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "~false".parse().unwrap(); + let formula: Fof = "~false".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "~P(x)".parse().unwrap(); + let formula: Fof = "~P(x)".parse().unwrap(); assert_debug_string!("~P(x)", formula.simplify()); } { - let formula: FOF = "true & true".parse().unwrap(); + let formula: Fof = "true & true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false & false".parse().unwrap(); + let formula: Fof = "false & false".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "false & true".parse().unwrap(); + let formula: Fof = "false & true".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "true & false".parse().unwrap(); + let formula: Fof = "true & false".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "P(x) & true".parse().unwrap(); + let formula: Fof = "P(x) & true".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "false & P(x)".parse().unwrap(); + let formula: Fof = "false & P(x)".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "P(x) & false".parse().unwrap(); + let formula: Fof = "P(x) & false".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "true & P(x)".parse().unwrap(); + let formula: Fof = "true & P(x)".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "P(x) & Q(x)".parse().unwrap(); + let formula: Fof = "P(x) & Q(x)".parse().unwrap(); assert_debug_string!("P(x) & Q(x)", formula.simplify()); } { - let formula: FOF = "true | true".parse().unwrap(); + let formula: Fof = "true | true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false | false".parse().unwrap(); + let formula: Fof = "false | false".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "false | true".parse().unwrap(); + let formula: Fof = "false | true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "true | false".parse().unwrap(); + let formula: Fof = "true | false".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "P(x) | true".parse().unwrap(); + let formula: Fof = "P(x) | true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false | P(x)".parse().unwrap(); + let formula: Fof = "false | P(x)".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "P(x) | false".parse().unwrap(); + let formula: Fof = "P(x) | false".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "true | P(x)".parse().unwrap(); + let formula: Fof = "true | P(x)".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "P(x) | Q(x)".parse().unwrap(); + let formula: Fof = "P(x) | Q(x)".parse().unwrap(); assert_debug_string!("P(x) | Q(x)", formula.simplify()); } { - let formula: FOF = "true -> true".parse().unwrap(); + let formula: Fof = "true -> true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false -> false".parse().unwrap(); + let formula: Fof = "false -> false".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false -> true".parse().unwrap(); + let formula: Fof = "false -> true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "true -> false".parse().unwrap(); + let formula: Fof = "true -> false".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "P(x) -> true".parse().unwrap(); + let formula: Fof = "P(x) -> true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false -> P(x)".parse().unwrap(); + let formula: Fof = "false -> P(x)".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "P(x) -> false".parse().unwrap(); + let formula: Fof = "P(x) -> false".parse().unwrap(); assert_debug_string!("~P(x)", formula.simplify()); } { - let formula: FOF = "true -> P(x)".parse().unwrap(); + let formula: Fof = "true -> P(x)".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "P(x) -> Q(x)".parse().unwrap(); + let formula: Fof = "P(x) -> Q(x)".parse().unwrap(); assert_debug_string!("P(x) -> Q(x)", formula.simplify()); } { - let formula: FOF = "true <=> true".parse().unwrap(); + let formula: Fof = "true <=> true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false <=> false".parse().unwrap(); + let formula: Fof = "false <=> false".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false <=> true".parse().unwrap(); + let formula: Fof = "false <=> true".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "true <=> false".parse().unwrap(); + let formula: Fof = "true <=> false".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } { - let formula: FOF = "P(x) <=> true".parse().unwrap(); + let formula: Fof = "P(x) <=> true".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "false <=> P(x)".parse().unwrap(); + let formula: Fof = "false <=> P(x)".parse().unwrap(); assert_debug_string!("~P(x)", formula.simplify()); } { - let formula: FOF = "P(x) <=> false".parse().unwrap(); + let formula: Fof = "P(x) <=> false".parse().unwrap(); assert_debug_string!("~P(x)", formula.simplify()); } { - let formula: FOF = "true <=> P(x)".parse().unwrap(); + let formula: Fof = "true <=> P(x)".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "P(x) <=> Q(x)".parse().unwrap(); + let formula: Fof = "P(x) <=> Q(x)".parse().unwrap(); assert_debug_string!("P(x) <=> Q(x)", formula.simplify()); } { - let formula: FOF = "?x, y. P(y, z)".parse().unwrap(); + let formula: Fof = "?x, y. P(y, z)".parse().unwrap(); assert_debug_string!("? y. P(y, z)", formula.simplify()); } { - let formula: FOF = "?x. P(x)".parse().unwrap(); + let formula: Fof = "?x. P(x)".parse().unwrap(); assert_debug_string!("? x. P(x)", formula.simplify()); } { - let formula: FOF = "?x. P(y)".parse().unwrap(); + let formula: Fof = "?x. P(y)".parse().unwrap(); assert_debug_string!("P(y)", formula.simplify()); } { - let formula: FOF = "!x, y. P(y, z)".parse().unwrap(); + let formula: Fof = "!x, y. P(y, z)".parse().unwrap(); assert_debug_string!("! y. P(y, z)", formula.simplify()); } { - let formula: FOF = "!x. P(x)".parse().unwrap(); + let formula: Fof = "!x. P(x)".parse().unwrap(); assert_debug_string!("! x. P(x)", formula.simplify()); } { - let formula: FOF = "!x. P(y)".parse().unwrap(); + let formula: Fof = "!x. P(y)".parse().unwrap(); assert_debug_string!("P(y)", formula.simplify()); } // random formulae { - let formula: FOF = "~~P(x)".parse().unwrap(); + let formula: Fof = "~~P(x)".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "~~~P(x)".parse().unwrap(); + let formula: Fof = "~~~P(x)".parse().unwrap(); assert_debug_string!("~P(x)", formula.simplify()); } { - let formula: FOF = "~(true -> false)".parse().unwrap(); + let formula: Fof = "~(true -> false)".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "false | (P(x) & true)".parse().unwrap(); + let formula: Fof = "false | (P(x) & true)".parse().unwrap(); assert_debug_string!("P(x)", formula.simplify()); } { - let formula: FOF = "?x. P(x) | true".parse().unwrap(); + let formula: Fof = "?x. P(x) | true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "?y. (P(x) -> false) & (false -> Q(x))".parse().unwrap(); + let formula: Fof = "?y. (P(x) -> false) & (false -> Q(x))".parse().unwrap(); assert_debug_string!("~P(x)", formula.simplify()); } { - let formula: FOF = "!x. ?y. P(x, y) | true".parse().unwrap(); + let formula: Fof = "!x. ?y. P(x, y) | true".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "(((x = y -> false) -> false) -> false) -> false" + let formula: Fof = "(((x = y -> false) -> false) -> false) -> false" .parse() .unwrap(); assert_debug_string!("x = y", formula.simplify()); } { - let formula: FOF = "!x, y, z. ?z. P(x) | w = x".parse().unwrap(); + let formula: Fof = "!x, y, z. ?z. P(x) | w = x".parse().unwrap(); assert_debug_string!("! x. (P(x) | w = x)", formula.simplify()); } { - let formula: FOF = "(P(x) | false) | (P(x) | true)".parse().unwrap(); + let formula: Fof = "(P(x) | false) | (P(x) | true)".parse().unwrap(); assert_debug_string!("true", formula.simplify()); } { - let formula: FOF = "(P(x) & false) & (P(x) & true)".parse().unwrap(); + let formula: Fof = "(P(x) & false) & (P(x) & true)".parse().unwrap(); assert_debug_string!("false", formula.simplify()); } } diff --git a/razor-fol/src/transform/snf.rs b/razor-fol/src/transform/snf.rs index f151ae0..f4846ee 100644 --- a/razor-fol/src/transform/snf.rs +++ b/razor-fol/src/transform/snf.rs @@ -1,90 +1,90 @@ /*! Defines formulae in Skolem Normal Form (SNF) and implements an algorithm for transforming -a [`PNF`] to an [`SNF`]. +a [`Pnf`] to an [`Snf`]. -[`PNF`]: crate::transform::PNF +[`Pnf`]: crate::transform::Pnf */ -use super::{ToPNF, PNF}; -use crate::syntax::{formula::qff::QFF, formula::*, term::Complex, Const, Func, Var, FOF}; +use super::{Pnf, ToPnf}; +use crate::syntax::{formula::qff::Qff, formula::*, term::Complex, Const, Fof, Func, Var}; use std::collections::HashMap; /// Represents a formula in Skolem Normal Form (SNF). /// -/// **Hint**: An SNF is a [PNF] with only universal quantifiers +/// **Hint**: An SNF is a [Pnf] with only universal quantifiers /// (see: ). /// -/// [PNF]: crate::transform::PNF +/// [Pnf]: crate::transform::Pnf #[derive(Clone, Debug)] -pub enum SNF { - /// Is the quantifier-free part of the [`SNF`]. - QFF(QFF), +pub enum Snf { + /// Is the quantifier-free part of the [`Snf`]. + QFF(Qff), /// Is a universally quantified formula, wrapping a [`Forall`]. - Forall(Box>), + Forall(Box>), } -impl From> for SNF { +impl From> for Snf { fn from(value: Atom) -> Self { Self::QFF(value.into()) } } -impl From> for SNF { +impl From> for Snf { fn from(value: Equals) -> Self { Self::QFF(value.into()) } } -impl From> for SNF { - fn from(value: Not) -> Self { +impl From> for Snf { + fn from(value: Not) -> Self { Self::QFF(value.into()) } } -impl From> for SNF { - fn from(value: And) -> Self { +impl From> for Snf { + fn from(value: And) -> Self { Self::QFF(value.into()) } } -impl From> for SNF { - fn from(value: Or) -> Self { +impl From> for Snf { + fn from(value: Or) -> Self { Self::QFF(value.into()) } } -impl From> for SNF { - fn from(value: Implies) -> Self { +impl From> for Snf { + fn from(value: Implies) -> Self { Self::QFF(value.into()) } } -impl From> for SNF { - fn from(value: Iff) -> Self { +impl From> for Snf { + fn from(value: Iff) -> Self { Self::QFF(value.into()) } } -impl From> for SNF { - fn from(value: Forall) -> Self { +impl From> for Snf { + fn from(value: Forall) -> Self { Self::Forall(Box::new(value)) } } -impl From for SNF { - fn from(value: QFF) -> Self { +impl From for Snf { + fn from(value: Qff) -> Self { Self::QFF(value) } } -/// Is the trait of [`Formula`] types that can be transformed to [`SNF`]. -pub trait ToSNF: Formula { - /// Is similar to [`ToSNF::snf`] but uses a custom closure to generate Skolem +/// Is the trait of [`Formula`] types that can be transformed to [`Snf`]. +pub trait ToSnf: Formula { + /// Is similar to [`ToSnf::snf`] but uses a custom closure to generate Skolem /// function and constant names. /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToSNF; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToSnf; /// /// let mut c_counter = 0; /// let mut f_counter = 0; @@ -98,12 +98,12 @@ pub trait ToSNF: Formula { /// f_counter += 1; /// format!("skolem_fn{}", c).into() /// }; - /// let formula: FOF = "∃ y. P(x, y)".parse().unwrap(); + /// let formula: Fof = "∃ y. P(x, y)".parse().unwrap(); /// let snf = formula.snf_with(&mut const_generator, &mut fn_generator); /// /// assert_eq!("P(x, skolem_fn0(x))", snf.to_string()); /// ``` - fn snf_with(&self, const_generator: &mut CG, fn_generator: &mut FG) -> SNF + fn snf_with(&self, const_generator: &mut CG, fn_generator: &mut FG) -> Snf where CG: FnMut() -> Const, FG: FnMut() -> Func; @@ -112,15 +112,15 @@ pub trait ToSNF: Formula { /// /// **Example**: /// ```rust - /// # use razor_fol::syntax::FOF; - /// use razor_fol::transform::ToSNF; + /// # use razor_fol::syntax::Fof; + /// use razor_fol::transform::ToSnf; /// - /// let formula: FOF = "∃ y. P(x, y)".parse().unwrap(); + /// let formula: Fof = "∃ y. P(x, y)".parse().unwrap(); /// let snf = formula.snf(); /// /// assert_eq!("P(x, f#0(x))", snf.to_string()); /// ``` - fn snf(&self) -> SNF { + fn snf(&self) -> Snf { let mut c_counter = 0; let mut f_counter = 0; let mut const_generator = || { @@ -138,19 +138,19 @@ pub trait ToSNF: Formula { } } -impl ToSNF for PNF { - fn snf_with(&self, const_generator: &mut CG, fn_generator: &mut FG) -> SNF +impl ToSnf for Pnf { + fn snf_with(&self, const_generator: &mut CG, fn_generator: &mut FG) -> Snf where CG: FnMut() -> Const, FG: FnMut() -> Func, { let free_vars = self.free_vars().into_iter().cloned().collect(); - SNF::new(self.clone(), free_vars, const_generator, fn_generator) + Snf::new(self.clone(), free_vars, const_generator, fn_generator) } } -impl ToSNF for T { - fn snf_with(&self, const_generator: &mut CG, fn_generator: &mut FG) -> SNF +impl ToSnf for T { + fn snf_with(&self, const_generator: &mut CG, fn_generator: &mut FG) -> Snf where CG: FnMut() -> Const, FG: FnMut() -> Func, @@ -159,15 +159,15 @@ impl ToSNF for T { } } -impl From for SNF { +impl From for Snf { fn from(value: T) -> Self { value.snf() } } -impl SNF { +impl Snf { fn new( - pnf: PNF, + pnf: Pnf, mut skolem_vars: Vec, const_generator: &mut CG, fn_generator: &mut FG, @@ -177,15 +177,15 @@ impl SNF { FG: FnMut() -> Func, { match pnf { - PNF::Forall(this) => { + Pnf::Forall(this) => { let variables = this.variables; skolem_vars.append(&mut variables.to_vec()); - SNF::forall( + Snf::forall( variables.to_vec(), Self::new(this.formula, skolem_vars, const_generator, fn_generator), ) } - PNF::Exists(this) => { + Pnf::Exists(this) => { let variables = this.variables; let mut map: HashMap<&Var, Complex> = HashMap::new(); @@ -202,38 +202,38 @@ impl SNF { let substituted = this.formula.substitute(&map); Self::new(substituted, skolem_vars, const_generator, fn_generator) } - PNF::QFF(this) => this.into(), + Pnf::QFF(this) => this.into(), } } - // Creates a universally quantified [`SNF`]. + // Creates a universally quantified [`Snf`]. #[inline(always)] fn forall(variables: Vec, formula: Self) -> Self { Forall { variables, formula }.into() } } -impl Formula for SNF { +impl Formula for Snf { type Term = Complex; fn signature(&self) -> Result { match self { - SNF::QFF(this) => this.signature(), - SNF::Forall(this) => this.signature(), + Snf::QFF(this) => this.signature(), + Snf::Forall(this) => this.signature(), } } fn free_vars(&self) -> Vec<&Var> { match self { - SNF::QFF(this) => this.free_vars(), - SNF::Forall(this) => this.free_vars(), + Snf::QFF(this) => this.free_vars(), + Snf::Forall(this) => this.free_vars(), } } fn transform_term(&self, f: &impl Fn(&Complex) -> Complex) -> Self { match self { - SNF::QFF(this) => this.transform_term(f).into(), - SNF::Forall(this) => Forall { + Snf::QFF(this) => this.transform_term(f).into(), + Snf::Forall(this) => Forall { variables: this.variables.clone(), formula: this.formula.transform_term(f), } @@ -242,32 +242,32 @@ impl Formula for SNF { } } -impl FormulaEx for SNF { +impl FormulaEx for Snf { fn precedence(&self) -> u8 { match self { - SNF::QFF(this) => this.precedence(), - SNF::Forall(this) => this.precedence(), + Snf::QFF(this) => this.precedence(), + Snf::Forall(this) => this.precedence(), } } } -impl std::fmt::Display for SNF { +impl std::fmt::Display for Snf { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - FOF::from(self).fmt(f) + Fof::from(self).fmt(f) } } -impl From for FOF { - fn from(value: SNF) -> Self { +impl From for Fof { + fn from(value: Snf) -> Self { match value { - SNF::QFF(this) => this.into(), - SNF::Forall(this) => FOF::forall(this.variables, this.formula.into()), + Snf::QFF(this) => this.into(), + Snf::Forall(this) => Fof::forall(this.variables, this.formula.into()), } } } -impl From<&SNF> for FOF { - fn from(value: &SNF) -> Self { +impl From<&Snf> for Fof { + fn from(value: &Snf) -> Self { value.clone().into() } } @@ -282,14 +282,14 @@ mod tests { Sig, EQ_SYM, }, term, - transform::ToPNF, + transform::ToPnf, v, }; - fn snf(formula: &FOF) -> FOF { + fn snf(formula: &Fof) -> Fof { formula.pnf().snf().into() } - fn snf_with(formula: &FOF, const_generator: &mut CG, fn_generator: &mut FG) -> FOF + fn snf_with(formula: &Fof, const_generator: &mut CG, fn_generator: &mut FG) -> Fof where CG: FnMut() -> Const, FG: FnMut() -> Func, @@ -388,7 +388,7 @@ mod tests { }; assert_eq!( fof!(!x . {! y . {[[P(z, y)] & [Q(w)]] -> [[(x) = (z)] | [~{R(z, z)}]]}}), - FOF::from(snf.transform_term(&f)) + Fof::from(snf.transform_term(&f)) ); } diff --git a/razor/src/utils.rs b/razor/src/utils.rs index 9a402eb..5f48166 100644 --- a/razor/src/utils.rs +++ b/razor/src/utils.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::Error; use itertools::Itertools; use razor_chase::chase::{r#impl::relational::RelModel, Model, Observation}; -use razor_fol::syntax::{Theory, FOF}; +use razor_fol::syntax::{Fof, Theory}; use std::{ fs, io::{stdin, Read}, @@ -33,7 +33,7 @@ pub(crate) fn stylus(color: bool) -> Stylus { stylus } -pub(crate) fn read_theory_from_file(filename: &str) -> Result, Error> { +pub(crate) fn read_theory_from_file(filename: &str) -> Result, Error> { let mut f = fs::File::open(filename) .map_err(|e| Error::new(e).context("failed to find the input file"))?; @@ -46,7 +46,7 @@ pub(crate) fn read_theory_from_file(filename: &str) -> Result, Error .map_err(|e| Error::new(e).context("failed to parse the input theory")) } -pub(crate) fn read_theory_from_stdin() -> Result, Error> { +pub(crate) fn read_theory_from_stdin() -> Result, Error> { let mut buf: Vec = Vec::new(); stdin().read_to_end(&mut buf)?; let s = String::from_utf8(buf)?;