From 700595056587395beaac278101634882d063d1df Mon Sep 17 00:00:00 2001 From: SimonGuilloud <simon.guilloud@bluewin.ch> Date: Sat, 2 Dec 2023 13:18:19 +0100 Subject: [PATCH] Atomics, improve lisa.fol.FOL's logic and simplify it (#194) * Renamed some elements of the formula hierarchy using the word "atomic" * removed the match type for ***. Instead, use opaque types and extension methods. Should be a bit more efficient and less prone to dotty bugs * remove ***. Only ** left * removing apply for sequences (use applyUnsafe) * mostly good but one theorem doesn't pass anymore * everything goes, no more *** (i.e. no match type) * progress * PredKer * mend * ConstantAtomicLabel, AtomicFormula * All atomic renaming completed * back to compile * finished tests, removed ConsOrPred * next step: Removes contravariant labels and terms and formulas extending |-> * finish predicates, compiles * progress, Binders to sort and organize, some renaming to do in other files. Can remove - in labels. * finished cleaning and uniformizing definitions in Commons.scala, adapted other files accordingly. Compiles, tests passes, formated. * re-checked some warning, removed some redundant type checks. * fix substituteUnsafe2 * Add "lisa-sets / compile" and "lisa-examples / compile" to the CI. --- .github/workflows/ci.yml | 4 + Reference Manual/kernel.tex | 16 +- Reference Manual/lisa.pdf | Bin 254780 -> 255269 bytes Reference Manual/shortcuts.tex | 2 +- .../lisa/kernel/fol/EquivalenceChecker.scala | 26 +- .../lisa/kernel/fol/FormulaDefinitions.scala | 30 +- .../kernel/fol/FormulaLabelDefinitions.scala | 16 +- .../scala/lisa/kernel/fol/Substitutions.scala | 24 +- .../lisa/kernel/proof/RunningTheory.scala | 26 +- .../lisa/kernel/proof/SCProofChecker.scala | 14 +- .../lisa/kernel/proof/SequentCalculus.scala | 2 +- .../main/scala/lisa/SetTheoryLibrary.scala | 2 +- .../scala/lisa/automation/CommonTactics.scala | 45 +- .../scala/lisa/automation/Substitution.scala | 77 +-- .../main/scala/lisa/automation/Tableau.scala | 21 +- .../scala/lisa/automation/Tautology.scala | 10 +- .../settheory/SetTheoryTactics.scala | 2 +- .../lisa/maths/settheory/InductiveSets.scala | 2 +- .../maths/settheory/orderings/Recursion.scala | 2 +- .../peano_example/PeanoArithmetics.scala | 2 +- .../src/main/scala/lisa/fol/Common.scala | 447 ++++++++++-------- .../src/main/scala/lisa/fol/FOLHelpers.scala | 39 +- .../src/main/scala/lisa/fol/Lambdas.scala | 8 +- .../src/main/scala/lisa/fol/Predef.scala | 2 +- .../src/main/scala/lisa/fol/Sequents.scala | 10 +- .../scala/lisa/prooflib/BasicStepTactic.scala | 36 +- .../scala/lisa/prooflib/ProofsHelpers.scala | 54 +-- .../scala/lisa/prooflib/WithTheorems.scala | 2 +- .../main/scala/lisa/utils/KernelHelpers.scala | 28 +- .../main/scala/lisa/utils/ProofsShrink.scala | 4 +- .../main/scala/lisa/utils/Serialization.scala | 16 +- .../scala/lisa/utils/parsing/Parser.scala | 34 +- .../lisa/utils/parsing/SynonymInfo.scala | 2 +- .../scala/lisa/utils/tptp/KernelParser.scala | 6 +- .../utils/unification/UnificationUtils.scala | 14 +- .../test/scala/lisa/TestTheoryAxioms.scala | 4 +- .../lisa/kernel/EquivalenceCheckerTests.scala | 12 +- .../src/test/scala/lisa/kernel/FolTests.scala | 16 +- .../lisa/kernel/IncorrectProofsTests.scala | 6 +- .../test/scala/lisa/kernel/ProofTests.scala | 8 +- .../scala/lisa/kernel/SubstitutionTest.scala | 8 +- .../scala/lisa/utils/BasicTacticTest.scala | 28 +- .../test/scala/lisa/utils/ParserTest.scala | 62 +-- .../test/scala/lisa/utils/PrinterTest.scala | 72 +-- .../src/test/scala/lisa/utils/TestUtils.scala | 8 +- 45 files changed, 644 insertions(+), 605 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7cf713b..592af2bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,4 +21,8 @@ jobs: run: sbt "scalafixAll --check" - name: Check format run: sbt scalafmtCheckAll + - name: Compile sets + run: sbt "lisa-sets / compile" + - name: Compile examples + run: sbt "lisa-examples / compile" diff --git a/Reference Manual/kernel.tex b/Reference Manual/kernel.tex index 11da88b3..8d0fd362 100644 --- a/Reference Manual/kernel.tex +++ b/Reference Manual/kernel.tex @@ -69,7 +69,7 @@ Schematic symbols on the other hand, are uninterpreted --- they can represent an where $\mathcal{L}_{Predicate}$ is the set of \textit{predicate labels}: % \begin{align} - \mathcal{L}_{Predicate} := & ~\ConstantPredicateLabel(\textnormal{Id}, \textnormal{Arity}) \\ + \mathcal{L}_{Predicate} := & ~\ConstantAtomicLabel(\textnormal{Id}, \textnormal{Arity}) \\ \mid & ~\SchematicPredicateLabel(\textnormal{Id}, \textnormal{Arity})~, \end{align} % @@ -114,11 +114,11 @@ Schematic symbols on the other hand, are uninterpreted --- they can represent an \end{definition} \begin{example}[Formula]The following are typical examples of formula labels: \begin{align*} - \True & := \ConstantPredicateLabel(``\True", 0) \\ - \False & := \ConstantPredicateLabel(``\False", 0) \\ + \True & := \ConstantAtomicLabel(``\True", 0) \\ + \False & := \ConstantAtomicLabel(``\False", 0) \\ X & := \SchematicPredicateLabel(``X", 0) \\ - = & := \ConstantPredicateLabel(``=", 2) \\ - {\in} & := \ConstantPredicateLabel(``{\in}", 2) \\ + = & := \ConstantAtomicLabel(``=", 2) \\ + {\in} & := \ConstantAtomicLabel(``{\in}", 2) \\ P & := \SchematicPredicateLabel(``P", 1) \\ \neg & := \ConstantConnectorLabel(``{\neg}", 1) \\ \land & := \ConstantConnectorLabel(``{\land}", -1) \\ @@ -728,7 +728,7 @@ LISA's kernel allows to define two kinds of objects: Function (or Term) symbols A definition in LISA is one of those two kinds of objects: A predicate definition or a function definition. \begin{lstlisting} PredicateDefinition( - label: ConstantPredicateLabel, + label: ConstantAtomicLabel, expression: LambdaTermFormula ) \end{lstlisting} @@ -807,7 +807,7 @@ Once a definition has been introduced, future theorems can refer to those defini A predicate definition & \begin{lstlisting}[linewidth=19.5em] PredicateDefinition( - label: ConstantPredicateLabel, + label: ConstantAtomicLabel, expression: LambdaTermFormula ) @@ -861,7 +861,7 @@ Once a definition has been introduced, future theorems can refer to those defini \makecell[l]{Make a new \\predicate definition} & \begin{lstlisting}[linewidth=19.5em] makePredicateDefinition( - label: ConstantPredicateLabel, + label: ConstantAtomicLabel, expression: LambdaTermFormula ) \end{lstlisting} diff --git a/Reference Manual/lisa.pdf b/Reference Manual/lisa.pdf index eaf56b7b5c01b55cc12b6f2af64db6b51935ed3d..371e8030840fa106d5fd471a92ace6ccf3f6ad19 100644 GIT binary patch delta 66014 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%0AVel1kJaEXHZhs9@>ntVCCX<8wB@z%yIZ>AU- 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 PjVw(qxl~nM{oS|#aIHyE delta 65432 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%0Da<=1p`E~=GY`;&2t%&F!8u7x`P%AbY&`SZW@ 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 diff --git a/Reference Manual/shortcuts.tex b/Reference Manual/shortcuts.tex index 6518fc5c..4f33644a 100644 --- a/Reference Manual/shortcuts.tex +++ b/Reference Manual/shortcuts.tex @@ -4,7 +4,7 @@ \newcommand\ConstantTermLabel{\operatorname{ConstantTermLabel}} \newcommand\SchematicTermLabel{\operatorname{SchematicTermLabel}} -\newcommand\ConstantPredicateLabel{\operatorname{ConstantPredicateLabel}} +\newcommand\ConstantAtomicLabel{\operatorname{ConstantAtomicLabel}} \newcommand\SchematicPredicateLabel{\operatorname{SchematicPredicateLabel}} \newcommand\ConstantConnectorLabel{\operatorname{ConstantConnectorLabel}} diff --git a/lisa-kernel/src/main/scala/lisa/kernel/fol/EquivalenceChecker.scala b/lisa-kernel/src/main/scala/lisa/kernel/fol/EquivalenceChecker.scala index ee35a369..dccfed2b 100644 --- a/lisa-kernel/src/main/scala/lisa/kernel/fol/EquivalenceChecker.scala +++ b/lisa-kernel/src/main/scala/lisa/kernel/fol/EquivalenceChecker.scala @@ -80,7 +80,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { private[EquivalenceChecker] var normalForm: Option[NormalFormula] = None def getNormalForm = normalForm } - case class SimplePredicate(id: PredicateLabel, args: Seq[Term], polarity: Boolean) extends SimpleFormula { + case class SimplePredicate(id: AtomicLabel, args: Seq[Term], polarity: Boolean) extends SimpleFormula { override def toString: String = s"SimplePredicate($id, $args, $polarity)" val size = 1 } @@ -125,7 +125,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { def recoverFormula: Formula = toFormulaAIG(this) } sealed abstract class NonTraversable extends NormalFormula - case class NormalPredicate(id: PredicateLabel, args: Seq[Term], polarity: Boolean) extends NonTraversable { + case class NormalPredicate(id: AtomicLabel, args: Seq[Term], polarity: Boolean) extends NonTraversable { override def toString: String = s"NormalPredicate($id, $args, $polarity)" } case class NormalSchemConnector(id: SchematicConnectorLabel, args: Seq[NormalFormula], polarity: Boolean) extends NonTraversable @@ -141,7 +141,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { else { val r: Formula = f match { case NormalPredicate(id, args, polarity) => - if (polarity) PredicateFormula(id, args) else ConnectorFormula(Neg, Seq(PredicateFormula(id, args))) + if (polarity) AtomicFormula(id, args) else ConnectorFormula(Neg, Seq(AtomicFormula(id, args))) case NormalSchemConnector(id, args, polarity) => val f = ConnectorFormula(id, args.map(toFormulaAIG)) if (polarity) f else ConnectorFormula(Neg, Seq(f)) @@ -151,7 +151,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { case NormalForall(x, inner, polarity) => val f = BinderFormula(Forall, VariableLabel(x), toFormulaAIG(inner)) if (polarity) f else ConnectorFormula(Neg, Seq(f)) - case NormalLiteral(polarity) => if (polarity) PredicateFormula(top, Seq()) else PredicateFormula(bot, Seq()) + case NormalLiteral(polarity) => if (polarity) AtomicFormula(top, Seq()) else AtomicFormula(bot, Seq()) } f.formulaAIG = Some(r) r @@ -171,7 +171,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { } val r = f match{ case NormalPredicate(id, args, polarity) => - if (positive==polarity) PredicateFormula(id, args) else ConnectorFormula(Neg, Seq(PredicateFormula(id, args))) + if (positive==polarity) AtomicFormula(id, args) else ConnectorFormula(Neg, Seq(AtomicFormula(id, args))) case NormalSchemConnector(id, args, polarity) => val f = ConnectorFormula(id, args.map(toFormulaNNF(_, true))) if (positive==polarity) f else ConnectorFormula(Neg, Seq(f)) @@ -185,7 +185,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { BinderFormula(Forall, VariableLabel(x), toFormulaNNF(inner, true)) else BinderFormula(Exists, VariableLabel(x), toFormulaNNF(inner, false)) - case NormalLiteral(polarity) => if (polarity) PredicateFormula(top, Seq()) else PredicateFormula(bot, Seq()) + case NormalLiteral(polarity) => if (polarity) AtomicFormula(top, Seq()) else AtomicFormula(bot, Seq()) } if (positive) f.formulaP = Some(r) else f.formulaN = Some(r) @@ -246,7 +246,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { getInversePolar(f.polarFormula.get) } else { val r = f match { - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => if (label == top) SimpleLiteral(polarity) else if (label == bot) SimpleLiteral(!polarity) else SimplePredicate(label, args, polarity) @@ -279,7 +279,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { case Exists => SimpleForall(bound.id, polarize(inner, false), !polarity) case ExistsOne => val y = VariableLabel(freshId(inner.freeVariables.map(_.id), bound.id)) - val c = PredicateFormula(equality, Seq(VariableTerm(bound), VariableTerm(y))) + val c = AtomicFormula(equality, Seq(VariableTerm(bound), VariableTerm(y))) val newInner = polarize(ConnectorFormula(Iff, Seq(c, inner)), true) SimpleForall(y.id, SimpleForall(bound.id, newInner, false), !polarity) } @@ -489,7 +489,7 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { // transform a LISA formula into a simpler, desugarised version with less symbols. Conjunction, implication, iff, existsOne are treated as alliases and translated. def removeSugar1(phi: Formula): PolarFormula = { phi match { - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => if (label == top) PolarLiteral(true) else if (label == bot) PolarLiteral(false) else PolarPredicate(label, args.toList) @@ -627,8 +627,8 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { val r: List[NormalFormula] = phi match { case PolarPredicate(label, args) => val lab = label match { - case _: ConstantPredicateLabel => "cp_" + label.id + "_" + label.arity - case _: SchematicVarOrPredLabel => "sp_" + label.id + "_" + label.arity + case _: ConstantAtomicLabel => "cp_" + label.id + "_" + label.arity + case _: SchematicAtomicLabel => "sp_" + label.id + "_" + label.arity } if (label == top) { phi.normalForm = Some(NLiteral(true)) @@ -675,8 +675,8 @@ private[fol] trait EquivalenceChecker extends FormulaDefinitions { val r: List[NormalFormula] = phi match { case PolarPredicate(label, args) => val lab = label match { - case _: ConstantPredicateLabel => "cp_" + label.id + "_" + label.arity - case _: SchematicVarOrPredLabel => "sp_" + label.id + "_" + label.arity + case _: ConstantAtomicLabel => "cp_" + label.id + "_" + label.arity + case _: SchematicAtomicLabel => "sp_" + label.id + "_" + label.arity } if (label == top) { phi.normalForm = Some(NLiteral(true)) diff --git a/lisa-kernel/src/main/scala/lisa/kernel/fol/FormulaDefinitions.scala b/lisa-kernel/src/main/scala/lisa/kernel/fol/FormulaDefinitions.scala index 4ff7416b..192460ce 100644 --- a/lisa-kernel/src/main/scala/lisa/kernel/fol/FormulaDefinitions.scala +++ b/lisa-kernel/src/main/scala/lisa/kernel/fol/FormulaDefinitions.scala @@ -33,12 +33,12 @@ private[fol] trait FormulaDefinitions extends FormulaLabelDefinitions with TermD /** * @return The list of constant predicate symbols in the formula. */ - def constantPredicateLabels: Set[ConstantPredicateLabel] + def constantAtomicLabels: Set[ConstantAtomicLabel] /** * @return The list of schematic predicate symbols in the formula, including variable formulas . */ - def schematicPredicateLabels: Set[SchematicVarOrPredLabel] + def schematicAtomicLabels: Set[SchematicAtomicLabel] /** * @return The list of schematic connector symbols in the formula. @@ -49,7 +49,7 @@ private[fol] trait FormulaDefinitions extends FormulaLabelDefinitions with TermD * @return The list of schematic connector, predicate and formula variable symbols in the formula. */ def schematicFormulaLabels: Set[SchematicFormulaLabel] = - (schematicPredicateLabels.toSet: Set[SchematicFormulaLabel]) union (schematicConnectorLabels.toSet: Set[SchematicFormulaLabel]) + (schematicAtomicLabels.toSet: Set[SchematicFormulaLabel]) union (schematicConnectorLabels.toSet: Set[SchematicFormulaLabel]) /** * @return The list of free formula variable symbols in the formula @@ -66,9 +66,9 @@ private[fol] trait FormulaDefinitions extends FormulaLabelDefinitions with TermD } /** - * The formula counterpart of [[PredicateLabel]]. + * The formula counterpart of [[AtomicLabel]]. */ - sealed case class PredicateFormula(label: PredicateLabel, args: Seq[Term]) extends Formula { + sealed case class AtomicFormula(label: AtomicLabel, args: Seq[Term]) extends Formula { require(label.arity == args.size) override def constantTermLabels: Set[ConstantFunctionLabel] = args.foldLeft(Set.empty[ConstantFunctionLabel])((prev, next) => prev union next.constantTermLabels) @@ -78,12 +78,12 @@ private[fol] trait FormulaDefinitions extends FormulaLabelDefinitions with TermD args.foldLeft(Set.empty[SchematicTermLabel])((prev, next) => prev union next.freeSchematicTermLabels) override def freeVariables: Set[VariableLabel] = args.foldLeft(Set.empty[VariableLabel])((prev, next) => prev union next.freeVariables) - override def constantPredicateLabels: Set[ConstantPredicateLabel] = label match { - case l: ConstantPredicateLabel => Set(l) + override def constantAtomicLabels: Set[ConstantAtomicLabel] = label match { + case l: ConstantAtomicLabel => Set(l) case _ => Set() } - override def schematicPredicateLabels: Set[SchematicVarOrPredLabel] = label match { - case l: SchematicVarOrPredLabel => Set(l) + override def schematicAtomicLabels: Set[SchematicAtomicLabel] = label match { + case l: SchematicAtomicLabel => Set(l) case _ => Set() } override def schematicConnectorLabels: Set[SchematicConnectorLabel] = Set() @@ -108,10 +108,10 @@ private[fol] trait FormulaDefinitions extends FormulaLabelDefinitions with TermD args.foldLeft(Set.empty[SchematicTermLabel])((prev, next) => prev union next.freeSchematicTermLabels) override def freeVariables: Set[VariableLabel] = args.foldLeft(Set.empty[VariableLabel])((prev, next) => prev union next.freeVariables) - override def constantPredicateLabels: Set[ConstantPredicateLabel] = - args.foldLeft(Set.empty[ConstantPredicateLabel])((prev, next) => prev union next.constantPredicateLabels) - override def schematicPredicateLabels: Set[SchematicVarOrPredLabel] = - args.foldLeft(Set.empty[SchematicVarOrPredLabel])((prev, next) => prev union next.schematicPredicateLabels) + override def constantAtomicLabels: Set[ConstantAtomicLabel] = + args.foldLeft(Set.empty[ConstantAtomicLabel])((prev, next) => prev union next.constantAtomicLabels) + override def schematicAtomicLabels: Set[SchematicAtomicLabel] = + args.foldLeft(Set.empty[SchematicAtomicLabel])((prev, next) => prev union next.schematicAtomicLabels) override def schematicConnectorLabels: Set[SchematicConnectorLabel] = label match { case l: ConstantConnectorLabel => args.foldLeft(Set.empty[SchematicConnectorLabel])((prev, next) => prev union next.schematicConnectorLabels) @@ -130,8 +130,8 @@ private[fol] trait FormulaDefinitions extends FormulaLabelDefinitions with TermD override def schematicTermLabels: Set[SchematicTermLabel] = inner.schematicTermLabels override def freeSchematicTermLabels: Set[SchematicTermLabel] = inner.freeSchematicTermLabels - bound override def freeVariables: Set[VariableLabel] = inner.freeVariables - bound - override def constantPredicateLabels: Set[ConstantPredicateLabel] = inner.constantPredicateLabels - override def schematicPredicateLabels: Set[SchematicVarOrPredLabel] = inner.schematicPredicateLabels + override def constantAtomicLabels: Set[ConstantAtomicLabel] = inner.constantAtomicLabels + override def schematicAtomicLabels: Set[SchematicAtomicLabel] = inner.schematicAtomicLabels override def schematicConnectorLabels: Set[SchematicConnectorLabel] = inner.schematicConnectorLabels override def freeVariableFormulaLabels: Set[VariableFormulaLabel] = inner.freeVariableFormulaLabels } diff --git a/lisa-kernel/src/main/scala/lisa/kernel/fol/FormulaLabelDefinitions.scala b/lisa-kernel/src/main/scala/lisa/kernel/fol/FormulaLabelDefinitions.scala index d7245a15..61e75077 100644 --- a/lisa-kernel/src/main/scala/lisa/kernel/fol/FormulaLabelDefinitions.scala +++ b/lisa-kernel/src/main/scala/lisa/kernel/fol/FormulaLabelDefinitions.scala @@ -16,7 +16,7 @@ private[fol] trait FormulaLabelDefinitions extends CommonDefinitions { * The label for a predicate, namely a function taking a fixed number of terms and returning a formula. * In logical terms it is a predicate symbol. */ - sealed trait PredicateLabel extends FormulaLabel { + sealed trait AtomicLabel extends FormulaLabel { require(arity < MaxArity && arity >= 0) } @@ -30,15 +30,15 @@ private[fol] trait FormulaLabelDefinitions extends CommonDefinitions { /** * A standard predicate symbol. Typical example are equality (=) and membership (∈) */ - sealed case class ConstantPredicateLabel(id: Identifier, arity: Int) extends PredicateLabel with ConstantLabel + sealed case class ConstantAtomicLabel(id: Identifier, arity: Int) extends AtomicLabel with ConstantLabel /** * The equality symbol (=) for first order logic. * It is represented as any other predicate symbol but has unique semantic and deduction rules. */ - val equality: ConstantPredicateLabel = ConstantPredicateLabel(Identifier("="), 2) - val top: ConstantPredicateLabel = ConstantPredicateLabel(Identifier("⊤"), 0) - val bot: ConstantPredicateLabel = ConstantPredicateLabel(Identifier("⊥"), 0) + val equality: ConstantAtomicLabel = ConstantAtomicLabel(Identifier("="), 2) + val top: ConstantAtomicLabel = ConstantAtomicLabel(Identifier("⊤"), 0) + val bot: ConstantAtomicLabel = ConstantAtomicLabel(Identifier("⊥"), 0) /** * The label for a connector, namely a function taking a fixed number of formulas and returning another formula. @@ -63,19 +63,19 @@ private[fol] trait FormulaLabelDefinitions extends CommonDefinitions { /** * A schematic symbol whose arguments are any number of Terms. This means the symbol is either a variable formula or a predicate schema */ - sealed trait SchematicVarOrPredLabel extends SchematicFormulaLabel with PredicateLabel + sealed trait SchematicAtomicLabel extends SchematicFormulaLabel with AtomicLabel /** * A predicate symbol of arity 0 that can be instantiated with any formula. */ - sealed case class VariableFormulaLabel(id: Identifier) extends SchematicVarOrPredLabel { + sealed case class VariableFormulaLabel(id: Identifier) extends SchematicAtomicLabel { val arity = 0 } /** * A predicate symbol of non-zero arity that can be instantiated with any functional formula taking term arguments. */ - sealed case class SchematicPredicateLabel(id: Identifier, arity: Int) extends SchematicVarOrPredLabel + sealed case class SchematicPredicateLabel(id: Identifier, arity: Int) extends SchematicAtomicLabel /** * A predicate symbol of non-zero arity that can be instantiated with any functional formula taking formula arguments. diff --git a/lisa-kernel/src/main/scala/lisa/kernel/fol/Substitutions.scala b/lisa-kernel/src/main/scala/lisa/kernel/fol/Substitutions.scala index eec5e3ec..f3f04bc2 100644 --- a/lisa-kernel/src/main/scala/lisa/kernel/fol/Substitutions.scala +++ b/lisa-kernel/src/main/scala/lisa/kernel/fol/Substitutions.scala @@ -88,7 +88,7 @@ trait Substitutions extends FormulaDefinitions { * @return t[m] */ def substituteVariablesInFormula(phi: Formula, m: Map[VariableLabel, Term], takenIds: Seq[Identifier] = Seq[Identifier]()): Formula = phi match { - case PredicateFormula(label, args) => PredicateFormula(label, args.map(substituteVariablesInTerm(_, m))) + case AtomicFormula(label, args) => AtomicFormula(label, args.map(substituteVariablesInTerm(_, m))) case ConnectorFormula(label, args) => ConnectorFormula(label, args.map(substituteVariablesInFormula(_, m))) case BinderFormula(label, bound, inner) => val newSubst = m - bound @@ -109,8 +109,8 @@ trait Substitutions extends FormulaDefinitions { * @return t[m] */ def substituteFormulaVariables(phi: Formula, m: Map[VariableFormulaLabel, Formula], takenIds: Seq[Identifier] = Seq[Identifier]()): Formula = phi match { - case PredicateFormula(label: VariableFormulaLabel, _) => m.getOrElse(label, phi) - case _: PredicateFormula => phi + case AtomicFormula(label: VariableFormulaLabel, _) => m.getOrElse(label, phi) + case _: AtomicFormula => phi case ConnectorFormula(label, args) => ConnectorFormula(label, args.map(substituteFormulaVariables(_, m, takenIds))) case BinderFormula(label, bound, inner) => val fv = m.values.flatMap(_.freeVariables).toSet @@ -132,7 +132,7 @@ trait Substitutions extends FormulaDefinitions { def instantiateTermSchemas(phi: Formula, m: Map[SchematicTermLabel, LambdaTermTerm]): Formula = { require(m.forall { case (symbol, LambdaTermTerm(arguments, body)) => arguments.length == symbol.arity }) phi match { - case PredicateFormula(label, args) => PredicateFormula(label, args.map(a => instantiateTermSchemasInTerm(a, m))) + case AtomicFormula(label, args) => AtomicFormula(label, args.map(a => instantiateTermSchemasInTerm(a, m))) case ConnectorFormula(label, args) => ConnectorFormula(label, args.map(instantiateTermSchemas(_, m))) case BinderFormula(label, bound, inner) => val newSubst = m - bound @@ -152,12 +152,12 @@ trait Substitutions extends FormulaDefinitions { * @param m The map from schematic predicate symbols to lambda expressions Term(s) -> Formula [[LambdaTermFormula]]. * @return phi[m] */ - def instantiatePredicateSchemas(phi: Formula, m: Map[SchematicVarOrPredLabel, LambdaTermFormula]): Formula = { + def instantiatePredicateSchemas(phi: Formula, m: Map[SchematicAtomicLabel, LambdaTermFormula]): Formula = { require(m.forall { case (symbol, LambdaTermFormula(arguments, body)) => arguments.length == symbol.arity }) phi match { - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => label match { - case label: SchematicVarOrPredLabel if m.contains(label) => m(label)(args) + case label: SchematicAtomicLabel if m.contains(label) => m(label)(args) case _ => phi } case ConnectorFormula(label, args) => ConnectorFormula(label, args.map(instantiatePredicateSchemas(_, m))) @@ -181,7 +181,7 @@ trait Substitutions extends FormulaDefinitions { def instantiateConnectorSchemas(phi: Formula, m: Map[SchematicConnectorLabel, LambdaFormulaFormula]): Formula = { require(m.forall { case (symbol, LambdaFormulaFormula(arguments, body)) => arguments.length == symbol.arity }) phi match { - case _: PredicateFormula => phi + case _: AtomicFormula => phi case ConnectorFormula(label, args) => val newArgs = args.map(instantiateConnectorSchemas(_, m)) label match { @@ -208,18 +208,18 @@ trait Substitutions extends FormulaDefinitions { def instantiateSchemas( phi: Formula, mCon: Map[SchematicConnectorLabel, LambdaFormulaFormula], - mPred: Map[SchematicVarOrPredLabel, LambdaTermFormula], + mPred: Map[SchematicAtomicLabel, LambdaTermFormula], mTerm: Map[SchematicTermLabel, LambdaTermTerm] ): Formula = { require(mCon.forall { case (symbol, LambdaFormulaFormula(arguments, body)) => arguments.length == symbol.arity }) require(mPred.forall { case (symbol, LambdaTermFormula(arguments, body)) => arguments.length == symbol.arity }) require(mTerm.forall { case (symbol, LambdaTermTerm(arguments, body)) => arguments.length == symbol.arity }) phi match { - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => val newArgs = args.map(a => instantiateTermSchemasInTerm(a, mTerm)) label match { - case label: SchematicVarOrPredLabel if mPred.contains(label) => mPred(label)(newArgs) - case _ => PredicateFormula(label, newArgs) + case label: SchematicAtomicLabel if mPred.contains(label) => mPred(label)(newArgs) + case _ => AtomicFormula(label, newArgs) } case ConnectorFormula(label, args) => val newArgs = args.map(a => instantiateSchemas(a, mCon, mPred, mTerm)) diff --git a/lisa-kernel/src/main/scala/lisa/kernel/proof/RunningTheory.scala b/lisa-kernel/src/main/scala/lisa/kernel/proof/RunningTheory.scala index b8bd954e..8167d9f7 100644 --- a/lisa-kernel/src/main/scala/lisa/kernel/proof/RunningTheory.scala +++ b/lisa-kernel/src/main/scala/lisa/kernel/proof/RunningTheory.scala @@ -45,7 +45,7 @@ class RunningTheory { * @param label The name and arity of the new symbol * @param expression The formula, depending on terms, that define the symbol. */ - sealed case class PredicateDefinition private[RunningTheory] (label: ConstantPredicateLabel, expression: LambdaTermFormula) extends Definition + sealed case class PredicateDefinition private[RunningTheory] (label: ConstantAtomicLabel, expression: LambdaTermFormula) extends Definition /** * Define a function symbol as the unique element that has some property. The existence and uniqueness @@ -63,7 +63,7 @@ class RunningTheory { private[proof] val theorems: mMap[String, Theorem] = mMap.empty private[proof] val funDefinitions: mMap[ConstantFunctionLabel, Option[FunctionDefinition]] = mMap.empty - private[proof] val predDefinitions: mMap[ConstantPredicateLabel, Option[PredicateDefinition]] = mMap(equality -> None, top -> None, bot -> None) + private[proof] val predDefinitions: mMap[ConstantAtomicLabel, Option[PredicateDefinition]] = mMap(equality -> None, top -> None, bot -> None) private[proof] val knownSymbols: mMap[Identifier, ConstantLabel] = mMap(equality.id -> equality) @@ -113,11 +113,11 @@ class RunningTheory { * @param expression The functional formula defining the predicate. * @return A definition object if the parameters are correct, */ - def makePredicateDefinition(label: ConstantPredicateLabel, expression: LambdaTermFormula): RunningTheoryJudgement[this.PredicateDefinition] = { + def makePredicateDefinition(label: ConstantAtomicLabel, expression: LambdaTermFormula): RunningTheoryJudgement[this.PredicateDefinition] = { val LambdaTermFormula(vars, body) = expression if (belongsToTheory(body)) if (isAvailable(label)) - if (body.freeSchematicTermLabels.subsetOf(vars.toSet) && body.schematicPredicateLabels.isEmpty) { + if (body.freeSchematicTermLabels.subsetOf(vars.toSet) && body.schematicAtomicLabels.isEmpty) { val newDef = PredicateDefinition(label, expression) predDefinitions.update(label, Some(newDef)) knownSymbols.update(label.id, label) @@ -196,7 +196,7 @@ class RunningTheory { case Theorem(name, proposition, _) => proposition case Axiom(name, ax) => Sequent(Set.empty, Set(ax)) case PredicateDefinition(label, LambdaTermFormula(vars, body)) => - val inner = ConnectorFormula(Iff, Seq(PredicateFormula(label, vars.map(VariableTerm.apply)), body)) + val inner = ConnectorFormula(Iff, Seq(AtomicFormula(label, vars.map(VariableTerm.apply)), body)) Sequent(Set(), Set(inner)) case FunctionDefinition(label, out, LambdaTermFormula(vars, body), _) => val inner = BinderFormula( @@ -205,7 +205,7 @@ class RunningTheory { ConnectorFormula( Iff, Seq( - PredicateFormula(equality, Seq(Term(label, vars.map(VariableTerm.apply)), VariableTerm(out))), + AtomicFormula(equality, Seq(Term(label, vars.map(VariableTerm.apply)), VariableTerm(out))), body ) ) @@ -242,7 +242,7 @@ class RunningTheory { knownSymbols.update(s.id, s) s match { case c: ConstantFunctionLabel => funDefinitions.update(c, None) - case c: ConstantPredicateLabel => predDefinitions.update(c, None) + case c: ConstantAtomicLabel => predDefinitions.update(c, None) } } else {} } @@ -251,7 +251,7 @@ class RunningTheory { * Add all constant symbols in the sequent. Note that this can't be reversed and will prevent from giving them a definition later. */ def makeFormulaBelongToTheory(phi: Formula): Unit = { - phi.constantPredicateLabels.foreach(addSymbol) + phi.constantAtomicLabels.foreach(addSymbol) phi.constantTermLabels.foreach(addSymbol) } @@ -270,9 +270,9 @@ class RunningTheory { * @return Weather phi belongs to the specified language */ def belongsToTheory(phi: Formula): Boolean = phi match { - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => label match { - case l: ConstantPredicateLabel => isSymbol(l) && args.forall(belongsToTheory) + case l: ConstantAtomicLabel => isSymbol(l) && args.forall(belongsToTheory) case _ => args.forall(belongsToTheory) } case ConnectorFormula(label, args) => args.forall(belongsToTheory) @@ -315,7 +315,7 @@ class RunningTheory { */ def isSymbol(label: ConstantLabel): Boolean = label match { case c: ConstantFunctionLabel => funDefinitions.contains(c) - case c: ConstantPredicateLabel => predDefinitions.contains(c) + case c: ConstantAtomicLabel => predDefinitions.contains(c) } /** @@ -344,7 +344,7 @@ class RunningTheory { /** * Get the definition of the given label, if it is defined in the theory. */ - def getDefinition(label: ConstantPredicateLabel): Option[PredicateDefinition] = predDefinitions.get(label).flatten + def getDefinition(label: ConstantAtomicLabel): Option[PredicateDefinition] = predDefinitions.get(label).flatten /** * Get the definition of the given label, if it is defined in the theory. @@ -365,7 +365,7 @@ class RunningTheory { * Get the definition for the given identifier, if it is defined in the theory. */ def getDefinition(name: Identifier): Option[Definition] = knownSymbols.get(name).flatMap { - case f: ConstantPredicateLabel => getDefinition(f) + case f: ConstantAtomicLabel => getDefinition(f) case f: ConstantFunctionLabel => getDefinition(f) } diff --git a/lisa-kernel/src/main/scala/lisa/kernel/proof/SCProofChecker.scala b/lisa-kernel/src/main/scala/lisa/kernel/proof/SCProofChecker.scala index 08ea38d4..a4c89b54 100644 --- a/lisa-kernel/src/main/scala/lisa/kernel/proof/SCProofChecker.scala +++ b/lisa-kernel/src/main/scala/lisa/kernel/proof/SCProofChecker.scala @@ -42,7 +42,7 @@ object SCProofChecker { * Γ |- Γ */ case RestateTrue(s) => - val truth = Sequent(Set(), Set(PredicateFormula(top, Nil))) + val truth = Sequent(Set(), Set(AtomicFormula(top, Nil))) if (isSameSequent(s, truth)) SCValidProof(SCProof(step)) else SCInvalidProof(SCProof(step), Nil, s"The desired conclusion is not a trivial tautology") /* * @@ -180,7 +180,7 @@ object SCProofChecker { */ case LeftExistsOne(b, t1, phi, x) => val y = VariableLabel(freshId(phi.freeVariables.map(_.id), x.id)) - val temp = BinderFormula(Exists, y, BinderFormula(Forall, x, ConnectorFormula(Iff, List(PredicateFormula(equality, List(VariableTerm(x), VariableTerm(y))), phi)))) + val temp = BinderFormula(Exists, y, BinderFormula(Forall, x, ConnectorFormula(Iff, List(AtomicFormula(equality, List(VariableTerm(x), VariableTerm(y))), phi)))) if (isSameSet(b.right, ref(t1).right)) if (isSameSet(b.left + temp, ref(t1).left + BinderFormula(ExistsOne, x, phi))) SCValidProof(SCProof(step)) @@ -296,7 +296,7 @@ object SCProofChecker { */ case RightExistsOne(b, t1, phi, x) => val y = VariableLabel(freshId(phi.freeVariables.map(_.id), x.id)) - val temp = BinderFormula(Exists, y, BinderFormula(Forall, x, ConnectorFormula(Iff, List(PredicateFormula(equality, List(VariableTerm(x), VariableTerm(y))), phi)))) + val temp = BinderFormula(Exists, y, BinderFormula(Forall, x, ConnectorFormula(Iff, List(AtomicFormula(equality, List(VariableTerm(x), VariableTerm(y))), phi)))) if (isSameSet(b.left, ref(t1).left)) if (isSameSet(b.right + temp, ref(t1).right + BinderFormula(ExistsOne, x, phi))) SCValidProof(SCProof(step)) @@ -322,7 +322,7 @@ object SCProofChecker { */ case LeftRefl(b, t1, phi) => phi match { - case PredicateFormula(`equality`, Seq(left, right)) => + case AtomicFormula(`equality`, Seq(left, right)) => if (isSameTerm(left, right)) if (isSameSet(b.right, ref(t1).right)) if (isSameSet(b.left + phi, ref(t1).left)) @@ -340,7 +340,7 @@ object SCProofChecker { */ case RightRefl(b, phi) => phi match { - case PredicateFormula(`equality`, Seq(left, right)) => + case AtomicFormula(`equality`, Seq(left, right)) => if (isSameTerm(left, right)) if (contains(b.right, phi)) SCValidProof(SCProof(step)) @@ -358,7 +358,7 @@ object SCProofChecker { val (s_es, t_es) = equals.unzip val phi_s_for_f = lambdaPhi(s_es) val phi_t_for_f = lambdaPhi(t_es) - val sEqT_es = equals map { case (s, t) => PredicateFormula(equality, Seq(s, t)) } + val sEqT_es = equals map { case (s, t) => AtomicFormula(equality, Seq(s, t)) } if (isSameSet(b.right, ref(t1).right)) if ( @@ -380,7 +380,7 @@ object SCProofChecker { * Γ, (s=t)_ |- φ(t_), Δ */ case RightSubstEq(b, t1, equals, lambdaPhi) => - val sEqT_es = equals map { case (s, t) => PredicateFormula(equality, Seq(s, t)) } + val sEqT_es = equals map { case (s, t) => AtomicFormula(equality, Seq(s, t)) } if (isSameSet(ref(t1).left ++ sEqT_es, b.left)) { val (s_es, t_es) = equals.unzip val phi_s_for_f = lambdaPhi(s_es) diff --git a/lisa-kernel/src/main/scala/lisa/kernel/proof/SequentCalculus.scala b/lisa-kernel/src/main/scala/lisa/kernel/proof/SequentCalculus.scala index 44e8df4b..d089f29a 100644 --- a/lisa-kernel/src/main/scala/lisa/kernel/proof/SequentCalculus.scala +++ b/lisa-kernel/src/main/scala/lisa/kernel/proof/SequentCalculus.scala @@ -317,7 +317,7 @@ object SequentCalculus { bot: Sequent, t1: Int, mCon: Map[SchematicConnectorLabel, LambdaFormulaFormula], - mPred: Map[SchematicVarOrPredLabel, LambdaTermFormula], + mPred: Map[SchematicAtomicLabel, LambdaTermFormula], mTerm: Map[SchematicTermLabel, LambdaTermTerm] ) extends SCProofStep { val premises = Seq(t1) } diff --git a/lisa-sets/src/main/scala/lisa/SetTheoryLibrary.scala b/lisa-sets/src/main/scala/lisa/SetTheoryLibrary.scala index 27dec673..12c9f70f 100644 --- a/lisa-sets/src/main/scala/lisa/SetTheoryLibrary.scala +++ b/lisa-sets/src/main/scala/lisa/SetTheoryLibrary.scala @@ -249,7 +249,7 @@ object SetTheoryLibrary extends lisa.prooflib.Library { def ∈(that: Term): Formula = in(thi, that) def ⊆(that: Term): Formula = subset(thi, that) - def =/=(that: Term): Formula = !(===(thi, that)) + def =/=(that: Term): Formula = !(thi === that) } diff --git a/lisa-sets/src/main/scala/lisa/automation/CommonTactics.scala b/lisa-sets/src/main/scala/lisa/automation/CommonTactics.scala index 81b299ca..6de053d7 100644 --- a/lisa-sets/src/main/scala/lisa/automation/CommonTactics.scala +++ b/lisa-sets/src/main/scala/lisa/automation/CommonTactics.scala @@ -110,10 +110,10 @@ object CommonTactics { // Infer y from the equalities in the uniqueness sequent uniquenessSeq.right.collectFirst { - case F.PredicateFormula(F.`equality`, Seq(`x`, (y: F.Variable))) if x != y && F.contains(uniquenessSeq.left, phi.substitute(x := y)) => + case F.AppliedPredicate(F.`equality`, Seq(`x`, (y: F.Variable))) if x != y && F.contains(uniquenessSeq.left, phi.substitute(x := y)) => y - case F.PredicateFormula(F.`equality`, List(F.AppliedTerm(y: F.Variable, _), F.AppliedTerm(`x`, _))) if x != y && F.contains(uniquenessSeq.left, phi.substitute(x := y)) => + case F.AppliedPredicate(F.`equality`, List(F.AppliedFunction(y: F.Variable, _), F.AppliedFunction(`x`, _))) if x != y && F.contains(uniquenessSeq.left, phi.substitute(x := y)) => y } match { case Some(y) => ExistenceAndUniqueness.withParameters(phi, x, y)(existence, uniqueness)(bot) @@ -144,11 +144,11 @@ object CommonTactics { case _ => return proof.InvalidProofTactic("Could not get definition of function.") } val method = expr.f.substituteUnsafe(expr.vars.zip(xs).toMap) match { - case F.ConnectorFormula( + case F.AppliedConnector( F.And, Seq( - F.ConnectorFormula(F.Implies, Seq(a, _)), - F.ConnectorFormula(F.Implies, Seq(b, _)) + F.AppliedConnector(F.Implies, Seq(a, _)), + F.AppliedConnector(F.Implies, Seq(b, _)) ) ) if F.isSame(F.Neg(a), b) => conditional @@ -173,20 +173,21 @@ object CommonTactics { } val y = definition.out val vars = definition.vars + val fxs = f.applyUnsafe(xs) // Instantiate terms in the definition val subst = vars.zip(xs).map(tup => tup._1 := tup._2) val P = definition.f.substitute(subst: _*) - val expected = P.substitute(y := f(xs)) + val expected = P.substitute(y := fxs) if (!F.isSame(expected, bot.right.head)) { return proof.InvalidProofTactic("Right-hand side of bottom sequent should be of the form P(f(xs)).") } TacticSubproof { - lib.have(F.∀(y, (y === f(xs)) <=> P)) by Tautology.from(uniqueness, definition.of(subst: _*)) - lib.thenHave((y === f(xs)) <=> P) by InstantiateForall(y) - lib.thenHave((f(xs) === f(xs)) <=> P.substitute(y := f(xs))) by InstFunSchema(Map(y -> f(xs))) - lib.thenHave(P.substitute(y := f(xs))) by Restate + lib.have(F.∀(y, (y === fxs) <=> P)) by Tautology.from(uniqueness, definition.of(subst: _*)) + lib.thenHave((y === fxs) <=> P) by InstantiateForall(y) + lib.thenHave((fxs === fxs) <=> P.substitute(y := fxs)) by InstFunSchema(Map(y -> fxs)) + lib.thenHave(P.substitute(y := fxs)) by Restate } case _ => proof.InvalidProofTactic("Could not get definition of function.") @@ -223,11 +224,11 @@ object CommonTactics { // Unfold the conditional definition to find Q val phi = F.And(bot.left.toSeq) val Q: F.LambdaExpression[F.Term, F.Formula, 1] = P.body match { - case F.ConnectorFormula( + case F.AppliedConnector( F.And, Seq( - F.ConnectorFormula(F.Implies, Seq(a, f)), - F.ConnectorFormula(F.Implies, Seq(b, g)) + F.AppliedConnector(F.Implies, Seq(a, f)), + F.AppliedConnector(F.Implies, Seq(b, g)) ) ) if F.isSame(F.Neg(a), b) => if (F.isSame(a, phi)) F.lambda(y, f) @@ -238,18 +239,20 @@ object CommonTactics { return proof.InvalidProofTactic("Definition is not conditional.") } - val expected = P.substitute(y := f(xs)) + val fxs = f.applyUnsafe(xs) + + val expected = P.substitute(y := fxs) if (!F.isSame(expected, bot.right.head)) { - return proof.InvalidProofTactic("Right-hand side of bottom sequent should be of the form Q(f(xs)).") + return proof.InvalidProofTactic("Right-hand side of bottom sequent should be of the form Q(fxs).") } TacticSubproof { - lib.have(F.∀(y, (y === f(xs)) <=> P(Seq(y)))) by Tautology.from(uniqueness, definition.of(subst: _*)) - lib.thenHave((y === f(xs)) <=> P(Seq(y))) by InstantiateForall(y) - lib.thenHave((f(xs) === f(xs)) <=> P(Seq(f(xs)))) by InstFunSchema(Map(y -> f(xs))) - lib.thenHave(P(Seq(f(xs)))) by Restate - lib.thenHave(phi ==> Q(Seq(f(xs)))) by Tautology - lib.thenHave(phi |- Q(Seq(f(xs)))) by Restate + lib.have(F.∀(y, (y === fxs) <=> P)) by Tautology.from(uniqueness, definition.of(subst: _*)) + lib.thenHave((y === fxs) <=> P) by InstantiateForall(y) + lib.thenHave((fxs === fxs) <=> P.substitute(y := fxs)) by InstFunSchema(Map(y -> fxs)) + lib.thenHave(P.substitute(y := fxs)) by Restate + lib.thenHave(phi ==> Q(fxs)) by Tautology + lib.thenHave(phi |- Q(fxs)) by Restate } case _ => proof.InvalidProofTactic("Could not get definition of function.") diff --git a/lisa-sets/src/main/scala/lisa/automation/Substitution.scala b/lisa-sets/src/main/scala/lisa/automation/Substitution.scala index 31d7fad9..c5fd1620 100644 --- a/lisa-sets/src/main/scala/lisa/automation/Substitution.scala +++ b/lisa-sets/src/main/scala/lisa/automation/Substitution.scala @@ -87,28 +87,28 @@ object Substitution { substitutions.foreach { case f: F.Formula => f match { - case F.PredicateFormula(F.equality, Seq(l, r)) => + case F.AppliedPredicate(F.equality, Seq(l, r)) => confinedEqualitiesPre = (l, r) :: confinedEqualitiesPre - case F.ConnectorFormula(F.Iff, Seq(l, r)) => + case F.AppliedConnector(F.Iff, Seq(l, r)) => confinedIffsPre = (l, r) :: confinedIffsPre case _ => () } case j: lib.JUSTIFICATION => j.statement.right.head match { - case F.PredicateFormula(F.equality, Seq(l, r)) => + case F.AppliedPredicate(F.equality, Seq(l, r)) => updateSource((l, r), j) freeEqualitiesPre = (l, r) :: freeEqualitiesPre - case F.ConnectorFormula(F.Iff, Seq(l, r)) => + case F.AppliedConnector(F.Iff, Seq(l, r)) => updateSource((l, r), j) freeIffsPre = (l, r) :: freeIffsPre case _ => () } case f: proof.Fact @unchecked => proof.sequentOfFact(f).right.head match { - case F.PredicateFormula(F.equality, Seq(l, r)) => + case F.AppliedPredicate(F.equality, Seq(l, r)) => updateSource((l, r), f) confinedEqualitiesPre = (l, r) :: confinedEqualitiesPre - case F.ConnectorFormula(F.Iff, Seq(l, r)) => + case F.AppliedConnector(F.Iff, Seq(l, r)) => updateSource((l, r), f) confinedIffsPre = (l, r) :: confinedIffsPre case _ => () @@ -122,14 +122,14 @@ object Substitution { val confinedIffs: List[(F.Formula, F.Formula)] = confinedIffsPre ++ confinedIffsPre.map(_.swap) val filteredPrem: Seq[F.Formula] = (premiseSequent.left filter { - case F.PredicateFormula(F.equality, Seq(l, r)) if freeEqualities.contains((l, r)) || confinedEqualities.contains((l, r)) => false - case F.ConnectorFormula(F.Iff, Seq(l, r)) if freeIffs.contains((l, r)) || confinedIffs.contains((l, r)) => false + case F.AppliedPredicate(F.equality, Seq(l, r)) if freeEqualities.contains((l, r)) || confinedEqualities.contains((l, r)) => false + case F.AppliedConnector(F.Iff, Seq(l, r)) if freeIffs.contains((l, r)) || confinedIffs.contains((l, r)) => false case _ => true }).toSeq val filteredBot: Seq[F.Formula] = (bot.left filter { - case F.PredicateFormula(F.equality, Seq(l, r)) if freeEqualities.contains((l, r)) || confinedEqualities.contains((l, r)) => false - case F.ConnectorFormula(F.Iff, Seq(l, r)) if freeIffs.contains((l, r)) || confinedIffs.contains((l, r)) => false + case F.AppliedPredicate(F.equality, Seq(l, r)) if freeEqualities.contains((l, r)) || confinedEqualities.contains((l, r)) => false + case F.AppliedConnector(F.Iff, Seq(l, r)) if freeIffs.contains((l, r)) || confinedIffs.contains((l, r)) => false case _ => true }).toSeq @@ -167,15 +167,15 @@ object Substitution { // actually construct proof TacticSubproof { - def eq(rule: (Term, Term)) = PredicateFormula(equality, Seq(rule._1, rule._2)) - def iff(rule: (Formula, Formula)) = ConnectorFormula(Iff, Seq(rule._1, rule._2)) + def eq(rule: (Term, Term)) = AppliedPredicate(equality, Seq(rule._1, rule._2)) + def iff(rule: (Formula, Formula)) = AppliedConnector(Iff, Seq(rule._1, rule._2)) def eqSource(rule: (Term, Term)) = lib.have(eq(rule) |- eq(rule)) by SimpleDeducedSteps.Restate def iffSource(rule: (Formula, Formula)) = lib.have(iff(rule) |- iff(rule)) by SimpleDeducedSteps.Restate val leftContexts: Seq[UnificationUtils.FormulaRewriteLambda] = leftContextsOpt.get // remove the options val rightContexts: Seq[UnificationUtils.FormulaRewriteLambda] = rightContextsOpt.get // remove the options - val leftBody = ConnectorFormula(And, leftContexts.map(f => f.body)) + val leftBody = AppliedConnector(And, leftContexts.map(f => f.body)) val defaultLeft = UnificationUtils.FormulaRewriteLambda(body = leftBody) @@ -187,7 +187,7 @@ object Substitution { ) } - val rightBody = ConnectorFormula(Or, rightContexts.map(f => f.body)) + val rightBody = AppliedConnector(Or, rightContexts.map(f => f.body)) val defaultRight = UnificationUtils.FormulaRewriteLambda(body = rightBody) @@ -274,7 +274,7 @@ object Substitution { val (formulaInputsL, formulaInputsR) = (formulaInputs.map(_._1), formulaInputs.map(_._2)) // get premise into the right form - val prem = ConnectorFormula(And, filteredPrem.toSeq) |- ConnectorFormula(Or, premiseSequent.right.toSeq) + val prem = AppliedConnector(And, filteredPrem.toSeq) |- AppliedConnector(Or, premiseSequent.right.toSeq) val eqs = termInputs.map(eq(_)) val iffs = formulaInputs.map(iff(_)) val premiseWithSubst = prem ++<< (eqs |- ()) ++<< (iffs |- ()) @@ -383,7 +383,8 @@ object Substitution { else { val induct = condflat(t.args.map(te => findSubterm2(te, subs))) if (!induct._2) (t, false) - else (t.label(induct._1), true) + else + (t.label.applySeq(induct._1), true) } @@ -392,14 +393,14 @@ object Substitution { f match { case f: VariableFormula => (f, false) case f: ConstantFormula => (f, false) - case PredicateFormula(label, args) => + case AppliedPredicate(label, args) => val induct = condflat(args.map(findSubterm2(_, subs))) if (!induct._2) (f, false) - else (PredicateFormula(label, induct._1), true) - case ConnectorFormula(label, args) => + else (AppliedPredicate(label, induct._1), true) + case AppliedConnector(label, args) => val induct = condflat(args.map(findSubterm2(_, subs))) if (!induct._2) (f, false) - else (ConnectorFormula(label, induct._1), true) + else (AppliedConnector(label, induct._1), true) case BinderFormula(label, bound, inner) => val fv_in_f = subs.flatMap(e => e._2.freeVariables + e._1) if (!fv_in_f.contains(bound)) { @@ -422,10 +423,10 @@ object Substitution { else f match { case f: AtomicFormula => (f, false) - case ConnectorFormula(label, args) => + case AppliedConnector(label, args) => val induct = condflat(args.map(findSubformula2(_, subs))) if (!induct._2) (f, false) - else (ConnectorFormula(label, induct._1), true) + else (AppliedConnector(label, induct._1), true) case BinderFormula(label, bound, inner) => val fv_in_f = subs.flatMap(_._2.freeVariables) if (!fv_in_f.contains(bound)) { @@ -468,13 +469,13 @@ object Substitution { )(premise: proof.Fact)(rightLeft: Boolean = false, toLeft: Boolean = true, toRight: Boolean = true): proof.ProofTacticJudgement = { import lisa.utils.K val originSequent = proof.getSequent(premise) - val leftOrigin = ConnectorFormula(And, originSequent.left.toSeq) - val rightOrigin = ConnectorFormula(Or, originSequent.right.toSeq) + val leftOrigin = AppliedConnector(And, originSequent.left.toSeq) + val rightOrigin = AppliedConnector(Or, originSequent.right.toSeq) if (!toLeft && !toRight) return proof.InvalidProofTactic("applyLeftRight called with no substitution selected (toLeft or toRight).") phi match { - case PredicateFormula(label, args) if label == equality => + case AppliedPredicate(label, args) if label == equality => val left = args(0) val right = args(1) val fv_in_phi = (originSequent.left ++ originSequent.right).flatMap(_.allSchematicLabels).map(_.id) @@ -490,12 +491,12 @@ object Substitution { case v: proof.ValidProofTactic => return v } - val leftForm = ConnectorFormula(And, isolatedLeft.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.body).toSeq) - val rightForm = ConnectorFormula(Or, isolatedRight.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.body).toSeq) - val newleft = if (toLeft) isolatedLeft.map((f, ltf) => if (ltf.isEmpty) f else ltf.get(Seq(right))) else originSequent.left - val newright = if (toRight) isolatedRight.map((f, ltf) => if (ltf.isEmpty) f else ltf.get(Seq(right))) else originSequent.right - val result1: Sequent = (ConnectorFormula(And, newleft.toSeq), phi) |- rightOrigin - val result2: Sequent = result1.left |- ConnectorFormula(Or, newright.toSeq) + val leftForm = AppliedConnector(And, isolatedLeft.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.body).toSeq) + val rightForm = AppliedConnector(Or, isolatedRight.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.body).toSeq) + val newleft = if (toLeft) isolatedLeft.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.applyUnsafe(Seq(right))) else originSequent.left + val newright = if (toRight) isolatedRight.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.applyUnsafe(Seq(right))) else originSequent.right + val result1: Sequent = (AppliedConnector(And, newleft.toSeq), phi) |- rightOrigin + val result2: Sequent = result1.left |- AppliedConnector(Or, newright.toSeq) var scproof: Seq[K.SCProofStep] = Seq(K.Restate((leftOrigin |- rightOrigin).underlying, -1)) if (toLeft) scproof = scproof :+ K.LeftSubstEq(result1.underlying, scproof.length - 1, List(left.underlying -> right.underlying), K.LambdaTermFormula(Seq(v.underlyingLabel), leftForm.underlying)) @@ -510,7 +511,7 @@ object Substitution { Seq(premise) ) - case ConnectorFormula(label, args) if label == Iff => + case AppliedConnector(label, args) if label == Iff => val left = args(0) val right = args(1) val fv_in_phi = (originSequent.left ++ originSequent.right).flatMap(_.allSchematicLabels).map(_.id) @@ -526,12 +527,12 @@ object Substitution { case v: proof.ValidProofTactic => return v } - val leftForm = ConnectorFormula(And, isolatedLeft.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.body).toSeq) - val rightForm = ConnectorFormula(Or, isolatedRight.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.body).toSeq) - val newleft = if (toLeft) isolatedLeft.map((f, ltf) => if (ltf.isEmpty) f else ltf.get(Seq(right))) else originSequent.left - val newright = if (toRight) isolatedRight.map((f, ltf) => if (ltf.isEmpty) f else ltf.get(Seq(right))) else originSequent.right - val result1: Sequent = (ConnectorFormula(And, newleft.toSeq), phi) |- rightOrigin - val result2: Sequent = result1.left |- ConnectorFormula(Or, newright.toSeq) + val leftForm = AppliedConnector(And, isolatedLeft.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.body).toSeq) + val rightForm = AppliedConnector(Or, isolatedRight.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.body).toSeq) + val newleft = if (toLeft) isolatedLeft.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.applyUnsafe(Seq(right))) else originSequent.left + val newright = if (toRight) isolatedRight.map((f, ltf) => if (ltf.isEmpty) f else ltf.get.applyUnsafe(Seq(right))) else originSequent.right + val result1: Sequent = (AppliedConnector(And, newleft.toSeq), phi) |- rightOrigin + val result2: Sequent = result1.left |- AppliedConnector(Or, newright.toSeq) var scproof: Seq[K.SCProofStep] = Seq(K.Restate((leftOrigin |- rightOrigin).underlying, -1)) if (toLeft) diff --git a/lisa-sets/src/main/scala/lisa/automation/Tableau.scala b/lisa-sets/src/main/scala/lisa/automation/Tableau.scala index ebc26493..f084af4e 100644 --- a/lisa-sets/src/main/scala/lisa/automation/Tableau.scala +++ b/lisa-sets/src/main/scala/lisa/automation/Tableau.scala @@ -102,7 +102,7 @@ object Tableau extends ProofTactic with ProofSequentTactic with ProofFactSequent beta: List[ConnectorFormula], // label = Or delta: List[BinderFormula], // Exists(...)) gamma: List[BinderFormula], // Forall(...) - atoms: (List[PredicateFormula], List[PredicateFormula]), // split into positive and negatives! + atoms: (List[AtomicFormula], List[AtomicFormula]), // split into positive and negatives! unifiable: Map[VariableLabel, BinderFormula], // map between metavariables and the original formula they came from skolemized: Set[VariableLabel], // set of variables that have been skolemized triedInstantiation: Map[VariableLabel, Set[Term]], // map between metavariables and the term they were already instantiated with @@ -119,9 +119,9 @@ object Tableau extends ProofTactic with ProofSequentTactic with ProofFactSequent if (gamma.nonEmpty && gamma.head.uniqueNumber == f.uniqueNumber) copy(gamma = gamma.tail) else throw Exception("First formula of gamma is not f") case ConnectorFormula(And, args) => if (alpha.nonEmpty && alpha.head.uniqueNumber == f.uniqueNumber) copy(alpha = alpha.tail) else throw Exception("First formula of alpha is not f") - case f @ PredicateFormula(id, args) => + case f @ AtomicFormula(id, args) => throw Exception("Should not pop Atoms") - case f @ ConnectorFormula(Neg, List(PredicateFormula(id, args))) => + case f @ ConnectorFormula(Neg, List(AtomicFormula(id, args))) => throw Exception("Should not pop Atoms") case _ => ??? @@ -130,9 +130,9 @@ object Tableau extends ProofTactic with ProofSequentTactic with ProofFactSequent case f @ ConnectorFormula(Or, args) => this.copy(beta = f :: beta) case f @ BinderFormula(Exists, x, inner) => this.copy(delta = f :: delta) case f @ BinderFormula(Forall, x, inner) => this.copy(gamma = f :: gamma) - case f @ PredicateFormula(id, args) => + case f @ AtomicFormula(id, args) => this.copy(atoms = (f :: atoms._1, atoms._2)) - case ConnectorFormula(Neg, List(f @ PredicateFormula(id, args))) => + case ConnectorFormula(Neg, List(f @ AtomicFormula(id, args))) => this.copy(atoms = (atoms._1, f :: atoms._2)) case _ => ??? @@ -164,7 +164,7 @@ object Tableau extends ProofTactic with ProofSequentTactic with ProofFactSequent (l :+ nf, nn, ns) ) (ConnectorFormula(label, nArgs), nnId, nSeen) - case pf: PredicateFormula => (pf, nextId, seen) + case pf: AtomicFormula => (pf, nextId, seen) case BinderFormula(label, x, inner) => if (seen.contains(x)) val (nInner, nnId, nSeen) = makeVariableNamesUnique(inner, nextId + 1, seen) @@ -211,9 +211,9 @@ object Tableau extends ProofTactic with ProofSequentTactic with ProofFactSequent /** * Detect if two atoms can be unified, and if so, return a substitution that unifies them. */ - def unifyPred(pos: PredicateFormula, neg: PredicateFormula, br: Branch): Option[Substitution] = { + def unifyPred(pos: AtomicFormula, neg: AtomicFormula, br: Branch): Option[Substitution] = { (pos, neg) match - case (PredicateFormula(id1, args1), PredicateFormula(id2, args2)) if (id1 == id2 && args1.size == args2.size) => + case (AtomicFormula(id1, args1), AtomicFormula(id2, args2)) if (id1 == id2 && args1.size == args2.size) => args1 .zip(args2) .foldLeft(Some(Substitution.empty): Option[Substitution])((prev, next) => @@ -239,7 +239,7 @@ object Tableau extends ProofTactic with ProofSequentTactic with ProofFactSequent val newMapTerm = newMap.map((k, v) => k -> VariableTerm(v)) val inverseNewMap = newMap.map((k, v) => v -> k).toMap val inverseNewMapTerm = inverseNewMap.map((k, v) => k -> VariableTerm(v)) - val pos = branch.atoms._1.map(pred => substituteVariablesInFormula(pred, newMapTerm, Seq())).asInstanceOf[List[PredicateFormula]].iterator + val pos = branch.atoms._1.map(pred => substituteVariablesInFormula(pred, newMapTerm, Seq())).asInstanceOf[List[AtomicFormula]].iterator var substitutions: List[(Substitution, Set[Formula])] = Nil while (pos.hasNext) { @@ -255,7 +255,6 @@ object Tableau extends ProofTactic with ProofSequentTactic with ProofFactSequent } } - val cr1 = substitutions.map((sub, set) => ( sub.flatMap((v, t) => @@ -437,6 +436,6 @@ object Tableau extends ProofTactic with ProofSequentTactic with ProofFactSequent def instantiate(f: Formula, x: VariableLabel, t: Term): Formula = f match case ConnectorFormula(label, args) => ConnectorFormula(label, args.map(instantiate(_, x, t))) - case PredicateFormula(id, args) => PredicateFormula(id, args.map(substituteVariablesInTerm(_, Substitution(x -> t)))) + case AtomicFormula(id, args) => AtomicFormula(id, args.map(substituteVariablesInTerm(_, Substitution(x -> t)))) case BinderFormula(label, y, inner) => if (x == y) f else BinderFormula(label, y, instantiate(inner, x, t)) } diff --git a/lisa-sets/src/main/scala/lisa/automation/Tautology.scala b/lisa-sets/src/main/scala/lisa/automation/Tautology.scala index d9bd7a2b..f217058c 100644 --- a/lisa-sets/src/main/scala/lisa/automation/Tautology.scala +++ b/lisa-sets/src/main/scala/lisa/automation/Tautology.scala @@ -109,8 +109,8 @@ object Tautology extends ProofTactic with ProofSequentTactic with ProofFactSeque def findBestAtom(f: Formula): Option[Formula] = { val atoms: scala.collection.mutable.Map[Formula, Int] = scala.collection.mutable.Map.empty def findAtoms2(f: Formula, add: Formula => Unit): Unit = f match { - case PredicateFormula(label, _) if label != top && label != bot => add(f) - case PredicateFormula(_, _) => () + case AtomicFormula(label, _) if label != top && label != bot => add(f) + case AtomicFormula(_, _) => () case ConnectorFormula(label, args) => label match { case label: ConstantConnectorLabel => args.foreach(c => findAtoms2(c, add)) @@ -172,10 +172,10 @@ object Tautology extends ProofTactic with ProofSequentTactic with ProofFactSeque private def findSubterm2(f: Formula, subs: Seq[(VariableLabel, Term)]): (Formula, Boolean) = { f match { - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => val induct = condflat(args.map(findSubterm2(_, subs))) if (!induct._2) (f, false) - else (PredicateFormula(label, induct._1), true) + else (AtomicFormula(label, induct._1), true) case ConnectorFormula(label, args) => val induct = condflat(args.map(findSubterm2(_, subs))) if (!induct._2) (f, false) @@ -201,7 +201,7 @@ object Tautology extends ProofTactic with ProofSequentTactic with ProofFactSeque if (eq.nonEmpty) (eq.get._1(), true) else f match { - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => (f, false) case ConnectorFormula(label, args) => val induct = condflat(args.map(findSubformula2(_, subs))) diff --git a/lisa-sets/src/main/scala/lisa/automation/settheory/SetTheoryTactics.scala b/lisa-sets/src/main/scala/lisa/automation/settheory/SetTheoryTactics.scala index e36014f0..09dcb5e2 100644 --- a/lisa-sets/src/main/scala/lisa/automation/settheory/SetTheoryTactics.scala +++ b/lisa-sets/src/main/scala/lisa/automation/settheory/SetTheoryTactics.scala @@ -56,7 +56,7 @@ object SetTheoryTactics { val t1 = Variable(freshId(takenIDs, x.id)) val t2 = Variable(freshId(takenIDs, y.id)) - val prop = (in(t2, originalSet) /\ separationPredicate(Seq(t2, originalSet))) + val prop = (in(t2, originalSet) /\ separationPredicate(t2, originalSet)) // TODO (Seq(t2, originalSet) def fprop(z: Term) = forall(t2, in(t2, z) <=> prop) /** diff --git a/lisa-sets/src/main/scala/lisa/maths/settheory/InductiveSets.scala b/lisa-sets/src/main/scala/lisa/maths/settheory/InductiveSets.scala index 17a98e48..996d55ee 100644 --- a/lisa-sets/src/main/scala/lisa/maths/settheory/InductiveSets.scala +++ b/lisa-sets/src/main/scala/lisa/maths/settheory/InductiveSets.scala @@ -61,7 +61,7 @@ object InductiveSets extends lisa.Main { * Natural Numbers (Inductive definition) --- The intersection of all * inductive sets is the set of natural numbers, N. */ - val naturalsInductive = DEF(EmptyTuple) --> The(z, ∀(t, in(t, z) <=> (∀(y, inductive(y) ==> in(t, y)))))(inductiveIntersectionUniqueness) + val naturalsInductive = DEF() --> The(z, ∀(t, in(t, z) <=> (∀(y, inductive(y) ==> in(t, y)))))(inductiveIntersectionUniqueness) /** * Theorem --- Natural numbers form an inductive set diff --git a/lisa-sets/src/main/scala/lisa/maths/settheory/orderings/Recursion.scala b/lisa-sets/src/main/scala/lisa/maths/settheory/orderings/Recursion.scala index 5308dac9..6182209b 100644 --- a/lisa-sets/src/main/scala/lisa/maths/settheory/orderings/Recursion.scala +++ b/lisa-sets/src/main/scala/lisa/maths/settheory/orderings/Recursion.scala @@ -548,7 +548,7 @@ object Recursion extends lisa.Main { ) ) by Tautology.from( lastStep, - universalEquivalenceDistribution of (P -> lambda(b, in(b, B) ==> (in(pair(n, b), p2) \/ (n === b))), Q -> lambda( + universalEquivalenceDistribution of (P := lambda(b, in(b, B) ==> (in(pair(n, b), p2) \/ (n === b))), Q := lambda( b, (in(b, initialSegment(p, a1)) /\ !(app(k1, b) === app(k2, b))) ==> (in(pair(n, b), p2) \/ (n === b)) )) diff --git a/lisa-sets/src/test/scala/lisa/examples/peano_example/PeanoArithmetics.scala b/lisa-sets/src/test/scala/lisa/examples/peano_example/PeanoArithmetics.scala index 4e889f4e..e422b6f1 100644 --- a/lisa-sets/src/test/scala/lisa/examples/peano_example/PeanoArithmetics.scala +++ b/lisa-sets/src/test/scala/lisa/examples/peano_example/PeanoArithmetics.scala @@ -23,7 +23,7 @@ object PeanoArithmetics extends lisa.prooflib.Library { final val ax6timesDistrib: Formula = forall(x, forall(y, times(x, s(y)) === plus(times(x, y), x))) final val ax7induction: Formula = (sPhi(zero) /\ forall(x, sPhi(x) ==> sPhi(s(x)))) ==> forall(x, sPhi(x)) - final val functions: Set[ConstantTermLabel] = Set(ConstantFunctionLabel("0", 0), s, plus, times) + final val functions: Set[ConstantTermLabel[?]] = Set(ConstantFunctionLabel("0", 0), s, plus, times) functions.foreach(l => theory.addSymbol(l.underlyingLabel)) private val peanoAxioms: Set[(String, Formula)] = Set( diff --git a/lisa-utils/src/main/scala/lisa/fol/Common.scala b/lisa-utils/src/main/scala/lisa/fol/Common.scala index 0e12da49..cc698916 100644 --- a/lisa-utils/src/main/scala/lisa/fol/Common.scala +++ b/lisa-utils/src/main/scala/lisa/fol/Common.scala @@ -5,9 +5,8 @@ import lisa.utils.UserLisaException import scala.annotation.nowarn import scala.annotation.showAsInfix +import scala.annotation.targetName import scala.compiletime.ops.int.- -import scala.reflect.ClassTag -import scala.runtime.ScalaRunTime import K.given_Conversion_Identifier_String @@ -21,34 +20,17 @@ trait Common { type Arity = Int & Singleton /** - * Define the type of tuples of Arity N. If N=-1, T***N = List[T] (arbitrary arity). + * Type of sequences of length N */ - @showAsInfix - type ***[+T, N <: Arity] <: (Tuple | Seq[T]) & Matchable = N match { - case -1 => Seq[T] - case 0 => EmptyTuple - case _ => T *: (T *** (N - 1)) + opaque type **[+T, N <: Arity] >: Seq[T] = Seq[T] + object ** { + def apply[T, N <: Arity](args: T*): T ** N = args.toSeq + def unapplySeq[T, N <: Arity](arg: T ** N): Option[Seq[T]] = Some(arg) } - /** - * The union of the types of N-tuples and lists. Usually, filling a List for a T**N forfeits arity checking at compile time. - */ - type **[+T, N <: Arity] = Seq[T] | ***[T, N] - extension [T, N <: Arity](self: T ** N) { - @nowarn("msg=checked at runtime") - @nowarn("msg=match may not be exhaustive") - def toSeq: Seq[T] = self match { - case l: Seq[T] => l - case tup: Tuple => - tup.productIterator.toSeq.asInstanceOf[Seq[T]] - } - @nowarn("msg=checked at runtime") - @nowarn("msg=match may not be exhaustive") - def map[U](f: T => U): U ** N = self match { - case l: Seq[T] => l.map(f).asInstanceOf[(U ** (N))] - case tup: Tuple => tup.map[[t] =>> U]([u] => (x: u) => f(x.asInstanceOf[T])).asInstanceOf - } + def toSeq: Seq[T] = self + def map[U](f: T => U): U ** N = self.map(f) } @@ -95,8 +77,8 @@ trait Common { def lift: T & this.type = this /** - * Substitution in the LisaObject of schematics by values. It is not guaranteed by the type system that types of schematics and values match, and the substitution can fail if that is the case. - * This is the substitution that should be implemented. + * Substitution in the LisaObject of schematics symbols by values. It is not guaranteed by the type system that types of schematics and values match, and the substitution can fail if that is the case. + * This is the substitution function that should be implemented. */ def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): T def substituteUnsafe2[A <: SchematicLabel[?], B <: LisaObject[B]](map: Map[A, B]): T = substituteUnsafe(map.asInstanceOf) @@ -133,7 +115,7 @@ trait Common { */ @showAsInfix infix trait |->[-I, +O <: LisaObject[O]] extends LisaObject[I |-> O] { - def apply(arg: I): O + def applyUnsafe(arg: I): O } @@ -179,7 +161,7 @@ trait Common { /** * ConstantLabel represent constants in the theory and can't be freely substituted. */ - sealed trait ConstantLabel[-A <: LisaObject[A]] extends Label[A] with Matchable { + sealed trait ConstantLabel[-A <: LisaObject[A]] extends Label[A] { this: A & LisaObject[A] => def rename(newid: Identifier): ConstantLabel[A] def freshRename(taken: Iterable[Identifier]): ConstantLabel[A] @@ -205,10 +187,9 @@ trait Common { * The type of terms, corresponding to [[K.Term]]. It can be either of a [[Variable]], a [[Constant]] * a [[ConstantFunctionLabel]] or a [[SchematicFunctionLabel]]. */ - sealed trait Term extends TermOrFormula with LisaObject[Term] with (Term ** 0 |-> Term) { - def apply(args: Term ** 0): Term = this + sealed trait Term extends TermOrFormula with LisaObject[Term] { val underlying: K.Term - val label: TermLabel + val label: TermLabel[?] val args: Seq[Term] def toStringSeparated(): String = toString() } @@ -217,13 +198,17 @@ trait Common { * A TermLabel is a [[LisaObject]] of type ((Term ** N) |-> Term), that is represented by a functional label. * It can be either a [[SchematicFunctionLabel]] or a [[ConstantFunctionLabel]]. It corresponds to [[K.TermLabel]] */ - sealed trait TermLabel extends (Seq[Term] |-> Term) with Absolute { + sealed trait TermLabel[A <: (Term | (Seq[Term] |-> Term)) & LisaObject[A]] extends Label[A] with Absolute { + this: A & LisaObject[A] => val arity: Arity def id: Identifier val underlyingLabel: K.TermLabel - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): (Seq[Term] |-> Term) - def rename(newid: Identifier): TermLabel - def freshRename(taken: Iterable[Identifier]): TermLabel + def applySeq(args: Seq[Term]): Term = this match + case l: Variable => l.applyUnsafe(args) + case l: Constant => l.applyUnsafe(args) + case l: FunctionLabel[?] => l.applyUnsafe(args) + def rename(newid: Identifier): TermLabel[A] + def freshRename(taken: Iterable[Identifier]): TermLabel[A] def mkString(args: Seq[Term]): String def mkStringSeparated(args: Seq[Term]): String = mkString(args) } @@ -231,11 +216,12 @@ trait Common { /** * A constant [[TermLabel]], which can be either a [[Constant]] symbol or a [[ConstantFunctionSymbol]]. Corresponds to a [[K.ConstantFunctionLabel]] */ - sealed trait ConstantTermLabel extends TermLabel with ConstantLabel[Seq[Term] |-> Term] { + sealed trait ConstantTermLabel[A <: (Term | (Seq[Term] |-> Term)) & LisaObject[A]] extends TermLabel[A] with ConstantLabel[A] { + this: A & LisaObject[A] => val underlyingLabel: K.ConstantFunctionLabel - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): ConstantTermLabel - override def rename(newid: Identifier): ConstantTermLabel - def freshRename(taken: Iterable[Identifier]): ConstantTermLabel + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): ConstantTermLabel[A] + override def rename(newid: Identifier): ConstantTermLabel[A] + def freshRename(taken: Iterable[Identifier]): ConstantTermLabel[A] } object ConstantTermLabel { @@ -246,7 +232,7 @@ trait Common { * @param arity The arity of the new symbol * @return The new symbol */ - def apply[N <: Arity](id: Identifier, arity: N): ConstantFunctionLabelOfArity[N] = arity match { + def apply[N <: Arity](id: Identifier, arity: N): ConstantTermLabelOfArity[N] = arity match { case a: 0 => Constant(id) case n: N => ConstantFunctionLabel[N](id, arity) } @@ -255,29 +241,18 @@ trait Common { /** * Types of constant term labels: [[Constant]] for if N = 0, [[ConstantFunctionLabel]] otherwise. */ - type ConstantFunctionLabelOfArity[N <: Arity] <: ConstantTermLabel = N match + type ConstantTermLabelOfArity[N <: Arity] <: ConstantTermLabel[?] = N match case 0 => Constant case N => ConstantFunctionLabel[N] - object ConstantFunctionLabelOfArity { - - /** - * Construct a ConstantTermLabel according to arity: - * A [[Constant]] for arity 0, a [[ConstantFunctionLabel]] otherwise. - * @param id The identifier of the new symbol - * @param arity The arity of the new symbol - * @return The new symbol - */ - def apply[N <: Arity](id: Identifier, arity: N): ConstantFunctionLabelOfArity[N] = ConstantTermLabel[N](id, arity) - } /** * A schematic [[TermLabel]], which can be either a [[Variable]] symbol or a [[SchematicFunctionSymbol]]. Corresponds to a [[K.SchematicFunctionLabel]] */ - sealed trait SchematicTermLabel extends TermLabel with SchematicLabel[Seq[Term] |-> Term] { + sealed trait SchematicTermLabel[A <: (Term | (Seq[Term] |-> Term)) & LisaObject[A]] extends TermLabel[A] with SchematicLabel[A] { + this: A & LisaObject[A] => val underlyingLabel: K.SchematicTermLabel - override def rename(newid: Identifier): SchematicTermLabel - def freshRename(taken: Iterable[Identifier]): SchematicTermLabel - def mkString(args: Seq[Term]): String + override def rename(newid: Identifier): SchematicTermLabel[A] + def freshRename(taken: Iterable[Identifier]): SchematicTermLabel[A] } object SchematicTermLabel { // Companion /** @@ -292,34 +267,34 @@ trait Common { case n: N => new SchematicFunctionLabel[N](id, arity) } } - type SchematicFunctionLabelOfArity[N <: Arity] <: SchematicTermLabel = N match + type SchematicFunctionLabelOfArity[N <: Arity] <: SchematicTermLabel[?] = N match case 0 => Variable case N => SchematicFunctionLabel[N] - object SchematicFunctionLabelOfArity { // Companion - /** - * Construct a SchematicTermLabel according to arity: - * A [[Variable]] for arity 0, a [[SchematicFunctionLabel]] otherwise. - * @param id The identifier of the new symbol - * @param arity The arity of the new symbol - * @return The new symbol - */ - def apply[N <: Arity](id: Identifier, arity: N): SchematicFunctionLabelOfArity[N] = SchematicTermLabel[N](id, arity) + + /** + * Can be either a [[ConstantFunctionSymbol]] symbol or a [[SchematicFunctionSymbol]]. Corresponds to a [[K.TermLabel]] + */ + sealed trait FunctionLabel[N <: Arity] extends TermLabel[(Term ** N) |-> Term] with ((Term ** N) |-> Term) { + val underlyingLabel: K.TermLabel + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): (Term ** N) |-> Term + def applyUnsafe(args: (Term ** N)): Term = AppliedFunction(this, args.toSeq) + override def rename(newid: Identifier): FunctionLabel[N] + def freshRename(taken: Iterable[Identifier]): FunctionLabel[N] } /** * A Variable, corresponding to [[K.VariableLabel]], is a schematic symbol for terms. * It counts both as the label and as the term itself. */ - case class Variable(id: Identifier) extends SchematicTermLabel with Term with Absolute with SchematicLabel[Term] { + case class Variable(id: Identifier) extends SchematicTermLabel[Term] with Term with Absolute { val arity: 0 = 0 val label: Variable = this val args: Seq[Nothing] = Seq.empty - override val underlyingLabel: K.VariableLabel = K.VariableLabel(id) - override val underlying = K.VariableTerm(underlyingLabel) - override def apply(args: Term ** 0) = this - @nowarn("msg=Unreachable") - override def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Term = { - map.get(this.asInstanceOf) match { + val underlyingLabel: K.VariableLabel = K.VariableLabel(id) + val underlying = K.VariableTerm(underlyingLabel) + def applyUnsafe(args: Term ** 0) = this + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Term = { + map.get(this) match { case Some(subst) => subst match { case s: Term => s @@ -330,7 +305,7 @@ trait Common { } def freeSchematicLabels: Set[SchematicLabel[?]] = Set(this) def allSchematicLabels: Set[SchematicLabel[?]] = Set(this) - override def rename(newid: Identifier): Variable = Variable(newid) + def rename(newid: Identifier): Variable = Variable(newid) def freshRename(taken: Iterable[Identifier]): Variable = rename(K.freshId(taken, id)) override def toString(): String = id def mkString(args: Seq[Term]): String = if (args.size == 0) toString() else toString() + "(" + "illegal_arguments: " + args.mkString(", ") + ")" @@ -340,18 +315,18 @@ trait Common { * A Constant, corresponding to [[K.ConstantLabel]], is a label for terms. * It counts both as the label and as the term itself. */ - case class Constant(id: Identifier) extends ConstantTermLabel with Term with Absolute with ConstantLabel[Constant] with LisaObject[Constant] { + case class Constant(id: Identifier) extends Term with Absolute with ConstantTermLabel[Constant] with LisaObject[Constant] { val arity: 0 = 0 val label: Constant = this val args: Seq[Nothing] = Seq.empty - override val underlyingLabel: K.ConstantFunctionLabel = K.ConstantFunctionLabel(id, 0) - override val underlying = K.Term(underlyingLabel, Seq()) - override def apply(args: Term ** 0) = this + val underlyingLabel: K.ConstantFunctionLabel = K.ConstantFunctionLabel(id, 0) + val underlying = K.Term(underlyingLabel, Seq.empty) + def applyUnsafe(args: Term ** 0) = this def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Constant = this - override def rename(newid: Identifier): Constant = Constant(newid) - def freshRename(taken: Iterable[Identifier]): Constant = rename(K.freshId(taken, id)) def freeSchematicLabels: Set[SchematicLabel[?]] = Set.empty def allSchematicLabels: Set[SchematicLabel[?]] = Set.empty + def rename(newid: Identifier): Constant = Constant(newid) + def freshRename(taken: Iterable[Identifier]): Constant = rename(K.freshId(taken, id)) override def toString(): String = id def mkString(args: Seq[Term]): String = if (args.size == 0) toString() else toString() + "(" + "illegal_arguments: " + args.mkString(", ") + ")" } @@ -360,16 +335,16 @@ trait Common { * A schematic functional label (corresponding to [[K.SchematicFunctionLabel]]) is a functional label and also a schematic label. * It can be substituted by any expression of type (Term ** N) |-> Term */ - case class SchematicFunctionLabel[N <: Arity](val id: Identifier, val arity: N) extends SchematicTermLabel with SchematicLabel[(Term ** N) |-> Term] with ((Term ** N) |-> Term) { + case class SchematicFunctionLabel[N <: Arity](val id: Identifier, val arity: N) extends SchematicTermLabel[(Term ** N) |-> Term] with FunctionLabel[N] { val underlyingLabel: K.SchematicTermLabel = K.SchematicFunctionLabel(id, arity) - def apply(args: (Term ** N)): Term = AppliedTerm(this, args.toSeq) - def unapplySeq(t: AppliedTerm): Seq[Term] = t match { - case AppliedTerm(label, args) if (label == this) => args + + def unapplySeq(t: AppliedFunction): Seq[Term] = t match { + case AppliedFunction(label, args) if (label == this) => args case _ => Seq.empty } - @nowarn + @nowarn("msg=the type test for.*cannot be checked at runtime because its type arguments") def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): ((Term ** N) |-> Term) = { - map.get(this.asInstanceOf) match { + map.get(this) match { case Some(subst) => subst match { case s: ((Term ** N) |-> Term) => s @@ -390,20 +365,18 @@ trait Common { /** * A constant functional label of arity N. */ - case class ConstantFunctionLabel[N <: Arity](id: Identifier, arity: N) extends ConstantTermLabel with ConstantLabel[((Term ** N) |-> Term)] with ((Term ** N) |-> Term) { + case class ConstantFunctionLabel[N <: Arity](id: Identifier, arity: N) extends ConstantTermLabel[((Term ** N) |-> Term)] with FunctionLabel[N] { val underlyingLabel: K.ConstantFunctionLabel = K.ConstantFunctionLabel(id, arity) - var infix: Boolean = false - def apply(args: (Term ** N)): Term = AppliedTerm(this, args.toSeq) - def unapplySeq(t: AppliedTerm): Seq[Term] = t match { - case AppliedTerm(label, args) if (label == this) => args + private var infix: Boolean = false + def unapplySeq(t: AppliedFunction): Seq[Term] = t match { + case AppliedFunction(label, args) if (label == this) => args case _ => Seq.empty } - inline def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): this.type = - this - def rename(newid: Identifier): ConstantFunctionLabel[N] = ConstantFunctionLabel(newid, arity) - def freshRename(taken: Iterable[Identifier]): ConstantFunctionLabel[N] = rename(K.freshId(taken, id)) + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): ConstantFunctionLabel[N] = this def freeSchematicLabels: Set[SchematicLabel[?]] = Set.empty def allSchematicLabels: Set[SchematicLabel[?]] = Set.empty + def rename(newid: Identifier): ConstantFunctionLabel[N] = ConstantFunctionLabel(newid, arity) + def freshRename(taken: Iterable[Identifier]): ConstantFunctionLabel[N] = rename(K.freshId(taken, id)) override def toString(): String = id def mkString(args: Seq[Term]): String = if (infix) (args(0).toString() + " " + toString() + " " + args(1).toString()) else toString() + "(" + args.mkString(", ") + ")" override def mkStringSeparated(args: Seq[Term]): String = if (infix) "(" + mkString(args) + ")" else mkString(args) @@ -418,19 +391,15 @@ trait Common { /** * A term made from a functional label of arity N and N arguments */ - case class AppliedTerm(f: TermLabel, args: Seq[Term]) extends Term with Absolute { - val label: TermLabel = f - assert(f.arity != 0) - override val underlying = K.Term(f.underlyingLabel, args.map(_.underlying)) - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Term = { - f.substituteUnsafe(map)( - args.map[Term]((x: Term) => x.substituteUnsafe(map)) - ) - } - def freeSchematicLabels: Set[SchematicLabel[?]] = f.freeSchematicLabels ++ args.flatMap(_.freeSchematicLabels) - def allSchematicLabels: Set[SchematicLabel[?]] = f.allSchematicLabels ++ args.flatMap(_.allSchematicLabels) - override def toString: String = f.mkString(args) - override def toStringSeparated(): String = f.mkString(args) + case class AppliedFunction(label: FunctionLabel[?], args: Seq[Term]) extends Term with Absolute { + override val underlying = K.Term(label.underlyingLabel, args.map(_.underlying)) + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Term = + label.substituteUnsafe(map).applyUnsafe(args.map[Term]((x: Term) => x.substituteUnsafe(map))) + + def freeSchematicLabels: Set[SchematicLabel[?]] = label.freeSchematicLabels ++ args.flatMap(_.freeSchematicLabels) + def allSchematicLabels: Set[SchematicLabel[?]] = label.allSchematicLabels ++ args.flatMap(_.allSchematicLabels) + override def toString: String = label.mkString(args) + override def toStringSeparated(): String = label.mkString(args) } ////////////////////////////////////// @@ -440,11 +409,7 @@ trait Common { /** * The type of formulas, corresponding to [[K.Formula]] */ - sealed trait Formula extends TermOrFormula with LisaObject[Formula] with ((Term ** 0) |-> Formula) { - val arity: Arity = 0 - // val label:PredicateLabel|ConnectorLabel - // val args:Seq[Term]|Seq[Formula] - def apply(args: Term ** 0): Formula = this + sealed trait Formula extends TermOrFormula with LisaObject[Formula] { val underlying: K.Formula def toStringSeparated() = toString() } @@ -454,61 +419,119 @@ trait Common { ///////////////////// sealed trait AtomicFormula extends Formula { - val label: PredicateLabel + val label: AtomicLabel[?] val args: Seq[Term] } /** - * A PredicateLabel is a [[LisaObject]] of type ((Term ** N) |-> Formula), that is represented by a predicate label. + * A AtomicLabel is a [[LisaObject]] of type ((Term ** N) |-> Formula), that is represented by a predicate label. * It can be either a [[SchematicPredicateLabel]] or a [[ConstantPredicateLabel]]. */ - sealed trait PredicateLabel extends (Seq[Term] |-> Formula) with Absolute { + sealed trait AtomicLabel[A <: (Formula | (Seq[Term] |-> Formula)) & LisaObject[A]] extends Label[A] with Absolute { + this: A & LisaObject[A] => val arity: Arity def id: Identifier - val underlyingLabel: K.PredicateLabel - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): (Seq[Term] |-> Formula) - def rename(newid: Identifier): PredicateLabel - def freshRename(taken: Iterable[Identifier]): PredicateLabel + val underlyingLabel: K.AtomicLabel + def applySeq(args: Seq[Term]): Formula = this match + case l: VariableFormula => l.applyUnsafe(args) + case l: ConstantFormula => l.applyUnsafe(args) + case l: PredicateLabel[?] => l.applyUnsafe(args) + + def rename(newid: Identifier): AtomicLabel[A] + def freshRename(taken: Iterable[Identifier]): AtomicLabel[A] def mkString(args: Seq[Term]): String def mkStringSeparated(args: Seq[Term]): String = mkString(args) } - sealed trait ConstantConstOrPredLabel extends PredicateLabel with ConstantLabel[Seq[Term] |-> Formula] { - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): ConstantConstOrPredLabel - override def rename(newid: Identifier): ConstantConstOrPredLabel - def freshRename(taken: Iterable[Identifier]): ConstantConstOrPredLabel + /** + * A constant [[AtomicLabel]], which can be either a [[ConstantFormula]] symbol or a [[ConstantPredicateSymbol]]. Corresponds to a [[K.ConstantAtomicLabel]] + */ + sealed trait ConstantAtomicLabel[A <: (Formula | (Seq[Term] |-> Formula)) & LisaObject[A]] extends AtomicLabel[A] with ConstantLabel[A] { + this: A & LisaObject[A] => + val underlyingLabel: K.ConstantAtomicLabel + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): ConstantAtomicLabel[A] + override def rename(newid: Identifier): ConstantAtomicLabel[A] + def freshRename(taken: Iterable[Identifier]): ConstantAtomicLabel[A] + } + object ConstantAtomicLabel { + + /** + * Construct a ConstantTermLabel according to arity: + * A [[Constant]] for arity 0, a [[ConstantFunctionLabel]] otherwise. + * @param id The identifier of the new symbol + * @param arity The arity of the new symbol + * @return The new symbol + */ + def apply[N <: Arity](id: Identifier, arity: N): ConstantAtomicLabelOfArity[N] = arity match { + case a: 0 => ConstantFormula(id) + case n: N => ConstantPredicateLabel[N](id, arity) + } } - type ConstantPredicateLabelOfArity[N <: Arity] <: ConstantConstOrPredLabel = N match { + + /** + * Types of constant atomic labels: [[ConstantFormula]] for if N = 0, [[ConstantPredicateLabel]] otherwise. + */ + type ConstantAtomicLabelOfArity[N <: Arity] <: ConstantAtomicLabel[?] = N match { case 0 => ConstantFormula case N => ConstantPredicateLabel[N] } - sealed trait SchematicVarOrPredLabel extends PredicateLabel with SchematicLabel[Seq[Term] |-> Formula] { - override def rename(newid: Identifier): SchematicVarOrPredLabel - def freshRename(taken: Iterable[Identifier]): SchematicVarOrPredLabel + /** + * A schematic [[AtomicLabel]], which can be either a [[VariableFormula]] symbol or a [[SchematicPredicateLabel]]. Corresponds to a [[K.SchematicAtomicLabel]] + */ + sealed trait SchematicAtomicLabel[A <: (Formula | (Seq[Term] |-> Formula)) & LisaObject[A]] extends AtomicLabel[A] with SchematicLabel[A] { + this: A & LisaObject[A] => + override def rename(newid: Identifier): SchematicAtomicLabel[A] + def freshRename(taken: Iterable[Identifier]): SchematicAtomicLabel[A] + } - type SchematicPredicateLabelOfArity[N <: Arity] <: SchematicVarOrPredLabel = N match { + object SchematicAtomicLabel { // Companion + /** + * Construct a SchematicTermLabel according to arity: + * A [[Variable]] for arity 0, a [[SchematicFunctionLabel]] otherwise. + * @param id The identifier of the new symbol + * @param arity The arity of the new symbol + * @return The new symbol + */ + def apply[N <: Arity](id: Identifier, arity: N): SchematicAtomicLabelOfArity[N] = arity match { + case a: 0 => new VariableFormula(id) + case n: N => new SchematicPredicateLabel[N](id, arity) + } + } + + type SchematicAtomicLabelOfArity[N <: Arity] <: SchematicAtomicLabel[?] = N match { case 0 => VariableFormula case N => SchematicPredicateLabel[N] } + /** + * Can be either a [[ConstantFunctionSymbol]] symbol or a [[SchematicFunctionSymbol]]. Corresponds to a [[K.TermLabel]] + */ + sealed trait PredicateLabel[N <: Arity] extends AtomicLabel[(Term ** N) |-> Formula] with ((Term ** N) |-> Formula) with Absolute { + val underlyingLabel: K.AtomicLabel + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): (Term ** N) |-> Formula + def applyUnsafe(args: (Term ** N)): Formula = AppliedPredicate(this, args.toSeq) + override def rename(newid: Identifier): PredicateLabel[N] + def freshRename(taken: Iterable[Identifier]): PredicateLabel[N] + } + /** * A Variable for formulas, corresponding to [[K.VariableFormulaLabel]], is a schematic symbol for formulas. * It counts both as the label and as the term itself. */ - case class VariableFormula(id: Identifier) extends SchematicVarOrPredLabel with AtomicFormula with Absolute with SchematicLabel[Formula] { + case class VariableFormula(id: Identifier) extends SchematicAtomicLabel[Formula] with AtomicFormula with Absolute { override val arity: 0 = 0 val label: VariableFormula = this - val args: Seq[Nothing] = Seq() + val args: Seq[Nothing] = Seq.empty val underlyingLabel: K.VariableFormulaLabel = K.VariableFormulaLabel(id) - val underlying = K.PredicateFormula(underlyingLabel, Seq()) - override def apply(args: Term ** 0): Formula = this - @nowarn("msg=Unreachable") + val underlying = K.AtomicFormula(underlyingLabel, Seq.empty) + def applyUnsafe(args: Term ** 0): Formula = this def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Formula = { - map.get(this.asInstanceOf) match { + map.get(this) match { case Some(subst) => subst match { case s: Formula => s + case _ => throw SubstitutionException() } case None => this } @@ -525,14 +548,14 @@ trait Common { * A Constant formula, corresponding to [[K.ConstantFormulaLabel]]. * It counts both as the label and as the formula itself. Usually either True or False. */ - case class ConstantFormula(id: Identifier) extends ConstantConstOrPredLabel with AtomicFormula with Absolute with ConstantLabel[Formula] { + case class ConstantFormula(id: Identifier) extends ConstantAtomicLabel[Formula] with AtomicFormula with Absolute with ConstantLabel[Formula] { override val arity: 0 = 0 val label: ConstantFormula = this - val args: Seq[Nothing] = Seq() - val underlyingLabel: K.ConstantPredicateLabel = K.ConstantPredicateLabel(id, 0) - val underlying = K.PredicateFormula(underlyingLabel, Seq()) - override def apply(args: Term ** 0): Formula = this - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): this.type = this + val args: Seq[Nothing] = Seq.empty + val underlyingLabel: K.ConstantAtomicLabel = K.ConstantAtomicLabel(id, 0) + val underlying = K.AtomicFormula(underlyingLabel, Seq.empty) + def applyUnsafe(args: Term ** 0): Formula = this + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): ConstantFormula = this def freeSchematicLabels: Set[SchematicLabel[?]] = Set.empty def allSchematicLabels: Set[SchematicLabel[?]] = Set.empty def rename(newid: Identifier): ConstantFormula = ConstantFormula(newid) @@ -542,22 +565,22 @@ trait Common { } /** - * A schematic predicate label (corresponding to [[K.SchematicPredicateLabel]]) is a [[PredicateLabel]] and also a [[SchematicLabel]]. + * A schematic predicate label (corresponding to [[K.SchematicPredicateLabel]]) is a [[AtomicLabel]] and also a [[SchematicLabel]]. * It can be substituted by any expression of type (Term ** N) |-> Formula */ - case class SchematicPredicateLabel[N <: Arity](id: Identifier, arity: N) extends SchematicVarOrPredLabel with SchematicLabel[(Term ** N) |-> Formula] with ((Term ** N) |-> Formula) { + case class SchematicPredicateLabel[N <: Arity](id: Identifier, arity: N) extends SchematicAtomicLabel[(Term ** N) |-> Formula] with PredicateLabel[N] { val underlyingLabel: K.SchematicPredicateLabel = K.SchematicPredicateLabel(id, arity) - def apply(args: (Term ** N)): Formula = PredicateFormula(this, args.toSeq) - def unapplySeq(t: AppliedTerm): Seq[Term] = t match { - case AppliedTerm(label, args) if (label == this) => args + def unapplySeq(t: AppliedFunction): Seq[Term] = t match { + case AppliedFunction(label, args) if (label == this) => args case _ => Seq.empty } - @nowarn + @nowarn("msg=the type test for.*cannot be checked at runtime because its type arguments") def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): |->[Term ** N, Formula] = { - map.get(this.asInstanceOf) match { + map.get(this) match { case Some(subst) => subst match { case s: |->[Term ** N, Formula] => s + case _ => throw SubstitutionException() } case None => this } @@ -569,21 +592,19 @@ trait Common { override def toString(): String = id def mkString(args: Seq[Term]): String = toString() + "(" + args.mkString(", ") + ")" override def mkStringSeparated(args: Seq[Term]): String = mkString(args) - } /** - * A constant predicate label corresponding to [[K.ConstantPredicateLabel]]. + * A constant predicate label corresponding to [[K.ConstantAtomicLabel]] of arity >= 1. */ - case class ConstantPredicateLabel[N <: Arity](id: Identifier, arity: N) extends ConstantConstOrPredLabel with ConstantLabel[Term ** N |-> Formula] with ((Term ** N) |-> Formula) { - val underlyingLabel: K.ConstantPredicateLabel = K.ConstantPredicateLabel(id, arity) + case class ConstantPredicateLabel[N <: Arity](id: Identifier, arity: N) extends ConstantAtomicLabel[Term ** N |-> Formula] with PredicateLabel[N] { + val underlyingLabel: K.ConstantAtomicLabel = K.ConstantAtomicLabel(id, arity) private var infix = false - def apply(args: (Term ** N)): Formula = PredicateFormula(this, args.toSeq) - def unapplySeq(f: PredicateFormula): Seq[Term] = f match { - case PredicateFormula(label, args) if (label == this) => args + def unapplySeq(f: AppliedPredicate): Seq[Term] = f match { + case AppliedPredicate(label, args) if (label == this) => args case _ => Seq.empty } - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): this.type = this + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): ConstantPredicateLabel[N] = this def freeSchematicLabels: Set[SchematicLabel[?]] = Set.empty def allSchematicLabels: Set[SchematicLabel[?]] = Set.empty def rename(newid: Identifier): ConstantPredicateLabel[N] = ConstantPredicateLabel(newid, arity) @@ -602,18 +623,16 @@ trait Common { /** * A formula made from a predicate label of arity N and N arguments */ - case class PredicateFormula(p: PredicateLabel, args: Seq[Term]) extends AtomicFormula with Absolute { - assert(p.arity != 0) - val label: PredicateLabel = p - override val underlying = K.PredicateFormula(p.underlyingLabel, args.map(_.underlying)) + case class AppliedPredicate(label: PredicateLabel[?], args: Seq[Term]) extends AtomicFormula with Absolute { + override val underlying = K.AtomicFormula(label.underlyingLabel, args.map(_.underlying)) def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Formula = - p.substituteUnsafe(map)(args.map[Term]((x: Term) => x.substituteUnsafe(map))) + label.substituteUnsafe(map).applyUnsafe(args.map[Term]((x: Term) => x.substituteUnsafe(map))) - def freeSchematicLabels: Set[SchematicLabel[?]] = p.freeSchematicLabels ++ args.toSeq.flatMap(_.freeSchematicLabels) - def allSchematicLabels: Set[SchematicLabel[?]] = p.allSchematicLabels ++ args.toSeq.flatMap(_.allSchematicLabels) + def freeSchematicLabels: Set[SchematicLabel[?]] = label.freeSchematicLabels ++ args.toSeq.flatMap(_.freeSchematicLabels) + def allSchematicLabels: Set[SchematicLabel[?]] = label.allSchematicLabels ++ args.toSeq.flatMap(_.allSchematicLabels) - override def toString: String = p.mkString(args) - override def toStringSeparated(): String = p.mkString(args) + override def toString: String = label.mkString(args) + override def toStringSeparated(): String = label.mkString(args) } //////////////// @@ -624,15 +643,16 @@ trait Common { * A ConnectorLabel is a [[LisaObject]] of type ((Formula ** N) |-> Formula), that is represented by a connector label in the kernel. * It can be either a [[SchematicConnectorLabel]] or a [[ConstantConnectorLabel]]. */ - sealed trait ConnectorLabel extends (Seq[Formula] |-> Formula) with Absolute { + sealed trait ConnectorLabel extends (Seq[Formula] |-> Formula) with Label[(Seq[Formula] |-> Formula)] with Absolute { val arity: Arity def id: Identifier val underlyingLabel: K.ConnectorLabel + def applySeq(args: Seq[Formula]): Formula = applyUnsafe(args) def rename(newid: Identifier): ConnectorLabel def freshRename(taken: Iterable[Identifier]): ConnectorLabel def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): |->[Seq[Formula], Formula] def mkString(args: Seq[Formula]): String - def mkStringSeparated(args: Seq[Formula]): String = mkString(args) + def mkStringSeparated(args: Seq[Formula]): String } @@ -642,28 +662,31 @@ trait Common { */ case class SchematicConnectorLabel[N <: Arity](id: Identifier, arity: N) extends ConnectorLabel with SchematicLabel[Formula ** N |-> Formula] with ((Formula ** N) |-> Formula) { val underlyingLabel: K.SchematicConnectorLabel = K.SchematicConnectorLabel(id, arity) - @nowarn + def unapplySeq(f: AppliedPredicate): Seq[Term] = f match { + case AppliedPredicate(label, args) if (label == this) => args + case _ => Seq.empty + } + @nowarn("msg=the type test for.*cannot be checked at runtime because its type arguments") def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): |->[Formula ** N, Formula] = { - map.get(this.asInstanceOf) match { + map.get(this) match { case Some(subst) => subst match { case s: |->[Formula ** N, Formula] => s + case _ => throw SubstitutionException() } case None => this } } // def apply(args: Seq[Formula]): Formula = apply(args) - def apply(args: Formula ** N): Formula = ConnectorFormula(this, args.toSeq) - def unapplySeq(f: PredicateFormula): Seq[Term] = f match { - case PredicateFormula(label, args) if (label == this) => args - case _ => Seq.empty - } + def applyUnsafe(args: Formula ** N): Formula = AppliedConnector(this, args.toSeq) + def freeSchematicLabels: Set[SchematicLabel[?]] = Set(this) def allSchematicLabels: Set[SchematicLabel[?]] = Set(this) def rename(newid: Identifier): SchematicConnectorLabel[N] = SchematicConnectorLabel(newid, arity) def freshRename(taken: Iterable[Identifier]): SchematicConnectorLabel[N] = rename(K.freshId(taken, id)) override def toString(): String = id def mkString(args: Seq[Formula]): String = toString() + "(" + args.mkString(", ") + ")" + def mkStringSeparated(args: Seq[Formula]): String = mkString(args) } @@ -674,18 +697,18 @@ trait Common { trait ConstantConnectorLabel[N <: Arity] extends ConnectorLabel with ConstantLabel[Formula ** N |-> Formula] with ((Formula ** N) |-> Formula) { val underlyingLabel: K.ConstantConnectorLabel def id: Identifier = underlyingLabel.id - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): this.type = this - def apply(args: Formula ** N): Formula = ConnectorFormula(this, args.toSeq) - def unapplySeq(f: ConnectorFormula): Seq[Formula] = f match { - case ConnectorFormula(label, args) if (label == this) => args + def unapplySeq(f: AppliedConnector): Seq[Formula] = f match { + case AppliedConnector(label, args) if (label == this) => args case _ => Seq.empty } + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): this.type = this + def applyUnsafe(args: Formula ** N): Formula = AppliedConnector(this, args.toSeq) def freeSchematicLabels: Set[SchematicLabel[?]] = Set.empty def allSchematicLabels: Set[SchematicLabel[?]] = Set.empty def rename(newid: Identifier): ConstantConnectorLabel[N] = throw new Error("Can't rename a constant connector label") def freshRename(taken: Iterable[Identifier]): ConstantConnectorLabel[N] = rename(K.freshId(taken, id)) override def toString(): String = id - def mkString(args: Seq[Formula]): String = if (args.length == 2) ("(" + args(0).toString() + " " + toString() + " " + args(1).toString()) + ")" else toString() + "(" + args.mkString(", ") + ")" + def mkString(args: Seq[Formula]): String = if (args.length == 2) (args(0).toString() + " " + toString() + " " + args(1).toString()) else toString() + "(" + args.mkString(", ") + ")" override def mkStringSeparated(args: Seq[Formula]): String = if (args.length == 2) "(" + mkString(args) + ")" else mkString(args) } @@ -693,24 +716,16 @@ trait Common { /** * A formula made from a connector label of arity N and N arguments */ - case class ConnectorFormula(p: ConnectorLabel, args: Seq[Formula]) extends Formula with Absolute { - // assert(args.length == p.arity) - val label: ConnectorLabel = p - override val underlying = K.ConnectorFormula(p.underlyingLabel, args.map(_.underlying)) - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Formula = { - val p2 = p.substituteUnsafe(map) - p2 match { - case p2: ConnectorLabel => ConnectorFormula(p2, args.map[Formula]((x: Formula) => x.substituteUnsafe(map))) - case _ => p2(args.map[Formula]((x: Formula) => x.substituteUnsafe(map))) - } - } - - def freeSchematicLabels: Set[SchematicLabel[?]] = p.freeSchematicLabels ++ args.flatMap(_.freeSchematicLabels) - def allSchematicLabels: Set[SchematicLabel[?]] = p.allSchematicLabels ++ args.flatMap(_.allSchematicLabels) - // override def substituteUnsafe(v: Variable, subs: Term) = PredicateFormulaFormula[N](f, args.map(_.substituteUnsafe(v, subs))) + case class AppliedConnector(label: ConnectorLabel, args: Seq[Formula]) extends Formula with Absolute { + override val underlying = K.ConnectorFormula(label.underlyingLabel, args.map(_.underlying)) + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Formula = + label.applyUnsafe(args.map[Formula]((x: Formula) => x.substituteUnsafe(map))) + def freeSchematicLabels: Set[SchematicLabel[?]] = label.freeSchematicLabels ++ args.flatMap(_.freeSchematicLabels) + def allSchematicLabels: Set[SchematicLabel[?]] = label.allSchematicLabels ++ args.flatMap(_.allSchematicLabels) + // override def substituteUnsafe(v: Variable, subs: Term) = AppliedPredicateFormula[N](f, args.map(_.substituteUnsafe(v, subs))) - override def toString: String = p.mkString(args) - override def toStringSeparated(): String = p.mkString(args) + override def toString: String = label.mkString(args) + override def toStringSeparated(): String = label.mkString(args) } ///////////// @@ -727,10 +742,11 @@ trait Common { /** * A binder label that exactly correspond to a kernel binder, i.e. \exists, \forall and \exists! */ - trait BaseBinderLabel extends BinderLabel with Absolute { + trait BaseBinderLabel extends BinderLabel with ((Variable, Formula) |-> BinderFormula) with Absolute { val underlyingLabel: K.BinderLabel - def apply(arg: (Variable, Formula)): BinderFormula = BinderFormula(this, arg._1, arg._2) + def applyUnsafe(arg: (Variable, Formula)): BinderFormula = BinderFormula(this, arg._1, arg._2) + def apply(v: Variable, f: Formula): BinderFormula = applyUnsafe((v, f)) inline def freeSchematicLabels: Set[SchematicLabel[?]] = Set.empty inline def allSchematicLabels: Set[SchematicLabel[?]] = Set.empty inline def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): this.type = this @@ -741,13 +757,13 @@ trait Common { /** * A quantified formula made of a [[BaseBinderLabel]] and an underlying formula, in a namefull representation. */ - case class BinderFormula(f: BaseBinderLabel, bound: Variable, body: Formula) extends Formula with Absolute { + case class BinderFormula(f: BaseBinderLabel, bound: Variable, body: Formula) extends Absolute with Formula with LisaObject[BinderFormula] { override val underlying = K.BinderFormula(f.underlyingLabel, bound.underlyingLabel, body.underlying) def allSchematicLabels: Set[Common.this.SchematicLabel[?]] = body.allSchematicLabels + bound def freeSchematicLabels: Set[Common.this.SchematicLabel[?]] = body.freeSchematicLabels - bound - def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): Formula = { - val newSubst = map - bound.asInstanceOf + def substituteUnsafe(map: Map[SchematicLabel[_], LisaObject[_]]): BinderFormula = { + val newSubst = map - bound if (map.values.flatMap(_.freeSchematicLabels).toSet.contains(bound)) { val taken: Set[SchematicLabel[?]] = body.allSchematicLabels ++ map.keys val newBound: Variable = bound.rename(lisa.utils.KernelHelpers.freshId(taken.map(_.id), bound.id)) @@ -763,4 +779,29 @@ trait Common { } def instantiateBinder(f: BinderFormula, t: Term): Formula = f.body.substituteUnsafe(Map(f.bound -> t)) + // Application methods for |-> + + extension [S, T <: LisaObject[T]](t: (S ** -1) |-> T) { + def apply(s: Seq[S]): T = t.applyUnsafe(s) + } + extension [S, T <: LisaObject[T], N <: Arity](t: (S ** N) |-> T) { + def applySeq(s: Seq[S]): T = t.applyUnsafe(s) + } + + extension [S, T <: LisaObject[T]](t: (S ** 1) |-> T) { + def apply(s1: S): T = t.applyUnsafe(Seq(s1)) + } + extension [S, T <: LisaObject[T]](t: (S ** 2) |-> T) { + def apply(s1: S, s2: S): T = t.applyUnsafe(Seq(s1, s2)) + } + extension [S <: LisaObject[S], T <: LisaObject[T]](t: (S ** 3) |-> T) { + def apply(s1: S, s2: S, s3: S): T = t.applyUnsafe(Seq(s1, s2, s3)) + } + extension [S <: LisaObject[S], T <: LisaObject[T]](t: (S ** 4) |-> T) { + def apply(s1: S, s2: S, s3: S, s4: S): T = t.applyUnsafe(Seq(s1, s2, s3, s4)) + } + extension [S <: LisaObject[S], T <: LisaObject[T]](t: (S ** 5) |-> T) { + def apply(s1: S, s2: S, s3: S, s4: S, s5: S): T = t.applyUnsafe(Seq(s1, s2, s3, s4, s5)) + } + } diff --git a/lisa-utils/src/main/scala/lisa/fol/FOLHelpers.scala b/lisa-utils/src/main/scala/lisa/fol/FOLHelpers.scala index e4039adf..576a279c 100644 --- a/lisa-utils/src/main/scala/lisa/fol/FOLHelpers.scala +++ b/lisa-utils/src/main/scala/lisa/fol/FOLHelpers.scala @@ -6,9 +6,6 @@ import lisa.utils.FOLParser import lisa.utils.K import lisa.utils.LisaException -import scala.annotation.targetName -import scala.reflect.ClassTag - /** * A helper file that provides various syntactic sugars for LISA's FOL and proofs. Best imported through utilities.Helpers * Usage: @@ -36,7 +33,7 @@ object FOLHelpers { LambdaExpression(s, a._2, s.length.asInstanceOf) } - given [T <: LisaObject[T]]: Conversion[T, T *** 1] = _ *: EmptyTuple + given [T <: LisaObject[T]]: Conversion[T, T ** 1] = **.apply[T, 1](_) given Conversion[Int, Arity] = _.asInstanceOf @@ -58,13 +55,13 @@ object FOLHelpers { //////////////////////////////////////// // TermLabel - def asFrontLabel(tl: K.TermLabel): TermLabel = tl match + def asFrontLabel(tl: K.TermLabel): TermLabel[?] = tl match case tl: K.ConstantFunctionLabel => asFrontLabel(tl) case tl: K.SchematicTermLabel => asFrontLabel(tl) - def asFrontLabel[N <: Arity](cfl: K.ConstantFunctionLabel): ConstantFunctionLabelOfArity[N] = cfl.arity.asInstanceOf[N] match + def asFrontLabel[N <: Arity](cfl: K.ConstantFunctionLabel): ConstantTermLabelOfArity[N] = cfl.arity.asInstanceOf[N] match case n: 0 => Constant(cfl.id) case n: N => ConstantFunctionLabel[N](cfl.id, n) - def asFrontLabel(stl: K.SchematicTermLabel): SchematicTermLabel = stl match + def asFrontLabel(stl: K.SchematicTermLabel): SchematicTermLabel[?] = stl match case v: K.VariableLabel => asFrontLabel(v) case v: K.SchematicFunctionLabel => asFrontLabel(v) def asFrontLabel[N <: Arity](sfl: K.SchematicFunctionLabel): SchematicFunctionLabel[N] = @@ -72,28 +69,28 @@ object FOLHelpers { def asFrontLabel(v: K.VariableLabel): Variable = Variable(v.id) // Term - def asFront(t: K.Term): Term = asFrontLabel(t.label)(t.args.map(asFront)) + def asFront(t: K.Term): Term = asFrontLabel(t.label).applySeq(t.args.map(asFront)) // FormulaLabel - def asFrontLabel(fl: K.FormulaLabel): PredicateLabel | ConnectorLabel | BinderLabel = fl match + def asFrontLabel(fl: K.FormulaLabel): AtomicLabel[?] | ConnectorLabel | BinderLabel = fl match case fl: K.ConnectorLabel => asFrontLabel(fl) - case fl: K.PredicateLabel => asFrontLabel(fl) + case fl: K.AtomicLabel => asFrontLabel(fl) case fl: K.BinderLabel => asFrontLabel(fl) - def asFrontLabel(pl: K.PredicateLabel): PredicateLabel = pl match - case pl: K.ConstantPredicateLabel => asFrontLabel(pl) - case pl: K.SchematicVarOrPredLabel => asFrontLabel(pl) + def asFrontLabel(pl: K.AtomicLabel): AtomicLabel[?] = pl match + case pl: K.ConstantAtomicLabel => asFrontLabel(pl) + case pl: K.SchematicAtomicLabel => asFrontLabel(pl) def asFrontLabel(cl: K.ConnectorLabel): ConnectorLabel = cl match case cl: K.ConstantConnectorLabel => asFrontLabel(cl) case cl: K.SchematicConnectorLabel => asFrontLabel(cl) - def asFrontLabel[N <: Arity](cpl: K.ConstantPredicateLabel): ConstantPredicateLabelOfArity[N] = cpl.arity.asInstanceOf[N] match + def asFrontLabel[N <: Arity](cpl: K.ConstantAtomicLabel): ConstantAtomicLabelOfArity[N] = cpl.arity.asInstanceOf[N] match case n: 0 => ConstantFormula(cpl.id) case n: N => ConstantPredicateLabel(cpl.id, cpl.arity.asInstanceOf) - def asFrontLabel(sfl: K.SchematicFormulaLabel): SchematicVarOrPredLabel | SchematicConnectorLabel[?] = + def asFrontLabel(sfl: K.SchematicFormulaLabel): SchematicAtomicLabel[?] | SchematicConnectorLabel[?] = sfl match case v: K.VariableFormulaLabel => asFrontLabel(v) case v: K.SchematicPredicateLabel => asFrontLabel(v) case v: K.SchematicConnectorLabel => asFrontLabel(v) - def asFrontLabel(svop: K.SchematicVarOrPredLabel): SchematicVarOrPredLabel = svop match + def asFrontLabel(svop: K.SchematicAtomicLabel): SchematicAtomicLabel[?] = svop match case v: K.VariableFormulaLabel => asFrontLabel(v) case v: K.SchematicPredicateLabel => asFrontLabel(v) def asFrontLabel(v: K.VariableFormulaLabel): VariableFormula = VariableFormula(v.id) @@ -115,15 +112,15 @@ object FOLHelpers { // Formula def asFront(f: K.Formula): Formula = f match - case f: K.PredicateFormula => asFront(f) + case f: K.AtomicFormula => asFront(f) case f: K.ConnectorFormula => asFront(f) case f: K.BinderFormula => asFront(f) - def asFront(pf: K.PredicateFormula): Formula = - asFrontLabel(pf.label)(pf.args.map(asFront)) + def asFront(pf: K.AtomicFormula): Formula = + asFrontLabel(pf.label).applySeq(pf.args.map(asFront)) def asFront(cf: K.ConnectorFormula): Formula = - asFrontLabel(cf.label)(cf.args.map(asFront)) + asFrontLabel(cf.label).applyUnsafe(cf.args.map(asFront)) def asFront(bf: K.BinderFormula): BinderFormula = - asFrontLabel(bf.label)(asFrontLabel(bf.bound), asFront(bf.inner)) + asFrontLabel(bf.label).apply(asFrontLabel(bf.bound), asFront(bf.inner)) // Sequents def asFront(s: K.Sequent): Sequent = Sequent(s.left.map(asFront), s.right.map(asFront)) diff --git a/lisa-utils/src/main/scala/lisa/fol/Lambdas.scala b/lisa-utils/src/main/scala/lisa/fol/Lambdas.scala index 2f20405a..2bc2a984 100644 --- a/lisa-utils/src/main/scala/lisa/fol/Lambdas.scala +++ b/lisa-utils/src/main/scala/lisa/fol/Lambdas.scala @@ -23,7 +23,7 @@ trait Lambdas extends Common { assert(arity == bounds.length) private val seqBounds = bounds.toSeq - def apply(args: T ** N): R = body.substituteUnsafe((bounds zip args.toSeq).toMap) + def applyUnsafe(args: T ** N): R = body.substituteUnsafe((bounds zip args.toSeq).toMap) def appUnsafe(args: Seq[T]): R = body.substituteUnsafe((bounds zip args.toSeq).toMap) /** @@ -61,11 +61,11 @@ trait Lambdas extends Common { * Construct a Lambda expression with multiple variables */ def lambda[T <: LisaObject[T], R <: LisaObject[R], N <: Arity, Tu <: Tuple](bounds: Tu, body: R)(using Tuple.Union[Tu] <:< SchematicLabel[T], Tuple.Size[Tu] =:= N): LambdaExpression[T, R, N] = { - val boundsSeq = bounds.asInstanceOf[SchematicLabel[T] *** N].toSeq - LambdaExpression[T, R, N](boundsSeq, body, boundsSeq.length.asInstanceOf) + val boundsSeq = bounds.toList + LambdaExpression[T, R, N](boundsSeq.asInstanceOf, body, boundsSeq.length.asInstanceOf) } def lambda[T <: LisaObject[T], R <: LisaObject[R]](bounds: Seq[SchematicLabel[T]], body: R): LambdaExpression[T, R, ?] = { - val boundsSeq = bounds.toSeq + val boundsSeq = bounds LambdaExpression(boundsSeq, body, boundsSeq.length.asInstanceOf) } diff --git a/lisa-utils/src/main/scala/lisa/fol/Predef.scala b/lisa-utils/src/main/scala/lisa/fol/Predef.scala index 4d280b38..c5cd8d3a 100644 --- a/lisa-utils/src/main/scala/lisa/fol/Predef.scala +++ b/lisa-utils/src/main/scala/lisa/fol/Predef.scala @@ -66,7 +66,7 @@ trait Predef extends Common { val ∃! : ExistsOne.type = existsOne extension (f: Formula) { - def unary_! = Neg(f *: EmptyTuple) + def unary_! = Neg(f) infix inline def ==>(g: Formula): Formula = Implies(f, g) infix inline def <=>(g: Formula): Formula = Iff(f, g) infix inline def /\(g: Formula): Formula = And(List(f, g)) diff --git a/lisa-utils/src/main/scala/lisa/fol/Sequents.scala b/lisa-utils/src/main/scala/lisa/fol/Sequents.scala index 31c62f3c..8209575d 100644 --- a/lisa-utils/src/main/scala/lisa/fol/Sequents.scala +++ b/lisa-utils/src/main/scala/lisa/fol/Sequents.scala @@ -40,9 +40,9 @@ trait Sequents extends Common with lisa.fol.Lambdas { p._2 match { case l: LambdaExpression[Term, Term, ?] @unchecked if (l.bounds.isEmpty || l.bounds.head.isInstanceOf[Variable]) & l.body.isInstanceOf[Term] => (p._1.asInstanceOf, l) - case s: TermLabel => + case s: TermLabel[?] => val vars = nFreshId(Seq(s.id), s.arity).map(id => Variable(id)) - (sl, LambdaExpression(vars, s(vars), s.arity)) + (sl, LambdaExpression(vars, s.applySeq(vars), s.arity)) } } ) @@ -53,9 +53,9 @@ trait Sequents extends Common with lisa.fol.Lambdas { case sl: SchematicPredicateLabel[?] => p._2 match { case l: LambdaExpression[Term, Formula, ?] @unchecked if (l.bounds.isEmpty || l.bounds.head.isInstanceOf[Variable]) & l.body.isInstanceOf[Formula] => (sl, l) - case s: PredicateLabel => + case s: AtomicLabel[?] => val vars = nFreshId(Seq(s.id), s.arity).map(id => Variable(id)) - (sl, LambdaExpression(vars, s(vars), s.arity)) + (sl, LambdaExpression(vars, s.applySeq(vars), s.arity)) } } ) @@ -66,7 +66,7 @@ trait Sequents extends Common with lisa.fol.Lambdas { case l: LambdaExpression[Formula, Formula, ?] @unchecked if (l.bounds.isEmpty || l.bounds.head.isInstanceOf[VariableFormula]) & l.body.isInstanceOf[Formula] => (sl, l) case s: ConnectorLabel => val vars = nFreshId(Seq(s.id), s.arity).map(VariableFormula.apply) - (sl, LambdaExpression(vars, s(vars), s.arity)) + (sl, LambdaExpression(vars, s.applyUnsafe(vars), s.arity)) } } ) diff --git a/lisa-utils/src/main/scala/lisa/prooflib/BasicStepTactic.scala b/lisa-utils/src/main/scala/lisa/prooflib/BasicStepTactic.scala index 80f40640..320ea5a6 100644 --- a/lisa-utils/src/main/scala/lisa/prooflib/BasicStepTactic.scala +++ b/lisa-utils/src/main/scala/lisa/prooflib/BasicStepTactic.scala @@ -43,7 +43,7 @@ object BasicStepTactic { object RewriteTrue extends ProofTactic with ProofSequentTactic { def apply(using lib: Library, proof: lib.Proof)(bot: F.Sequent): proof.ProofTacticJudgement = { val botK = bot.underlying - if (!K.isSameSequent(botK, () `K|-` K.PredicateFormula(K.top, Nil))) + if (!K.isSameSequent(botK, () `K|-` K.AtomicFormula(K.top, Nil))) proof.InvalidProofTactic("The desired conclusion is not a trivial tautology.") else proof.ValidProofTactic(bot, Seq(K.RestateTrue(botK)), Seq()) @@ -130,7 +130,7 @@ object BasicStepTactic { if (!pivot.isEmpty && pivot.tail.isEmpty) pivot.head match { - case F.ConnectorFormula(F.And, Seq(phi, psi)) => + case F.AppliedConnector(F.And, Seq(phi, psi)) => if (premiseSequent.left.contains(phi)) LeftAnd.withParameters(phi, psi)(premise)(bot) else @@ -280,7 +280,7 @@ object BasicStepTactic { proof.InvalidProofTactic("Right-hand side of conclusion is not a superset of the premises.") else pivot.head match { - case F.ConnectorFormula(F.Implies, Seq(phi, psi)) => LeftIff.withParameters(phi, psi)(premise)(bot) + case F.AppliedConnector(F.Implies, Seq(phi, psi)) => LeftIff.withParameters(phi, psi)(premise)(bot) case _ => proof.InvalidProofTactic("Could not infer a pivot implication from premise.") } } @@ -501,7 +501,7 @@ object BasicStepTactic { K.BinderFormula( K.Forall, xK, - K.ConnectorFormula(K.Iff, List(K.PredicateFormula(K.equality, List(K.VariableTerm(xK), K.VariableTerm(y))), phiK)) + K.ConnectorFormula(K.Iff, List(K.AtomicFormula(K.equality, List(K.VariableTerm(xK), K.VariableTerm(y))), phiK)) ) ) lazy val quantified = K.BinderFormula(K.ExistsOne, xK, phiK) @@ -528,7 +528,7 @@ object BasicStepTactic { else if (instantiatedPivot.tail.isEmpty) { instantiatedPivot.head match { // ∃_. ∀x. _ ⇔ φ == extract ==> x, phi - case F.BinderFormula(F.Exists, _, F.BinderFormula(F.Forall, x, F.ConnectorFormula(F.Iff, Seq(_, phi)))) => LeftExistsOne.withParameters(phi, x)(premise)(bot) + case F.BinderFormula(F.Exists, _, F.BinderFormula(F.Forall, x, F.AppliedConnector(F.Iff, Seq(_, phi)))) => LeftExistsOne.withParameters(phi, x)(premise)(bot) case _ => proof.InvalidProofTactic("Could not infer an existentially quantified pivot from premise and conclusion.") } } else @@ -624,7 +624,7 @@ object BasicStepTactic { if (!pivot.isEmpty && pivot.tail.isEmpty) pivot.head match { - case F.ConnectorFormula(F.Or, Seq(phi, psi)) => + case F.AppliedConnector(F.Or, Seq(phi, psi)) => if (premiseSequent.left.contains(phi)) RightOr.withParameters(phi, psi)(premise)(bot) else @@ -728,7 +728,7 @@ object BasicStepTactic { proof.InvalidProofTactic("Left-hand side of conclusion is not a superset of the premises.") else if (pivot.tail.isEmpty) pivot.head match { - case F.ConnectorFormula(F.Implies, Seq(phi, psi)) => RightIff.withParameters(phi, psi)(prem1, prem2)(bot) + case F.AppliedConnector(F.Implies, Seq(phi, psi)) => RightIff.withParameters(phi, psi)(prem1, prem2)(bot) case _ => proof.InvalidProofTactic("Could not infer an implication as pivot from premise and conclusion.") } else @@ -954,7 +954,7 @@ object BasicStepTactic { K.BinderFormula( K.Forall, xK, - K.ConnectorFormula(K.Iff, List(K.PredicateFormula(K.equality, List(K.VariableTerm(xK), K.VariableTerm(y))), phiK)) + K.ConnectorFormula(K.Iff, List(K.AtomicFormula(K.equality, List(K.VariableTerm(xK), K.VariableTerm(y))), phiK)) ) ) lazy val quantified = K.BinderFormula(K.ExistsOne, xK, phiK) @@ -981,7 +981,7 @@ object BasicStepTactic { else if (instantiatedPivot.tail.isEmpty) { instantiatedPivot.head match { // ∃_. ∀x. _ ⇔ φ == extract ==> x, phi - case F.BinderFormula(F.Exists, _, F.BinderFormula(F.Forall, x, F.ConnectorFormula(F.Iff, Seq(_, phi)))) => + case F.BinderFormula(F.Exists, _, F.BinderFormula(F.Forall, x, F.AppliedConnector(F.Iff, Seq(_, phi)))) => RightExistsOne.withParameters(phi, x)(premise)(bot) case _ => proof.InvalidProofTactic("Could not infer an existentially quantified pivot from premise and conclusion.") } @@ -1036,7 +1036,7 @@ object BasicStepTactic { proof.InvalidProofTactic("Right-hand side of the premise is not the same as the right-hand side of the conclusion.") else faK match { - case K.PredicateFormula(K.equality, Seq(left, right)) => + case K.AtomicFormula(K.equality, Seq(left, right)) => if (K.isSameTerm(left, right)) proof.ValidProofTactic(bot, Seq(K.LeftRefl(botK, -1, faK)), Seq(premise)) else @@ -1071,7 +1071,7 @@ object BasicStepTactic { proof.InvalidProofTactic("Right-hand side of conclusion does not contain φ.") else faK match { - case K.PredicateFormula(K.equality, Seq(left, right)) => + case K.AtomicFormula(K.equality, Seq(left, right)) => if (K.isSameTerm(left, right)) proof.ValidProofTactic(bot, Seq(K.RightRefl(botK, faK)), Seq()) else @@ -1087,8 +1087,8 @@ object BasicStepTactic { val pivot: Option[F.Formula] = bot.right.find(f => val Eq = F.equality // (F.equality: (F.|->[F.**[F.Term, 2], F.Formula])) f match { - case F.PredicateFormula(e, Seq(l, r)) => - (F.equality: F.PredicateLabel) == (e: F.PredicateLabel) && l == r // termequality + case F.AppliedPredicate(e, Seq(l, r)) => + (F.equality) == (e) && l == r // termequality case _ => false } ) @@ -1124,7 +1124,7 @@ object BasicStepTactic { lazy val (s_es, t_es) = equalsK.unzip lazy val phi_s = lambdaPhiK(s_es) lazy val phi_t = lambdaPhiK(t_es) - lazy val equalities = equalsK map { case (s, t) => K.PredicateFormula(K.equality, Seq(s, t)) } + lazy val equalities = equalsK map { case (s, t) => K.AtomicFormula(K.equality, Seq(s, t)) } if (!K.isSameSet(botK.right, premiseSequent.right)) proof.InvalidProofTactic("Right-hand side of the premise is not the same as the right-hand side of the conclusion.") @@ -1159,7 +1159,7 @@ object BasicStepTactic { lazy val (s_es, t_es) = equalsK.unzip lazy val phi_s = lambdaPhiK(s_es) lazy val phi_t = lambdaPhiK(t_es) - lazy val equalities = equalsK map { case (s, t) => K.PredicateFormula(K.equality, Seq(s, t)) } + lazy val equalities = equalsK map { case (s, t) => K.AtomicFormula(K.equality, Seq(s, t)) } if (!K.isSameSet(botK.left, premiseSequent.left ++ equalities)) proof.InvalidProofTactic("Left-hand side of the conclusion is not the same as the left-hand side of the premise + (s=t)_.") @@ -1175,10 +1175,10 @@ object BasicStepTactic { def apply2(using lib: Library, proof: lib.Proof)(premise: proof.Fact)(bot: F.Sequent): proof.ProofTacticJudgement = { lazy val premiseSequent = proof.getSequent(premise) - val premRight = F.ConnectorFormula(F.Or, premiseSequent.right.toSeq) - val botRight = F.ConnectorFormula(F.Or, bot.right.toSeq) + val premRight = F.AppliedConnector(F.Or, premiseSequent.right.toSeq) + val botRight = F.AppliedConnector(F.Or, bot.right.toSeq) - val equalities = bot.left.toSeq.collect { case F.PredicateFormula(F.equality, Seq(l, r)) => (l, r) } + val equalities = bot.left.toSeq.collect { case F.AppliedPredicate(F.equality, Seq(l, r)) => (l, r) } val undereqs = equalities.toList.map(p => (p._1.underlying, p._2.underlying)) val canReach = UnificationUtils.getContextFormula( first = premRight, diff --git a/lisa-utils/src/main/scala/lisa/prooflib/ProofsHelpers.scala b/lisa-utils/src/main/scala/lisa/prooflib/ProofsHelpers.scala index 23ba931d..b6541e71 100644 --- a/lisa-utils/src/main/scala/lisa/prooflib/ProofsHelpers.scala +++ b/lisa-utils/src/main/scala/lisa/prooflib/ProofsHelpers.scala @@ -146,24 +146,30 @@ trait ProofsHelpers { class The(val out: Variable, val f: Formula)( val just: JUSTIFICATION ) - class definitionWithVars[N <: Arity](val args: Variable *** N) { + class definitionWithVars[N <: Arity](val args: Seq[Variable]) { // inline infix def -->(using om: OutputManager, name: sourcecode.FullName, line: sourcecode.Line, file: sourcecode.File)(t: Term) = simpleDefinition(lambda(args, t, args.length)) // inline infix def -->(using om: OutputManager, name: sourcecode.FullName, line: sourcecode.Line, file: sourcecode.File)(f: Formula) = predicateDefinition(lambda(args, f, args.length)) - inline infix def -->(using om: OutputManager, name: sourcecode.FullName, line: sourcecode.Line, file: sourcecode.File)(t: The): ConstantFunctionLabelOfArity[N] = - FunctionDefinition[N](name.value, line.value, file.value)(args.toSeq, t.out, t.f, t.just).label + inline infix def -->(using om: OutputManager, name: sourcecode.FullName, line: sourcecode.Line, file: sourcecode.File)(t: The): ConstantTermLabelOfArity[N] = + FunctionDefinition[N](name.value, line.value, file.value)(args, t.out, t.f, t.just).label - inline infix def -->(using om: OutputManager, name: sourcecode.FullName, line: sourcecode.Line, file: sourcecode.File)(term: Term): ConstantFunctionLabelOfArity[N] = - SimpleFunctionDefinition[N](name.value, line.value, file.value)(lambda(args.toSeq, term).asInstanceOf).label + inline infix def -->(using om: OutputManager, name: sourcecode.FullName, line: sourcecode.Line, file: sourcecode.File)(term: Term): ConstantTermLabelOfArity[N] = + SimpleFunctionDefinition[N](name.value, line.value, file.value)(lambda(args, term).asInstanceOf).label - inline infix def -->(using om: OutputManager, name: sourcecode.FullName, line: sourcecode.Line, file: sourcecode.File)(formula: Formula): ConstantPredicateLabelOfArity[N] = - PredicateDefinition[N](name.value, line.value, file.value)(lambda(args.toSeq, formula).asInstanceOf).label + inline infix def -->(using om: OutputManager, name: sourcecode.FullName, line: sourcecode.Line, file: sourcecode.File)(formula: Formula): ConstantAtomicLabelOfArity[N] = + PredicateDefinition[N](name.value, line.value, file.value)(lambda(args, formula).asInstanceOf).label } - def DEF[N <: Arity, T <: Tuple](args: T)(using Tuple.Size[T] =:= N, Tuple.Union[T] <:< Variable): definitionWithVars[N] = new definitionWithVars[N](args.asInstanceOf) - def DEF(arg: Variable): definitionWithVars[1] = new definitionWithVars[1](EmptyTuple.*:[Variable, EmptyTuple](arg)) // todo conversion to empty tuple gets bad type + def DEF(): definitionWithVars[0] = new definitionWithVars[0](Nil) + def DEF(a: Variable): definitionWithVars[1] = new definitionWithVars[1](Seq(a)) + def DEF(a: Variable, b: Variable): definitionWithVars[2] = new definitionWithVars[2](Seq(a, b)) + def DEF(a: Variable, b: Variable, c: Variable): definitionWithVars[3] = new definitionWithVars[3](Seq(a, b, c)) + def DEF(a: Variable, b: Variable, c: Variable, d: Variable): definitionWithVars[4] = new definitionWithVars[4](Seq(a, b, c, d)) + def DEF(a: Variable, b: Variable, c: Variable, d: Variable, e: Variable): definitionWithVars[5] = new definitionWithVars[5](Seq(a, b, c, d, e)) + def DEF(a: Variable, b: Variable, c: Variable, d: Variable, e: Variable, f: Variable): definitionWithVars[6] = new definitionWithVars[6](Seq(a, b, c, d, e, f)) + def DEF(a: Variable, b: Variable, c: Variable, d: Variable, e: Variable, f: Variable, g: Variable): definitionWithVars[7] = new definitionWithVars[7](Seq(a, b, c, d, e, f, g)) // def DEF: definitionWithVars[0] = new definitionWithVars[0](EmptyTuple) //todo conversion to empty tuple gets bad type @@ -178,12 +184,13 @@ trait ProofsHelpers { val f: F.Formula, j: JUSTIFICATION ) extends DEFINITION(line, file) { + def funWithArgs = label.applySeq(vars) override def repr: String = - s" ${if (withSorry) " Sorry" else ""} Definition of function symbol ${label(vars)} := the ${out} such that ${(out === label(vars)) <=> f})\n" + s" ${if (withSorry) " Sorry" else ""} Definition of function symbol ${funWithArgs} := the ${out} such that ${(out === funWithArgs) <=> f})\n" // val expr = LambdaExpression[Term, Formula, N](vars, f, valueOf[N]) - lazy val label: ConstantFunctionLabelOfArity[N] = (if (vars.length == 0) F.Constant(name) else F.ConstantFunctionLabel[N](name, vars.length.asInstanceOf)).asInstanceOf + lazy val label: ConstantTermLabelOfArity[N] = (if (vars.length == 0) F.Constant(name) else F.ConstantFunctionLabel[N](name, vars.length.asInstanceOf)).asInstanceOf val innerJustification: theory.FunctionDefinition = { val conclusion: F.Sequent = j.statement @@ -209,8 +216,8 @@ trait ProofsHelpers { } val proven = conclusion.right.head match { case F.BinderFormula(F.ExistsOne, bound, inner) => inner - case F.BinderFormula(F.Exists, x, F.BinderFormula(F.Forall, y, F.ConnectorFormula(F.Iff, Seq(l, r)))) if F.isSame(l, x === y) => r - case F.BinderFormula(F.Exists, x, F.BinderFormula(F.Forall, y, F.ConnectorFormula(F.Iff, Seq(l, r)))) if F.isSame(r, x === y) => l + case F.BinderFormula(F.Exists, x, F.BinderFormula(F.Forall, y, F.AppliedConnector(F.Iff, Seq(l, r)))) if F.isSame(l, x === y) => r + case F.BinderFormula(F.Exists, x, F.BinderFormula(F.Forall, y, F.AppliedConnector(F.Iff, Seq(l, r)))) if F.isSame(r, x === y) => l case _ => om.lisaThrow( UserInvalidDefinitionException( @@ -266,13 +273,7 @@ trait ProofsHelpers { () |- F.Forall( out, Iff( - equality( - (label match { - case l: F.Constant => l - case l: F.ConstantFunctionLabel[?] => l(vars) - }), - out - ), + equality(label.applySeq(vars), out), f ) ) @@ -306,11 +307,11 @@ trait ProofsHelpers { lazy val vars: Seq[F.Variable] = lambda.bounds.asInstanceOf val arity = lambda.arity - lazy val label: ConstantPredicateLabelOfArity[N] = { + lazy val label: ConstantAtomicLabelOfArity[N] = { ( if (vars.length == 0) F.ConstantFormula(name) else F.ConstantPredicateLabel[N](name, vars.length.asInstanceOf[N]) - ).asInstanceOf[ConstantPredicateLabelOfArity[N]] + ).asInstanceOf[ConstantAtomicLabelOfArity[N]] } val innerJustification: theory.PredicateDefinition = { @@ -354,14 +355,7 @@ trait ProofsHelpers { } } - val statement: F.Sequent = () |- Iff( - (label match { - case l: F.ConstantFormula => l - case l: F.ConstantPredicateLabel[?] => l(vars) - }), - lambda.body - ) - + val statement: F.Sequent = () |- Iff(label.applySeq(vars), lambda.body) library.last = Some(this) } } diff --git a/lisa-utils/src/main/scala/lisa/prooflib/WithTheorems.scala b/lisa-utils/src/main/scala/lisa/prooflib/WithTheorems.scala index 2fa698e2..24614ca3 100644 --- a/lisa-utils/src/main/scala/lisa/prooflib/WithTheorems.scala +++ b/lisa-utils/src/main/scala/lisa/prooflib/WithTheorems.scala @@ -41,7 +41,7 @@ trait WithTheorems { fact: Fact, insts: Seq[F.SubstPair] /*, instsConn: Map[K.SchematicConnectorLabel, K.LambdaFormulaFormula], - instsPred: Map[K.SchematicVarOrPredLabel, K.LambdaTermFormula], + instsPred: Map[K.SchematicAtomicLabel, K.LambdaTermFormula], instsTerm: Map[K.SchematicTermLabel, K.LambdaTermTerm]*/ ) { val baseFormula: F.Sequent = sequentOfFact(fact) diff --git a/lisa-utils/src/main/scala/lisa/utils/KernelHelpers.scala b/lisa-utils/src/main/scala/lisa/utils/KernelHelpers.scala index 62381a49..122f418d 100644 --- a/lisa-utils/src/main/scala/lisa/utils/KernelHelpers.scala +++ b/lisa-utils/src/main/scala/lisa/utils/KernelHelpers.scala @@ -54,12 +54,12 @@ object KernelHelpers { } } - extension [L <: PredicateLabel](label: L) { - def apply(args: Term*): Formula = PredicateFormula(label, args) + extension [L <: AtomicLabel](label: L) { + def apply(args: Term*): Formula = AtomicFormula(label, args) @targetName("applySeq") - def apply(args: Seq[Term]): Formula = PredicateFormula(label, args) + def apply(args: Seq[Term]): Formula = AtomicFormula(label, args) def unapply(f: Formula): Option[Seq[Term]] = f match { - case PredicateFormula(`label`, args) => Some(args) + case AtomicFormula(`label`, args) => Some(args) case _ => None } } @@ -93,18 +93,18 @@ object KernelHelpers { } extension (t: Term) { - infix def ===(u: Term): Formula = PredicateFormula(equality, Seq(t, u)) - infix def =(u: Term): Formula = PredicateFormula(equality, Seq(t, u)) + infix def ===(u: Term): Formula = AtomicFormula(equality, Seq(t, u)) + infix def =(u: Term): Formula = AtomicFormula(equality, Seq(t, u)) } /* Conversions */ given Conversion[TermLabel, Term] = Term(_, Seq()) given Conversion[Term, TermLabel] = _.label - given Conversion[PredicateLabel, PredicateFormula] = PredicateFormula(_, Seq()) - given Conversion[PredicateFormula, PredicateLabel] = _.label + given Conversion[AtomicLabel, AtomicFormula] = AtomicFormula(_, Seq()) + given Conversion[AtomicFormula, AtomicLabel] = _.label - given Conversion[VariableFormulaLabel, PredicateFormula] = PredicateFormula(_, Seq()) + given Conversion[VariableFormulaLabel, AtomicFormula] = AtomicFormula(_, Seq()) given Conversion[(Boolean, List[Int], String), Option[(List[Int], String)]] = tr => if (tr._1) None else Some(tr._2, tr._3) given Conversion[Formula, Sequent] = () |- _ @@ -196,7 +196,7 @@ object KernelHelpers { // Instatiation functions for formulas lifted to sequents. - def instantiatePredicateSchemaInSequent(s: Sequent, m: Map[SchematicVarOrPredLabel, LambdaTermFormula]): Sequent = { + def instantiatePredicateSchemaInSequent(s: Sequent, m: Map[SchematicAtomicLabel, LambdaTermFormula]): Sequent = { s.left.map(phi => instantiatePredicateSchemas(phi, m)) |- s.right.map(phi => instantiatePredicateSchemas(phi, m)) } @@ -207,7 +207,7 @@ object KernelHelpers { def instantiateSchemaInSequent( s: Sequent, mCon: Map[SchematicConnectorLabel, LambdaFormulaFormula], - mPred: Map[SchematicVarOrPredLabel, LambdaTermFormula], + mPred: Map[SchematicAtomicLabel, LambdaTermFormula], mTerm: Map[SchematicTermLabel, LambdaTermTerm] ): Sequent = { s.left.map(phi => instantiateSchemas(phi, mCon, mPred, mTerm)) |- s.right.map(phi => instantiateSchemas(phi, mCon, mPred, mTerm)) @@ -372,7 +372,7 @@ object KernelHelpers { * of the theorem to have more explicit writing and for sanity check. See also [[lisa.kernel.proof.RunningTheory.makePredicateDefinition]] */ def predicateDefinition(symbol: String, expression: LambdaTermFormula): RunningTheoryJudgement[theory.PredicateDefinition] = { - val label = ConstantPredicateLabel(symbol, expression.vars.size) + val label = ConstantAtomicLabel(symbol, expression.vars.size) theory.makePredicateDefinition(label, expression) } @@ -389,9 +389,9 @@ object KernelHelpers { * @return The List of undefined symols */ def findUndefinedSymbols(phi: Formula): Set[ConstantLabel] = phi match { - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => label match { - case l: ConstantPredicateLabel => ((if (theory.isSymbol(l)) Nil else List(l)) ++ args.flatMap(findUndefinedSymbols)).toSet + case l: ConstantAtomicLabel => ((if (theory.isSymbol(l)) Nil else List(l)) ++ args.flatMap(findUndefinedSymbols)).toSet case _ => args.flatMap(findUndefinedSymbols).toSet } case ConnectorFormula(label, args) => args.flatMap(findUndefinedSymbols).toSet diff --git a/lisa-utils/src/main/scala/lisa/utils/ProofsShrink.scala b/lisa-utils/src/main/scala/lisa/utils/ProofsShrink.scala index cc898057..5f620aa8 100644 --- a/lisa-utils/src/main/scala/lisa/utils/ProofsShrink.scala +++ b/lisa-utils/src/main/scala/lisa/utils/ProofsShrink.scala @@ -172,8 +172,8 @@ object ProofsShrink { isSubset(subset.left, superset.left) && isSubset(subset.right, superset.right) def schematicConnectorLabels(sequent: Sequent): Set[SchematicConnectorLabel] = (sequent.left ++ sequent.right).flatMap(_.schematicConnectorLabels) - def schematicPredicatesLabels(sequent: Sequent): Set[SchematicVarOrPredLabel] = - (sequent.left ++ sequent.right).flatMap(_.schematicPredicateLabels) + def schematicPredicatesLabels(sequent: Sequent): Set[SchematicAtomicLabel] = + (sequent.left ++ sequent.right).flatMap(_.schematicAtomicLabels) def schematicTermLabels(sequent: Sequent): Set[SchematicTermLabel] = (sequent.left ++ sequent.right).flatMap(_.schematicTermLabels) def schematicLabels(sequent: Sequent): Set[SchematicLabel] = { diff --git a/lisa-utils/src/main/scala/lisa/utils/Serialization.scala b/lisa-utils/src/main/scala/lisa/utils/Serialization.scala index 8abcd231..88e0e8db 100644 --- a/lisa-utils/src/main/scala/lisa/utils/Serialization.scala +++ b/lisa-utils/src/main/scala/lisa/utils/Serialization.scala @@ -52,7 +52,7 @@ object Serialization { // Injectively represent a FormulaLabel as a string. def formulaLabelToString(label: FormulaLabel): String = label match - case l: ConstantPredicateLabel => "cpl_" + l.id.name + "_" + l.id.no + "_" + l.arity + case l: ConstantAtomicLabel => "cpl_" + l.id.name + "_" + l.id.no + "_" + l.arity case l: SchematicPredicateLabel => "spl_" + l.id.name + "_" + l.id.no + "_" + l.arity case l: ConstantConnectorLabel => "ccl_" + l.id.name + "_" + l.id.no + "_" + l.arity case l: SchematicConnectorLabel => "scl_" + l.id.name + "_" + l.id.no + "_" + l.arity @@ -79,7 +79,7 @@ object Serialization { // write a formula label to an OutputStream def formulaLabelToDOS(label: FormulaLabel, dos: DataOutputStream): Unit = label match - case l: ConstantPredicateLabel => + case l: ConstantAtomicLabel => dos.writeByte(3) dos.writeUTF(l.id.name) dos.writeInt(l.id.no) @@ -133,7 +133,7 @@ object Serialization { case Some(line) => line case None => val nextLine = formula match - case PredicateFormula(label, args) => + case AtomicFormula(label, args) => val na = args.map(t => lineOfTerm(t)) formulaLabelToDOS(label, treesDOS) na.foreach(t => treesDOS.writeInt(t)) @@ -426,7 +426,7 @@ object Serialization { val name = dis.readUTF() val no = dis.readInt() val arity = dis.readInt() - ConstantPredicateLabel(Identifier(name, no), arity) + ConstantAtomicLabel(Identifier(name, no), arity) case 4 => val name = dis.readUTF() val no = dis.readInt() @@ -469,9 +469,9 @@ object Serialization { termMap(lineNo) = Term(l, args) case l: FormulaLabel => val formula = label match - case l: PredicateLabel => + case l: AtomicLabel => val args = (1 to l.arity).map(_ => termMap(treesDIS.readInt())).toSeq - PredicateFormula(l, args) + AtomicFormula(l, args) case l: ConnectorLabel => val ar = treesDIS.readShort() val args = (1 to ar).map(_ => formulaMap(treesDIS.readInt())).toSeq @@ -590,7 +590,7 @@ object Serialization { sequentFromProofDIS(), proofDIS.readInt(), (1 to proofDIS.readShort()).map(_ => (labelFromInputStream(proofDIS).asInstanceOf[SchematicConnectorLabel], lffFromProofDIS())).toMap, - (1 to proofDIS.readShort()).map(_ => (labelFromInputStream(proofDIS).asInstanceOf[SchematicVarOrPredLabel], ltfFromProofDIS())).toMap, + (1 to proofDIS.readShort()).map(_ => (labelFromInputStream(proofDIS).asInstanceOf[SchematicAtomicLabel], ltfFromProofDIS())).toMap, (1 to proofDIS.readShort()).map(_ => (labelFromInputStream(proofDIS).asInstanceOf[SchematicTermLabel], lttFromProofDIS())).toMap ) else if (psType == sorry) Sorry(sequentFromProofDIS()) @@ -659,7 +659,7 @@ object Serialization { case Array(name, no, arity) => theory.getDefinition(ConstantFunctionLabel(Identifier(name, no.toInt), arity.toInt)).get case 'p' => name.split("_") match - case Array(name, no, arity) => theory.getDefinition(ConstantPredicateLabel(Identifier(name, no.toInt), arity.toInt)).get + case Array(name, no, arity) => theory.getDefinition(ConstantAtomicLabel(Identifier(name, no.toInt), arity.toInt)).get } if debug then // To avoid conflicts where a theorem already exists, for example in test suits. diff --git a/lisa-utils/src/main/scala/lisa/utils/parsing/Parser.scala b/lisa-utils/src/main/scala/lisa/utils/parsing/Parser.scala index 683905e0..eb45a000 100644 --- a/lisa-utils/src/main/scala/lisa/utils/parsing/Parser.scala +++ b/lisa-utils/src/main/scala/lisa/utils/parsing/Parser.scala @@ -43,7 +43,7 @@ object UnreachableException extends ParserException("Internal error: expected un class PrintFailedException(inp: Sequent | Formula | Term) extends ParserException(s"Printing of $inp failed unexpectedly") /** - * @param synonymToCanonical information about synonyms that correspond to the same FunctionLabel / PredicateLabel. + * @param synonymToCanonical information about synonyms that correspond to the same FunctionLabel / AtomicLabel. * Can be constructed with [[lisa.utils.SynonymInfoBuilder]] * @param infixPredicates list of infix predicates' names * @param infixFunctions list of infix functions and their associativity in the decreasing order of priority @@ -140,7 +140,7 @@ class Parser( .printTermula(f.toTermula) .getOrElse({ f match { - case PredicateFormula(_, args) => args.foreach(printTerm) + case AtomicFormula(_, args) => args.foreach(printTerm) case ConnectorFormula(_, args) => args.foreach(printFormula) case BinderFormula(_, _, inner) => printFormula(inner) } @@ -312,24 +312,24 @@ class Parser( * <p> - to be converted to a formula, `args` of the termula are interpreted as formulas until a predicate application is observed; * `args` of the predicate application are terms. * - * <p> Convention: since the difference between `TermLabel`s and `PredicateLabel`s is purely semantic and Termula needs + * <p> Convention: since the difference between `TermLabel`s and `AtomicLabel`s is purely semantic and Termula needs * FormulaLabels (because of connector and binder labels), all TermLabels are translated to the corresponding * PredicateLabels (see [[toTermula]]). * - * @param label `PredicateLabel` for predicates and functions, `ConnectorLabel` or `BinderLabel` - * @param args Predicate / function arguments for `PredicateLabel`, connected formulas for `ConnectorLabel`, + * @param label `AtomicLabel` for predicates and functions, `ConnectorLabel` or `BinderLabel` + * @param args Predicate / function arguments for `AtomicLabel`, connected formulas for `ConnectorLabel`, * `Seq(VariableFormulaLabel(bound), inner)` for `BinderLabel` */ case class Termula(label: RangedLabel, args: Seq[Termula], range: (Int, Int)) { def toTerm: Term = label.folLabel match { case _: BinderLabel | _: ConnectorLabel => throw ExpectedTermGotFormula(range) - case t: ConstantPredicateLabel => Term(ConstantFunctionLabel(t.id, t.arity), args.map(_.toTerm)) + case t: ConstantAtomicLabel => Term(ConstantFunctionLabel(t.id, t.arity), args.map(_.toTerm)) case t: SchematicPredicateLabel => Term(SchematicFunctionLabel(t.id, t.arity), args.map(_.toTerm)) case v: VariableFormulaLabel => Term(VariableLabel(v.id), Seq()) } def toFormula: Formula = label.folLabel match { - case p: PredicateLabel => PredicateFormula(p, args.map(_.toTerm)) + case p: AtomicLabel => AtomicFormula(p, args.map(_.toTerm)) case c: ConnectorLabel => ConnectorFormula(c, args.map(_.toFormula)) case b: BinderLabel => args match { @@ -349,7 +349,7 @@ class Parser( } f match { - case PredicateFormula(label, args) => Termula(label, args.map(_.toTermula), UNKNOWN_RANGE) + case AtomicFormula(label, args) => Termula(label, args.map(_.toTermula), UNKNOWN_RANGE) // case ConnectorFormula(And | Or, Seq(singleArg)) => singleArg.toTermula case ConnectorFormula(label, args) => Termula(label, args.map(_.toTermula), UNKNOWN_RANGE) case BinderFormula(label, bound, inner) => Termula(label, Seq(Termula(VariableFormulaLabel(bound.id), Seq(), UNKNOWN_RANGE), inner.toTermula), UNKNOWN_RANGE) @@ -363,7 +363,7 @@ class Parser( def apply(f: FOL.FormulaLabel): RangedLabel = RangedLabel(f, UNKNOWN_RANGE) } val newLabel = t.label match { - case ConstantFunctionLabel(id, arity) => ConstantPredicateLabel(id, arity) + case ConstantFunctionLabel(id, arity) => ConstantAtomicLabel(id, arity) case SchematicFunctionLabel(id, arity) => SchematicPredicateLabel(id, arity) case VariableLabel(id) => VariableFormulaLabel(id) } @@ -499,7 +499,7 @@ class Parser( t.label.folLabel match { case VariableFormulaLabel(id) => SchematicToken(id, t.label.range) ~ None case SchematicPredicateLabel(id, _) => SchematicToken(id, t.range) ~ Some(RangedTermulaSeq(t.args, argsRange)) - case ConstantPredicateLabel(id, arity) => + case ConstantAtomicLabel(id, arity) => ConstantToken(synonymToCanonical.getPrintName(id), t.label.range) ~ (if (arity == 0) None else Some(RangedTermulaSeq(t.args, argsRange))) case _ => throw UnreachableException @@ -512,7 +512,7 @@ class Parser( val args: Seq[Termula] = optArgs.map(_.ts).getOrElse(Seq()) val l = p match { - case ConstantToken(id, _) => ConstantPredicateLabel(synonymToCanonical.getInternalName(id), args.size) + case ConstantToken(id, _) => ConstantAtomicLabel(synonymToCanonical.getInternalName(id), args.size) case SchematicToken(id, _) => if (args.isEmpty) VariableFormulaLabel(id) else SchematicPredicateLabel(id, args.size) case SchematicConnectorToken(id, _) => SchematicConnectorLabel(id, args.size) @@ -523,7 +523,7 @@ class Parser( Termula(RangedLabel(l, p.range), args, (p.range._1, optArgs.map(_.range._2).getOrElse(p.range._2))) }, { - case t @ Termula(RangedLabel(_: PredicateLabel, _), _, _) => Seq(reconstructPrefixApplication(t)) + case t @ Termula(RangedLabel(_: AtomicLabel, _), _, _) => Seq(reconstructPrefixApplication(t)) case t @ Termula(RangedLabel(SchematicConnectorLabel(id, _), r), args, _) => val argsRange = (t.label.range._2 + 1, t.range._2) Seq(SchematicConnectorToken(id, r) ~ Some(RangedTermulaSeq(args, argsRange))) @@ -541,11 +541,11 @@ class Parser( val infixFunctionLabels: List[PrecedenceLevel[RangedLabel]] = infixFunctions.map({ case (l, assoc) => elem(InfixKind(l)).map[RangedLabel]( { - case InfixToken(`l`, range) => RangedLabel(ConstantPredicateLabel(synonymToCanonical.getInternalName(l), INFIX_ARITY), range) + case InfixToken(`l`, range) => RangedLabel(ConstantAtomicLabel(synonymToCanonical.getInternalName(l), INFIX_ARITY), range) case _ => throw UnreachableException }, { - case RangedLabel(ConstantPredicateLabel(id, INFIX_ARITY), range) => Seq(InfixToken(synonymToCanonical.getPrintName(id), range)) + case RangedLabel(ConstantAtomicLabel(id, INFIX_ARITY), range) => Seq(InfixToken(synonymToCanonical.getPrintName(id), range)) case _ => throw UnreachableException } ) has assoc @@ -554,11 +554,11 @@ class Parser( val infixPredicateLabels: List[PrecedenceLevel[RangedLabel]] = infixPredicates.map(l => elem(InfixKind(l)).map[RangedLabel]( { - case InfixToken(`l`, range) => RangedLabel(ConstantPredicateLabel(synonymToCanonical.getInternalName(l), INFIX_ARITY), range) + case InfixToken(`l`, range) => RangedLabel(ConstantAtomicLabel(synonymToCanonical.getInternalName(l), INFIX_ARITY), range) case _ => throw UnreachableException }, { - case RangedLabel(ConstantPredicateLabel(id, INFIX_ARITY), range) => Seq(InfixToken(synonymToCanonical.getPrintName(id), range)) + case RangedLabel(ConstantAtomicLabel(id, INFIX_ARITY), range) => Seq(InfixToken(synonymToCanonical.getPrintName(id), range)) case _ => throw UnreachableException } ) has Associativity.None @@ -609,7 +609,7 @@ class Parser( )( (l, conn, r) => Termula(conn, Seq(l, r), (l.range._1, r.range._2)), { - case Termula(pred @ RangedLabel(ConstantPredicateLabel(_, INFIX_ARITY), _), Seq(l, r), _) => (l, pred, r) + case Termula(pred @ RangedLabel(ConstantAtomicLabel(_, INFIX_ARITY), _), Seq(l, r), _) => (l, pred, r) case Termula(conn @ RangedLabel(_: ConnectorLabel, _), Seq(l, r), _) => (l, conn, r) case Termula(conn @ RangedLabel(_: ConnectorLabel, _), l +: rest, _) if rest.nonEmpty => diff --git a/lisa-utils/src/main/scala/lisa/utils/parsing/SynonymInfo.scala b/lisa-utils/src/main/scala/lisa/utils/parsing/SynonymInfo.scala index f930b5ef..2ab84429 100644 --- a/lisa-utils/src/main/scala/lisa/utils/parsing/SynonymInfo.scala +++ b/lisa-utils/src/main/scala/lisa/utils/parsing/SynonymInfo.scala @@ -12,7 +12,7 @@ case class SynonymInfo(private val synonymToCanonical: Map[String, CanonicalId]) def getPrintName(id: String): String = synonymToCanonical.get(id).map(_.print).getOrElse(id) /** - * @return the synonym of `id` that is used to construct the corresponding `ConstantPredicateLabel` or + * @return the synonym of `id` that is used to construct the corresponding `ConstantAtomicLabel` or * `ConstantFunctionLabel`. If not available, `id` has no known synonyms, so return `id` itself. */ def getInternalName(id: String): String = synonymToCanonical.get(id).map(_.internal).getOrElse(id) diff --git a/lisa-utils/src/main/scala/lisa/utils/tptp/KernelParser.scala b/lisa-utils/src/main/scala/lisa/utils/tptp/KernelParser.scala index 41e3ffb0..18202949 100644 --- a/lisa-utils/src/main/scala/lisa/utils/tptp/KernelParser.scala +++ b/lisa-utils/src/main/scala/lisa/utils/tptp/KernelParser.scala @@ -32,7 +32,7 @@ object KernelParser { */ def convertToKernel(formula: FOF.Formula): K.Formula = { formula match { - case FOF.AtomicFormula(f, args) => K.PredicateFormula(K.ConstantPredicateLabel(f, args.size), args map convertTermToKernel) + case FOF.AtomicFormula(f, args) => K.AtomicFormula(K.ConstantAtomicLabel(f, args.size), args map convertTermToKernel) case FOF.QuantifiedFormula(quantifier, variableList, body) => quantifier match { case FOF.! => variableList.foldRight(convertToKernel(body))((s, f) => K.Forall(K.VariableLabel(s), f)) @@ -63,8 +63,8 @@ object KernelParser { K.ConnectorFormula( K.Or, formula.map { - case CNF.PositiveAtomic(formula) => K.PredicateFormula(K.ConstantPredicateLabel(formula.f, formula.args.size), formula.args.map(convertTermToKernel).toList) - case CNF.NegativeAtomic(formula) => !K.PredicateFormula(K.ConstantPredicateLabel(formula.f, formula.args.size), formula.args.map(convertTermToKernel).toList) + case CNF.PositiveAtomic(formula) => K.AtomicFormula(K.ConstantAtomicLabel(formula.f, formula.args.size), formula.args.map(convertTermToKernel).toList) + case CNF.NegativeAtomic(formula) => !K.AtomicFormula(K.ConstantAtomicLabel(formula.f, formula.args.size), formula.args.map(convertTermToKernel).toList) case CNF.Equality(left, right) => K.equality(convertTermToKernel(left), convertTermToKernel(right)) case CNF.Inequality(left, right) => !K.equality(convertTermToKernel(left), convertTermToKernel(right)) } diff --git a/lisa-utils/src/main/scala/lisa/utils/unification/UnificationUtils.scala b/lisa-utils/src/main/scala/lisa/utils/unification/UnificationUtils.scala index f8f481f6..dcc762fa 100644 --- a/lisa-utils/src/main/scala/lisa/utils/unification/UnificationUtils.scala +++ b/lisa-utils/src/main/scala/lisa/utils/unification/UnificationUtils.scala @@ -203,7 +203,7 @@ object UnificationUtils { } } - case (ConnectorFormula(labelR, argsR), ConnectorFormula(labelT, argsT)) if labelR == labelT => + case (AppliedConnector(labelR, argsR), AppliedConnector(labelT, argsT)) if labelR == labelT => if (argsR.length != argsT.length) // quick discard None @@ -222,7 +222,7 @@ object UnificationUtils { else if (template == reference && reference == formulaSubstitution.getOrElse(template, reference)) Some(formulaSubstitution, termSubstitution) else None - case (PredicateFormula(labelR, argsR), PredicateFormula(labelT, argsT)) if labelR == labelT => + case (AppliedPredicate(labelR, argsR), AppliedPredicate(labelT, argsT)) if labelR == labelT => if (argsR.length != argsT.length) // quick discard None @@ -419,7 +419,7 @@ object UnificationUtils { if (innerSubstitutions.exists(_.isEmpty)) None else { val retrieved = innerSubstitutions.map(_.get) - val body = first.label(retrieved.map(_.body)) + val body = first.label.applySeq(retrieved.map(_.body)) val lambda = retrieved.foldLeft(TermRewriteLambda(body = body)) { case (currentLambda, nextLambda) => TermRewriteLambda( @@ -564,7 +564,7 @@ object UnificationUtils { innerSubst.map(s => s.copy(body = BinderFormula(labelF, freshVar, s.body))) } - case (ConnectorFormula(labelF, argsF), ConnectorFormula(labelS, argsS)) => + case (AppliedConnector(labelF, argsF), AppliedConnector(labelS, argsS)) => if (argsF.length != argsS.length) // quick discard None @@ -575,7 +575,7 @@ object UnificationUtils { if (innerSubstitutions.exists(_.isEmpty)) None else { val retrieved = innerSubstitutions.map(_.get) - val body = ConnectorFormula(labelF, retrieved.map(_.body)) + val body = AppliedConnector(labelF, retrieved.map(_.body)) val lambda = retrieved.foldLeft(FormulaRewriteLambda(body = body)) { case (currentLambda, nextLambda) => FormulaRewriteLambda( @@ -588,7 +588,7 @@ object UnificationUtils { } } - case (PredicateFormula(labelF, argsF), PredicateFormula(labelS, argsS)) => + case (AppliedPredicate(labelF, argsF), AppliedPredicate(labelS, argsS)) => if (argsF.length != argsS.length) // quick discard None @@ -599,7 +599,7 @@ object UnificationUtils { if (innerSubstitutions.exists(_.isEmpty)) None else { val retrieved = innerSubstitutions.map(_.get) - val body = PredicateFormula(labelF, retrieved.map(_.body)) + val body = AppliedPredicate(labelF, retrieved.map(_.body)) val lambda = retrieved.foldLeft(FormulaRewriteLambda(body = body)) { case (currentLambda, nextLambda) => FormulaRewriteLambda( diff --git a/lisa-utils/src/test/scala/lisa/TestTheoryAxioms.scala b/lisa-utils/src/test/scala/lisa/TestTheoryAxioms.scala index 37a37463..aeaa403d 100644 --- a/lisa-utils/src/test/scala/lisa/TestTheoryAxioms.scala +++ b/lisa-utils/src/test/scala/lisa/TestTheoryAxioms.scala @@ -5,8 +5,8 @@ import lisa.kernel.proof.RunningTheory import lisa.utils.KernelHelpers.{_, given} trait TestTheoryAxioms { - final val p1 = ConstantPredicateLabel("p1", 1) - final val p2 = ConstantPredicateLabel("p2", 1) + final val p1 = ConstantAtomicLabel("p1", 1) + final val p2 = ConstantAtomicLabel("p2", 1) final val f1 = ConstantFunctionLabel("f1", 1) final val fixedElement = ConstantFunctionLabel("fixedElement", 0) final val anotherFixed = ConstantFunctionLabel("anotherElement", 0) diff --git a/lisa-utils/src/test/scala/lisa/kernel/EquivalenceCheckerTests.scala b/lisa-utils/src/test/scala/lisa/kernel/EquivalenceCheckerTests.scala index d4cf7f0e..81a39258 100644 --- a/lisa-utils/src/test/scala/lisa/kernel/EquivalenceCheckerTests.scala +++ b/lisa-utils/src/test/scala/lisa/kernel/EquivalenceCheckerTests.scala @@ -54,7 +54,7 @@ class EquivalenceCheckerTests extends AnyFunSuite { val generator = nameGenerator() () => { val id = generator() - PredicateFormula(ConstantPredicateLabel(id, 0), Seq.empty) + AtomicFormula(ConstantAtomicLabel(id, 0), Seq.empty) } } @@ -81,7 +81,7 @@ class EquivalenceCheckerTests extends AnyFunSuite { // Reuse existing name connectors(random.nextInt(connectors.size)) } - PredicateFormula(ConstantPredicateLabel(name, 0), Seq.empty) + AtomicFormula(ConstantAtomicLabel(name, 0), Seq.empty) } else { // Branch val nextP = p * c @@ -169,7 +169,7 @@ class EquivalenceCheckerTests extends AnyFunSuite { def repeatApply[T](n: Int)(f: T => T)(initial: T): T = if (n > 0) repeatApply(n - 1)(f)(f(initial)) else initial def commutativeShuffle(iterations: Int)(random: Random)(f: Formula): Formula = { def transform(f: Formula): Formula = f match { - case PredicateFormula(label, args) => f + case AtomicFormula(label, args) => f case ConnectorFormula(label, args) => val newArgs = label match { case And | Or | Iff => random.shuffle(args) @@ -182,7 +182,7 @@ class EquivalenceCheckerTests extends AnyFunSuite { } def associativeShuffle(iterations: Int)(random: Random)(f: Formula): Formula = { def transform(f: Formula): Formula = f match { - case PredicateFormula(label, args) => f + case AtomicFormula(label, args) => f // Simple for now, assume binary operations case ConnectorFormula(label1 @ (And | Or), Seq(ConnectorFormula(label2, Seq(a1, a2)), a3)) if label1 == label2 => if (random.nextBoolean()) { @@ -206,7 +206,7 @@ class EquivalenceCheckerTests extends AnyFunSuite { if (random.nextDouble() < p) neg(neg(transform(f))) else f match { - case _: PredicateFormula => f + case _: AtomicFormula => f case ConnectorFormula(label, args) => ConnectorFormula(label, args.map(transform)) case BinderFormula(label, bound, inner) => BinderFormula(label, bound, transform(inner)) } @@ -214,7 +214,7 @@ class EquivalenceCheckerTests extends AnyFunSuite { } def addDeMorgans(p: Double)(random: Random)(f: Formula): Formula = { def transform(f: Formula): Formula = f match { - case _: PredicateFormula => f + case _: AtomicFormula => f case ConnectorFormula(label, args) => val map: Map[ConnectorLabel, ConnectorLabel] = Map(And -> Or, Or -> And) map.get(label) match { diff --git a/lisa-utils/src/test/scala/lisa/kernel/FolTests.scala b/lisa-utils/src/test/scala/lisa/kernel/FolTests.scala index b38d2283..bc769dd8 100644 --- a/lisa-utils/src/test/scala/lisa/kernel/FolTests.scala +++ b/lisa-utils/src/test/scala/lisa/kernel/FolTests.scala @@ -60,20 +60,20 @@ class FolTests extends AnyFunSuite { val r = gen.between(0, 7) if (r <= 1) { val name = "" + ('A' to 'E')(gen.between(0, 5)) - PredicateFormula(ConstantPredicateLabel(name, 0), Seq()) + AtomicFormula(ConstantAtomicLabel(name, 0), Seq()) } else if (r <= 3) { val name = "" + ('A' to 'E')(gen.between(0, 5)) - PredicateFormula(ConstantPredicateLabel(name, 1), Seq(termGenerator(maxDepth - 1, gen))) + AtomicFormula(ConstantAtomicLabel(name, 1), Seq(termGenerator(maxDepth - 1, gen))) } else if (r <= 5) { val s = gen.between(0, 3) - if (s == 0) PredicateFormula(equality, Seq(termGenerator(maxDepth - 1, gen), termGenerator(maxDepth - 1, gen))) + if (s == 0) AtomicFormula(equality, Seq(termGenerator(maxDepth - 1, gen), termGenerator(maxDepth - 1, gen))) else { val name = "" + ('A' to 'E')(gen.between(0, 5)) - PredicateFormula(ConstantPredicateLabel(name, 2), Seq(termGenerator(maxDepth - 1, gen), termGenerator(maxDepth - 1, gen))) + AtomicFormula(ConstantAtomicLabel(name, 2), Seq(termGenerator(maxDepth - 1, gen), termGenerator(maxDepth - 1, gen))) } } else { val name = "" + ('A' to 'E')(gen.between(0, 5)) - PredicateFormula(ConstantPredicateLabel(name, 3), Seq(termGenerator(maxDepth - 1, gen), termGenerator(maxDepth - 1, gen), termGenerator(maxDepth - 1, gen))) + AtomicFormula(ConstantAtomicLabel(name, 3), Seq(termGenerator(maxDepth - 1, gen), termGenerator(maxDepth - 1, gen), termGenerator(maxDepth - 1, gen))) } } else { @@ -98,9 +98,9 @@ class FolTests extends AnyFunSuite { private val x = VariableLabel("x") private val y = VariableLabel("y") private val z = VariableLabel("z") - private val a = PredicateFormula(ConstantPredicateLabel("A", 0), Seq()) - private val b = PredicateFormula(ConstantPredicateLabel("B", 0), Seq()) - private val fp = ConstantPredicateLabel("F", 1) + private val a = AtomicFormula(ConstantAtomicLabel("A", 0), Seq()) + private val b = AtomicFormula(ConstantAtomicLabel("B", 0), Seq()) + private val fp = ConstantAtomicLabel("F", 1) private val sT = VariableLabel("t") def test_some_random_formulas(n: Int, maxDepth: Int): Unit = { diff --git a/lisa-utils/src/test/scala/lisa/kernel/IncorrectProofsTests.scala b/lisa-utils/src/test/scala/lisa/kernel/IncorrectProofsTests.scala index 13df37d7..05933f01 100644 --- a/lisa-utils/src/test/scala/lisa/kernel/IncorrectProofsTests.scala +++ b/lisa-utils/src/test/scala/lisa/kernel/IncorrectProofsTests.scala @@ -20,9 +20,9 @@ class IncorrectProofsTests extends ProofCheckerSuite { implicit def proofStepToProof(proofStep: SCProofStep): SCProof = SCProof(proofStep) val (fl, gl, hl) = (VariableFormulaLabel("f"), VariableFormulaLabel("g"), VariableFormulaLabel("h")) - val f = PredicateFormula(fl, Seq.empty) // Some arbitrary formulas - val g = PredicateFormula(gl, Seq.empty) - val h = PredicateFormula(hl, Seq.empty) + val f = AtomicFormula(fl, Seq.empty) // Some arbitrary formulas + val g = AtomicFormula(gl, Seq.empty) + val h = AtomicFormula(hl, Seq.empty) val incorrectProofs: Seq[SCProof] = List( SCProof( diff --git a/lisa-utils/src/test/scala/lisa/kernel/ProofTests.scala b/lisa-utils/src/test/scala/lisa/kernel/ProofTests.scala index 9e06ffad..474f4fee 100644 --- a/lisa-utils/src/test/scala/lisa/kernel/ProofTests.scala +++ b/lisa-utils/src/test/scala/lisa/kernel/ProofTests.scala @@ -19,9 +19,9 @@ class ProofTests extends AnyFunSuite { private val x = VariableLabel("x") private val y = VariableLabel("y") private val z = VariableLabel("z") - private val a = PredicateFormula(ConstantPredicateLabel("A", 0), Seq()) - private val b = PredicateFormula(ConstantPredicateLabel("B", 0), Seq()) - private val fp = ConstantPredicateLabel("F", 1) + private val a = AtomicFormula(ConstantAtomicLabel("A", 0), Seq()) + private val b = AtomicFormula(ConstantAtomicLabel("B", 0), Seq()) + private val fp = ConstantAtomicLabel("F", 1) val sT = VariableLabel("t") test("Verification of Pierce law") { @@ -44,7 +44,7 @@ class ProofTests extends AnyFunSuite { test("Commutativity on a random large formula") { val k = 9 val r = new Random() - val vars = (0 until 1 << k).map(i => PredicateFormula(ConstantPredicateLabel(s"P$i", 0), Seq())) + val vars = (0 until 1 << k).map(i => AtomicFormula(ConstantAtomicLabel(s"P$i", 0), Seq())) val pairs = vars.grouped(2) val sPairs = vars.grouped(2) diff --git a/lisa-utils/src/test/scala/lisa/kernel/SubstitutionTest.scala b/lisa-utils/src/test/scala/lisa/kernel/SubstitutionTest.scala index 8a2fa3e7..e1ee7a35 100644 --- a/lisa-utils/src/test/scala/lisa/kernel/SubstitutionTest.scala +++ b/lisa-utils/src/test/scala/lisa/kernel/SubstitutionTest.scala @@ -97,7 +97,7 @@ class SubstitutionTest extends AnyFunSuite { } test("Substitution of Predicates in Formulas") { - case class $(f: Formula, m: (SchematicVarOrPredLabel, LambdaTermFormula)*) + case class $(f: Formula, m: (SchematicAtomicLabel, LambdaTermFormula)*) extension (c: $) { inline infix def _VS_(t2: Formula): Assertion = { assert( @@ -141,7 +141,7 @@ class SubstitutionTest extends AnyFunSuite { } test("Simultaneous Substitutions in Formulas") { - case class $(f: Formula, m: ((SchematicConnectorLabel, LambdaFormulaFormula) | (SchematicVarOrPredLabel, LambdaTermFormula) | (SchematicTermLabel, LambdaTermTerm))*) + case class $(f: Formula, m: ((SchematicConnectorLabel, LambdaFormulaFormula) | (SchematicAtomicLabel, LambdaTermFormula) | (SchematicTermLabel, LambdaTermTerm))*) extension (c: $) { inline infix def _VS_(t2: Formula): Assertion = { val mCon: Map[SchematicConnectorLabel, LambdaFormulaFormula] = c.m @@ -150,9 +150,9 @@ class SubstitutionTest extends AnyFunSuite { }) .toMap .asInstanceOf - val mPred: Map[SchematicVarOrPredLabel, LambdaTermFormula] = c.m + val mPred: Map[SchematicAtomicLabel, LambdaTermFormula] = c.m .collect({ - case e if e._1.isInstanceOf[SchematicVarOrPredLabel] => e + case e if e._1.isInstanceOf[SchematicAtomicLabel] => e }) .toMap .asInstanceOf diff --git a/lisa-utils/src/test/scala/lisa/utils/BasicTacticTest.scala b/lisa-utils/src/test/scala/lisa/utils/BasicTacticTest.scala index e7c6520d..8d46bbcf 100644 --- a/lisa-utils/src/test/scala/lisa/utils/BasicTacticTest.scala +++ b/lisa-utils/src/test/scala/lisa/utils/BasicTacticTest.scala @@ -1477,23 +1477,23 @@ class BasicTacticTest extends ProofTacticTestLib { val Z = LambdaTermFormula(Seq(x, y), g(x, y)) val correct = List( - ("'P('x); 'f('x) |- 'R('y)", "'P('x); ('x = 'x) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](f -> Y)), - ("'P('x); 'Q('x) /\\ 'f('x) |- 'R('y)", "'P('x); 'Q('x) /\\ 'x = 'x |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](f -> Y)), - ("'P('x); 'h('x, 'y) |- 'R('y)", "'P('x); 'g('x, 'y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z)), - ("'h('y, 'y); 'h('x, 'y) |- 'R('y)", "'g('y, 'y); 'g('x, 'y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z)), - ("'P('x); 'g('x, 'y) |- 'R('y)", "'P('x); 'g('x, 'y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z)), - ("'P('x); 'g('x, 'y) |- 'R('y); 'f('x)", "'P('x); 'g('x, 'y) |- 'R('y); 'x = 'x", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z, f -> Y)) + ("'P('x); 'f('x) |- 'R('y)", "'P('x); ('x = 'x) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](f -> Y)), + ("'P('x); 'Q('x) /\\ 'f('x) |- 'R('y)", "'P('x); 'Q('x) /\\ 'x = 'x |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](f -> Y)), + ("'P('x); 'h('x, 'y) |- 'R('y)", "'P('x); 'g('x, 'y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z)), + ("'h('y, 'y); 'h('x, 'y) |- 'R('y)", "'g('y, 'y); 'g('x, 'y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z)), + ("'P('x); 'g('x, 'y) |- 'R('y)", "'P('x); 'g('x, 'y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z)), + ("'P('x); 'g('x, 'y) |- 'R('y); 'f('x)", "'P('x); 'g('x, 'y) |- 'R('y); 'x = 'x", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z, f -> Y)) ) val incorrect = List( - ("'P('x); 'f('x) = 'y |- 'R('y)", "'P('x); !('x = 'y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](f -> Y)), - ("'P('x); 'f('x) |- 'R('y)", "'P('x); 'Q('y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](f -> Y)), - ("'P('x); 'h('x, 'y) |- 'R('y)", "'P('x); 'h('x, 'y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z)), - ("'h('y, 'y); 'h('x, 'y) |- 'R('y)", "'g('y, 'y); 'g('y, 'y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z)), - ("'P('x); 'g('x, 'y) |- 'R('y)", "'P('x); 'h('x, 'y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z)), - ("'P('x); 'g('x, 'y) |- 'R('y); 'f('x)", "'P('x); 'g('x, 'y) |- 'R('y); 'x = 't", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z, f -> Y)), - ("'P('x); 'g('x, 'y) |- 'R('y); 'f('x)", "'P('x); 'g('x, 'y) |- 'R('y); 'x = 'x", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z)), - ("'P('x); 'g('x, 'y) |- 'R('y); 'f('x)", "'P('x); 'g('x, 'y) |- 'R('y)", Map[SchematicVarOrPredLabel, LambdaTermFormula](h -> Z, f -> Y)) + ("'P('x); 'f('x) = 'y |- 'R('y)", "'P('x); !('x = 'y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](f -> Y)), + ("'P('x); 'f('x) |- 'R('y)", "'P('x); 'Q('y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](f -> Y)), + ("'P('x); 'h('x, 'y) |- 'R('y)", "'P('x); 'h('x, 'y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z)), + ("'h('y, 'y); 'h('x, 'y) |- 'R('y)", "'g('y, 'y); 'g('y, 'y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z)), + ("'P('x); 'g('x, 'y) |- 'R('y)", "'P('x); 'h('x, 'y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z)), + ("'P('x); 'g('x, 'y) |- 'R('y); 'f('x)", "'P('x); 'g('x, 'y) |- 'R('y); 'x = 't", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z, f -> Y)), + ("'P('x); 'g('x, 'y) |- 'R('y); 'f('x)", "'P('x); 'g('x, 'y) |- 'R('y); 'x = 'x", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z)), + ("'P('x); 'g('x, 'y) |- 'R('y); 'f('x)", "'P('x); 'g('x, 'y) |- 'R('y)", Map[SchematicAtomicLabel, LambdaTermFormula](h -> Z, f -> Y)) ) testTacticCases(correct, incorrect) { (stmt1, stmt2, termMap) => diff --git a/lisa-utils/src/test/scala/lisa/utils/ParserTest.scala b/lisa-utils/src/test/scala/lisa/utils/ParserTest.scala index 01457e99..a0cad24c 100644 --- a/lisa-utils/src/test/scala/lisa/utils/ParserTest.scala +++ b/lisa-utils/src/test/scala/lisa/utils/ParserTest.scala @@ -44,8 +44,8 @@ class ParserTest extends AnyFunSuite with TestUtils { } test("0-ary predicate") { - assert(FOLParser.parseFormula("a") == PredicateFormula(ConstantPredicateLabel("a", 0), Seq())) - assert(FOLParser.parseFormula("a()") == PredicateFormula(ConstantPredicateLabel("a", 0), Seq())) + assert(FOLParser.parseFormula("a") == AtomicFormula(ConstantAtomicLabel("a", 0), Seq())) + assert(FOLParser.parseFormula("a()") == AtomicFormula(ConstantAtomicLabel("a", 0), Seq())) } test("boolean constants") { @@ -61,14 +61,14 @@ class ParserTest extends AnyFunSuite with TestUtils { } test("predicate application") { - assert(FOLParser.parseFormula("p(x, y, z)") == PredicateFormula(ConstantPredicateLabel("p", 3), Seq(cx, cy, cz))) - assert(FOLParser.parseFormula("p('x, 'y, 'z)") == PredicateFormula(ConstantPredicateLabel("p", 3), Seq(x, y, z))) + assert(FOLParser.parseFormula("p(x, y, z)") == AtomicFormula(ConstantAtomicLabel("p", 3), Seq(cx, cy, cz))) + assert(FOLParser.parseFormula("p('x, 'y, 'z)") == AtomicFormula(ConstantAtomicLabel("p", 3), Seq(x, y, z))) } test("equality") { - assert(FOLParser.parseFormula("(x = x)") == PredicateFormula(equality, Seq(cx, cx))) - assert(FOLParser.parseFormula("x = x") == PredicateFormula(equality, Seq(cx, cx))) - assert(FOLParser.parseFormula("a ∧ ('x = 'x)") == ConnectorFormula(And, Seq(a, PredicateFormula(equality, Seq(x, x))))) + assert(FOLParser.parseFormula("(x = x)") == AtomicFormula(equality, Seq(cx, cx))) + assert(FOLParser.parseFormula("x = x") == AtomicFormula(equality, Seq(cx, cx))) + assert(FOLParser.parseFormula("a ∧ ('x = 'x)") == ConnectorFormula(And, Seq(a, AtomicFormula(equality, Seq(x, x))))) } test("unicode connectors") { @@ -131,13 +131,13 @@ class ParserTest extends AnyFunSuite with TestUtils { } test("quantifiers") { - assert(FOLParser.parseFormula("∀ 'x. (p)") == BinderFormula(Forall, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) - assert(FOLParser.parseFormula("∃ 'x. (p)") == BinderFormula(Exists, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) - assert(FOLParser.parseFormula("∃! 'x. (p)") == BinderFormula(ExistsOne, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) + assert(FOLParser.parseFormula("∀ 'x. (p)") == BinderFormula(Forall, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) + assert(FOLParser.parseFormula("∃ 'x. (p)") == BinderFormula(Exists, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) + assert(FOLParser.parseFormula("∃! 'x. (p)") == BinderFormula(ExistsOne, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) - assert(FOLParser.parseFormula("∀ 'x. p") == BinderFormula(Forall, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) - assert(FOLParser.parseFormula("∃ 'x. p") == BinderFormula(Exists, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) - assert(FOLParser.parseFormula("∃! 'x. p") == BinderFormula(ExistsOne, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) + assert(FOLParser.parseFormula("∀ 'x. p") == BinderFormula(Forall, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) + assert(FOLParser.parseFormula("∃ 'x. p") == BinderFormula(Exists, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) + assert(FOLParser.parseFormula("∃! 'x. p") == BinderFormula(ExistsOne, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) } test("nested quantifiers") { @@ -150,7 +150,7 @@ class ParserTest extends AnyFunSuite with TestUtils { FOLParser.parseFormula("∀ 'x. p('x) ∧ q('x)") == BinderFormula( Forall, x, - ConnectorFormula(And, Seq(PredicateFormula(ConstantPredicateLabel("p", 1), Seq(x)), PredicateFormula(ConstantPredicateLabel("q", 1), Seq(x)))) + ConnectorFormula(And, Seq(AtomicFormula(ConstantAtomicLabel("p", 1), Seq(x)), AtomicFormula(ConstantAtomicLabel("q", 1), Seq(x)))) ) ) @@ -160,8 +160,8 @@ class ParserTest extends AnyFunSuite with TestUtils { FOLParser.parseFormula("(∀ 'x. p('x)) ∧ q('x)") == ConnectorFormula( And, Seq( - BinderFormula(Forall, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 1), Seq(x))), - PredicateFormula(ConstantPredicateLabel("q", 1), Seq(x)) + BinderFormula(Forall, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 1), Seq(x))), + AtomicFormula(ConstantAtomicLabel("q", 1), Seq(x)) ) ) ) @@ -181,7 +181,7 @@ class ParserTest extends AnyFunSuite with TestUtils { } test("complex formulas") { - assert(FOLParser.parseFormula("∀x. 'x = 'x") == BinderFormula(Forall, x, PredicateFormula(equality, Seq(x, x)))) + assert(FOLParser.parseFormula("∀x. 'x = 'x") == BinderFormula(Forall, x, AtomicFormula(equality, Seq(x, x)))) } test("parser limitations") { @@ -191,23 +191,23 @@ class ParserTest extends AnyFunSuite with TestUtils { } test("sequent") { - val forallEq = BinderFormula(Forall, x, PredicateFormula(equality, Seq(x, x))) + val forallEq = BinderFormula(Forall, x, AtomicFormula(equality, Seq(x, x))) assert(FOLParser.parseSequent("∀x. 'x = 'x") == Sequent(Set(), Set(forallEq))) assert(FOLParser.parseSequent("⊢ ∀x. 'x = 'x") == Sequent(Set(), Set(forallEq))) assert(FOLParser.parseSequent("∀x. 'x = 'x ⊢ ∀x. 'x = 'x") == Sequent(Set(forallEq), Set(forallEq))) - val existsXEq = BinderFormula(Exists, x, PredicateFormula(equality, Seq(x, x))) + val existsXEq = BinderFormula(Exists, x, AtomicFormula(equality, Seq(x, x))) assert(FOLParser.parseSequent("∀x. 'x = 'x ⊢ ∃x. 'x = 'x") == Sequent(Set(forallEq), Set(existsXEq))) - val existsYEq = BinderFormula(Exists, y, PredicateFormula(equality, Seq(y, y))) + val existsYEq = BinderFormula(Exists, y, AtomicFormula(equality, Seq(y, y))) assert(FOLParser.parseSequent("∀x. 'x = 'x ⊢ ∃x. 'x = 'x; ∃y. 'y = 'y") == Sequent(Set(forallEq), Set(existsYEq, existsXEq))) assert( FOLParser.parseSequent("p ; ∀x. 'x = 'x ⊢ ∃x. 'x = 'x; ∃y. 'y = 'y") == - Sequent(Set(forallEq, PredicateFormula(ConstantPredicateLabel("p", 0), Seq())), Set(existsYEq, existsXEq)) + Sequent(Set(forallEq, AtomicFormula(ConstantAtomicLabel("p", 0), Seq())), Set(existsYEq, existsXEq)) ) } test("sequents from Mapping and SetTheory") { val va = VariableLabel("a") - val leftAndRight = BinderFormula(ExistsOne, x, PredicateFormula(sPhi2, Seq(x, va))) + val leftAndRight = BinderFormula(ExistsOne, x, AtomicFormula(sPhi2, Seq(x, va))) assert(FOLParser.parseSequent("∃!x. 'phi('x, 'a) ⊢ ∃!x. 'phi('x, 'a)") == Sequent(Set(leftAndRight), Set(leftAndRight))) assert( @@ -233,11 +233,11 @@ class ParserTest extends AnyFunSuite with TestUtils { test("equivalent names") { val parser = Parser(SynonymInfoBuilder().addSynonyms(in.id, "∊").build, "∊" :: Nil, Nil) - assert(parser.parseFormula("x∊y") == PredicateFormula(in, Seq(cx, cy))) - assert(parser.parseFormula("x ∊ y") == PredicateFormula(in, Seq(cx, cy))) - assert(parser.parseFormula("'x ∊ 'y") == PredicateFormula(in, Seq(x, y))) - assert(parser.parseFormula("('x ∊ 'y) /\\ a") == ConnectorFormula(And, Seq(PredicateFormula(in, Seq(x, y)), a))) - assert(parser.parseFormula("a \\/ ('x ∊ 'y)") == ConnectorFormula(Or, Seq(a, PredicateFormula(in, Seq(x, y))))) + assert(parser.parseFormula("x∊y") == AtomicFormula(in, Seq(cx, cy))) + assert(parser.parseFormula("x ∊ y") == AtomicFormula(in, Seq(cx, cy))) + assert(parser.parseFormula("'x ∊ 'y") == AtomicFormula(in, Seq(x, y))) + assert(parser.parseFormula("('x ∊ 'y) /\\ a") == ConnectorFormula(And, Seq(AtomicFormula(in, Seq(x, y)), a))) + assert(parser.parseFormula("a \\/ ('x ∊ 'y)") == ConnectorFormula(Or, Seq(a, AtomicFormula(in, Seq(x, y))))) } test("infix functions") { @@ -248,19 +248,19 @@ class ParserTest extends AnyFunSuite with TestUtils { test("mix of infix functions and infix predicates") { val parser = Parser(SynonymInfoBuilder().addSynonyms(in.id, "∊").addSynonyms(plus.id, "+").build, "∊" :: Nil, ("+", Associativity.Left) :: Nil) - assert(parser.parseFormula("(x + y) ∊ z") == PredicateFormula(in, Seq(Term(plus, Seq(cx, cy)), cz))) + assert(parser.parseFormula("(x + y) ∊ z") == AtomicFormula(in, Seq(Term(plus, Seq(cx, cy)), cz))) assert( parser.parseFormula("x ∊ y /\\ x ∊ z /\\ (x + y) ∊ z") == ConnectorFormula( And, - Seq(ConnectorFormula(And, Seq(PredicateFormula(in, Seq(cx, cy)), PredicateFormula(in, Seq(cx, cz)))), PredicateFormula(in, Seq(Term(plus, Seq(cx, cy)), cz))) + Seq(ConnectorFormula(And, Seq(AtomicFormula(in, Seq(cx, cy)), AtomicFormula(in, Seq(cx, cz)))), AtomicFormula(in, Seq(Term(plus, Seq(cx, cy)), cz))) ) ) } test("infix function and predicate priority") { val parser = Parser(SynonymInfoBuilder().addSynonyms(plus.id, "+").build, equality.id :: Nil, ("+", Associativity.Left) :: Nil) - assert(parser.parseFormula("(x + y) = (y + x)") == PredicateFormula(equality, Seq(plus(cx, cy), plus(cy, cx)))) - assert(parser.parseFormula("x + y = y + x") == PredicateFormula(equality, Seq(plus(cx, cy), plus(cy, cx)))) + assert(parser.parseFormula("(x + y) = (y + x)") == AtomicFormula(equality, Seq(plus(cx, cy), plus(cy, cx)))) + assert(parser.parseFormula("x + y = y + x") == AtomicFormula(equality, Seq(plus(cx, cy), plus(cy, cx)))) } test("parser exception: unexpected input") { diff --git a/lisa-utils/src/test/scala/lisa/utils/PrinterTest.scala b/lisa-utils/src/test/scala/lisa/utils/PrinterTest.scala index 5a776019..8f213241 100644 --- a/lisa-utils/src/test/scala/lisa/utils/PrinterTest.scala +++ b/lisa-utils/src/test/scala/lisa/utils/PrinterTest.scala @@ -31,17 +31,17 @@ class PrinterTest extends AnyFunSuite with TestUtils { FOLParser.printFormula(ConnectorFormula(And, Seq(ConnectorFormula(And, Seq(ConnectorFormula(Neg, Seq(a)), ConnectorFormula(Neg, Seq(b)))), ConnectorFormula(Neg, Seq(c))))) == "¬a ∧ ¬b ∧ ¬c" ) - assert(FOLParser.printFormula(ConnectorFormula(And, Seq(a, PredicateFormula(equality, Seq(x, x))))) == "a ∧ 'x = 'x") + assert(FOLParser.printFormula(ConnectorFormula(And, Seq(a, AtomicFormula(equality, Seq(x, x))))) == "a ∧ 'x = 'x") - assert(FOLParser.printFormula(BinderFormula(Forall, x, PredicateFormula(equality, Seq(x, x)))) == "∀'x. 'x = 'x") - assert(FOLParser.printFormula(ConnectorFormula(And, Seq(a, BinderFormula(Forall, x, PredicateFormula(equality, Seq(x, x)))))) == "a ∧ (∀'x. 'x = 'x)") + assert(FOLParser.printFormula(BinderFormula(Forall, x, AtomicFormula(equality, Seq(x, x)))) == "∀'x. 'x = 'x") + assert(FOLParser.printFormula(ConnectorFormula(And, Seq(a, BinderFormula(Forall, x, AtomicFormula(equality, Seq(x, x)))))) == "a ∧ (∀'x. 'x = 'x)") assert(FOLParser.printFormula(ConnectorFormula(And, Seq(BinderFormula(Forall, x, b), a))) == "(∀'x. b) ∧ a") assert(FOLParser.printFormula(ConnectorFormula(And, Seq(ConnectorFormula(And, Seq(a, BinderFormula(Forall, x, b))), a))) == "a ∧ (∀'x. b) ∧ a") assert(FOLParser.printFormula(ConnectorFormula(Or, Seq(ConnectorFormula(And, Seq(a, BinderFormula(Forall, x, b))), a))) == "a ∧ (∀'x. b) ∨ a") assert(FOLParser.printFormula(BinderFormula(Forall, x, BinderFormula(Exists, y, BinderFormula(ExistsOne, z, a)))) == "∀'x. ∃'y. ∃!'z. a") - assert(FOLParser.printFormula(PredicateFormula(ConstantPredicateLabel("f", 3), Seq(x, y, z))) == "f('x, 'y, 'z)") + assert(FOLParser.printFormula(AtomicFormula(ConstantAtomicLabel("f", 3), Seq(x, y, z))) == "f('x, 'y, 'z)") } test("constant") { @@ -77,17 +77,17 @@ class PrinterTest extends AnyFunSuite with TestUtils { } test("0-ary predicate") { - assert(FOLParser.printFormula(PredicateFormula(ConstantPredicateLabel("a", 0), Seq())) == "a") + assert(FOLParser.printFormula(AtomicFormula(ConstantAtomicLabel("a", 0), Seq())) == "a") } test("predicate application") { - assert(FOLParser.printFormula(PredicateFormula(ConstantPredicateLabel("p", 3), Seq(cx, cy, cz))) == "p(x, y, z)") - assert(FOLParser.printFormula(PredicateFormula(ConstantPredicateLabel("p", 3), Seq(x, y, z))) == "p('x, 'y, 'z)") + assert(FOLParser.printFormula(AtomicFormula(ConstantAtomicLabel("p", 3), Seq(cx, cy, cz))) == "p(x, y, z)") + assert(FOLParser.printFormula(AtomicFormula(ConstantAtomicLabel("p", 3), Seq(x, y, z))) == "p('x, 'y, 'z)") } test("equality") { - assert(FOLParser.printFormula(PredicateFormula(equality, Seq(cx, cx))) == "x = x") - assert(FOLParser.printFormula(ConnectorFormula(And, Seq(a, PredicateFormula(equality, Seq(x, x))))) == "a ∧ 'x = 'x") + assert(FOLParser.printFormula(AtomicFormula(equality, Seq(cx, cx))) == "x = x") + assert(FOLParser.printFormula(ConnectorFormula(And, Seq(a, AtomicFormula(equality, Seq(x, x))))) == "a ∧ 'x = 'x") } test("toplevel connectors") { @@ -166,9 +166,9 @@ class PrinterTest extends AnyFunSuite with TestUtils { } test("quantifiers") { - assert(FOLParser.printFormula(BinderFormula(Forall, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) == "∀'x. p") - assert(FOLParser.printFormula(BinderFormula(Exists, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) == "∃'x. p") - assert(FOLParser.printFormula(BinderFormula(ExistsOne, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 0), Seq()))) == "∃!'x. p") + assert(FOLParser.printFormula(BinderFormula(Forall, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) == "∀'x. p") + assert(FOLParser.printFormula(BinderFormula(Exists, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) == "∃'x. p") + assert(FOLParser.printFormula(BinderFormula(ExistsOne, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 0), Seq()))) == "∃!'x. p") } test("nested quantifiers") { @@ -182,7 +182,7 @@ class PrinterTest extends AnyFunSuite with TestUtils { BinderFormula( Forall, x, - ConnectorFormula(And, Seq(PredicateFormula(ConstantPredicateLabel("p", 1), Seq(x)), PredicateFormula(ConstantPredicateLabel("q", 1), Seq(x)))) + ConnectorFormula(And, Seq(AtomicFormula(ConstantAtomicLabel("p", 1), Seq(x)), AtomicFormula(ConstantAtomicLabel("q", 1), Seq(x)))) ) ) == "∀'x. p('x) ∧ q('x)" ) @@ -194,8 +194,8 @@ class PrinterTest extends AnyFunSuite with TestUtils { ConnectorFormula( And, Seq( - BinderFormula(Forall, VariableLabel("x"), PredicateFormula(ConstantPredicateLabel("p", 1), Seq(x))), - PredicateFormula(ConstantPredicateLabel("q", 1), Seq(x)) + BinderFormula(Forall, VariableLabel("x"), AtomicFormula(ConstantAtomicLabel("p", 1), Seq(x))), + AtomicFormula(ConstantAtomicLabel("q", 1), Seq(x)) ) ) ) == "(∀'x. p('x)) ∧ q('x)" @@ -215,35 +215,35 @@ class PrinterTest extends AnyFunSuite with TestUtils { } test("complex formulas") { - assert(FOLParser.printFormula(BinderFormula(Forall, x, PredicateFormula(equality, Seq(x, x)))) == "∀'x. 'x = 'x") + assert(FOLParser.printFormula(BinderFormula(Forall, x, AtomicFormula(equality, Seq(x, x)))) == "∀'x. 'x = 'x") } test("sequent") { - val forallEq = BinderFormula(Forall, x, PredicateFormula(equality, Seq(x, x))) + val forallEq = BinderFormula(Forall, x, AtomicFormula(equality, Seq(x, x))) assert(FOLParser.printSequent(Sequent(Set(), Set(forallEq))) == "⊢ ∀'x. 'x = 'x") assert(FOLParser.printSequent(Sequent(Set(forallEq), Set(forallEq))) == "∀'x. 'x = 'x ⊢ ∀'x. 'x = 'x") - val existsXEq = BinderFormula(Exists, x, PredicateFormula(equality, Seq(x, x))) + val existsXEq = BinderFormula(Exists, x, AtomicFormula(equality, Seq(x, x))) assert(FOLParser.printSequent(Sequent(Set(forallEq), Set(existsXEq))) == "∀'x. 'x = 'x ⊢ ∃'x. 'x = 'x") } // warning: this test might be flaky because formula order is not fixed in sequents but fixed in the string representation test("sequent with multiple formulas") { - val forallEq = BinderFormula(Forall, x, PredicateFormula(equality, Seq(x, x))) - val existsXEq = BinderFormula(Exists, x, PredicateFormula(equality, Seq(x, x))) - val existsYEq = BinderFormula(Exists, y, PredicateFormula(equality, Seq(y, y))) + val forallEq = BinderFormula(Forall, x, AtomicFormula(equality, Seq(x, x))) + val existsXEq = BinderFormula(Exists, x, AtomicFormula(equality, Seq(x, x))) + val existsYEq = BinderFormula(Exists, y, AtomicFormula(equality, Seq(y, y))) assert( FOLParser.printSequent(Sequent(Set(forallEq), Set(existsYEq, existsXEq))) == "∀'x. 'x = 'x ⊢ ∃'y. 'y = 'y; " + "∃'x. 'x = 'x" ) assert( - FOLParser.printSequent(Sequent(Set(forallEq, PredicateFormula(ConstantPredicateLabel("p", 0), Seq())), Set(existsYEq, existsXEq))) == "∀'x. 'x = 'x; p ⊢ ∃'y. 'y = 'y; ∃'x. 'x = 'x" + FOLParser.printSequent(Sequent(Set(forallEq, AtomicFormula(ConstantAtomicLabel("p", 0), Seq())), Set(existsYEq, existsXEq))) == "∀'x. 'x = 'x; p ⊢ ∃'y. 'y = 'y; ∃'x. 'x = 'x" ) } // warning: this test might be flaky because formula order is not fixed in sequents but fixed in the string representation test("sequents from Mapping and SetTheory") { val va = VariableLabel("a") - val leftAndRight = BinderFormula(ExistsOne, x, PredicateFormula(sPhi2, Seq(x, va))) + val leftAndRight = BinderFormula(ExistsOne, x, AtomicFormula(sPhi2, Seq(x, va))) assert(FOLParser.printSequent(Sequent(Set(leftAndRight), Set(leftAndRight))) == "∃!'x. 'phi('x, 'a) ⊢ ∃!'x. 'phi('x, 'a)") assert( @@ -274,18 +274,18 @@ class PrinterTest extends AnyFunSuite with TestUtils { } test("infix predicates") { - val in = ConstantPredicateLabel("∊", 2) - val prefixIn = ConstantPredicateLabel("elem", 2) + val in = ConstantAtomicLabel("∊", 2) + val prefixIn = ConstantAtomicLabel("elem", 2) val parser = Parser(SynonymInfoBuilder().addSynonyms(prefixIn.id, in.id).build, in.id :: Nil, Nil) - assert(parser.printFormula(PredicateFormula(in, Seq(cx, cy))) == "x ∊ y") - assert(parser.printFormula(PredicateFormula(in, Seq(x, y))) == "'x ∊ 'y") - assert(parser.printFormula(ConnectorFormula(And, Seq(PredicateFormula(in, Seq(x, y)), a))) == "'x ∊ 'y ∧ a") - assert(parser.printFormula(ConnectorFormula(Or, Seq(a, PredicateFormula(in, Seq(x, y))))) == "a ∨ 'x ∊ 'y") - - assert(parser.printFormula(PredicateFormula(prefixIn, Seq(cx, cy))) == "x ∊ y") - assert(parser.printFormula(PredicateFormula(prefixIn, Seq(x, y))) == "'x ∊ 'y") - assert(parser.printFormula(ConnectorFormula(And, Seq(PredicateFormula(prefixIn, Seq(x, y)), a))) == "'x ∊ 'y ∧ a") - assert(parser.printFormula(ConnectorFormula(Or, Seq(a, PredicateFormula(prefixIn, Seq(x, y))))) == "a ∨ 'x ∊ 'y") + assert(parser.printFormula(AtomicFormula(in, Seq(cx, cy))) == "x ∊ y") + assert(parser.printFormula(AtomicFormula(in, Seq(x, y))) == "'x ∊ 'y") + assert(parser.printFormula(ConnectorFormula(And, Seq(AtomicFormula(in, Seq(x, y)), a))) == "'x ∊ 'y ∧ a") + assert(parser.printFormula(ConnectorFormula(Or, Seq(a, AtomicFormula(in, Seq(x, y))))) == "a ∨ 'x ∊ 'y") + + assert(parser.printFormula(AtomicFormula(prefixIn, Seq(cx, cy))) == "x ∊ y") + assert(parser.printFormula(AtomicFormula(prefixIn, Seq(x, y))) == "'x ∊ 'y") + assert(parser.printFormula(ConnectorFormula(And, Seq(AtomicFormula(prefixIn, Seq(x, y)), a))) == "'x ∊ 'y ∧ a") + assert(parser.printFormula(ConnectorFormula(Or, Seq(a, AtomicFormula(prefixIn, Seq(x, y))))) == "a ∨ 'x ∊ 'y") } test("infix functions") { @@ -296,12 +296,12 @@ class PrinterTest extends AnyFunSuite with TestUtils { /* test("mix of infix functions and infix predicates") { val parser = Parser(SynonymInfoBuilder().addSynonyms(in.id, "∊").addSynonyms(plus.id, "+").build, "∊" :: Nil, ("+", Associativity.Left) :: Nil) - assert(parser.printFormula(PredicateFormula(in, Seq(Term(plus, Seq(cx, cy)), cz))) == "x + y ∊ z") + assert(parser.printFormula(AtomicFormula(in, Seq(Term(plus, Seq(cx, cy)), cz))) == "x + y ∊ z") assert( parser.printFormula( ConnectorFormula( And, - Seq(ConnectorFormula(And, Seq(PredicateFormula(in, Seq(cx, cy)), PredicateFormula(in, Seq(cx, cz)))), PredicateFormula(in, Seq(Term(plus, Seq(cx, cy)), cz))) + Seq(ConnectorFormula(And, Seq(AtomicFormula(in, Seq(cx, cy)), AtomicFormula(in, Seq(cx, cz)))), AtomicFormula(in, Seq(Term(plus, Seq(cx, cy)), cz))) ) ) == "x ∊ y ∧ x ∊ z ∧ x + y ∊ z" ) diff --git a/lisa-utils/src/test/scala/lisa/utils/TestUtils.scala b/lisa-utils/src/test/scala/lisa/utils/TestUtils.scala index daaa0667..243bd3c1 100644 --- a/lisa-utils/src/test/scala/lisa/utils/TestUtils.scala +++ b/lisa-utils/src/test/scala/lisa/utils/TestUtils.scala @@ -8,8 +8,8 @@ import lisa.utils.KernelHelpers.{_, given} import lisa.utils.{_, given} trait TestUtils { - val (a, b, c) = (ConstantPredicateLabel("a", 0), ConstantPredicateLabel("b", 0), ConstantPredicateLabel("c", 0)) - val p = ConstantPredicateLabel("p", 1) + val (a, b, c) = (ConstantAtomicLabel("a", 0), ConstantAtomicLabel("b", 0), ConstantAtomicLabel("c", 0)) + val p = ConstantAtomicLabel("p", 1) val (x, y, z) = (VariableLabel("x"), VariableLabel("y"), VariableLabel("z")) val (x1, y1, z1) = (VariableLabel("x1"), VariableLabel("y1"), VariableLabel("z1")) val (xPrime, yPrime, zPrime) = (VariableLabel("x'"), VariableLabel("y'"), VariableLabel("z'")) @@ -18,9 +18,9 @@ trait TestUtils { val (sf1, sf2, sf3) = (SchematicFunctionLabel("f", 1), SchematicFunctionLabel("f", 2), SchematicFunctionLabel("f", 3)) val (sPhi1, sPhi2) = (SchematicPredicateLabel("phi", 1), SchematicPredicateLabel("phi", 2)) val (sc1, sc2) = (SchematicConnectorLabel("c", 1), SchematicConnectorLabel("c", 2)) - val (in, plus) = (ConstantPredicateLabel("elem", 2), ConstantFunctionLabel("+", 2)) + val (in, plus) = (ConstantAtomicLabel("elem", 2), ConstantFunctionLabel("+", 2)) - given Conversion[PredicateLabel, PredicateFormula] = PredicateFormula(_, Seq.empty) + given Conversion[AtomicLabel, AtomicFormula] = AtomicFormula(_, Seq.empty) given Conversion[ConstantFunctionLabel, Term] = Term(_, Seq()) -- GitLab