diff --git a/lisa-examples/src/main/scala/Example.scala b/lisa-examples/src/main/scala/Example.scala index d494a5222e25a1e35b95a2a19aabf47ff7ff342a..00a566cfcc080853d84838a66a405f9e73966e63 100644 --- a/lisa-examples/src/main/scala/Example.scala +++ b/lisa-examples/src/main/scala/Example.scala @@ -1,22 +1,25 @@ import lisa.Main +import lisa.automation.kernel.SimplePropositionalSolver.* import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof import lisa.kernel.proof.SCProofChecker import lisa.kernel.proof.SCProofChecker.* import lisa.kernel.proof.SequentCalculus.* -import lisa.automation.kernel.SimplePropositionalSolver.solveSequent import lisa.tptp.KernelParser.* import lisa.tptp.ProblemGatherer.* import lisa.tptp.* +import lisa.utils.Helpers.show import lisa.utils.Helpers.{_, given} import lisa.utils.Printer.* +import lisa.utils.tactics.ProofStepLib.ProofStep /** * Discover some of the elements of LISA to get started. */ object Example { def main(args: Array[String]): Unit = { - //proofExample() // uncomment when exercise finished + + proofExample() // uncomment when exercise finished // solverExample() // tptpExample() } @@ -27,23 +30,20 @@ object Example { * The last two lines don't need to be changed. */ def proofExample(): Unit = { + object Ex extends Main { - THEOREM("fixedPointDoubleApplication") of "" PROOF { - steps( - ???, - ???, - ?????(Set(P(x), P(f(x)), P(f(x)) ==> P(f(f(x)))) |- P(f(f(x))), 1, 0, ????, ????), - Hypothesis(Set(P(x), P(f(x)) ==> P(f(f(x)))) |- Set(P(x), P(f(f(x)))), P(x)), - LeftImplies(???? |- ????, 3, 2, ????, ????), - LeftForall(Set(????, ????, ????) |- ????, 4, ????, x, x), - LeftForall(Set(????, ????) |- ????, 5, P(x) ==> P(f(x)), x, f(x)), - RightImplies(forall(x, P(x) ==> P(f(x))) |- P(x) ==> P(f(f(x))), 6, P(x), P(f(f(x)))), - RightForall(forall(x, P(x) ==> P(f(x))) |- forall(x, P(x) ==> P(f(f(x)))), 7, P(x) ==> P(f(f(x))), x) - ) - } using () - show + THEOREM("fixedPointDoubleApplication") of "∀'x. 'P('x) ⇒ 'P('f('x)) ⊢ 'P('x) ⇒ 'P('f('f('x)))" PROOF { + assume(forall(x, P(x) ==> P(f(x)))) + val base = have((P(x) ==> P(f(x)), P(f(x)) ==> P(f(f(x)))) |- P(x) ==> P(f(f(x)))) by Trivial + have(() |- P(x) ==> P(f(f(x)))) by SUBPROOF { + have(P(f(x)) ==> P(f(f(x))) |- P(x) ==> P(f(f(x)))) by LeftForall(x)(base) + andThen(() |- P(x) ==> P(f(f(x)))) by LeftForall(f(x)) + } + } + show } + Ex.main(Array("")) } @@ -149,8 +149,11 @@ object Example { val A = PredicateFormula(VariableFormulaLabel("A"), Seq()) val B = PredicateFormula(VariableFormulaLabel("B"), Seq()) val C = PredicateFormula(VariableFormulaLabel("C"), Seq()) + val H = VariableFormulaLabel("H") val x = VariableLabel("x") - val f = ConstantFunctionLabel("f", 1) + val y = VariableLabel("y") + val z = VariableLabel("z") + val f = SchematicFunctionLabel("f", 1) def ???? : Formula = ??? def ?????(args: Any*) = ??? diff --git a/lisa-utils/src/main/scala/lisa/utils/KernelHelpers.scala b/lisa-utils/src/main/scala/lisa/utils/KernelHelpers.scala index 56981317d898906782d135b24b9458fdcdfd8f58..16af6f19d7cb4defeba3bb11b1af69c1c5d115a1 100644 --- a/lisa-utils/src/main/scala/lisa/utils/KernelHelpers.scala +++ b/lisa-utils/src/main/scala/lisa/utils/KernelHelpers.scala @@ -6,6 +6,9 @@ import lisa.kernel.proof.RunningTheoryJudgement.InvalidJustification import lisa.kernel.proof.SCProof import lisa.kernel.proof.SCProofCheckerJudgement.SCInvalidProof import lisa.kernel.proof.SequentCalculus.* +import lisa.utils.Parser.parseFormula +import lisa.utils.Parser.parseSequent +import lisa.utils.Parser.parseTerm /** * A helper file that provides various syntactic sugars for LISA's FOL and proofs. Best imported through utilities.Helpers @@ -181,4 +184,19 @@ trait KernelHelpers { |(step ${judgement.path.mkString("->")}): ${judgement.message}""".stripMargin } + implicit class Parsing(val sc: StringContext) { + + def seq(args: Any*): Sequent = parseSequent(sc.parts.mkString("")) + + def f(args: Any*): Formula = parseFormula(sc.parts.mkString("")) + + def t(args: Any*): Term = parseTerm(sc.parts.mkString("")) + + } + + given Conversion[String, Sequent] = parseSequent(_) + given Conversion[String, Formula] = parseFormula(_) + given Conversion[String, Term] = parseTerm(_) + given Conversion[String, VariableLabel] = s => VariableLabel(if (s.head == '?') s.tail else s) + } diff --git a/lisa-utils/src/main/scala/lisa/utils/Library.scala b/lisa-utils/src/main/scala/lisa/utils/Library.scala index cfcb6846d43d5f1d85ca03192ea0d9bcc21a7c4c..5acd4867851eea3f9762662c60634ac6ae0764f1 100644 --- a/lisa-utils/src/main/scala/lisa/utils/Library.scala +++ b/lisa-utils/src/main/scala/lisa/utils/Library.scala @@ -1,17 +1,25 @@ package lisa.utils import lisa.kernel.proof.RunningTheory +import lisa.kernel.proof.SCProofChecker +import lisa.kernel.proof.SCProofCheckerJudgement +import lisa.kernel.proof.SequentCalculus +import lisa.utils.tactics.ProofStepLib.ProofStep + +import scala.collection.mutable.Stack as stack /** * A class abstracting a [[lisa.kernel.proof.RunningTheory]] providing utility functions and a convenient syntax * to write and use Theorems and Definitions. * @param theory The inner RunningTheory */ -abstract class Library(val theory: RunningTheory) { +abstract class Library(val theory: RunningTheory) extends lisa.utils.tactics.WithProofs { + val library: Library = this given RunningTheory = theory - export lisa.kernel.fol.FOL.* - export lisa.kernel.proof.SequentCalculus.* - export lisa.kernel.proof.SCProof as Proof + export lisa.kernel.fol.FOL.{Formula, *} + val SC: SequentCalculus.type = lisa.kernel.proof.SequentCalculus + export lisa.kernel.proof.SequentCalculus.{Sequent, SCProofStep} + export lisa.kernel.proof.SCProof export theory.{Justification, Theorem, Definition, Axiom, PredicateDefinition, FunctionDefinition} export lisa.utils.Helpers.{_, given} import lisa.kernel.proof.RunningTheoryJudgement as Judgement @@ -23,16 +31,19 @@ abstract class Library(val theory: RunningTheory) { private var last: Option[Justification] = None + val proofStack: stack[Proof] = stack() + /** * A function intended for use to construct a proof: - * <pre> Proof(steps(...), imports(...))</pre> + * <pre> SCProof(steps(...), imports(...))</pre> * Must contains [[SCProofStep]]'s */ inline def steps(sts: SCProofStep*): IndexedSeq[SCProofStep] = sts.toIndexedSeq + inline def Nsteps(sts: ProofStep*): IndexedSeq[ProofStep] = sts.toIndexedSeq /** * A function intended for use to construct a proof: - * <pre> Proof(steps(...), imports(...))</pre> + * <pre> SCProof(steps(...), imports(...))</pre> * Must contains [[Justification]]'s, [[Formula]]'s or [[Sequent]], all of which are converted adequatly automatically. */ inline def imports(sqs: Sequentable*): IndexedSeq[Sequent] = sqs.map(sequantableToSequent).toIndexedSeq @@ -42,7 +53,7 @@ abstract class Library(val theory: RunningTheory) { /** * An alias to create a Theorem */ - def makeTheorem(name: String, statement: String, proof: Proof, justifications: Seq[theory.Justification]): Judgement[theory.Theorem] = + def makeTheorem(name: String, statement: String, proof: SCProof, justifications: Seq[theory.Justification]): Judgement[theory.Theorem] = theory.theorem(name, statement, proof, justifications) /** @@ -53,12 +64,28 @@ abstract class Library(val theory: RunningTheory) { /** * Syntax: <pre> THEOREM("name") of "the sequent concluding the proof" PROOF { the proof } using (assumptions) </pre> */ - def PROOF(proof: Proof)(using String => Unit)(using Throwable => Nothing): TheoremNameWithProof = TheoremNameWithProof(name, statement, proof) + def PROOF2(proof: SCProof)(using String => Unit)(using finishOutput: Throwable => Nothing): TheoremNameWithProof = TheoremNameWithProof(name, statement, proof) /** * Syntax: <pre> THEOREM("name") of "the sequent concluding the proof" PROOF { the proof } using (assumptions) </pre> */ - def PROOF(steps: IndexedSeq[SCProofStep])(using String => Unit)(using Throwable => Nothing): TheoremNameWithProof = TheoremNameWithProof(name, statement, Proof(steps)) + def PROOF2(steps: IndexedSeq[SCProofStep])(using String => Unit)(using finishOutput: Throwable => Nothing): TheoremNameWithProof = + TheoremNameWithProof(name, statement, SCProof(steps)) + + def PROOF(computeProof: => Unit)(using String => Unit)(using finishOutput: Throwable => Nothing): theory.Theorem = { + require(proofStack.isEmpty) // TODO: More explicit error + proofStack.push(if (proofStack.isEmpty) new Proof() else new Proof(proofStack.head.getAssumptions)) + computeProof + val r = TheoremNameWithProof(name, statement, proofStack.head.toSCProof) + val r2 = theory.theorem(r.name, r.statement, r.proof, proofStack.head.getImports.map(_.reference.asInstanceOf[theory.Justification])) match { + case Judgement.ValidJustification(just) => + last = Some(just) + just + case wrongJudgement: Judgement.InvalidJustification[?] => wrongJudgement.showAndGet + } + proofStack.pop + r2 + } } /** @@ -80,7 +107,7 @@ abstract class Library(val theory: RunningTheory) { /** * Syntax: <pre> THEOREM("name") of "the sequent concluding the proof" PROOF { the proof } using (assumptions) </pre> */ - case class TheoremNameWithProof(name: String, statement: String, proof: Proof)(using String => Unit)(using Throwable => Nothing) { + case class TheoremNameWithProof(name: String, statement: String, proof: SCProof)(using String => Unit)(using Throwable => Nothing) { infix def using(justifications: theory.Justification*): theory.Theorem = theory.theorem(name, statement, proof, justifications) match { case Judgement.ValidJustification(just) => last = Some(just) @@ -101,21 +128,22 @@ abstract class Library(val theory: RunningTheory) { */ def simpleDefinition(symbol: String, expression: LambdaTermTerm): Judgement[theory.FunctionDefinition] = { val LambdaTermTerm(vars, body) = expression + val out: VariableLabel = VariableLabel(freshId((vars.map(_.id) ++ body.schematicTermLabels.map(_.id)).toSet, "y")) - val proof: Proof = simpleFunctionDefinition(expression, out) + val proof: SCProof = simpleFunctionDefinition(expression, out) theory.functionDefinition(symbol, LambdaTermFormula(vars, out === body), out, proof, Nil) } /** * Allows to create a definition by existential uniqueness of a function symbol: */ - def complexDefinition(symbol: String, vars: Seq[VariableLabel], v: VariableLabel, f: Formula, proof: Proof, just: Seq[Justification]): Judgement[theory.FunctionDefinition] = { + def complexDefinition(symbol: String, vars: Seq[VariableLabel], v: VariableLabel, f: Formula, proof: SCProof, just: Seq[Justification]): Judgement[theory.FunctionDefinition] = { theory.functionDefinition(symbol, LambdaTermFormula(vars, f), v, proof, just) // theory.functionDefinition(symbol, LambdaTermFormula(vars, instantiateTermSchemas(f, Map(v -> LambdaTermTerm(Nil, out)))), out, proof, just) } /** - * Allows to create a definition by shortcut of a function symbol: + * Allows to create a definition by shortcut of a predicate symbol: */ def simpleDefinition(symbol: String, expression: LambdaTermFormula): Judgement[theory.PredicateDefinition] = theory.predicateDefinition(symbol, expression) @@ -130,7 +158,7 @@ abstract class Library(val theory: RunningTheory) { /** * Syntax: <pre> DEFINE("symbol", arguments) as "definition" </pre> */ - infix def as(t: Term)(using String => Unit)(using Throwable => Nothing): ConstantFunctionLabel = { + infix def as(t: Term)(using String => Unit)(using finishOutput: Throwable => Nothing): ConstantFunctionLabel = { val definition = simpleDefinition(symbol, LambdaTermTerm(vars, t)) match { case Judgement.ValidJustification(just) => last = Some(just) @@ -143,7 +171,7 @@ abstract class Library(val theory: RunningTheory) { /** * Syntax: <pre> DEFINE("symbol", arguments) as "definition" </pre> */ - infix def as(f: Formula)(using String => Unit)(using Throwable => Nothing): ConstantPredicateLabel = { + infix def as(f: Formula)(using String => Unit)(using finishOutput: Throwable => Nothing): ConstantPredicateLabel = { val definition = simpleDefinition(symbol, LambdaTermFormula(vars, f)) match { case Judgement.ValidJustification(just) => last = Some(just) @@ -178,18 +206,18 @@ abstract class Library(val theory: RunningTheory) { /** * Syntax: <pre> DEFINE("symbol", arguments) asThe x suchThat P(x) PROOF { the proof } using (assumptions) </pre> */ - infix def PROOF(proof: Proof): DefinitionWithProof = DefinitionWithProof(symbol, vars, out, f, proof) + infix def PROOF(proof: SCProof): DefinitionWithProof = DefinitionWithProof(symbol, vars, out, f, proof) } /** * Syntax: <pre> DEFINE("symbol", arguments) asThe x suchThat P(x) PROOF { the proof } using (assumptions) </pre> */ - case class DefinitionWithProof(symbol: String, vars: Seq[VariableLabel], out: VariableLabel, f: Formula, proof: Proof) { + case class DefinitionWithProof(symbol: String, vars: Seq[VariableLabel], out: VariableLabel, f: Formula, proof: SCProof) { /** * Syntax: <pre> DEFINE("symbol", arguments) asThe x suchThat P(x) PROOF { the proof } using (assumptions) </pre> */ - infix def using(justifications: theory.Justification*)(using String => Unit)(using Throwable => Nothing): ConstantFunctionLabel = { + infix def using(justifications: theory.Justification*)(using String => Unit)(using finishOutput: Throwable => Nothing): ConstantFunctionLabel = { val definition = complexDefinition(symbol, vars, out, f, proof, justifications) match { case Judgement.ValidJustification(just) => last = Some(just) @@ -202,7 +230,7 @@ abstract class Library(val theory: RunningTheory) { /** * Syntax: <pre> DEFINE("symbol", arguments) asThe x suchThat P(x) PROOF { the proof } using (assumptions) </pre> */ - infix def using(u: Unit)(using String => Unit)(using Throwable => Nothing): ConstantFunctionLabel = using() + infix def using(u: Unit)(using String => Unit)(using finishOutput: Throwable => Nothing): ConstantFunctionLabel = using() } /** @@ -213,21 +241,23 @@ abstract class Library(val theory: RunningTheory) { /** * For a definition of the type f(x) := term, construct the required proof ?!y. y = term. */ - private def simpleFunctionDefinition(expression: LambdaTermTerm, out: VariableLabel): Proof = { + private def simpleFunctionDefinition(expression: LambdaTermTerm, out: VariableLabel): SCProof = { val x = out val LambdaTermTerm(vars, body) = expression val xeb = x === body val y = VariableLabel(freshId(body.freeVariables.map(_.id) ++ vars.map(_.id) + out.id, "y")) - val s0 = RightRefl(() |- body === body, body === body) - val s1 = Rewrite(() |- (xeb) <=> (xeb), 0) - val s2 = RightForall(() |- forall(x, (xeb) <=> (xeb)), 1, (xeb) <=> (xeb), x) - val s3 = RightExists(() |- exists(y, forall(x, (x === y) <=> (xeb))), 2, forall(x, (x === y) <=> (xeb)), y, body) - val s4 = Rewrite(() |- existsOne(x, xeb), 3) + val s0 = SC.RightRefl(() |- body === body, body === body) + val s1 = SC.Rewrite(() |- (xeb) <=> (xeb), 0) + val s2 = SC.RightForall(() |- forall(x, (xeb) <=> (xeb)), 1, (xeb) <=> (xeb), x) + val s3 = SC.RightExists(() |- exists(y, forall(x, (x === y) <=> (xeb))), 2, forall(x, (x === y) <=> (xeb)), y, body) + val s4 = SC.Rewrite(() |- existsOne(x, xeb), 3) val v = Vector(s0, s1, s2, s3, s4) - Proof(v) + SCProof(v) } - // Implicit conversions + ////////////////////////////////////////// + // Tools for proof development // + ////////////////////////////////////////// given Conversion[TheoremNameWithProof, theory.Theorem] = _.using() @@ -274,7 +304,7 @@ abstract class Library(val theory: RunningTheory) { /** * Prints a short representation of the last theorem or definition introduced */ - def show(using String => Unit): Justification = last match { + def show(using String => Unit)(using finishOutput: Throwable => Nothing): Justification = last match { case Some(value) => value.show case None => throw new NoSuchElementException("There is nothing to show: No theorem or definition has been proved yet.") } @@ -304,4 +334,10 @@ abstract class Library(val theory: RunningTheory) { builder.result } + def showCurrentProof()(using output: String => Unit)(using finishOutput: Throwable => Nothing) = { + val proof = proofStack.head.toSCProof + output(s" Current proof (possibly uncomplete) is:\n${Printer.prettySCProof(proof)}\n") + + } + } diff --git a/lisa-utils/src/main/scala/lisa/utils/TheoriesHelpers.scala b/lisa-utils/src/main/scala/lisa/utils/TheoriesHelpers.scala index 9f6cfbc4858269d67a58d097cfcfeb3dbaf22bf3..a115e4c681db32b72666d9abe3c0ea9184aac51d 100644 --- a/lisa-utils/src/main/scala/lisa/utils/TheoriesHelpers.scala +++ b/lisa-utils/src/main/scala/lisa/utils/TheoriesHelpers.scala @@ -108,6 +108,26 @@ trait TheoriesHelpers extends KernelHelpers { } } + extension (proofJudgement: SCProofCheckerJudgement) { + + /** + * If the SCProof is valid, show the inner proof and returns it. + * Otherwise, output the error leading to the invalid justification and throw an error. + */ + def showAndGet(using output: String => Unit)(using finishOutput: Throwable => Nothing): SCProof = { + proofJudgement match { + case SCProofCheckerJudgement.SCValidProof(proof) => + output(Printer.prettySCProof(proofJudgement)) + proof + case ip @ SCProofCheckerJudgement.SCInvalidProof(proof, path, message) => + output(s"$message\n${Printer.prettySCProof(proofJudgement)}") + finishOutput(InvalidJustificationException("", Some(ip))) + } + } + } + + case class InvalidProofException(proofJudgement: SCProofCheckerJudgement.SCInvalidProof) extends Exception(proofJudgement.message) + /** * Output a readable representation of a proof. */ diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala new file mode 100644 index 0000000000000000000000000000000000000000..612bd42ae49f7f4a3593628a69501405163a9957 --- /dev/null +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala @@ -0,0 +1,965 @@ +package lisa.utils.tactics + +import lisa.kernel.fol.FOL.* +import lisa.kernel.proof.SCProof +import lisa.kernel.proof.SequentCalculus.SCProofStep +import lisa.kernel.proof.SequentCalculus.Sequent +import lisa.kernel.proof.{SequentCalculus => SC} +import lisa.utils.Library +import lisa.utils.tactics.ProofStepLib.{_, given} + +object BasicStepTactic { + + case object Hypothesis extends ProofStepWithoutBotNorPrem(0) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.Hypothesis(bot, bot.left.intersect(bot.right).head) + } + + case object Rewrite extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.Rewrite(bot, premises(0)) + } + + /** + * <pre> + * Γ |- Δ, φ φ, Σ |- Π+ * ------------------------ + * Γ, Σ |-Δ, Π+ * </pre> + */ + case class Cut(phi: Formula) extends ProofStepWithoutBotNorPrem(2) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.Cut(bot, premises(0), premises(1), phi) + } + + case object CutWithoutFormula extends ProofStepWithoutBotNorPrem(2) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val leftSequent = currentProof.getSequent(premises(0)) + val rightSequent = currentProof.getSequent(premises(1)) + val cutSet = rightSequent.left.diff(bot.left) ++ leftSequent.right.diff(bot.right) + lazy val intersectedCutSet = rightSequent.left & leftSequent.right + + if (!cutSet.isEmpty) + if (cutSet.tail.isEmpty) { + SC.Cut(bot, premises(0), premises(1), cutSet.head) + } else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Inferred cut pivot is not a singleton set.") + else if (!intersectedCutSet.isEmpty && intersectedCutSet.tail.isEmpty) + // can still find a pivot + SC.Cut(bot, premises(0), premises(1), intersectedCutSet.head) + else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "A consistent cut pivot cannot be inferred from the premises. Possibly a missing or extraneous clause." + ) + } + } + + case object Cut extends ProofStepWithoutBotNorPrem(2) { + // default construction: + // def apply(phi: Formula) = new Cut(phi) + def apply() = CutWithoutFormula + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + + } + + // Left rules + /** + * <pre> + * Γ, φ |- Δ Γ, φ, ψ |- Δ + * -------------- or -------------- + * Γ, φ∧ψ |- Δ Γ, φ∧ψ |- Δ + * </pre> + */ + case class LeftAnd(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftAnd(bot, premises(0), phi, psi) + } + + case object LeftAndWithoutFormula extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = bot.left.diff(premiseSequent.left) + + if (!pivot.isEmpty && pivot.tail.isEmpty) + pivot.head match { + case ConnectorFormula(And, Seq(phi, psi)) => + if (premiseSequent.left.contains(phi)) + SC.LeftAnd(bot, premises(0), phi, psi) + else + SC.LeftAnd(bot, premises(0), psi, phi) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer a conjunction as pivot from premise and conclusion.") + } + else + // try a rewrite, if it works, go ahead with it, otherwise malformed + if (SC.isSameSequent(premiseSequent, bot)) + SC.Rewrite(bot, premises(0)) + else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "Left-hand side of conclusion + φ∧ψ must be same as left-hand side of premise + either φ, ψ or both." + ) + } + } + + case object LeftAnd extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula, psi: Formula) = new LeftAnd(phi, psi) + def apply() = LeftAndWithoutFormula + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ, φ |- Δ Σ, ψ |- Π... + * -------------------------------- + * Γ, Σ, φ∨ψ∨... |- Δ, Π+ * </pre> + */ + case class LeftOr(disjuncts: Seq[Formula]) extends ProofStepWithoutBotNorPrem(-1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + SC.LeftOr(bot, premises, disjuncts) + } + } + case class LeftOrWithoutFormula() extends ProofStepWithoutBotNorPrem(-1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequents = premises.map(currentProof.getSequent(_)) + val pivots = premiseSequents.map(_.left.diff(bot.left)) + + if (pivots.exists(_.isEmpty)) + SC.Weakening(bot, premises(pivots.indexWhere(_.isEmpty))) + else if (pivots.forall(_.tail.isEmpty)) + SC.LeftOr(bot, premises, pivots.map(_.head)) + else + // some extraneous formulae + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "Left-hand side of conclusion + disjuncts is not the same as the union of the left-hand sides of the premises + φ∨ψ." + ) + } + } + + case object LeftOr extends ProofStepWithoutBotNorPrem(-1) { + // default construction: + // def apply(disjuncts: Seq[Formula]) = new LeftOr(disjuncts) + def apply() = new LeftOrWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ |- φ, Δ Σ, ψ |- Π+ * ------------------------ + * Γ, Σ, φ→ψ |- Δ, Π+ * </pre> + */ + case class LeftImplies(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(2) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftImplies(bot, premises(0), premises(1), phi, psi) + } + + case object LeftImpliesWithoutFormula extends ProofStepWithoutBotNorPrem(2) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val leftSequent = currentProof.getSequent(premises(0)) + val rightSequent = currentProof.getSequent(premises(1)) + val pivotLeft = leftSequent.right.diff(bot.right) + lazy val pivotRight = rightSequent.left.diff(bot.left) + + if (pivotLeft.isEmpty) + SC.Weakening(bot, premises(0)) + else if (pivotRight.isEmpty) + SC.Weakening(bot, premises(1)) + else if (pivotLeft.tail.isEmpty && pivotRight.tail.isEmpty) + SC.LeftImplies(bot, premises(0), premises(1), pivotLeft.head, pivotRight.head) + else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "Could not infer an implication as a pivot from the premises and conclusion, possible extraneous formulae in premises." + ) + } + } + + case object LeftImplies extends ProofStepWithoutBotNorPrem(2) { + // default construction: + // def apply(phi: Formula, psi: Formula) = new LeftImplies(phi, psi) + def apply() = LeftImpliesWithoutFormula + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ, φ→ψ |- Δ Γ, φ→ψ, ψ→φ |- Δ + * -------------- or -------------------- + * Γ, φ↔ψ |- Δ Γ, φ↔ψ |- Δ + * </pre> + */ + case class LeftIff(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftIff(bot, premises(0), phi, psi) + } + + case class LeftIffWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = premiseSequent.left.diff(bot.left) + + if (pivot.isEmpty) + SC.Weakening(bot, premises(0)) + else + pivot.head match { + case ConnectorFormula(Implies, Seq(phi, psi)) => SC.LeftIff(bot, premises(0), phi, psi) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer a pivot implication from premise.") + } + } + } + + case object LeftIff extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula, psi: Formula) = new LeftIff(phi, psi) + def apply() = new LeftIffWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ |- φ, Δ + * -------------- + * Γ, ¬φ |- Δ + * </pre> + */ + case class LeftNot(phi: Formula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftNot(bot, premises(0), phi) + } + + case class LeftNotWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = premiseSequent.right.diff(bot.right) + + if (pivot.isEmpty) + SC.Weakening(bot, premises(0)) + else if (pivot.tail.isEmpty) + SC.LeftNot(bot, premises(0), pivot.head) + else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Right-hand side of conclusion + φ must be the same as right-hand side of premise.") + + } + } + + case object LeftNot extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula) = new LeftNot(phi) + def apply() = new LeftNotWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ, φ[t/x] |- Δ + * ------------------- + * Γ, ∀x. φ |- Δ + * + * </pre> + */ + case class LeftForall(phi: Formula, x: VariableLabel, t: Term) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftForall(bot, premises(0), phi, x, t) + } + + case class LeftForallWithoutFormula(t: Term) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = bot.left.diff(premiseSequent.left) + lazy val instantiatedPivot = premiseSequent.left.diff(bot.left) + + if (!pivot.isEmpty) + if (pivot.tail.isEmpty) + pivot.head match { + case BinderFormula(Forall, x, phi) => SC.LeftForall(bot, premises(0), phi, x, t) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer a universally quantified pivot from premise and conclusion.") + } + else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ.") + else if (instantiatedPivot.isEmpty) SC.Weakening(bot, premises(0)) + else if (instantiatedPivot.tail.isEmpty) { + // go through conclusion to find a matching quantified formula + + val in: Formula = instantiatedPivot.head + val quantifiedPhi: Option[Formula] = bot.left.find(f => + f match { + case g @ BinderFormula(Forall, _, _) => isSame(instantiateBinder(g, t), in) + case _ => false + } + ) + + quantifiedPhi match { + case Some(BinderFormula(Forall, x, phi)) => SC.LeftForall(bot, premises(0), phi, x, t) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer a universally quantified pivot from premise and conclusion.") + } + } else ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ.") + } + } + + case object LeftForall { + // default construction: + // def apply(phi: Formula, x: VariableLabel, t: Term) = new LeftForall(phi, x, t) + def apply(t: Term) = new LeftForallWithoutFormula(t) + + // TODO: will require unification to infer input Term: + // def apply() = new LeftForallWithoutFormulaOrTerm() + + // usage without an argument list + // TODO: add `extends ProofStepWithoutBotNorPrem(1)` to object when uncommenting + // def asSCProof(bot: Sequent, premises:Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + // this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ, φ |- Δ + * ------------------- if x is not free in the resulting sequent + * Γ, ∃x φ|- Δ + * + * </pre> + */ + case class LeftExists(phi: Formula, x: VariableLabel) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftExists(bot, premises(0), phi, x) + } + + case class LeftExistsWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = bot.left.diff(premiseSequent.left) + lazy val instantiatedPivot = premiseSequent.left.diff(bot.left) + + if (pivot.isEmpty) + if (instantiatedPivot.isEmpty) SC.Rewrite(bot, premises(0)) + else if (instantiatedPivot.tail.isEmpty) { + val in: Formula = instantiatedPivot.head + val quantifiedPhi: Option[Formula] = bot.left.find(f => + f match { + case BinderFormula(Exists, _, g) => isSame(g, in) + case _ => false + } + ) + + quantifiedPhi match { + case Some(BinderFormula(Exists, x, phi)) => SC.LeftExists(bot, premises(0), phi, x) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existensially quantified pivot from premise and conclusion.") + } + } else ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") + else if (pivot.tail.isEmpty) + pivot.head match { + case BinderFormula(Exists, x, phi) => SC.LeftExists(bot, premises(0), phi, x) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existentially quantified pivot from premise and conclusion.") + } + else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") + } + } + + case object LeftExists extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula, x: VariableLabel) = new LeftExists(phi, x) + def apply() = new LeftExistsWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ, ∃y.∀x. (x=y) ↔ φ |- Δ + * ---------------------------- if y is not free in φ + * Γ, ∃!x. φ |- Δ + * </pre> + */ + case class LeftExistsOne(phi: Formula, x: VariableLabel) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftExistsOne(bot, premises(0), phi, x) + } + + case class LeftExistsOneWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = bot.left.diff(premiseSequent.left) + lazy val instantiatedPivot = premiseSequent.left.diff(bot.left) + + if (pivot.isEmpty) + if (instantiatedPivot.isEmpty) + SC.Rewrite(bot, premises(0)) + else if (instantiatedPivot.tail.isEmpty) { + instantiatedPivot.head match { + // ∃_. ∀x. _ ↔ φ == extract ==> x, phi + case BinderFormula(Exists, _, BinderFormula(Forall, x, ConnectorFormula(Iff, Seq(_, phi)))) => SC.LeftExistsOne(bot, premises(0), phi, x) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existentially quantified pivot from premise and conclusion.") + } + } else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") + else if (pivot.tail.isEmpty) + pivot.head match { + case BinderFormula(ExistsOne, x, phi) => SC.LeftExistsOne(bot, premises(0), phi, x) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existentially quantified pivot from premise and conclusion.") + } + else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") + } + } + + case object LeftExistsOne extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula, x: VariableLabel) = new LeftExistsOne(phi, x) + def apply() = new LeftExistsOneWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + // Right rules + /** + * <pre> + * Γ |- φ, Δ Σ |- ψ, Π... + * ------------------------------------ + * Γ, Σ |- φ∧ψ∧..., Π, Δ + * </pre> + */ + case class RightAnd(cunjuncts: Seq[Formula]) extends ProofStepWithoutBotNorPrem(-1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightAnd(bot, premises, cunjuncts) + } + case object RightAndWithoutFormula extends ProofStepWithoutBotNorPrem(-1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequents = premises.map(currentProof.getSequent(_)) + val pivots = premiseSequents.map(_.right.diff(bot.right)) + + if (pivots.exists(_.isEmpty)) + SC.Weakening(bot, premises(pivots.indexWhere(_.isEmpty))) + else if (pivots.forall(_.tail.isEmpty)) + SC.RightAnd(bot, premises, pivots.map(_.head)) + else + // some extraneous formulae + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "Right-hand side of conclusion + φ + ψ is not the same as the union of the right-hand sides of the premises +φ∧ψ." + ) + } + } + + case object RightAnd extends ProofStepWithoutBotNorPrem(-1) { + // default construction: + // def apply(conjuncts: Seq[Formula]) = new RightAnd(conjuncts) + def apply() = RightAndWithoutFormula + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ |- φ, Δ Γ |- φ, ψ, Δ + * -------------- or --------------- + * Γ |- φ∨ψ, Δ Γ |- φ∨ψ, Δ + * </pre> + */ + case class RightOr(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightOr(bot, premises(0), phi, psi) + } + + case class RightOrWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = bot.right.diff(premiseSequent.right) + + if (!pivot.isEmpty && pivot.tail.isEmpty) + pivot.head match { + case ConnectorFormula(Or, Seq(phi, psi)) => + if (premiseSequent.left.contains(phi)) + SC.RightOr(bot, premises(0), phi, psi) + else + SC.RightOr(bot, premises(0), psi, phi) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer a disjunction as pivot from premise and conclusion.") + } + else + // try a rewrite, if it works, go ahead with it, otherwise malformed + if (SC.isSameSequent(premiseSequent, bot)) + SC.Rewrite(bot, premises(0)) + else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "Right-hand side of conclusion + φ∧ψ must be same as right-hand side of premise + either φ, ψ or both." + ) + } + } + + case object RightOr extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula, psi: Formula) = new RightOr(phi, psi) + def apply() = new RightOrWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ, φ |- ψ, Δ + * -------------- + * Γ |- φ→ψ, Δ + * </pre> + */ + case class RightImplies(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightImplies(bot, premises(0), phi, psi) + } + + case class RightImpliesWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val leftPivot = premiseSequent.left.diff(bot.left) + val rightPivot = premiseSequent.right.diff(bot.right) + + if ( + !leftPivot.isEmpty && leftPivot.tail.isEmpty && + !rightPivot.isEmpty && rightPivot.tail.isEmpty + ) + SC.RightImplies(bot, premises(0), leftPivot.head, rightPivot.head) + else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Right-hand side of conclusion + ψ must be same as right-hand side of premise + φ→ψ.") + } + } + + case object RightImplies extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula, psi: Formula) = new RightImplies(phi, psi) + def apply() = new RightImpliesWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ |- φ→ψ, Δ Σ |- ψ→φ, Π+ * ---------------------------- + * Γ, Σ |- φ↔ψ, Π, Δ + * </pre> + */ + case class RightIff(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(2) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightIff(bot, premises(0), premises(1), phi, psi) + } + + case class RightIffWithoutFormula() extends ProofStepWithoutBotNorPrem(2) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = premiseSequent.right.diff(bot.right) + + if (pivot.isEmpty) + SC.Weakening(bot, premises(0)) + else if (pivot.tail.isEmpty) + pivot.head match { + case ConnectorFormula(Implies, Seq(phi, psi)) => SC.RightIff(bot, premises(0), premises(1), phi, psi) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an implication as pivot from premise and conclusion.") + } + else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "Right-hand side of conclusion + φ→ψ + ψ→φ is not the same as the union of the right-hand sides of the premises φ↔ψ." + ) + } + } + + case object RightIff extends ProofStepWithoutBotNorPrem(2) { + // default construction: + // def apply(phi: Formula, psi: Formula) = new RightIff(phi, psi) + def apply() = new RightIffWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ, φ |- Δ + * -------------- + * Γ |- ¬φ, Δ + * </pre> + */ + case class RightNot(phi: Formula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightNot(bot, premises(0), phi) + } + + case class RightNotWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = premiseSequent.left.diff(bot.left) + + if (pivot.isEmpty) + SC.Weakening(bot, premises(0)) + else if (pivot.tail.isEmpty) + SC.RightNot(bot, premises(0), pivot.head) + else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Left-hand side of conclusion + φ must be the same as left-hand side of premise.") + + } + } + + case object RightNot extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula) = new RightNot(phi) + def apply() = new RightNotWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ |- φ, Δ + * ------------------- if x is not free in the resulting sequent + * Γ |- ∀x. φ, Δ + * </pre> + */ + case class RightForall(phi: Formula, x: VariableLabel) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightForall(bot, premises(0), phi, x) + } + + case class RightForallWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = bot.right.diff(premiseSequent.right) + lazy val instantiatedPivot = premiseSequent.right.diff(bot.right) + + if (pivot.isEmpty) + if (instantiatedPivot.isEmpty) SC.Rewrite(bot, premises(0)) + else if (instantiatedPivot.tail.isEmpty) { + val in: Formula = instantiatedPivot.head + val quantifiedPhi: Option[Formula] = bot.right.find(f => + f match { + case BinderFormula(Forall, _, g) => isSame(g, in) + case _ => false + } + ) + + quantifiedPhi match { + case Some(BinderFormula(Forall, x, phi)) => SC.RightForall(bot, premises(0), phi, x) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer a universally quantified pivot from premise and conclusion.") + } + } else ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Right-hand side of conclusion + φ must be the same as right-hand side of premise + ∃x. φ.") + else if (pivot.tail.isEmpty) + pivot.head match { + case BinderFormula(Forall, x, phi) => SC.RightForall(bot, premises(0), phi, x) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer a universally quantified pivot from premise and conclusion.") + } + else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Right-hand side of conclusion + φ must be the same as right-hand side of premise + ∃x. φ.") + } + } + + case object RightForall extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula, x: VariableLabel) = new RightForall(phi, x) + def apply() = new RightForallWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ |- φ[t/x], Δ + * ------------------- + * Γ |- ∃x. φ, Δ + * + * (ln-x stands for locally nameless x) + * </pre> + */ + case class RightExists(phi: Formula, x: VariableLabel, t: Term) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightExists(bot, premises(0), phi, x, t) + } + + case class RightExistsWithoutFormula(t: Term) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = bot.right.diff(premiseSequent.right) + lazy val instantiatedPivot = premiseSequent.right.diff(bot.right) + + if (!pivot.isEmpty) + if (pivot.tail.isEmpty) + pivot.head match { + case BinderFormula(Exists, x, phi) => SC.RightExists(bot, premises(0), phi, x, t) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existentially quantified pivot from premise and conclusion.") + } + else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "Right-hand side of conclusion + φ[t/x] must be the same as right-hand side of premise + ∀x. φ." + ) + else if (instantiatedPivot.isEmpty) SC.Weakening(bot, premises(0)) + else if (instantiatedPivot.tail.isEmpty) { + // go through conclusion to find a matching quantified formula + + val in: Formula = instantiatedPivot.head + val quantifiedPhi: Option[Formula] = bot.right.find(f => + f match { + case g @ BinderFormula(Exists, _, _) => isSame(instantiateBinder(g, t), in) + case _ => false + } + ) + + quantifiedPhi match { + case Some(BinderFormula(Exists, x, phi)) => SC.RightExists(bot, premises(0), phi, x, t) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existentially quantified pivot from premise and conclusion.") + } + } else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "Right-hand side of conclusion + φ[t/x] must be the same as right-hand side of premise + ∀x. φ." + ) + } + } + + case object RightExists { + // default construction: + // def apply(phi: Formula, x: VariableLabel, t: Term) = new RightExists(phi, x, t) + def apply(t: Term) = new RightExistsWithoutFormula(t) + + // TODO: will require unification to infer input Term: + // def apply() = new RightExistsWithoutFormulaOrTerm() + + // usage without an argument list + // TODO: add `extends ProofStepWithoutBotNorPrem(1)` to object when uncommenting + // def asSCProof(bot: Sequent, premises:Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + // this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ |- ∃y.∀x. (x=y) ↔ φ, Δ + * ---------------------------- if y is not free in φ + * Γ|- ∃!x. φ, Δ + * </pre> + */ + case class RightExistsOne(phi: Formula, x: VariableLabel) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightExistsOne(bot, premises(0), phi, x) + } + + case class RightExistsOneWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + val pivot = bot.right.diff(premiseSequent.right) + lazy val instantiatedPivot = premiseSequent.right.diff(bot.right) + + if (pivot.isEmpty) + if (instantiatedPivot.isEmpty) + SC.Rewrite(bot, premises(0)) + else if (instantiatedPivot.tail.isEmpty) { + instantiatedPivot.head match { + // ∃_. ∀x. _ ↔ φ == extract ==> x, phi + case BinderFormula(Exists, _, BinderFormula(Forall, x, ConnectorFormula(Iff, Seq(_, phi)))) => SC.RightExistsOne(bot, premises(0), phi, x) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existentially quantified pivot from premise and conclusion.") + } + } else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Right-hand side of conclusion + φ must be the same as right-hand side of premise + ∃x. φ.") + else if (pivot.tail.isEmpty) + pivot.head match { + case BinderFormula(ExistsOne, x, phi) => SC.RightExistsOne(bot, premises(0), phi, x) + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existentially quantified pivot from premise and conclusion.") + } + else + ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Right-hand side of conclusion + φ must be the same as right-hand side of premise + ∃x. φ.") + } + } + + case object RightExistsOne extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(phi: Formula, x: VariableLabel) = new RightExistsOne(phi, x) + def apply() = new RightExistsOneWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + // Structural rules + /** + * <pre> + * Γ |- Δ + * -------------- + * Γ, Σ |- Δ, Π+ * </pre> + */ + case object Weakening extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.Weakening(bot, premises(0)) + } + + // Equality Rules + /** + * <pre> + * Γ, s=s |- Δ + * -------------- + * Γ |- Δ + * </pre> + */ + case class LeftRefl(fa: Formula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftRefl(bot, premises(0), fa) + } + + case class LeftReflWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.Rewrite(bot, premises(0)) + } + + case object LeftRefl extends ProofStepWithoutBotNorPrem(1) { + // default construction: + // def apply(fa: Formula) = new LeftRefl(fa) + def apply() = new LeftReflWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * + * -------------- + * |- s=s + * </pre> + */ + case class RightRefl(fa: Formula) extends ProofStepWithoutBotNorPrem(0) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightRefl(bot, fa) + } + + case class RightReflWithoutFormula() extends ProofStepWithoutBotNorPrem(0) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RewriteTrue(bot) + } + + case object RightRefl extends ProofStepWithoutBotNorPrem(0) { + // default construction: + // def apply(fa: Formula) = new RightRefl(fa) + def apply() = new RightReflWithoutFormula() + + // usage without an argument list + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + this().asSCProof(bot, premises, currentProof) + } + + /** + * <pre> + * Γ, φ(s1,...,sn) |- Δ + * --------------------- + * Γ, s1=premises(0), ..., sn=tn, φ(premises(0),...tn) |- Δ + * </pre> + */ + case class LeftSubstEq(equals: List[(Term, Term)], lambdaPhi: LambdaTermFormula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftSubstEq(bot, premises(0), equals, lambdaPhi) + } + + /** + * <pre> + * Γ |- φ(s1,...,sn), Δ + * --------------------- + * Γ, s1=premises(0), ..., sn=tn |- φ(premises(0),...tn), Δ + * </pre> + */ + case class RightSubstEq(equals: List[(Term, Term)], lambdaPhi: LambdaTermFormula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightSubstEq(bot, premises(0), equals, lambdaPhi) + } + + /** + * <pre> + * Γ, φ(a1,...an) |- Δ + * --------------------- + * Γ, a1↔b1, ..., an↔bn, φ(b1,...bn) |- Δ + * </pre> + */ + case class LeftSubstIff(equals: List[(Formula, Formula)], lambdaPhi: LambdaFormulaFormula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.LeftSubstIff(bot, premises(0), equals, lambdaPhi) + } + + /** + * <pre> + * Γ |- φ(a1,...an), Δ + * --------------------- + * Γ, a1↔b1, ..., an↔bn |- φ(b1,...bn), Δ + * </pre> + */ + case class RightSubstIff(equals: List[(Formula, Formula)], lambdaPhi: LambdaFormulaFormula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.RightSubstIff(bot, premises(0), equals, lambdaPhi) + } + + /** + * <pre> + * Γ |- Δ + * -------------------------- + * Γ[r(a)/?f] |- Δ[r(a)/?f] + * </pre> + */ + case class InstFunSchema(insts: Map[SchematicTermLabel, LambdaTermTerm]) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.InstFunSchema(bot, premises(0), insts) + } + + /** + * <pre> + * Γ |- Δ + * -------------------------- + * Γ[ψ(a)/?p] |- Δ[ψ(a)/?p] + * </pre> + */ + case class InstPredSchema(insts: Map[SchematicVarOrPredLabel, LambdaTermFormula]) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.InstPredSchema(bot, premises(0), insts) + } + + // Proof Organisation rules + case class SCSubproof(sp: SCProof, premises: Seq[Int] = Seq.empty, display: Boolean = true) extends ProofStep { + def asSCProof(currentProof: Library#Proof): ProofStepJudgement = + sp match { + case sp: SCProof => SC.SCSubproof(sp, premises, display) + } + } + +} diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/ProofStepJudgement.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/ProofStepJudgement.scala new file mode 100644 index 0000000000000000000000000000000000000000..57a9a4be766d81ce93e0ed641b87710c31ba36b2 --- /dev/null +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/ProofStepJudgement.scala @@ -0,0 +1,44 @@ +package lisa.utils.tactics + +import lisa.kernel.proof.SCProofCheckerJudgement +import lisa.kernel.proof.SequentCalculus.SCProofStep +import lisa.utils.tactics.ProofStepLib.ProofStep + +/** + * Contains the result of a tactic computing a SCProofStep. + * Can be successful or unsuccessful. + */ +sealed abstract class ProofStepJudgement { + import ProofStepJudgement.* + + /** + * Returns true if and only if the jusdgement is valid. + */ + def isValid: Boolean = this match { + case ValidProofStep(scps) => true + case InvalidProofStep(ps, error) => false + } + +} + +object ProofStepJudgement { + + /** + * Indicates an error in the building of a proof that was caught before the proof is passed to the logical kernel. + * May indicate a faulty tactic application. + */ + case class EarlyProofStepException(message: String) extends Exception(message) + + /** + * A Sequent Calculus proof step that has been correctly produced. + */ + case class ValidProofStep(scps: SCProofStep) extends ProofStepJudgement + + /** + * A proof step which led to an error when computing the corresponding Sequent Calculus proof step. + */ + case class InvalidProofStep(ps: ProofStep, message: String) extends ProofStepJudgement { + def launch: Nothing = throw EarlyProofStepException(message) + } + +} diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/ProofStepLib.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/ProofStepLib.scala new file mode 100644 index 0000000000000000000000000000000000000000..99c81eb29d5cc619bccc8dbf09fb276661042314 --- /dev/null +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/ProofStepLib.scala @@ -0,0 +1,143 @@ +package lisa.utils.tactics + +import lisa.kernel.proof +import lisa.kernel.proof.RunningTheory +import lisa.kernel.proof.RunningTheoryJudgement +import lisa.kernel.proof.RunningTheoryJudgement.InvalidJustification +import lisa.kernel.proof.RunningTheoryJudgement.InvalidJustificationException +import lisa.kernel.proof.SequentCalculus +import lisa.kernel.proof.SequentCalculus.SCProofStep +import lisa.kernel.proof.SequentCalculus.Sequent +import lisa.utils.Helpers.* +import lisa.utils.Library +import lisa.utils.Printer +import lisa.utils.tactics.ProofStepJudgement.* + +object ProofStepLib { + + /** + * A proofstep is an object that relies on a step of premises and which can be translated into pure Sequent Calculus. + */ + trait ProofStep { + val premises: Seq[Library#Proof#Fact] + + /** + * Add the proofstep to the current proof of the given library. + */ + def validate(l: Library)(using output: String => Unit)(using finishOutput: Throwable => Nothing): l.Proof#DoubleStep = { + l.proofStack.head.newDoubleStep(this) + } + + /** + * An abstract function transforming the ProofStep innto a SCProofStep in pure Sequent Calculus. + */ + def asSCProof(currentProof: Library#Proof): ProofStepJudgement + + } + + /** + * A proof step lacking a bottom/conclusion sequent. Once given a conclusion sequent, it can become a ProofStep. + */ + trait ProofStepWithoutBot { + val premises: Seq[Library#Proof#Fact] + + /** + * An abstract function transforming the ProofStepWithoutBot into a SCProofStep in pure Sequent Calculus, + * by being given access to a target conclusive sequent and the current state of the proof. + */ + def asSCProof(bot: Sequent, currentProof: Library#Proof): ProofStepJudgement + + /** + * Gives a targeted bottom sequent, as a partial application towards the SC transformation. + */ + def asProofStep(bot: Sequent): ProofStep = new ProofStepWithBot(this, bot) + } + + /** + * Intermediate datatype corresponding to a ProofStepWithoutBot once a targetted bottom sequent has been given to it. + */ + class ProofStepWithBot protected[ProofStepLib] ( + val underlying: ProofStepWithoutBot, + val givenBot: Sequent + ) extends ProofStep { + override val premises: Seq[Library#Proof#Fact] = underlying.premises + override def asSCProof(currentProof: Library#Proof): ProofStepJudgement = underlying.asSCProof(givenBot ++< (currentProof.getAssumptions |- ()), currentProof) + } + + /** + * Represent a ProofStep lacking the list of its premises, for partial application. + */ + trait ProofStepWithoutPrem { + + /** + * An abstract function transforming the ProofStepWithoutPrem innto a SCProofStep in pure Sequent Calculus. + */ + def asSCProof(premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement + + /** + * Gives the premises of the ProofStep, as a partial application towards the SC transformation. + */ + def asProofStep(premises: Seq[Library#Proof#Fact]): ProofStep = new ProofStepWithPrem(this, premises) + + /** + * Alias for [[asProofStep]] + */ + def by(premises: Seq[Library#Proof#Fact]): ProofStep = asProofStep(premises) + } + + /** + * Intermediate datatype corresponding to a [[ProofStepWithoutPrem]] once a sequence of premises has been given to it. + */ + class ProofStepWithPrem protected[ProofStepLib] ( + val underlying: ProofStepWithoutPrem, + val premises: Seq[Library#Proof#Fact] + ) extends ProofStep { + override def asSCProof(currentProof: Library#Proof): ProofStepJudgement = + if (premises.forall(prem => currentProof.validInThisProof(prem))) { + underlying.asSCProof(premises.map(prem => currentProof.getSequentAndInt(prem.asInstanceOf[currentProof.Fact])._2), currentProof) + } else { + ProofStepJudgement.InvalidProofStep(this, "Illegal reference to a previous step outside of this Proof's scope.") + } + } + + /** + * A ProofStep without premises nor targeted bottom sequent. + * Contains a tactic to reconstruct a partial Sequent Calculus proof if given those elements and the current proof. + */ + trait ProofStepWithoutBotNorPrem[N <: Int & Singleton](val numbPrem: N) { + + /** + * Contains a tactic to reconstruct a partial Sequent Calculus proof if given + * a list of premises, a targeted bottom sequent and the current proof. + */ + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement + def asProofStepWithoutBot(premises: Seq[Library#Proof#Fact]): ProofStepWithoutBot = + new ProofStepWithoutBotWithPrem[N](this, premises) + def apply(premises: Library#Proof#Fact*): ProofStepWithoutBot = asProofStepWithoutBot(premises) + } + + /** + * Intermediate datatype corresponding to a [[ProofStepWithoutBotNorPrem]] once a sequence of premises has been given to it. + */ + class ProofStepWithoutBotWithPrem[N <: Int & Singleton] protected[ProofStepLib] ( + val underlying: ProofStepWithoutBotNorPrem[N], + override val premises: Seq[Library#Proof#Fact] + ) extends ProofStepWithoutBot { + val numbPrem: N = underlying.numbPrem + + /** + * Contains a tactic to reconstruct a partial Sequent Calculus proof if given + * a targeted bottom sequent and the current proof. + */ + def asSCProof(bot: Sequent, currentProof: Library#Proof): ProofStepJudgement = { + if (premises.forall(prem => currentProof.validInThisProof(prem))) { + underlying.asSCProof(bot, premises.map(prem => currentProof.getSequentAndInt(prem.asInstanceOf[currentProof.Fact])._2), currentProof) + } else { + ProofStepJudgement.InvalidProofStep(asProofStep(bot), "Illegal reference to a previous step outside of this Proof's scope.") + } + } + } + + given Conversion[SCProofStep, ProofStepJudgement] = c => ProofStepJudgement.ValidProofStep(c) + +} diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/ProofsHelpers.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/ProofsHelpers.scala new file mode 100644 index 0000000000000000000000000000000000000000..2fa04fdd125b8cac21cdf053844f896d8a736456 --- /dev/null +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/ProofsHelpers.scala @@ -0,0 +1,134 @@ +package lisa.utils.tactics + +import lisa.kernel.fol.FOL.* +import lisa.kernel.proof.SCProofChecker +import lisa.kernel.proof.SequentCalculus.SCProofStep +import lisa.kernel.proof.SequentCalculus.Sequent +import lisa.utils.Library +import lisa.utils.Parser.parseFormula +import lisa.utils.Parser.parseSequent +import lisa.utils.Parser.parseTerm +import lisa.utils.tactics.ProofStepLib.* + +trait ProofsHelpers { + library: Library & WithProofs => + given Library = library + export BasicStepTactic.* + export SimpleDeducedSteps.* + private def proof: Proof = proofStack.head + + case class HaveSequent private[ProofsHelpers] (bot: Sequent) { + infix def by(just: ProofStepWithoutBot)(using String => Unit)(using finishOutput: Throwable => Nothing): library.Proof#DoubleStep = { + val r = just.asProofStep(bot) + r.validate(library) + } + } + + case class AndThenSequent private[ProofsHelpers] (bot: Sequent) { + infix def by[N <: Int & Singleton](just: ProofStepWithoutBotNorPrem[N])(using String => Unit)(using finishOutput: Throwable => Nothing): library.Proof#DoubleStep = { + val r = just.asProofStepWithoutBot(Seq(proof.mostRecentStep._2)).asProofStep(bot) + r.validate(library) + } + } + + /** + * Claim the given Sequent as a ProofStep, which may require a justification by a proof tactic and premises. + */ + def have(res: Sequent): HaveSequent = HaveSequent(res) + + /** + * Claim the given Sequent as a ProofStep, which may require a justification by a proof tactic and premises. + */ + def have(res: String): HaveSequent = HaveSequent(parseSequent(res)) + + /** + * Claim the given known Theorem, Definition or Axiom as a Sequent. + */ + def have(just: theory.Justification)(using String => Unit)(using finishOutput: Throwable => Nothing): library.Proof#DoubleStep = { + have(theory.sequentFromJustification(just)) by Restate(just.asInstanceOf[Library#Proof#Fact]) + } + + /* //TODO: After reviewing substitutions + def have(instJust: InstantiatedJustification)(using String => Unit)(using finishOutput: Throwable => Nothing): library.Proof#DoubleStep = { + val just = instJust.just + val (seq, ref) = proof.getSequentAndInt(just) + if (instJust.instsPred.isEmpty && instJust.instsTerm.isEmpty && instJust.instForall.isEmpty){ + have(seq) by Restate(ref) + } else if (instJust.instsPred.isEmpty && instJust.instForall.isEmpty){ + val res = (seq.left.map(phi => instantiateTermSchemas(phi, instJust.instsTerm)) |- seq.right.map(phi => instantiateTermSchemas(phi, instJust.instsTerm))) + have(res) by InstFunSchema(instJust.instsTerm)(ref) + } else if (instJust.instsTerm.isEmpty && instJust.instForall.isEmpty){ + val res = (seq.left.map(phi => instantiatePredicateSchemas(phi, instJust.instsPred)) |- seq.right.map(phi => instantiatePredicateSchemas(phi, instJust.instsPred))) + have(res) by InstPredSchema(instJust.instsPred)(ref) + } else if(instJust.instsPred.isEmpty && instJust.instsTerm.isEmpty){ + ??? + } else { + ??? + } + } + */ + + /** + * Claim the given Sequent as a ProofStep directly following the previously proven tactic, + * which may require a justification by a proof tactic. + */ + def andThen(res: Sequent): AndThenSequent = AndThenSequent(res) + + /** + * Claim the given Sequent as a ProofStep directly following the previously proven tactic, + * which may require a justification by a proof tactic. + */ + def andThen(res: String): AndThenSequent = AndThenSequent(parseSequent(res)) + + /** + * Import the given justification (Axiom, Theorem or Definition) into the current proof. + */ + def withImport(just: theory.Justification): library.Proof#ImportedFact = { + proofStack.head.newImportedFact(just) + + } + + /** + * Assume the given formula in all future left hand-side of claimed sequents. + */ + def assume(f: Formula): Formula = { + proofStack.head.addAssumption(f) + f + } + + /** + * Store the given import and use it to discharge the proof of one of its assumption at the very end. + */ + def endDischarge(ji: Library#Proof#ImportedFact): Unit = { + val p: Proof = proof + if (p.validInThisProof(ji)) { + val p = proof + p.addDischarge(ji.asInstanceOf[p.ImportedFact]) + } + } + + given Conversion[ProofStepWithoutBotNorPrem[0], ProofStepWithoutBot] = _.asProofStepWithoutBot(Seq()) + + // case class InstantiatedJustification(just:theory.Justification, instsPred: Map[SchematicVarOrPredLabel, LambdaTermFormula], instsTerm: Map[SchematicTermLabel, LambdaTermTerm], instForall:Seq[Term]) + + /* //TODO: After reviewing the substitutions + extension (just: theory.Justification) {/* + def apply(insts: ((SchematicVarOrPredLabel, LambdaTermFormula) | (SchematicTermLabel, LambdaTermTerm) | Term)*): InstantiatedJustification = { + val instsPred: Map[SchematicVarOrPredLabel, LambdaTermFormula] = insts.filter(isLTT).asInstanceOf[Seq[(SchematicVarOrPredLabel, LambdaTermFormula)]].toMap + val instsTerm: Map[SchematicTermLabel, LambdaTermTerm] = insts.filter(isLTF).asInstanceOf[Seq[(SchematicTermLabel, LambdaTermTerm)]].toMap + val instsForall: Seq[Term] = insts.filter(isTerm).asInstanceOf[Seq[Term]] + InstantiatedJustification(just, instsPred, instsTerm, instsForall) + }*/ + + def apply(insts: (VariableLabel, Term)*): InstantiatedJustification = { + InstantiatedJustification(just, Map(), insts.map((x:VariableLabel, t:Term) => (x, LambdaTermTerm(Seq(), t))).toMap, Seq()) + } + } + + private def isTerm(x: (SchematicVarOrPredLabel, LambdaTermFormula) | (SchematicTermLabel, LambdaTermTerm) | Term):Boolean = x.isInstanceOf[Term] + private def isLTT(x: (SchematicVarOrPredLabel, LambdaTermFormula) | (SchematicTermLabel, LambdaTermTerm) | Term):Boolean = x.isInstanceOf[Tuple2[_, _]] && x.asInstanceOf[Tuple2[_, _]]._2.isInstanceOf[LambdaTermTerm] + private def isLTF(x: (SchematicVarOrPredLabel, LambdaTermFormula) | (SchematicTermLabel, LambdaTermTerm) | Term):Boolean = x.isInstanceOf[Tuple2[_, _]] && x.asInstanceOf[Tuple2[_, _]]._2.isInstanceOf[LambdaTermFormula] + + */ + +} diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/SimpleDeducedSteps.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/SimpleDeducedSteps.scala new file mode 100644 index 0000000000000000000000000000000000000000..5516124b4d266223183f4c9057c5867ff92bce48 --- /dev/null +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/SimpleDeducedSteps.scala @@ -0,0 +1,438 @@ +package lisa.utils.tactics + +import lisa.kernel.fol.FOL +import lisa.kernel.proof.SCProof +import lisa.kernel.proof.SCProofChecker +import lisa.kernel.proof.SequentCalculus.RewriteTrue +import lisa.kernel.proof.SequentCalculus.SCProofStep +import lisa.kernel.proof.SequentCalculus.Sequent +import lisa.kernel.proof.{SequentCalculus => SC} +import lisa.utils.Helpers.{_, given} +import lisa.utils.Library +import lisa.utils.tactics.BasicStepTactic.SCSubproof +import lisa.utils.tactics.ProofStepLib.{_, given} + +object SimpleDeducedSteps { + + case object Restate extends ProofStepWithoutBot with ProofStepWithoutBotNorPrem(1) { + override val premises: Seq[Int] = Seq() + def asSCProof(bot: Sequent, currentProof: Library#Proof): ProofStepJudgement = + SC.RewriteTrue(bot) + + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = + SC.Rewrite(bot, premises(0)) + + } + + case class FormulaDischarge(f: FOL.Formula) extends ProofStepWithoutPrem { + override def asSCProof(premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val t1 = premises(0) + val (lastStep, t2) = currentProof.mostRecentStep + SC.Cut((lastStep.bot -< f) ++ (currentProof.getSequent(t1) -> f), t1, t2, f) + } + } + + class SUBPROOF(computeProof: => Unit)(using String => Unit)(using finishOutput: Throwable => Nothing) extends ProofStepWithoutBot { + private def cp(): Unit = computeProof + val premises: Seq[lisa.utils.Library#Proof#Fact] = Seq() + + override def asSCProof(bot: Sequent, currentProof: Library#Proof): ProofStepJudgement = { + val proof = currentProof.subproof(cp()) + val scproof = proof.toSCProof + val check = SCProofChecker.checkSCProof(scproof) + if (!check.isValid) check.showAndGet + SC.SCSubproof(scproof, proof.getImports.map(imf => imf.reference.asInstanceOf[Int])) + } + } + + case object Discharge extends ProofStepWithoutPrem { + override def asSCProof(premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val s = currentProof.getSequent(premises(0)) + if (s.right.size == 1) { + val f = s.right.head + val t1 = premises(0) + val (lastStep, t2) = currentProof.mostRecentStep + SC.Cut((lastStep.bot -< f) ++ (currentProof.getSequent(t1) -> f), t1, t2, f) + } else { + ProofStepJudgement.InvalidProofStep(this.asProofStep(premises), "When discharging this way, the target sequent must have only a single formula on the right handside.") + } + } + def apply(f: FOL.Formula): FormulaDischarge = FormulaDischarge(f) + def apply(ij: Library#Proof#Fact)(using library: Library)(using String => Unit)(using finishOutput: Throwable => Nothing): Unit = { + if (library.proofStack.head.validInThisProof(ij)) { + Discharge.asProofStep(Seq(ij)).validate(library) + } else { + val inv = ProofStepJudgement.InvalidProofStep(Discharge.asProofStep(Seq(ij)), "Illegal reference to justification from another proof in proofstep Discharge.") + finishOutput(inv.launch) + } + } + } + + /** + * Instantiate universal quantifier + * + * The premise is a proof of φ (phi), with φ (phi) of the form ∀x.ψ + * + * t is the term to instantiate the quantifier with + * + * <pre> + * Γ ⊢ ∀x.ψ, Δ + * ------------------------- + * Γ |- ψ[t/x], Δ + * + * </pre> + * + * Returns a subproof containing the instantiation steps + */ + case class InstantiateForall(phi: FOL.Formula, t: FOL.Term) extends ProofStepWithoutPrem with ProofStepWithoutBotNorPrem(1) { + + override def asSCProof(premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + + phi match { + case psi @ FOL.BinderFormula(FOL.Forall, _, _) => { + val in = FOL.instantiateBinder(psi, t) + + this.asSCProof(currentProof.getSequent(premises(0)) -> phi +> in, premises, currentProof) + } + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(() |- ()), "Input formula is not universally quantified") + } + + } + + override def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + + val premiseSequent = currentProof.getSequent(premises(0)) + + if (premiseSequent.right.contains(phi)) { + // valid derivation, construct proof + + phi match { + case psi @ FOL.BinderFormula(FOL.Forall, _, _) => { + + val tempVar = FOL.VariableLabel(FOL.freshId(psi.freeVariables.map(_.id), "x")) + + // instantiate the formula with input + val in = FOL.instantiateBinder(psi, t) + + // construct proof + val p0 = SC.Hypothesis(in |- in, in) + val p1 = SC.LeftForall(phi |- in, 0, FOL.instantiateBinder(psi, tempVar), tempVar, t) + val p2 = SC.Cut(bot, -1, 1, phi) + + /** + * in = ψ[t/x] + * + * s1 = Γ ⊢ ∀x.ψ, Δ Premise + * bot = Γ ⊢ ψ[t/x], Δ Result + * + * p0 = ψ[t/x] ⊢ ψ[t/x] Hypothesis + * p1 = ∀x.ψ ⊢ ψ[t/x] LeftForall p0 + * p2 = Γ ⊢ ψ[t/x], Δ Cut s1, p1 + */ + + SC.SCSubproof(SCProof(IndexedSeq(p0, p1, p2), IndexedSeq(premiseSequent)), Seq(premises(0))) + } + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Input formula is not universally quantified") + } + } else ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Input formula was not found in the RHS of the premise sequent.") + } + } + + /** + * Instantiate universal quantifier, with only one formula in the RHS + * + * The premise is a proof of φ (phi), with φ (phi) of the form ∀x.ψ, + * + * Asserts φ (phi) as the sole formula in the RHS of the premise's conclusion + * + * t is the term to instantiate the quantifier with + * + * <pre> + * Γ ⊢ ∀x.ψ + * ------------------------- + * Γ |- ψ[t/x] + * + * </pre> + * + * Returns a subproof containing the instantiation steps + */ + case class InstantiateForallWithoutFormula(t: FOL.Term) extends ProofStepWithoutPrem with ProofStepWithoutBotNorPrem(1) { + + override def asSCProof(premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + + if (premiseSequent.right.tail.isEmpty) + InstantiateForall(premiseSequent.right.head, t).asSCProof(premises, currentProof) + else + ProofStepJudgement.InvalidProofStep(this.asProofStep(premises), "RHS of premise sequent is not a singleton.") + } + + override def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val premiseSequent = currentProof.getSequent(premises(0)) + + if (premiseSequent.right.tail.isEmpty) { + // well formed + InstantiateForall(premiseSequent.right.head, t).asSCProof(bot, premises, currentProof) + } else ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "RHS of premise sequent is not a singleton.") + + } + } + + /** + * Instantiate multiple universal quantifiers + * + * The premise is a proof of φ (phi), with φ (phi) of the form ∀x1, x2, ..., xn.ψ, + * + * t* are the terms to instantiate the quantifiers + * + * Asserts t*.length = n + * + * Returns a subproof containing individual instantiations as its subproof steps + * + * <pre> + * Γ ⊢ ∀x1, x2, ..., xn .ψ, Δ + * -------------------------------------------- + * Γ |- ψ[t1/x1, t2/x2, ..., tn/xn], Δ + * + * </pre> + */ + case class InstantiateForallMultiple(phi: FOL.Formula, t: FOL.Term*) extends ProofStepWithoutPrem with ProofStepWithoutBotNorPrem(1) { + override def asSCProof(premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + + val premiseSequent = currentProof.getSequent(premises(0)) + + if (!premiseSequent.right.contains(phi)) { + ProofStepJudgement.InvalidProofStep(this.asProofStep(premises), "Input formula was not found in the RHS of the premise sequent.") + } else { + val emptyProof = SCProof(IndexedSeq(), IndexedSeq(currentProof.getSequent(premises(0)))) + val j = ProofStepJudgement.ValidProofStep(SC.Rewrite(premiseSequent, premises(0))) + + // some unfortunate code reuse + // DoubleStep tactics cannot be composed easily at the moment + + val res = t.foldLeft((emptyProof, phi, j: ProofStepJudgement)) { + case ((p, f, j), t) => { + j match { + case ProofStepJudgement.InvalidProofStep(_, _) => (p, f, j) // propagate error + case ProofStepJudgement.ValidProofStep(_) => { + // good state, continue instantiating + + // by construction the premise is well-formed + + // verify the formula structure and instantiate + f match { + case psi @ FOL.BinderFormula(FOL.Forall, _, _) => { + + val tempVar = FOL.VariableLabel(FOL.freshId(psi.freeVariables.map(_.id), "x")) + + // instantiate the formula with input + val in = FOL.instantiateBinder(psi, t) + val bot = p.conclusion -> f +> in + + // construct proof + val p0 = SC.Hypothesis(in |- in, in) + val p1 = SC.LeftForall(f |- in, 0, FOL.instantiateBinder(psi, tempVar), tempVar, t) + val p2 = SC.Cut(bot, -1, 1, f) + + /** + * in = ψ[t/x] + * + * s1 = Γ ⊢ ∀x.ψ, Δ Premise + * bot = Γ ⊢ ψ[t/x], Δ Result + * + * p0 = ψ[t/x] ⊢ ψ[t/x] Hypothesis + * p1 = ∀x.ψ ⊢ ψ[t/x] LeftForall p0 + * p2 = Γ ⊢ ψ[t/x], Δ Cut s1, p1 + */ + + val newStep = SC.SCSubproof(SCProof(IndexedSeq(p0, p1, p2), IndexedSeq(p.conclusion)), Seq(p.length - 1)) + + ( + p withNewSteps IndexedSeq(newStep), + in, + j + ) + } + case _ => { + ( + p, + f, + ProofStepJudgement.InvalidProofStep(this.asProofStep(premises), "Input formula is not universally quantified") + ) + } + } + } + } + } + } + + res._3 match { + case ProofStepJudgement.InvalidProofStep(_, _) => res._3 + case ProofStepJudgement.ValidProofStep(_) => SC.SCSubproof(res._1, Seq(premises(0))) + } + } + } + + override def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val res = this.asSCProof(premises, currentProof) + + res match { + case ProofStepJudgement.InvalidProofStep(_, _) => res + case ProofStepJudgement.ValidProofStep(SC.SCSubproof(proof: SCProof, _, _)) => { + // check if the same sequent was obtained + SC.SCSubproof( + proof withNewSteps IndexedSeq(SC.Rewrite(bot, proof.length - 1)), + Seq(premises(0)) + ) + } + case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Unreachable pattern match") + } + } + + } + + /** + * Instantiate multiple universal quantifiers, with only one formula in the RHS + * + * The premise is a proof of φ (phi), with φ (phi) of the form ∀x1, x2, ..., xn.ψ, + * + * Asserts φ (phi) is the sole formula in the RHS of the conclusion of the premise + * + * t* are the terms to instantiate the quantifiers + * + * Asserts t*.length = n + * + * Returns a subproof containing individual instantiations as its subproof steps + * + * <pre> + * Γ ⊢ ∀x1, x2, ..., xn .ψ + * -------------------------------------------- + * Γ |- ψ[t1/x1, t2/x2, ..., tn/xn] + * + * </pre> + */ + case class InstantiateForallMultipleWithoutFormula(t: FOL.Term*) extends ProofStepWithoutPrem with ProofStepWithoutBotNorPrem(1) { + override def asSCProof(premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + + val prem = currentProof.getSequent(premises(0)) + + if (prem.right.tail.isEmpty) { + // well formed + InstantiateForall(prem.right.head, t: _*).asSCProof(premises, currentProof) + } else ProofStepJudgement.InvalidProofStep(this.asProofStep(premises), "RHS of premise sequent is not a singleton.") + + } + + override def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + + val prem = currentProof.getSequent(premises(0)) + + if (prem.right.tail.isEmpty) { + // well formed + InstantiateForall(prem.right.head, t: _*).asSCProof(bot, premises, currentProof) + } else ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "RHS of premise sequent is not a singleton.") + + } + + } + + /** + * Overload instantiation for ease of use + * + * Generates a proof step of the relevant type + */ + object InstantiateForall { + + // default, automatic + // def apply(phi: FOL.Formula, t: FOL.Term) = InstantiateForall(phi, t) + def apply(t: FOL.Term) = InstantiateForallWithoutFormula(t) + def apply(phi: FOL.Formula, t: FOL.Term*) = InstantiateForallMultiple(phi, t: _*) + def apply(t: FOL.Term*) = InstantiateForallMultipleWithoutFormula(t: _*) + } + + /** + * Performs a cut when the formula to be used as pivot for the cut is + * inside a conjunction, preserving the conjunction structure + * + * <pre> + * + * PartialCut(ϕ, ϕ ∧ ψ)(left, right) : + * + * left: Γ ⊢ ϕ ∧ ψ, Δ right: ϕ, Σ ⊢ γ1 , γ2, …, γn + * ----------------------------------------------------------- + * Γ, Σ ⊢ Δ, ψ ∧ γ1, ψ ∧ γ2, … , ψ ∧ γn + * + * </pre> + */ + case class PartialCut(phi: FOL.Formula, conjunction: FOL.Formula) extends ProofStepWithoutBotNorPrem(2) { + override def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + + def invalid(message: String) = ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), message) + + val leftSequent = currentProof.getSequent(premises(0)) + val rightSequent = currentProof.getSequent(premises(1)) + + if (leftSequent.right.contains(conjunction)) { + + if (rightSequent.left.contains(phi)) { + // check conjunction matches with phi + conjunction match { + case FOL.ConnectorFormula(FOL.And, s: Seq[FOL.Formula]) => { + if (s.contains(phi)) { + // construct proof + + val psi: Seq[FOL.Formula] = s.filterNot(_ == phi) + val newConclusions: Set[FOL.Formula] = rightSequent.right.map((f: FOL.Formula) => FOL.ConnectorFormula(FOL.And, f +: psi)) + + val Sigma: Set[FOL.Formula] = rightSequent.left - phi + + val p0 = SC.Weakening(rightSequent ++< (psi |- ()), -2) + val p1 = SC.RewriteTrue(psi |- psi) + + // TODO: can be abstracted into a RightAndAll step + val emptyProof = SCProof(IndexedSeq(), IndexedSeq(p0.bot, p1.bot)) + val proofRightAndAll = rightSequent.right.foldLeft(emptyProof) { case (p, gamma) => + p withNewSteps IndexedSeq(SC.RightAnd(p.conclusion -> gamma +> FOL.ConnectorFormula(FOL.And, gamma +: psi), Seq(p.length - 1, -2), gamma +: psi)) + } + + val p2 = SC.SCSubproof(proofRightAndAll, Seq(0, 1)) + val p3 = SC.Rewrite(Sigma + conjunction |- newConclusions, 2) // sanity check and correct form + val p4 = SC.Cut(bot, -1, 3, conjunction) + + /** + * newConclusions = ψ ∧ γ1, ψ ∧ γ2, … , ψ ∧ γn + * + * left = Γ ⊢ ϕ ∧ ψ, Δ Premise + * right = ϕ, Σ ⊢ γ1 , γ2, …, γn Premise + * + * p0 = ϕ, Σ, ψ ⊢ γ1 , γ2, …, γn Weakening on right + * p1 = ψ ⊢ ψ Hypothesis + * p2 = Subproof: + * 2.1 = ϕ, Σ, ψ ⊢ ψ ∧ γ1 , γ2, …, γn RightAnd on p0 and p1 with ψ ∧ γ1 + * 2.2 = ϕ, Σ, ψ ⊢ ψ ∧ γ1 , ψ ∧ γ2, …, γn RightAnd on 2.1 and p1 ψ ∧ γ2 + * ... + * 2.n = ϕ, Σ, ψ ⊢ ψ ∧ γ1, ψ ∧ γ2, …, ψ ∧ γn RightAnd on 2.(n-1) and p1 with ψ ∧ γn + * + * p3 = ϕ ∧ ψ, Σ ⊢ ψ ∧ γ1, ψ ∧ γ2, … , ψ ∧ γn Rewrite on p2 (just to have a cleaner form) + * p2 = Γ, Σ ⊢ Δ, ψ ∧ γ1, ψ ∧ γ2, … , ψ ∧ γn Cut on left, p1 with ϕ ∧ ψ + * + * p2 is the result + */ + + SC.SCSubproof(SCProof(IndexedSeq(p0, p1, p2, p3, p4), IndexedSeq(leftSequent, rightSequent)), premises.take(2)) + } else { + invalid("Input conjunction does not contain the pivot.") + } + } + case _ => invalid("Input not a conjunction.") + } + } else { + invalid("Input pivot formula not found in right premise.") + } + } else { + invalid("Input conjunction not found in first premise.") + } + } + } + +} diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/WithProofs.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/WithProofs.scala new file mode 100644 index 0000000000000000000000000000000000000000..832110978ae74f5ad08c5d29290c4a640d539efd --- /dev/null +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/WithProofs.scala @@ -0,0 +1,255 @@ +package lisa.utils.tactics + +import lisa.kernel.fol.FOL.* +import lisa.kernel.proof.RunningTheory +import lisa.kernel.proof.SCProof +import lisa.kernel.proof.SequentCalculus.Sequent +import lisa.utils.Library +import lisa.utils.tactics.ProofStepJudgement.EarlyProofStepException +import lisa.utils.tactics.ProofStepJudgement.InvalidProofStep +import lisa.utils.tactics.ProofStepJudgement.ValidProofStep +import lisa.utils.tactics.ProofStepLib.ProofStep + +import scala.collection.mutable.{Buffer => mBuf} +import scala.collection.mutable.{Map => mMap} + +trait WithProofs extends ProofsHelpers { + library: Library => + + class Proof(assumpts: List[Formula] = Nil) { + type OutsideFact = (theory.Justification | Proof#DoubleStep) + // Maintaining the current state of the proof if an imperative environment // + private val that: Proof = this + private var steps: List[DoubleStep] = Nil + private var imports: List[ImportedFact] = Nil + private var assumptions: List[Formula] = assumpts + private var discharges: List[Fact] = Nil + + private val justMap: mMap[OutsideFact, ImportedFact] = mMap() + + private val parent: Option[Proof] = if (proofStack.isEmpty) None else Some(proofStack(0)) + + /** + * A step that has been added to a proof and its equivalent in pure sequent calculus. + */ + case class DoubleStep private (ps: ProofStep, scps: SCProofStep, position: Int) { + val bot: Sequent = scps.bot + } + + /** + * An import (theorem, axiom or definition) that has been added to the current proof. + */ + case class ImportedFact private (of: OutsideFact, seq: Sequent, position: Int, reference: Int | theory.Justification) {} + + /** + * The type of object which can be used as premises of proofsteps, similar to integers in pure sequent calculus. + */ + type Fact = DoubleStep | OutsideFact | ImportedFact | Int + + private def addStep(ds: DoubleStep): Unit = steps = ds :: steps + private def addImport(ji: ImportedFact): Unit = { + justMap.update(ji.of, ji) + imports = ji :: imports + } + + // Setters // + + /** + * @param f add the formula f as an assumption on the left handsides of all further (manually written) proofsteps in the proof. + */ + def addAssumption(f: Formula): Unit = { + if (!assumptions.contains(f)) assumptions = f :: assumptions + } + + /** + * @param ji Automatically discharge (by applying Cut rule) the given justification at the end of the proof. + */ + def addDischarge(ji: Fact): Unit = { + if (!discharges.contains(ji)) discharges = ji :: discharges + } + + private object DoubleStep { + def newDoubleStep(ps: ProofStep)(using output: String => Unit)(using finishOutput: Throwable => Nothing): DoubleStep = { + val judgement = ps.asSCProof(that) + judgement match { + case ValidProofStep(scps) => + val ds = DoubleStep(ps, scps, steps.length) + addStep(ds) + ds + case InvalidProofStep(ps, message) => + output(s"$message\n") + finishOutput(EarlyProofStepException(message)) + } + } + } + + /** + * Add a new proof step to the proof + */ + def newDoubleStep(ps: ProofStep)(using output: String => Unit)(using finishOutput: Throwable => Nothing): DoubleStep = + DoubleStep.newDoubleStep(ps: ProofStep) + + private object ImportedFact { + def newImportedFact(outFact: OutsideFact): ImportedFact = { + if (parent.isEmpty) { + outFact match { + case just: theory.Justification => + val imf: ImportedFact = ImportedFact(outFact, theory.sequentFromJustification(just), -(imports.length + 1), just) + addImport(imf) + imf + case ds: Proof#DoubleStep => throw InvalidJustificationException(ds) + } + } else { + val (seq, ref) = parent.get.getSequentAndInt(outFact) + val imf: ImportedFact = ImportedFact(outFact, seq, -(imports.length + 1), ref) + addImport(imf) + imf + } + } + } + + /** + * Add a new import to the proof. + */ + def newImportedFact(just: theory.Justification): ImportedFact = ImportedFact.newImportedFact(just) + + // Getters // + + /** + * Favour using getSequent when applicable. + * @return The list of ValidatedSteps (containing a high level ProofStep and the corresponding SCProofStep). + */ + def getSteps: List[DoubleStep] = steps.reverse + + /** + * Favour using getSequent when applicable. + * @return The list of Imports validated in the formula, with their original justification. + */ + def getImports: List[ImportedFact] = imports.reverse + + /** + * @return The list of formulas that are assumed for the reminder of the proof. + */ + def getAssumptions: List[Formula] = assumptions + + /** + * @return The list of Formula, typically proved by outer theorems or axioms that will get discharged in the end of the proof. + */ + def getDischarges: List[Fact] = discharges + + /** + * Tell if a justification for a ProofStep (an Index, and ProofStep, a theory Justification) is usable in the current proof + */ + def validInThisProof(ij: Library#Proof#Fact): Boolean = ij match { + case ds: library.Proof#DoubleStep => ds.isInstanceOf[this.DoubleStep] || (parent.nonEmpty && parent.get.validInThisProof(ij)) + case ji: library.Proof#ImportedFact => ji.isInstanceOf[this.ImportedFact] || (parent.nonEmpty && parent.get.validInThisProof(ij)) + case _: Int => true + case _: theory.Justification => true + case _ => false + } + + /** + * Tell if a justification for a ProofStep (ad ProofStep, a theory Justification) is usable in the current proof + */ + def validInThisProof(ji: Library#Proof#ImportedFact): Boolean = validInThisProof(ji.asInstanceOf[Library#Proof#Fact]) + + /** + * Tell if a justification for a ProofStep (ad ProofStep, a theory Justification) is usable in the current proof + */ + def validInThisProof(ds: Library#Proof#DoubleStep): Boolean = validInThisProof(ds.asInstanceOf[Library#Proof#Fact]) + + /** + * Compute the final, Kernel-pure, SCProof. + */ + def toSCProof(using String => Unit)(using finishOutput: Throwable => Nothing): lisa.kernel.proof.SCProof = { + discharges.foreach(i => Discharge(getSequentAndInt(i)._2)) + SCProof(steps.reverse.map(_.scps).toIndexedSeq, imports.reverse.map(_.seq).toIndexedSeq) + } + + /** + * Return the Sequent that a given justification proves as well as it's integer position in the steps or imports lists. + */ + def getSequentAndInt(ij: Fact): (Sequent, Int) = { + ij match { + case ds: DoubleStep => + (ds.bot, ds.position) + case ds: Proof#DoubleStep if parent.nonEmpty && parent.get.validInThisProof(ds) => + val r = justMap.get(ds) + r match { + case Some(importedFact) => getSequentAndInt(importedFact) + case None => + getSequentAndInt(ImportedFact.newImportedFact(ds)) + } + case ds: Proof#DoubleStep => throw InvalidJustificationException(ds) + case just: theory.Justification => + val r = justMap.get(just) + r match { + case Some(ji) => getSequentAndInt(ji) + case None => + if (parent.isEmpty) getSequentAndInt(ImportedFact.newImportedFact(just)) + else { + val i = parent.get.getSequentAndInt(just) + getSequentAndInt(ImportedFact.newImportedFact(just)) + } + } + case ji: ImportedFact => + (ji.seq, ji.position) + case i: Int => + ( + if (i >= 0) + if (i >= steps.length) throw new IndexOutOfBoundsException(s"index $i is out of bounds of the steps Seq") + else steps(steps.length - i - 1).bot + else { + val i2 = -(i + 1) + if (i2 >= imports.length) throw new IndexOutOfBoundsException(s"index $i is out of bounds of the imports Seq") + else imports(imports.length + i).seq + }, + i + ) + } + } + + /** + * Create a new proof with this proof as parent, execute the given code and then close the created proof (i.e. remove it from the proofstack). + */ + def subproof(proofAction: => Unit): Proof = { + assert(proofStack.head == this, "Can only create a subproof in the latest opened Proof.") + val p = new Proof(getAssumptions) + proofStack.push(p) + proofAction + proofStack.pop + } + + /** + * Return the Sequent that a given justification proves in the proof. + */ + def getSequent(ij: Fact): Sequent = getSequentAndInt(ij)._1 + + /** + * @return the most recently added proofstep. + */ + def mostRecentStep: (DoubleStep, Int) = (steps.head, steps.length - 1) + + /** + * @return Current number of steps in the proof. + */ + def length: Int = steps.length + + /** + * @return a Set of symbols free in the assumption and which shouldn't be bound or instantiated. + */ + def lockedSymbols: Set[SchematicLabel] = assumptions.toSet.flatMap(f => f.schematicFormulaLabels.toSet[SchematicLabel] ++ f.schematicTermLabels.toSet[SchematicLabel]) + + /** + * @return The sequent and integer position of a justification in the proof. Alias for [[getSequentAndInt]] + */ + def references(ij: Fact): (Sequent, Int) = getSequentAndInt(ij) + + } + + /** + * An error indicating that a given proof step was used in a proof while it does not belong to it or its parents. + */ + case class InvalidJustificationException(ds: Proof#DoubleStep) extends Exception("Reference to a step that does not belong to the current proof or on of its parents.") + +} diff --git a/src/main/scala/lisa/automation/kernel/SimplePropositionalSolver.scala b/src/main/scala/lisa/automation/kernel/SimplePropositionalSolver.scala index ab43254c250ccfe7fbc06550fc8c14cea36d87a2..def2e6640e2e99a8e66fdd6ce0524bc125113f6b 100644 --- a/src/main/scala/lisa/automation/kernel/SimplePropositionalSolver.scala +++ b/src/main/scala/lisa/automation/kernel/SimplePropositionalSolver.scala @@ -3,7 +3,10 @@ package lisa.automation.kernel import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof import lisa.kernel.proof.SequentCalculus.* -import lisa.utils.Helpers.* +import lisa.utils.Helpers.{_, given} +import lisa.utils.Library +import lisa.utils.tactics.ProofStepJudgement +import lisa.utils.tactics.ProofStepLib.{_, given} import scala.collection.mutable.Set as mSet @@ -165,4 +168,30 @@ object SimplePropositionalSolver { r4 } + case object Trivial extends ProofStepWithoutBot with ProofStepWithoutBotNorPrem(-1) { + override val premises: Seq[Int] = Seq() + def asSCProof(bot: Sequent, currentProof: Library#Proof): ProofStepJudgement = { + ProofStepJudgement.ValidProofStep(SCSubproof(solveSequent(bot))) + } + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + + val sp = SCSubproof( + { + val premsFormulas = premises.map(p => (p, sequentToFormula(currentProof.getSequent(p)))) + val initProof = premsFormulas.map(s => Rewrite(() |- s._2, s._1)).toList + val sqToProve = bot ++< (() |- premsFormulas.map(s => s._2).toSet) + val subpr = SCSubproof(solveSequent(sqToProve)) + val n = initProof.length - 1 + val stepsList = premsFormulas.zipWithIndex.foldLeft[List[SCProofStep]](subpr :: initProof)((prev: List[SCProofStep], cur) => { + val ((prem, form), position) = cur + Cut(prev.head.bot -< form, position, prev.length - 1, form) :: prev + }) + SCProof(stepsList.reverse.toIndexedSeq, premises.map(p => currentProof.getSequent(p)).toIndexedSeq) + }, + premises + ) + ProofStepJudgement.ValidProofStep(sp) + } + } + } diff --git a/src/main/scala/lisa/proven/mathematics/Mapping.scala b/src/main/scala/lisa/proven/mathematics/Mapping.scala index f318e41090dcd64a142a9cc59d0343b740ea7494..f45db00fb846349ac74aa2f4feb9cbc16855f5d3 100644 --- a/src/main/scala/lisa/proven/mathematics/Mapping.scala +++ b/src/main/scala/lisa/proven/mathematics/Mapping.scala @@ -12,7 +12,7 @@ import SetTheory.* object Mapping extends lisa.Main { THEOREM("functionalMapping") of - "∀ 'a. elem('a, 'A) ⇒ (∃! 'x. 'phi('x, 'a)) ⊢ ∃! 'X. ∀ 'x. elem('x, 'X) ↔ (∃ 'a. elem('a, 'A) ∧ 'phi('x, 'a))" PROOF { + "∀ 'a. elem('a, 'A) ⇒ (∃! 'x. 'phi('x, 'a)) ⊢ ∃! 'X. ∀ 'x. elem('x, 'X) ↔ (∃ 'a. elem('a, 'A) ∧ 'phi('x, 'a))" PROOF2 { val a = VariableLabel("a") val x = VariableLabel("x") val y = VariableLabel("y") @@ -30,79 +30,81 @@ object Mapping extends lisa.Main { val H = existsOne(x, phi(x, a)) val H1 = forall(a, in(a, A) ==> H) val s0 = hypothesis(H) // () |- existsOne(x, phi(x, a))) - val s1 = Weakening((H, in(a, A)) |- existsOne(x, phi(x, a)), 0) - val s2 = Rewrite((H) |- in(a, A) ==> existsOne(x, phi(x, a)), 1) - // val s3 = RightForall((H) |- forall(a, in(a, A) ==> existsOne(x, phi(x, a))), 2, in(a, A) ==> existsOne(x, phi(x, a)), a) // () |- ∀a∈A. ∃!x. phi(x, a) + val s1 = SC.Weakening((H, in(a, A)) |- existsOne(x, phi(x, a)), 0) + val s2 = SC.Rewrite((H) |- in(a, A) ==> existsOne(x, phi(x, a)), 1) + // val s3 = SC.RightForall((H) |- forall(a, in(a, A) ==> existsOne(x, phi(x, a))), 2, in(a, A) ==> existsOne(x, phi(x, a)), a) // () |- ∀a∈A. ∃!x. phi(x, a) val s3 = hypothesis(H1) val i1 = () |- replacementSchema - val p0 = InstPredSchema( + val p0 = SC.InstPredSchema( () |- instantiatePredicateSchemas(replacementSchema, Map(sPsi -> LambdaTermFormula(Seq(y, a, x), phi(x, a)))), -1, Map(sPsi -> LambdaTermFormula(Seq(y, a, x), phi(x, a))) ) - val p1 = instantiateForall(Proof(steps(p0), imports(i1)), A) - val s4 = SCSubproof(p1, Seq(-1)) // - val s5 = Rewrite(s3.bot.right.head |- exists(B, forall(x, in(x, A) ==> exists(y, in(y, B) /\ (phi(y, x))))), 4) - val s6 = Cut((H1) |- exists(B, forall(x, in(x, A) ==> exists(y, in(y, B) /\ (phi(y, x))))), 3, 5, s3.bot.right.head) // ⊢ ∃B. ∀x. (x ∈ A) ⇒ ∃y. (y ∈ B) ∧ (y = (x, b)) + val p1 = instantiateForall(SCProof(steps(p0), imports(i1)), A) + val s4 = SC.SCSubproof(p1, Seq(-1)) // + val s5 = SC.Rewrite(s3.bot.right.head |- exists(B, forall(x, in(x, A) ==> exists(y, in(y, B) /\ (phi(y, x))))), 4) + val s6 = SC.Cut((H1) |- exists(B, forall(x, in(x, A) ==> exists(y, in(y, B) /\ (phi(y, x))))), 3, 5, s3.bot.right.head) // ⊢ ∃B. ∀x. (x ∈ A) ⇒ ∃y. (y ∈ B) ∧ (y = (x, b)) val i2 = () |- comprehensionSchema // forall(z, exists(y, forall(x, in(x,y) <=> (in(x,z) /\ sPhi(x,z))))) - val q0 = InstPredSchema( + val q0 = SC.InstPredSchema( () |- instantiatePredicateSchemas(comprehensionSchema, Map(sPhi -> LambdaTermFormula(Seq(x, z), exists(a, in(a, A) /\ phi(x, a))))), -1, Map(sPhi -> LambdaTermFormula(Seq(x, z), exists(a, in(a, A) /\ phi(x, a)))) ) - val q1 = instantiateForall(Proof(steps(q0), imports(i2)), B) - val s7 = SCSubproof(q1, Seq(-2)) // ∃y. ∀x. (x ∈ y) ↔ (x ∈ B) ∧ ∃a. a ∈ A /\ x = (a, b) := exists(y, F(y) ) - Proof(steps(s0, s1, s2, s3, s4, s5, s6, s7), imports(i1, i2)) - val s8 = SCSubproof({ + val q1 = instantiateForall(SCProof(steps(q0), imports(i2)), B) + val s7 = SC.SCSubproof(q1, Seq(-2)) // ∃y. ∀x. (x ∈ y) ↔ (x ∈ B) ∧ ∃a. a ∈ A /\ x = (a, b) := exists(y, F(y) ) + SCProof(steps(s0, s1, s2, s3, s4, s5, s6, s7), imports(i1, i2)) + val s8 = SC.SCSubproof({ val y1 = VariableLabel("y1") val s0 = hypothesis(in(y1, B)) - val s1 = RightSubstEq((in(y1, B), x === y1) |- in(x, B), 0, List((x, y1)), LambdaTermFormula(Seq(f), in(f, B))) - val s2 = LeftSubstIff(Set(in(y1, B), (x === y1) <=> phi(x, a), phi(x, a)) |- in(x, B), 1, List(((x === y1), phi(x, a))), LambdaFormulaFormula(Seq(h), h())) - val s3 = LeftSubstEq(Set(y === y1, in(y1, B), (x === y) <=> phi(x, a), phi(x, a)) |- in(x, B), 2, List((y, y1)), LambdaTermFormula(Seq(f), (x === f) <=> phi(x, a))) - val s4 = LeftSubstIff(Set((y === y1) <=> phi(y1, a), phi(y1, a), in(y1, B), (x === y) <=> phi(x, a), phi(x, a)) |- in(x, B), 3, List((phi(y1, a), y1 === y)), LambdaFormulaFormula(Seq(h), h())) - val s5 = LeftForall(Set(forall(x, (y === x) <=> phi(x, a)), phi(y1, a), in(y1, B), (x === y) <=> phi(x, a), phi(x, a)) |- in(x, B), 4, (y === x) <=> phi(x, a), x, y1) - val s6 = LeftForall(Set(forall(x, (y === x) <=> phi(x, a)), phi(y1, a), in(y1, B), phi(x, a)) |- in(x, B), 5, (x === y) <=> phi(x, a), x, x) - val s7 = LeftExists(Set(exists(y, forall(x, (y === x) <=> phi(x, a))), phi(y1, a), in(y1, B), phi(x, a)) |- in(x, B), 6, forall(x, (y === x) <=> phi(x, a)), y) - val s8 = Rewrite(Set(exists(y, forall(x, (y === x) <=> phi(x, a))), phi(y1, a) /\ in(y1, B), phi(x, a)) |- in(x, B), 7) - val s9 = LeftExists(Set(exists(y, forall(x, (y === x) <=> phi(x, a))), exists(y1, phi(y1, a) /\ in(y1, B)), phi(x, a)) |- in(x, B), 8, phi(y1, a) /\ in(y1, B), y1) - val s10 = Rewrite(Set(exists(y, forall(x, (y === x) <=> phi(x, a))), True ==> exists(y, phi(y, a) /\ in(y, B)), phi(x, a)) |- in(x, B), 9) - val s11 = LeftSubstIff( + val s1 = SC.RightSubstEq((in(y1, B), x === y1) |- in(x, B), 0, List((x, y1)), LambdaTermFormula(Seq(f), in(f, B))) + val s2 = SC.LeftSubstIff(Set(in(y1, B), (x === y1) <=> phi(x, a), phi(x, a)) |- in(x, B), 1, List(((x === y1), phi(x, a))), LambdaFormulaFormula(Seq(h), h())) + val s3 = SC.LeftSubstEq(Set(y === y1, in(y1, B), (x === y) <=> phi(x, a), phi(x, a)) |- in(x, B), 2, List((y, y1)), LambdaTermFormula(Seq(f), (x === f) <=> phi(x, a))) + val s4 = + SC.LeftSubstIff(Set((y === y1) <=> phi(y1, a), phi(y1, a), in(y1, B), (x === y) <=> phi(x, a), phi(x, a)) |- in(x, B), 3, List((phi(y1, a), y1 === y)), LambdaFormulaFormula(Seq(h), h())) + val s5 = SC.LeftForall(Set(forall(x, (y === x) <=> phi(x, a)), phi(y1, a), in(y1, B), (x === y) <=> phi(x, a), phi(x, a)) |- in(x, B), 4, (y === x) <=> phi(x, a), x, y1) + val s6 = SC.LeftForall(Set(forall(x, (y === x) <=> phi(x, a)), phi(y1, a), in(y1, B), phi(x, a)) |- in(x, B), 5, (x === y) <=> phi(x, a), x, x) + val s7 = SC.LeftExists(Set(exists(y, forall(x, (y === x) <=> phi(x, a))), phi(y1, a), in(y1, B), phi(x, a)) |- in(x, B), 6, forall(x, (y === x) <=> phi(x, a)), y) + val s8 = SC.Rewrite(Set(exists(y, forall(x, (y === x) <=> phi(x, a))), phi(y1, a) /\ in(y1, B), phi(x, a)) |- in(x, B), 7) + val s9 = SC.LeftExists(Set(exists(y, forall(x, (y === x) <=> phi(x, a))), exists(y1, phi(y1, a) /\ in(y1, B)), phi(x, a)) |- in(x, B), 8, phi(y1, a) /\ in(y1, B), y1) + val s10 = SC.Rewrite(Set(exists(y, forall(x, (y === x) <=> phi(x, a))), True ==> exists(y, phi(y, a) /\ in(y, B)), phi(x, a)) |- in(x, B), 9) + val s11 = SC.LeftSubstIff( Set(exists(y, forall(x, (y === x) <=> phi(x, a))), in(a, A) ==> exists(y, phi(y, a) /\ in(y, B)), phi(x, a), in(a, A)) |- in(x, B), 10, List((True, in(a, A))), LambdaFormulaFormula(Seq(h), h() ==> exists(y, phi(y, a) /\ in(y, B))) ) - val s12 = LeftForall( + val s12 = SC.LeftForall( Set(exists(y, forall(x, (y === x) <=> phi(x, a))), forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))), phi(x, a), in(a, A)) |- in(x, B), 11, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B)), a, a ) - val s13 = LeftSubstIff( + val s13 = SC.LeftSubstIff( Set(in(a, A) ==> exists(y, forall(x, (y === x) <=> phi(x, a))), forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))), phi(x, a), in(a, A)) |- in(x, B), 12, List((True, in(a, A))), LambdaFormulaFormula(Seq(h), h() ==> exists(y, forall(x, (y === x) <=> phi(x, a)))) ) - val s14 = LeftForall( + val s14 = SC.LeftForall( Set(forall(a, in(a, A) ==> exists(y, forall(x, (y === x) <=> phi(x, a)))), forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))), phi(x, a), in(a, A)) |- in(x, B), 13, in(a, A) ==> exists(y, forall(x, (y === x) <=> phi(x, a))), a, a ) - val s15 = Rewrite(Set(forall(a, in(a, A) ==> exists(y, forall(x, (y === x) <=> phi(x, a)))), forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))), phi(x, a) /\ in(a, A)) |- in(x, B), 14) - val s16 = LeftExists( + val s15 = + SC.Rewrite(Set(forall(a, in(a, A) ==> exists(y, forall(x, (y === x) <=> phi(x, a)))), forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))), phi(x, a) /\ in(a, A)) |- in(x, B), 14) + val s16 = SC.LeftExists( Set(forall(a, in(a, A) ==> exists(y, forall(x, (y === x) <=> phi(x, a)))), forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))), exists(a, phi(x, a) /\ in(a, A))) |- in(x, B), 15, phi(x, a) /\ in(a, A), a ) val truc = forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))) - val s17 = Rewrite(Set(forall(a, in(a, A) ==> existsOne(x, phi(x, a))), forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))), exists(a, phi(x, a) /\ in(a, A))) |- in(x, B), 16) - Proof(steps(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17)) + val s17 = SC.Rewrite(Set(forall(a, in(a, A) ==> existsOne(x, phi(x, a))), forall(a, in(a, A) ==> exists(y, phi(y, a) /\ in(y, B))), exists(a, phi(x, a) /\ in(a, A))) |- in(x, B), 16) + SCProof(steps(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17)) // goal H, ∀a. (a ∈ A) ⇒ ∃y. y ∈ B ∧ phi(y, a), ∃a. a ∈ A ∧ phi(x, a) |- (x ∈ B) // redGoal ∀a.(a ∈ A) => ∃!x. phi(x, a), ∀a. (a ∈ A) ⇒ ∃y. y ∈ B ∧ phi(y, a), ∃a. a ∈ A ∧ phi(x, a) |- (x ∈ B) s17 // redGoal ∀a.(a ∈ A) => ∃y. ∀x. (x=y) ↔ phi(x, a), ∀a. (a ∈ A) ⇒ ∃y. y ∈ B ∧ phi(y, a), ∃a. a ∈ A ∧ phi(x, a) |- (x ∈ B) s16 @@ -128,31 +130,31 @@ object Mapping extends lisa.Main { val G = forall(a, in(a, A) ==> exists(y, in(y, B) /\ (phi(y, a)))) val F = forall(x, iff(in(x, B1), in(x, B) /\ exists(a, in(a, A) /\ (phi(x, a))))) - val s9 = SCSubproof({ - val p0 = instantiateForall(Proof(hypothesis(F)), x) + val s9 = SC.SCSubproof({ + val p0 = instantiateForall(SCProof(hypothesis(F)), x) val left = in(x, B1) val right = in(x, B) /\ exists(a, in(a, A) /\ (phi(x, a))) - val p1 = p0.withNewSteps(Vector(Rewrite(F |- (left ==> right) /\ (right ==> left), p0.length - 1))) + val p1 = p0.withNewSteps(Vector(SC.Rewrite(F |- (left ==> right) /\ (right ==> left), p0.length - 1))) val p2 = destructRightAnd(p1, (right ==> left), (left ==> right)) // F |- in(x, B) /\ exists(a, in(a, A) /\ (phi(x, a))) => in(x, B1) - val p3 = p2.withNewSteps(Vector(Rewrite(Set(F, in(x, B), exists(a, in(a, A) /\ (phi(x, a)))) |- in(x, B1), p2.length - 1))) + val p3 = p2.withNewSteps(Vector(SC.Rewrite(Set(F, in(x, B), exists(a, in(a, A) /\ (phi(x, a)))) |- in(x, B1), p2.length - 1))) p3 }) // have F, (x ∈ B), ∃a. a ∈ A ∧ x = (a, b) |- (x ∈ B1) - val s10 = Cut(Set(F, G, H1, exists(a, in(a, A) /\ (phi(x, a)))) |- in(x, B1), 8, 9, in(x, B)) // redGoal F, ∃a. a ∈ A ∧ x = (a, b), ∀a. (a ∈ A) ⇒ ∃y. y ∈ B ∧ y = (a, b) |- (x ∈ B1) - val s11 = Rewrite(Set(H1, G, F) |- exists(a, in(a, A) /\ (phi(x, a))) ==> in(x, B1), 10) // F |- ∃a. a ∈ A ∧ x = (a, b) => (x ∈ B1) --- half - val s12 = SCSubproof({ - val p0 = instantiateForall(Proof(hypothesis(F)), x) + val s10 = SC.Cut(Set(F, G, H1, exists(a, in(a, A) /\ (phi(x, a)))) |- in(x, B1), 8, 9, in(x, B)) // redGoal F, ∃a. a ∈ A ∧ x = (a, b), ∀a. (a ∈ A) ⇒ ∃y. y ∈ B ∧ y = (a, b) |- (x ∈ B1) + val s11 = SC.Rewrite(Set(H1, G, F) |- exists(a, in(a, A) /\ (phi(x, a))) ==> in(x, B1), 10) // F |- ∃a. a ∈ A ∧ x = (a, b) => (x ∈ B1) --- half + val s12 = SC.SCSubproof({ + val p0 = instantiateForall(SCProof(hypothesis(F)), x) val left = in(x, B1) val right = in(x, B) /\ exists(a, in(a, A) /\ (phi(x, a))) - val p1 = p0.withNewSteps(Vector(Rewrite(F |- (left ==> right) /\ (right ==> left), p0.length - 1))) + val p1 = p0.withNewSteps(Vector(SC.Rewrite(F |- (left ==> right) /\ (right ==> left), p0.length - 1))) val p2 = destructRightAnd(p1, (left ==> right), (right ==> left)) // F |- in(x, B1) => in(x, B) /\ exists(a, in(a, A) /\ (phi(x, a))) => - val p3 = p2.withNewSteps(Vector(Rewrite(Set(F, in(x, B1)) |- exists(a, in(a, A) /\ (phi(x, a))) /\ in(x, B), p2.length - 1))) + val p3 = p2.withNewSteps(Vector(SC.Rewrite(Set(F, in(x, B1)) |- exists(a, in(a, A) /\ (phi(x, a))) /\ in(x, B), p2.length - 1))) val p4 = destructRightAnd(p3, exists(a, in(a, A) /\ (phi(x, a))), in(x, B)) - val p5 = p4.withNewSteps(Vector(Rewrite(F |- in(x, B1) ==> exists(a, in(a, A) /\ (phi(x, a))), p4.length - 1))) + val p5 = p4.withNewSteps(Vector(SC.Rewrite(F |- in(x, B1) ==> exists(a, in(a, A) /\ (phi(x, a))), p4.length - 1))) p5 }) // have F |- (x ∈ B1) ⇒ ∃a. a ∈ A ∧ x = (a, b) --- other half - val s13 = RightIff((H1, G, F) |- in(x, B1) <=> exists(a, in(a, A) /\ (phi(x, a))), 11, 12, in(x, B1), exists(a, in(a, A) /\ (phi(x, a)))) // have F |- (x ∈ B1) <=> ∃a. a ∈ A ∧ x = (a, b) + val s13 = SC.RightIff((H1, G, F) |- in(x, B1) <=> exists(a, in(a, A) /\ (phi(x, a))), 11, 12, in(x, B1), exists(a, in(a, A) /\ (phi(x, a)))) // have F |- (x ∈ B1) <=> ∃a. a ∈ A ∧ x = (a, b) val s14 = - RightForall( + SC.RightForall( (H1, G, F) |- forall(x, in(x, B1) <=> exists(a, in(a, A) /\ (phi(x, a)))), 13, in(x, B1) <=> exists(a, in(a, A) /\ (phi(x, a))), @@ -160,46 +162,49 @@ object Mapping extends lisa.Main { ) // G, F |- ∀x. (x ∈ B1) <=> ∃a. a ∈ A ∧ x = (a, b) val i3 = () |- extensionalityAxiom - val s15 = SCSubproof( + val s15 = SC.SCSubproof( { val i1 = s13.bot // G, F |- (x ∈ B1) <=> ∃a. a ∈ A ∧ x = (a, b) val i2 = () |- extensionalityAxiom - val t0 = RightSubstIff( + val t0 = SC.RightSubstIff( Set(H1, G, F, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))) |- in(x, X) <=> in(x, B1), -1, List((in(x, X), exists(a, in(a, A) /\ (phi(x, a))))), LambdaFormulaFormula(Seq(h), h() <=> in(x, B1)) ) // redGoal2 F, (z ∈ X) <=> ∃a. a ∈ A ∧ z = (a, b) |- (z ∈ X) <=> (z ∈ B1) - val t1 = LeftForall( + val t1 = SC.LeftForall( Set(H1, G, F, forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))) |- in(x, X) <=> in(x, B1), 0, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))), x, x ) // redGoal2 F, [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] |- (z ∈ X) <=> (z ∈ B1) - val t2 = RightForall(t1.bot.left |- forall(x, in(x, X) <=> in(x, B1)), 1, in(x, X) <=> in(x, B1), x) // redGoal2 F, [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] |- ∀z. (z ∈ X) <=> (z ∈ B1) + val t2 = SC.RightForall(t1.bot.left |- forall(x, in(x, X) <=> in(x, B1)), 1, in(x, X) <=> in(x, B1), x) // redGoal2 F, [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] |- ∀z. (z ∈ X) <=> (z ∈ B1) val t3 = - SCSubproof(instantiateForall(Proof(steps(Rewrite(() |- extensionalityAxiom, -1)), imports(() |- extensionalityAxiom)), X, B1), Vector(-2)) // (∀z. (z ∈ X) <=> (z ∈ B1)) <=> (X === B1))) - val t4 = RightSubstIff( + SC.SCSubproof( + instantiateForall(SCProof(steps(SC.Rewrite(() |- extensionalityAxiom, -1)), imports(() |- extensionalityAxiom)), X, B1), + Vector(-2) + ) // (∀z. (z ∈ X) <=> (z ∈ B1)) <=> (X === B1))) + val t4 = SC.RightSubstIff( t1.bot.left ++ t3.bot.right |- X === B1, 2, List((X === B1, forall(z, in(z, X) <=> in(z, B1)))), LambdaFormulaFormula(Seq(h), h()) ) // redGoal2 F, [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)], (∀z. (z ∈ X) <=> (z ∈ B1)) <=> (X === B1))) |- X=B1 - val t5 = Cut(t1.bot.left |- X === B1, 3, 4, t3.bot.right.head) // redGoal2 F, [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] |- X=B1 - val t6 = Rewrite(Set(H1, G, F) |- forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))) ==> (X === B1), 5) // F |- [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] ==> X=B1 + val t5 = SC.Cut(t1.bot.left |- X === B1, 3, 4, t3.bot.right.head) // redGoal2 F, [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] |- X=B1 + val t6 = SC.Rewrite(Set(H1, G, F) |- forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))) ==> (X === B1), 5) // F |- [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] ==> X=B1 val i3 = s14.bot // F |- ∀x. (x ∈ B1) <=> ∃a. a ∈ A ∧ x = (a, b) - val t7 = RightSubstEq( + val t7 = SC.RightSubstEq( Set(H1, G, F, X === B1) |- forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))), -3, List((X, B1)), LambdaTermFormula(Seq(f), forall(x, in(x, f) <=> exists(a, in(a, A) /\ phi(x, a)))) ) // redGoal1 F, X=B1 |- [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] - val t8 = Rewrite( + val t8 = SC.Rewrite( Set(H1, G, F) |- X === B1 ==> forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))), 7 ) // redGoal1 F |- X=B1 ==> [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] -------second half with t6 - val t9 = RightIff( + val t9 = SC.RightIff( Set(H1, G, F) |- (X === B1) <=> forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))), 6, 8, @@ -207,36 +212,36 @@ object Mapping extends lisa.Main { forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))) ) // goal F |- X=B1 <=> [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] - Proof(steps(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9), imports(i1, i2, i3)) + SCProof(steps(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9), imports(i1, i2, i3)) }, Vector(13, -3, 14) ) // goal F |- X=B1 <=> [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] - val s16 = RightForall( + val s16 = SC.RightForall( (H1, G, F) |- forall(X, (X === B1) <=> forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))), 15, (X === B1) <=> forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))), X ) // goal F |- ∀X. X=B1 <=> [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] - val s17 = RightExists( + val s17 = SC.RightExists( (H1, G, F) |- exists(y, forall(X, (X === y) <=> forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a)))))), 16, forall(X, (X === y) <=> forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))), y, B1 ) - val s18 = LeftExists((exists(B1, F), G, H1) |- s17.bot.right, 17, F, B1) // ∃B1. F |- ∃B1. ∀X. X=B1 <=> [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] - val s19 = Rewrite(s18.bot.left |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))), 18) // ∃B1. F |- ∃!X. [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] - val s20 = Cut((G, H1) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))), 7, 19, exists(B1, F)) - val s21 = LeftExists((H1, exists(B, G)) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))), 20, G, B) - val s22 = Cut(H1 |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ phi(x, a)))), 6, 21, exists(B, G)) + val s18 = SC.LeftExists((exists(B1, F), G, H1) |- s17.bot.right, 17, F, B1) // ∃B1. F |- ∃B1. ∀X. X=B1 <=> [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] + val s19 = SC.Rewrite(s18.bot.left |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))), 18) // ∃B1. F |- ∃!X. [∀x. (x ∈ X) <=> ∃a. a ∈ A ∧ x = (a, b)] + val s20 = SC.Cut((G, H1) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))), 7, 19, exists(B1, F)) + val s21 = SC.LeftExists((H1, exists(B, G)) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ (phi(x, a))))), 20, G, B) + val s22 = SC.Cut(H1 |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ phi(x, a)))), 6, 21, exists(B, G)) val res = steps(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22) - Proof(res, imports(i1, i2, i3)) + SCProof(res, imports(i1, i2, i3)) } using (ax"replacementSchema", ax"comprehensionSchema", ax"extensionalityAxiom") show THEOREM("lemmaLayeredTwoArgumentsMap") of "∀ 'b. elem('b, 'B) ⇒ (∀ 'a. elem('a, 'A) ⇒ (∃! 'x. 'psi('x, 'a, 'b))) ⊢ " + - "∃! 'X. ∀ 'x. elem('x, 'X) ↔ (∃ 'b. elem('b, 'B) ∧ (∀ 'x1. elem('x1, 'x) ↔ (∃ 'a. elem('a, 'A) ∧ 'psi('x1, 'a, 'b))))" PROOF { + "∃! 'X. ∀ 'x. elem('x, 'X) ↔ (∃ 'b. elem('b, 'B) ∧ (∀ 'x1. elem('x1, 'x) ↔ (∃ 'a. elem('a, 'A) ∧ 'psi('x1, 'a, 'b))))" PROOF2 { val a = VariableLabel("a") val b = VariableLabel("b") val x = VariableLabel("x") @@ -255,24 +260,24 @@ object Mapping extends lisa.Main { val H1 = forall(a, in(a, A) ==> H) val i1 = thm"functionalMapping" val H2 = instantiatePredicateSchemas(H1, Map(phi -> LambdaTermFormula(Seq(x, a), psi(x, a, b)))) - val s0 = InstPredSchema((H2) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), -1, Map(phi -> LambdaTermFormula(Seq(x, a), psi(x, a, b)))) - val s1 = Weakening((H2, in(b, B)) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), 0) + val s0 = SC.InstPredSchema((H2) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), -1, Map(phi -> LambdaTermFormula(Seq(x, a), psi(x, a, b)))) + val s1 = SC.Weakening((H2, in(b, B)) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), 0) val s2 = - LeftSubstIff((in(b, B) ==> H2, in(b, B)) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), 1, List((in(b, B), And())), LambdaFormulaFormula(Seq(h), h() ==> H2)) - val s3 = LeftForall((forall(b, in(b, B) ==> H2), in(b, B)) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), 2, in(b, B) ==> H2, b, b) - val s4 = Rewrite(forall(b, in(b, B) ==> H2) |- in(b, B) ==> existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), 3) - val s5 = RightForall( + SC.LeftSubstIff((in(b, B) ==> H2, in(b, B)) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), 1, List((in(b, B), And())), LambdaFormulaFormula(Seq(h), h() ==> H2)) + val s3 = SC.LeftForall((forall(b, in(b, B) ==> H2), in(b, B)) |- existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), 2, in(b, B) ==> H2, b, b) + val s4 = SC.Rewrite(forall(b, in(b, B) ==> H2) |- in(b, B) ==> existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), 3) + val s5 = SC.RightForall( forall(b, in(b, B) ==> H2) |- forall(b, in(b, B) ==> existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b))))), 4, in(b, B) ==> existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b)))), b ) - val s6 = InstFunSchema( + val s6 = SC.InstFunSchema( forall(b, in(b, B) ==> existsOne(X, phi(X, b))) |- instantiateTermSchemas(i1.right.head, Map(A -> LambdaTermTerm(Nil, B))), -1, Map(A -> LambdaTermTerm(Nil, B)) ) - val s7 = InstPredSchema( + val s7 = SC.InstPredSchema( forall(b, in(b, B) ==> existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b))))) |- existsOne( X, forall(x, in(x, X) <=> exists(b, in(b, B) /\ forall(x1, in(x1, x) <=> exists(a, in(a, A) /\ psi(x1, a, b))))) @@ -280,13 +285,13 @@ object Mapping extends lisa.Main { 6, Map(phi -> LambdaTermFormula(Seq(y, b), forall(x, in(x, y) <=> exists(a, in(a, A) /\ psi(x, a, b))))) ) - val s8 = Cut( + val s8 = SC.Cut( forall(b, in(b, B) ==> H2) |- existsOne(X, forall(x, in(x, X) <=> exists(b, in(b, B) /\ forall(x1, in(x1, x) <=> exists(a, in(a, A) /\ psi(x1, a, b)))))), 5, 7, forall(b, in(b, B) ==> existsOne(X, forall(x, in(x, X) <=> exists(a, in(a, A) /\ psi(x, a, b))))) ) - Proof(Vector(s0, s1, s2, s3, s4, s5, s6, s7, s8), Vector(i1)) + SCProof(Vector(s0, s1, s2, s3, s4, s5, s6, s7, s8), Vector(i1)) // have ∀a. (a ∈ A) ⇒ ∃!x. ?psi(x, a, b) ⊢ ∃!X. ∀x. (x ∈ X) ↔ ∃a. (a ∈ A) ∧ ?psi(x, a, b) s0 // have (b ∈ B), ∀a. (a ∈ A) ⇒ ∃!x. ?psi(x, a, b) ⊢ ∃!X. ∀x. (x ∈ X) ↔ ∃a. (a ∈ A) ∧ ?psi(x, a, b) s1 // have (b ∈ B), (b ∈ B) ⇒ ∀a. (a ∈ A) ⇒ ∃!x. ?psi(x, a, b) ⊢ ∃!X. ∀x. (x ∈ X) ↔ ∃a. (a ∈ A) ∧ ?psi(x, a, b) s2 @@ -300,7 +305,7 @@ object Mapping extends lisa.Main { show THEOREM("applyFunctionToUniqueObject") of - "∃! 'x. 'phi('x) ⊢ ∃! 'z. ∃ 'x. ('z = 'F('x)) ∧ 'phi('x)" PROOF { + "∃! 'x. 'phi('x) ⊢ ∃! 'z. ∃ 'x. ('z = 'F('x)) ∧ 'phi('x)" PROOF2 { val x = VariableLabel("x") val x1 = VariableLabel("x1") val z = VariableLabel("z") @@ -310,47 +315,48 @@ object Mapping extends lisa.Main { val phi = SchematicPredicateLabel("phi", 1) val g = VariableFormulaLabel("g") - val g2 = SCSubproof({ + val g2 = SC.SCSubproof({ val s0 = hypothesis(F(x1) === z) - val s1 = LeftSubstEq((x === x1, F(x) === z) |- F(x1) === z, 0, List((x, x1)), LambdaTermFormula(Seq(f), F(f) === z)) - val s2 = LeftSubstIff(Set(phi(x) <=> (x === x1), phi(x), F(x) === z) |- F(x1) === z, 1, List((x === x1, phi(x))), LambdaFormulaFormula(Seq(g), g)) - val s3 = LeftForall(Set(forall(x, phi(x) <=> (x === x1)), phi(x), F(x) === z) |- F(x1) === z, 2, phi(x) <=> (x === x1), x, x) - val s4 = Rewrite(Set(forall(x, phi(x) <=> (x === x1)), phi(x) /\ (F(x) === z)) |- F(x1) === z, 3) - val s5 = LeftExists(Set(forall(x, phi(x) <=> (x === x1)), exists(x, phi(x) /\ (F(x) === z))) |- F(x1) === z, 4, phi(x) /\ (F(x) === z), x) - val s6 = Rewrite(forall(x, phi(x) <=> (x === x1)) |- exists(x, phi(x) /\ (F(x) === z)) ==> (F(x1) === z), 5) - Proof(steps(s0, s1, s2, s3, s4, s5, s6)) + val s1 = SC.LeftSubstEq((x === x1, F(x) === z) |- F(x1) === z, 0, List((x, x1)), LambdaTermFormula(Seq(f), F(f) === z)) + val s2 = SC.LeftSubstIff(Set(phi(x) <=> (x === x1), phi(x), F(x) === z) |- F(x1) === z, 1, List((x === x1, phi(x))), LambdaFormulaFormula(Seq(g), g)) + val s3 = SC.LeftForall(Set(forall(x, phi(x) <=> (x === x1)), phi(x), F(x) === z) |- F(x1) === z, 2, phi(x) <=> (x === x1), x, x) + val s4 = SC.Rewrite(Set(forall(x, phi(x) <=> (x === x1)), phi(x) /\ (F(x) === z)) |- F(x1) === z, 3) + val s5 = SC.LeftExists(Set(forall(x, phi(x) <=> (x === x1)), exists(x, phi(x) /\ (F(x) === z))) |- F(x1) === z, 4, phi(x) /\ (F(x) === z), x) + val s6 = SC.Rewrite(forall(x, phi(x) <=> (x === x1)) |- exists(x, phi(x) /\ (F(x) === z)) ==> (F(x1) === z), 5) + SCProof(steps(s0, s1, s2, s3, s4, s5, s6)) }) // redGoal2 ∀x. x=x1 <=> phi(x) ⊢ ∃x. z=F(x) /\ phi(x) ==> F(x1)=z g2.s5 - val g1 = SCSubproof({ + val g1 = SC.SCSubproof({ val s0 = hypothesis(phi(x1)) - val s1 = LeftForall(forall(x, (x === x1) <=> phi(x)) |- phi(x1), 0, (x === x1) <=> phi(x), x, x1) + val s1 = SC.LeftForall(forall(x, (x === x1) <=> phi(x)) |- phi(x1), 0, (x === x1) <=> phi(x), x, x1) val s2 = hypothesis(z === F(x1)) - val s3 = RightAnd((forall(x, (x === x1) <=> phi(x)), z === F(x1)) |- (z === F(x1)) /\ phi(x1), Seq(2, 1), Seq(z === F(x1), phi(x1))) - val s4 = RightExists((forall(x, (x === x1) <=> phi(x)), z === F(x1)) |- exists(x, (z === F(x)) /\ phi(x)), 3, (z === F(x)) /\ phi(x), x, x1) - val s5 = Rewrite(forall(x, (x === x1) <=> phi(x)) |- z === F(x1) ==> exists(x, (z === F(x)) /\ phi(x)), 4) - Proof(steps(s0, s1, s2, s3, s4, s5)) + val s3 = SC.RightAnd((forall(x, (x === x1) <=> phi(x)), z === F(x1)) |- (z === F(x1)) /\ phi(x1), Seq(2, 1), Seq(z === F(x1), phi(x1))) + val s4 = SC.RightExists((forall(x, (x === x1) <=> phi(x)), z === F(x1)) |- exists(x, (z === F(x)) /\ phi(x)), 3, (z === F(x)) /\ phi(x), x, x1) + val s5 = SC.Rewrite(forall(x, (x === x1) <=> phi(x)) |- z === F(x1) ==> exists(x, (z === F(x)) /\ phi(x)), 4) + SCProof(steps(s0, s1, s2, s3, s4, s5)) }) val s0 = g1 val s1 = g2 - val s2 = RightIff(forall(x, (x === x1) <=> phi(x)) |- (z === F(x1)) <=> exists(x, (z === F(x)) /\ phi(x)), 0, 1, z === F(x1), exists(x, (z === F(x)) /\ phi(x))) - val s3 = RightForall(forall(x, (x === x1) <=> phi(x)) |- forall(z, (z === F(x1)) <=> exists(x, (z === F(x)) /\ phi(x))), 2, (z === F(x1)) <=> exists(x, (z === F(x)) /\ phi(x)), z) - val s4 = RightExists( + val s2 = SC.RightIff(forall(x, (x === x1) <=> phi(x)) |- (z === F(x1)) <=> exists(x, (z === F(x)) /\ phi(x)), 0, 1, z === F(x1), exists(x, (z === F(x)) /\ phi(x))) + val s3 = SC.RightForall(forall(x, (x === x1) <=> phi(x)) |- forall(z, (z === F(x1)) <=> exists(x, (z === F(x)) /\ phi(x))), 2, (z === F(x1)) <=> exists(x, (z === F(x)) /\ phi(x)), z) + val s4 = SC.RightExists( forall(x, (x === x1) <=> phi(x)) |- exists(z1, forall(z, (z === z1) <=> exists(x, (z === F(x)) /\ phi(x)))), 3, forall(z, (z === z1) <=> exists(x, (z === F(x)) /\ phi(x))), z1, F(x1) ) - val s5 = LeftExists(exists(x1, forall(x, (x === x1) <=> phi(x))) |- exists(z1, forall(z, (z === z1) <=> exists(x, (z === F(x)) /\ phi(x)))), 4, forall(x, (x === x1) <=> phi(x)), x1) - val s6 = Rewrite(existsOne(x, phi(x)) |- existsOne(z, exists(x, (z === F(x)) /\ phi(x))), 5) // goal ∃!x. phi(x) ⊢ ∃!z. ∃x. z=F(x) /\ phi(x) - Proof(Vector(s0, s1, s2, s3, s4, s5, s6)) + val s5 = SC.LeftExists(exists(x1, forall(x, (x === x1) <=> phi(x))) |- exists(z1, forall(z, (z === z1) <=> exists(x, (z === F(x)) /\ phi(x)))), 4, forall(x, (x === x1) <=> phi(x)), x1) + val s6 = SC.Rewrite(existsOne(x, phi(x)) |- existsOne(z, exists(x, (z === F(x)) /\ phi(x))), 5) // goal ∃!x. phi(x) ⊢ ∃!z. ∃x. z=F(x) /\ phi(x) + SCProof(Vector(s0, s1, s2, s3, s4, s5, s6)) } using () show THEOREM("mapTwoArguments") of "∀ 'b. elem('b, 'B) ⇒ (∀ 'a. elem('a, 'A) ⇒ (∃! 'x. 'psi('x, 'a, 'b))) ⊢ " + - "∃! 'z. ∃ 'x. 'z = union('x) ∧ (∀ 'x_0. elem('x_0, 'x) ↔ (∃ 'b. elem('b, 'B) ∧ (∀ 'x1. elem('x1, 'x_0) ↔ (∃ 'a. elem('a, 'A) ∧ 'psi('x1, 'a, 'b)))))" PROOF { + "∃! 'z. ∃ 'x. 'z = union('x) ∧ (∀ 'x_0. elem('x_0, 'x) ↔ " + + "(∃ 'b. elem('b, 'B) ∧ (∀ 'x1. elem('x1, 'x_0) ↔ (∃ 'a. elem('a, 'A) ∧ 'psi('x1, 'a, 'b)))))" PROOF2 { val a = VariableLabel("a") val b = VariableLabel("b") val x = VariableLabel("x") @@ -366,11 +372,11 @@ object Mapping extends lisa.Main { val i2 = thm"applyFunctionToUniqueObject" val rPhi = forall(x, in(x, y) <=> exists(b, in(b, B) /\ forall(x1, in(x1, x) <=> exists(a, in(a, A) /\ psi(x1, a, b))))) val seq0 = instantiatePredicateSchemaInSequent(i2, Map(phi -> LambdaTermFormula(Seq(y), rPhi))) - val s0 = InstPredSchema(seq0, -2, Map(phi -> LambdaTermFormula(Seq(y), rPhi))) // val s0 = InstPredSchema(instantiatePredicateSchemaInSequent(i2, phi, rPhi, Seq(X)), -2, phi, rPhi, Seq(X)) + val s0 = SC.InstPredSchema(seq0, -2, Map(phi -> LambdaTermFormula(Seq(y), rPhi))) // val s0 = SC.InstPredSchema(instantiatePredicateSchemaInSequent(i2, phi, rPhi, Seq(X)), -2, phi, rPhi, Seq(X)) val seq1 = instantiateFunctionSchemaInSequent(seq0, Map(F -> LambdaTermTerm(Seq(x), union(x)))) - val s1 = InstFunSchema(seq1, 0, Map(F -> LambdaTermTerm(Seq(x), union(x)))) - val s2 = Cut(i1.left |- seq1.right, -1, 1, seq1.left.head) - Proof(steps(s0, s1, s2), imports(i1, i2)) + val s1 = SC.InstFunSchema(seq1, 0, Map(F -> LambdaTermTerm(Seq(x), union(x)))) + val s2 = SC.Cut(i1.left |- seq1.right, -1, 1, seq1.left.head) + SCProof(steps(s0, s1, s2), imports(i1, i2)) } using (thm"lemmaLayeredTwoArgumentsMap", thm"applyFunctionToUniqueObject") show @@ -378,55 +384,55 @@ object Mapping extends lisa.Main { val B = VariableLabel("B") private val z = VariableLabel("z") val cartesianProduct: ConstantFunctionLabel = - DEFINE("cartProd", A, B) asThe - z suchThat { - val a = VariableLabel("a") - val b = VariableLabel("b") - val x = VariableLabel("x") - val x0 = VariableLabel("x0") - val x1 = VariableLabel("x1") - val A = VariableLabel("A") - val B = VariableLabel("B") - exists(x, (z === union(x)) /\ forall(x0, in(x0, x) <=> exists(b, in(b, B) /\ forall(x1, in(x1, x0) <=> exists(a, in(a, A) /\ (x1 === oPair(a, b))))))) - } PROOF { - def makeFunctional(t: Term): Proof = { - val x = VariableLabel(freshId(t.freeVariables.map(_.id), "x")) - val y = VariableLabel(freshId(t.freeVariables.map(_.id), "y")) - val s0 = RightRefl(() |- t === t, t === t) - val s1 = Rewrite(() |- (x === t) <=> (x === t), 0) - val s2 = RightForall(() |- forall(x, (x === t) <=> (x === t)), 1, (x === t) <=> (x === t), x) - val s3 = RightExists(() |- exists(y, forall(x, (x === y) <=> (x === t))), 2, forall(x, (x === y) <=> (x === t)), y, t) - val s4 = Rewrite(() |- existsOne(x, x === t), 3) - Proof(s0, s1, s2, s3, s4) - } + DEFINE("cartProd", A, B) asThe z suchThat { + val a = VariableLabel("a") + val b = VariableLabel("b") + val x = VariableLabel("x") + val x0 = VariableLabel("x0") + val x1 = VariableLabel("x1") + val A = VariableLabel("A") + val B = VariableLabel("B") + exists(x, (z === union(x)) /\ forall(x0, in(x0, x) <=> exists(b, in(b, B) /\ forall(x1, in(x1, x0) <=> exists(a, in(a, A) /\ (x1 === oPair(a, b))))))) + } PROOF { + def makeFunctional(t: Term): SCProof = { + val x = VariableLabel(freshId(t.freeVariables.map(_.id), "x")) + val y = VariableLabel(freshId(t.freeVariables.map(_.id), "y")) + val s0 = SC.RightRefl(() |- t === t, t === t) + val s1 = SC.Rewrite(() |- (x === t) <=> (x === t), 0) + val s2 = SC.RightForall(() |- forall(x, (x === t) <=> (x === t)), 1, (x === t) <=> (x === t), x) + val s3 = SC.RightExists(() |- exists(y, forall(x, (x === y) <=> (x === t))), 2, forall(x, (x === y) <=> (x === t)), y, t) + val s4 = SC.Rewrite(() |- existsOne(x, x === t), 3) + SCProof(s0, s1, s2, s3, s4) + } + + val a = VariableLabel("a") + val b = VariableLabel("b") + val x = VariableLabel("x") + val A = VariableLabel("A") + val B = VariableLabel("B") + val psi = SchematicPredicateLabel("psi", 3) - val a = VariableLabel("a") - val b = VariableLabel("b") - val x = VariableLabel("x") - val A = VariableLabel("A") - val B = VariableLabel("B") - val psi = SchematicPredicateLabel("psi", 3) + val i1 = thm"mapTwoArguments" // ∀b. (b ∈ ?B) ⇒ ∀a. (a ∈ ?A) ⇒ ∃!x. ?psi(x, a, b) ⊢ ∃!z. ∃x. (z = U(x)) ∧ ∀x_0. (x_0 ∈ x) ↔ ∃b. (b ∈ ?B) ∧ ∀x1. (x1 ∈ x_0) ↔ ∃a. (a ∈ ?A) ∧ ?psi(x1, a, b) - val i1 = thm"mapTwoArguments" // ∀b. (b ∈ ?B) ⇒ ∀a. (a ∈ ?A) ⇒ ∃!x. ?psi(x, a, b) ⊢ ∃!z. ∃x. (z = U(x)) ∧ ∀x_0. (x_0 ∈ x) ↔ ∃b. (b ∈ ?B) ∧ ∀x1. (x1 ∈ x_0) ↔ ∃a. (a ∈ ?A) ∧ ?psi(x1, a, b) + val s0 = SC.SCSubproof({ + val s0 = SC.SCSubproof(makeFunctional(oPair(a, b))) + val s1 = SC.Weakening((in(b, B), in(a, A)) |- s0.bot.right, 0) + val s2 = SC.Rewrite(in(b, B) |- in(a, A) ==> s0.bot.right.head, 1) + val s3 = SC.RightForall(in(b, B) |- forall(a, in(a, A) ==> s0.bot.right.head), 2, in(a, A) ==> s0.bot.right.head, a) + val s4 = SC.Rewrite(() |- in(b, B) ==> forall(a, in(a, A) ==> s0.bot.right.head), 3) + val s5 = SC.RightForall(() |- forall(b, in(b, B) ==> forall(a, in(a, A) ==> s0.bot.right.head)), 4, in(b, B) ==> forall(a, in(a, A) ==> s0.bot.right.head), b) + SCProof(steps(s0, s1, s2, s3, s4, s5)) + }) // ∀b. (b ∈ ?B) ⇒ ∀a. (a ∈ ?A) ⇒ ∃!x. x= (a, b) - val s0 = SCSubproof({ - val s0 = SCSubproof(makeFunctional(oPair(a, b))) - val s1 = Weakening((in(b, B), in(a, A)) |- s0.bot.right, 0) - val s2 = Rewrite(in(b, B) |- in(a, A) ==> s0.bot.right.head, 1) - val s3 = RightForall(in(b, B) |- forall(a, in(a, A) ==> s0.bot.right.head), 2, in(a, A) ==> s0.bot.right.head, a) - val s4 = Rewrite(() |- in(b, B) ==> forall(a, in(a, A) ==> s0.bot.right.head), 3) - val s5 = RightForall(() |- forall(b, in(b, B) ==> forall(a, in(a, A) ==> s0.bot.right.head)), 4, in(b, B) ==> forall(a, in(a, A) ==> s0.bot.right.head), b) - Proof(steps(s0, s1, s2, s3, s4, s5)) - }) // ∀b. (b ∈ ?B) ⇒ ∀a. (a ∈ ?A) ⇒ ∃!x. x= (a, b) + val s1 = SC.InstPredSchema( + instantiatePredicateSchemaInSequent(i1, Map(psi -> LambdaTermFormula(Seq(x, a, b), x === oPair(a, b)))), + -1, + Map(psi -> LambdaTermFormula(Seq(x, a, b), x === oPair(a, b))) + ) + val s2 = SC.Cut(() |- s1.bot.right, 0, 1, s1.bot.left.head) + SCProof(steps(s0, s1, s2), imports(i1)) + } using (thm"mapTwoArguments") - val s1 = InstPredSchema( - instantiatePredicateSchemaInSequent(i1, Map(psi -> LambdaTermFormula(Seq(x, a, b), x === oPair(a, b)))), - -1, - Map(psi -> LambdaTermFormula(Seq(x, a, b), x === oPair(a, b))) - ) - val s2 = Cut(() |- s1.bot.right, 0, 1, s1.bot.left.head) - Proof(steps(s0, s1, s2), imports(i1)) - } using (thm"mapTwoArguments") show } diff --git a/src/main/scala/lisa/proven/mathematics/SetTheory.scala b/src/main/scala/lisa/proven/mathematics/SetTheory.scala index c02bd0c0f4fe96e3c9987d0f4d9de496655d316d..1b902db309846a3ba932a1b595eaaccc3cf2e15a 100644 --- a/src/main/scala/lisa/proven/mathematics/SetTheory.scala +++ b/src/main/scala/lisa/proven/mathematics/SetTheory.scala @@ -4,58 +4,58 @@ import lisa.automation.kernel.Destructors.* import lisa.automation.kernel.ProofTactics.* /** - * An embryo of mathematical development, containing a few example theorems and the definition of the ordered pair. + * An embryo of mathematical development, containing a few example theorems and the definition of the ordered unorderedPair. */ object SetTheory extends lisa.Main { THEOREM("russelParadox") of "∀'x. elem('x, 'y) ↔ ¬elem('x, 'x) ⊢" PROOF { val y = VariableLabel("y") val x = VariableLabel("x") - val s0 = RewriteTrue(in(y, y) <=> !in(y, y) |- ()) - val s1 = LeftForall(forall(x, in(x, y) <=> !in(x, x)) |- (), 0, in(x, y) <=> !in(x, x), x, y) - Proof(s0, s1) - } using () - thm"russelParadox".show + + have(in(y, y) <=> !in(y, y) |- ()) by Restate + andThen(forall(x, in(x, y) <=> !in(x, x)) |- ()) by LeftForall(in(x, y) <=> !in(x, x), x, y) + } + show THEOREM("unorderedPair_symmetry") of - "⊢ ∀'y. ∀'x. unordered_pair('x, 'y) = unordered_pair('y, 'x)" PROOF { + "⊢ ∀'y. ∀'x. unordered_pair('x, 'y) = unordered_pair('y, 'x)" PROOF2 { val x = VariableLabel("x") val y = VariableLabel("y") val z = VariableLabel("z") val h = VariableFormulaLabel("h") - val fin = SCSubproof( + val fin = SC.SCSubproof( { - val pr0 = SCSubproof( + val pr0 = SC.SCSubproof( { - val pairSame11 = instantiateForall(new Proof(steps(), imports(ax"pairAxiom")), pairAxiom, x) + val pairSame11 = instantiateForall(new SCProof(steps(), imports(ax"pairAxiom")), pairAxiom, x) val pairSame12 = instantiateForall(pairSame11, pairSame11.conclusion.right.head, y) instantiateForall(pairSame12, pairSame12.conclusion.right.head, z) }, Seq(-1) ) - val pr1 = SCSubproof( + val pr1 = SC.SCSubproof( { - val pairSame21 = instantiateForall(new Proof(steps(), imports(ax"pairAxiom")), pairAxiom, y) + val pairSame21 = instantiateForall(new SCProof(steps(), imports(ax"pairAxiom")), pairAxiom, y) val pairSame22 = instantiateForall(pairSame21, pairSame21.conclusion.right.head, x) instantiateForall(pairSame22, pairSame22.conclusion.right.head, z) }, Seq(-1) ) - val pr2 = RightSubstIff( + val pr2 = SC.RightSubstIff( Sequent(pr1.bot.right, Set(in(z, unorderedPair(x, y)) <=> in(z, unorderedPair(y, x)))), 0, List(((x === z) \/ (y === z), in(z, unorderedPair(y, x)))), LambdaFormulaFormula(Seq(h), in(z, unorderedPair(x, y)) <=> h) ) - val pr3 = Cut(Sequent(pr1.bot.left, pr2.bot.right), 1, 2, pr2.bot.left.head) - val pr4 = RightForall(Sequent(Set(), Set(forall(z, pr2.bot.right.head))), 3, pr2.bot.right.head, z) - Proof(steps(pr0, pr1, pr2, pr3, pr4), imports(ax"pairAxiom")) + val pr3 = SC.Cut(Sequent(pr1.bot.left, pr2.bot.right), 1, 2, pr2.bot.left.head) + val pr4 = SC.RightForall(Sequent(Set(), Set(forall(z, pr2.bot.right.head))), 3, pr2.bot.right.head, z) + SCProof(steps(pr0, pr1, pr2, pr3, pr4), imports(ax"pairAxiom")) }, Seq(-2) ) - val pairExt = SCSubproof( + val pairExt = SC.SCSubproof( { - val pairExt1 = instantiateForall(Proof(steps(), imports(ax"extensionalityAxiom")), ax"extensionalityAxiom", unorderedPair(x, y)) + val pairExt1 = instantiateForall(SCProof(steps(), imports(ax"extensionalityAxiom")), ax"extensionalityAxiom", unorderedPair(x, y)) instantiateForall(pairExt1, pairExt1.conclusion.right.head, unorderedPair(y, x)) }, Seq(-1) @@ -72,7 +72,7 @@ object SetTheory extends lisa.Main { // This proof is old and very unoptimised THEOREM("unorderedPair_deconstruction") of - "⊢ ∀'x. ∀'y. ∀ 'x1. ∀ 'y1. unordered_pair('x, 'y) = unordered_pair('x1, 'y1) ⇒ 'y1 = 'y ∧ 'x1 = 'x ∨ 'x = 'y1 ∧ 'y = 'x1" PROOF { + "⊢ ∀'x. ∀'y. ∀ 'x1. ∀ 'y1. unordered_pair('x, 'y) = unordered_pair('x1, 'y1) ⇒ 'y1 = 'y ∧ 'x1 = 'x ∨ 'x = 'y1 ∧ 'y = 'x1" PROOF2 { val x = VariableLabel("x") val y = VariableLabel("y") val x1 = VariableLabel("x'") @@ -82,147 +82,147 @@ object SetTheory extends lisa.Main { val h = VariableFormulaLabel("h") val pxy = unorderedPair(x, y) val pxy1 = unorderedPair(x1, y1) - val p0 = SCSubproof( + val p0 = SC.SCSubproof( { - val p0 = SCSubproof( + val p0 = SC.SCSubproof( { val zf = in(z, pxy) val p1_0 = hypothesis(zf) - val p1_1 = RightImplies(emptySeq +> (zf ==> zf), 0, zf, zf) - val p1_2 = RightIff(emptySeq +> (zf <=> zf), 1, 1, zf, zf) // |- (z in {x,y} <=> z in {x,y}) - val p1_3 = RightSubstEq(emptySeq +< (pxy === pxy1) +> (zf <=> in(z, pxy1)), 2, List((pxy, pxy1)), LambdaTermFormula(Seq(g), zf <=> in(z, g))) - Proof(IndexedSeq(p1_0, p1_1, p1_2, p1_3), IndexedSeq(() |- pairAxiom)) + val p1_1 = SC.RightImplies(emptySeq +> (zf ==> zf), 0, zf, zf) + val p1_2 = SC.RightIff(emptySeq +> (zf <=> zf), 1, 1, zf, zf) // |- (z in {x,y} <=> z in {x,y}) + val p1_3 = SC.RightSubstEq(emptySeq +< (pxy === pxy1) +> (zf <=> in(z, pxy1)), 2, List((pxy, pxy1)), LambdaTermFormula(Seq(g), zf <=> in(z, g))) + SCProof(IndexedSeq(p1_0, p1_1, p1_2, p1_3), IndexedSeq(() |- pairAxiom)) }, Seq(-1), display = true ) // ({x,y}={x',y'}) |- ((z∈{x,y})↔(z∈{x',y'})) - val p1 = SCSubproof( + val p1 = SC.SCSubproof( { - val p1_0 = Rewrite(() |- pairAxiom, -1) // |- ∀∀∀((z$1∈{x$3,y$2})↔((x$3=z$1)∨(y$2=z$1))) - val p1_1 = instantiateForall(Proof(IndexedSeq(p1_0), IndexedSeq(() |- pairAxiom)), x, y, z) + val p1_0 = SC.Rewrite(() |- pairAxiom, -1) // |- ∀∀∀((z$1∈{x$3,y$2})↔((x$3=z$1)∨(y$2=z$1))) + val p1_1 = instantiateForall(SCProof(IndexedSeq(p1_0), IndexedSeq(() |- pairAxiom)), x, y, z) p1_1 }, Seq(-1), display = true ) // |- (z in {x,y}) <=> (z=x \/ z=y) - val p2 = SCSubproof( + val p2 = SC.SCSubproof( { - val p2_0 = Rewrite(() |- pairAxiom, -1) // |- ∀∀∀((z$1∈{x$3,y$2})↔((x$3=z$1)∨(y$2=z$1))) - val p2_1 = instantiateForall(Proof(IndexedSeq(p2_0), IndexedSeq(() |- pairAxiom)), x1, y1, z) + val p2_0 = SC.Rewrite(() |- pairAxiom, -1) // |- ∀∀∀((z$1∈{x$3,y$2})↔((x$3=z$1)∨(y$2=z$1))) + val p2_1 = instantiateForall(SCProof(IndexedSeq(p2_0), IndexedSeq(() |- pairAxiom)), x1, y1, z) p2_1 }, Seq(-1) ) // |- (z in {x',y'}) <=> (z=x' \/ z=y') - val p3 = RightSubstEq( + val p3 = SC.RightSubstEq( emptySeq +< (pxy === pxy1) +> (in(z, pxy1) <=> ((z === x) \/ (z === y))), 1, List((pxy, pxy1)), LambdaTermFormula(Seq(g), in(z, g) <=> ((z === x) \/ (z === y))) ) // ({x,y}={x',y'}) |- ((z∈{x',y'})↔((z=x)∨(z=y))) - val p4 = RightSubstIff( + val p4 = SC.RightSubstIff( emptySeq +< p3.bot.left.head +< p2.bot.right.head +> (((z === x) \/ (z === y)) <=> ((z === x1) \/ (z === y1))), 3, List(((z === x1) \/ (z === y1), in(z, pxy1))), LambdaFormulaFormula(Seq(h), h <=> ((z === x) \/ (z === y))) ) // ((z∈{x',y'})↔((x'=z)∨(y'=z))), ({x,y}={x',y'}) |- (((z=x)∨(z=y))↔((z=x')∨(z=y'))) - val p5 = Cut(emptySeq ++< p3.bot ++> p4.bot, 2, 4, p2.bot.right.head) - Proof(IndexedSeq(p0, p1, p2, p3, p4, p5), IndexedSeq(() |- pairAxiom)) + val p5 = SC.Cut(emptySeq ++< p3.bot ++> p4.bot, 2, 4, p2.bot.right.head) + SCProof(IndexedSeq(p0, p1, p2, p3, p4, p5), IndexedSeq(() |- pairAxiom)) }, Seq(-1) ) // ({x,y}={x',y'}) |- (((z=x)∨(z=y))↔((z=x')∨(z=y'))) - val p1 = SCSubproof( - Proof( + val p1 = SC.SCSubproof( + SCProof( byCase(x === x1)( - SCSubproof( + SC.SCSubproof( { val pcm1 = p0 - val pc0 = SCSubproof( - Proof( + val pc0 = SC.SCSubproof( + SCProof( byCase(y === x)( - SCSubproof( + SC.SCSubproof( { val pam1 = pcm1 - val pa0 = SCSubproof( + val pa0 = SC.SCSubproof( { val f1 = z === x val pa0_m1 = pcm1 // ({x,y}={x',y'}) |- (((z=x)∨(z=y))↔((z=x')∨(z=y'))) - val pa0_0 = SCSubproof( + val pa0_0 = SC.SCSubproof( { val pa0_0_0 = hypothesis(f1) - val pa0_1_1 = RightOr(emptySeq +< f1 +> (f1 \/ f1), 0, f1, f1) - val pa0_1_2 = RightImplies(emptySeq +> (f1 ==> (f1 \/ f1)), 1, f1, f1 \/ f1) - val pa0_1_3 = LeftOr(emptySeq +< (f1 \/ f1) +> f1, Seq(0, 0), Seq(f1, f1)) - val pa0_1_4 = RightImplies(emptySeq +> ((f1 \/ f1) ==> f1), 3, f1 \/ f1, f1) - val pa0_1_5 = RightIff(emptySeq +> ((f1 \/ f1) <=> f1), 2, 4, (f1 \/ f1), f1) - val r = Proof(pa0_0_0, pa0_1_1, pa0_1_2, pa0_1_3, pa0_1_4, pa0_1_5) + val pa0_1_1 = SC.RightOr(emptySeq +< f1 +> (f1 \/ f1), 0, f1, f1) + val pa0_1_2 = SC.RightImplies(emptySeq +> (f1 ==> (f1 \/ f1)), 1, f1, f1 \/ f1) + val pa0_1_3 = SC.LeftOr(emptySeq +< (f1 \/ f1) +> f1, Seq(0, 0), Seq(f1, f1)) + val pa0_1_4 = SC.RightImplies(emptySeq +> ((f1 \/ f1) ==> f1), 3, f1 \/ f1, f1) + val pa0_1_5 = SC.RightIff(emptySeq +> ((f1 \/ f1) <=> f1), 2, 4, (f1 \/ f1), f1) + val r = SCProof(pa0_0_0, pa0_1_1, pa0_1_2, pa0_1_3, pa0_1_4, pa0_1_5) r }, display = false ) // |- (((z=x)∨(z=x))↔(z=x)) - val pa0_1 = RightSubstEq( + val pa0_1 = SC.RightSubstEq( emptySeq +< (pxy === pxy1) +< (x === y) +> ((f1 \/ f1) <=> (z === x1) \/ (z === y1)), -1, List((x, y)), LambdaTermFormula(Seq(g), (f1 \/ (z === g)) <=> ((z === x1) \/ (z === y1))) ) // ({x,y}={x',y'}) y=x|- (z=x)\/(z=x) <=> (z=x' \/ z=y') - val pa0_2 = RightSubstIff( + val pa0_2 = SC.RightSubstIff( emptySeq +< (pxy === pxy1) +< (x === y) +< (f1 <=> (f1 \/ f1)) +> (f1 <=> ((z === x1) \/ (z === y1))), 1, List((f1, f1 \/ f1)), LambdaFormulaFormula(Seq(h), h <=> ((z === x1) \/ (z === y1))) ) val pa0_3 = - Cut(emptySeq +< (pxy === pxy1) +< (x === y) +> (f1 <=> ((z === x1) \/ (z === y1))), 0, 2, f1 <=> (f1 \/ f1)) // (x=y), ({x,y}={x',y'}) |- ((z=x)↔((z=x')∨(z=y'))) - val pa0_4 = RightForall(emptySeq +< (pxy === pxy1) +< (x === y) +> forall(z, f1 <=> ((z === x1) \/ (z === y1))), 3, f1 <=> ((z === x1) \/ (z === y1)), z) - val ra0_0 = instantiateForall(Proof(IndexedSeq(pa0_0, pa0_1, pa0_2, pa0_3, pa0_4), IndexedSeq(pa0_m1.bot)), y1) // (x=y), ({x,y}={x',y'}) |- ((y'=x)↔((y'=x')∨(y'=y'))) + SC.Cut(emptySeq +< (pxy === pxy1) +< (x === y) +> (f1 <=> ((z === x1) \/ (z === y1))), 0, 2, f1 <=> (f1 \/ f1)) // (x=y), ({x,y}={x',y'}) |- ((z=x)↔((z=x')∨(z=y'))) + val pa0_4 = SC.RightForall(emptySeq +< (pxy === pxy1) +< (x === y) +> forall(z, f1 <=> ((z === x1) \/ (z === y1))), 3, f1 <=> ((z === x1) \/ (z === y1)), z) + val ra0_0 = instantiateForall(SCProof(IndexedSeq(pa0_0, pa0_1, pa0_2, pa0_3, pa0_4), IndexedSeq(pa0_m1.bot)), y1) // (x=y), ({x,y}={x',y'}) |- ((y'=x)↔((y'=x')∨(y'=y'))) ra0_0 }, IndexedSeq(-1) ) // ({x,y}={x',y'}) y=x|- ((y'=x)↔((y'=x')∨(y'=y'))) - val pa1 = SCSubproof( + val pa1 = SC.SCSubproof( { - val pa1_0 = RightRefl(emptySeq +> (y1 === y1), y1 === y1) - val pa1_1 = RightOr(emptySeq +> ((y1 === y1) \/ (y1 === x1)), 0, y1 === y1, y1 === x1) - Proof(pa1_0, pa1_1) + val pa1_0 = SC.RightRefl(emptySeq +> (y1 === y1), y1 === y1) + val pa1_1 = SC.RightOr(emptySeq +> ((y1 === y1) \/ (y1 === x1)), 0, y1 === y1, y1 === x1) + SCProof(pa1_0, pa1_1) }, display = false ) // |- (y'=x' \/ y'=y') val ra3 = byEquiv(pa0.bot.right.head, pa1.bot.right.head)(pa0, pa1) // ({x,y}={x',y'}) y=x|- ((y'=x) - val pal = RightSubstEq(emptySeq ++< pa0.bot +> (y1 === y), ra3.length - 1, List((x, y)), LambdaTermFormula(Seq(g), y1 === g)) - Proof(ra3.steps, IndexedSeq(pam1.bot)).appended(pal) // (x=y), ({x,y}={x',y'}) |- (y'=y) + val pal = SC.RightSubstEq(emptySeq ++< pa0.bot +> (y1 === y), ra3.length - 1, List((x, y)), LambdaTermFormula(Seq(g), y1 === g)) + SCProof(ra3.steps, IndexedSeq(pam1.bot)).appended(pal) // (x=y), ({x,y}={x',y'}) |- (y'=y) }, IndexedSeq(-1) ) // (x=y), ({x,y}={x',y'}) |- (y'=y) , - SCSubproof( + SC.SCSubproof( { val pbm1 = pcm1 // ({x,y}={x',y'}) |- (((z=x)∨(z=y))↔((z=x')∨(z=y'))) - val pb0_0 = SCSubproof( + val pb0_0 = SC.SCSubproof( { - val pb0_0 = RightForall(emptySeq ++< pcm1.bot +> forall(z, pcm1.bot.right.head), -1, pcm1.bot.right.head, z) - instantiateForall(Proof(IndexedSeq(pb0_0), IndexedSeq(pcm1.bot)), y) + val pb0_0 = SC.RightForall(emptySeq ++< pcm1.bot +> forall(z, pcm1.bot.right.head), -1, pcm1.bot.right.head, z) + instantiateForall(SCProof(IndexedSeq(pb0_0), IndexedSeq(pcm1.bot)), y) }, IndexedSeq(-1) ) // ({x,y}={x',y'}) |- (((y=x)∨(y=y))↔((y=x')∨(y=y'))) - val pb0_1 = SCSubproof( + val pb0_1 = SC.SCSubproof( { - val pa1_0 = RightRefl(emptySeq +> (y === y), y === y) - val pa1_1 = RightOr(emptySeq +> ((y === y) \/ (y === x)), 0, y === y, y === x) - Proof(pa1_0, pa1_1) + val pa1_0 = SC.RightRefl(emptySeq +> (y === y), y === y) + val pa1_1 = SC.RightOr(emptySeq +> ((y === y) \/ (y === x)), 0, y === y, y === x) + SCProof(pa1_0, pa1_1) }, display = false ) // |- (y=x)∨(y=y) val rb0 = byEquiv(pb0_0.bot.right.head, pb0_1.bot.right.head)(pb0_0, pb0_1) // ({x,y}={x',y'}) |- (y=x')∨(y=y') val pb1 = - RightSubstEq(emptySeq ++< rb0.conclusion +< (x === x1) +> ((y === x) \/ (y === y1)), rb0.length - 1, List((x, x1)), LambdaTermFormula(Seq(g), (y === g) \/ (y === y1))) + SC.RightSubstEq(emptySeq ++< rb0.conclusion +< (x === x1) +> ((y === x) \/ (y === y1)), rb0.length - 1, List((x, x1)), LambdaTermFormula(Seq(g), (y === g) \/ (y === y1))) val rb1 = destructRightOr( rb0.appended(pb1), // ({x,y}={x',y'}) , x=x'|- (y=x)∨(y=y') y === x, y === y1 ) - val rb2 = rb1.appended(LeftNot(rb1.conclusion +< !(y === x) -> (y === x), rb1.length - 1, y === x)) // (x=x'), ({x,y}={x',y'}), ¬(y=x) |- (y=y') - Proof(rb2.steps, IndexedSeq(pbm1.bot)) + val rb2 = rb1.appended(SC.LeftNot(rb1.conclusion +< !(y === x) -> (y === x), rb1.length - 1, y === x)) // (x=x'), ({x,y}={x',y'}), ¬(y=x) |- (y=y') + SCProof(rb2.steps, IndexedSeq(pbm1.bot)) }, IndexedSeq(-1) @@ -232,87 +232,87 @@ object SetTheory extends lisa.Main { ), IndexedSeq(-1) ) // (x=x'), ({x,y}={x',y'}) |- (y'=y) - val pc1 = RightRefl(emptySeq +> (x === x), x === x) - val pc2 = RightAnd(emptySeq ++< pc0.bot +> ((y1 === y) /\ (x === x)), Seq(0, 1), Seq(y1 === y, x === x)) // ({x,y}={x',y'}), x=x' |- (x=x /\ y=y') + val pc1 = SC.RightRefl(emptySeq +> (x === x), x === x) + val pc2 = SC.RightAnd(emptySeq ++< pc0.bot +> ((y1 === y) /\ (x === x)), Seq(0, 1), Seq(y1 === y, x === x)) // ({x,y}={x',y'}), x=x' |- (x=x /\ y=y') val pc3 = - RightSubstEq(emptySeq ++< pc2.bot +> ((y1 === y) /\ (x1 === x)), 2, List((x, x1)), LambdaTermFormula(Seq(g), (y1 === y) /\ (g === x))) // ({x,y}={x',y'}), x=x' |- (x=x' /\ y=y') - val pc4 = RightOr( + SC.RightSubstEq(emptySeq ++< pc2.bot +> ((y1 === y) /\ (x1 === x)), 2, List((x, x1)), LambdaTermFormula(Seq(g), (y1 === y) /\ (g === x))) // ({x,y}={x',y'}), x=x' |- (x=x' /\ y=y') + val pc4 = SC.RightOr( emptySeq ++< pc3.bot +> (pc3.bot.right.head \/ ((x === y1) /\ (y === x1))), 3, pc3.bot.right.head, (x === y1) /\ (y === x1) ) // ({x,y}={x',y'}), x=x' |- (x=x' /\ y=y')\/(x=y' /\ y=x') - val r = Proof(IndexedSeq(pc0, pc1, pc2, pc3, pc4), IndexedSeq(pcm1.bot)) + val r = SCProof(IndexedSeq(pc0, pc1, pc2, pc3, pc4), IndexedSeq(pcm1.bot)) r }, IndexedSeq(-1) ) // ({x,y}={x',y'}), x=x' |- (x=x' /\ y=y')\/(x=y' /\ y=x') , - SCSubproof( + SC.SCSubproof( { val pdm1 = p0 - val pd0 = SCSubproof( + val pd0 = SC.SCSubproof( { val pd0_m1 = pdm1 - val pd0_0 = SCSubproof { + val pd0_0 = SC.SCSubproof { val ex1x1 = x1 === x1 - val pd0_0_0 = RightRefl(emptySeq +> ex1x1, ex1x1) // |- x'=x' - val pd0_0_1 = RightOr(emptySeq +> (ex1x1 \/ (x1 === y1)), 0, ex1x1, x1 === y1) // |- (x'=x' \/ x'=y') - Proof(IndexedSeq(pd0_0_0, pd0_0_1)) + val pd0_0_0 = SC.RightRefl(emptySeq +> ex1x1, ex1x1) // |- x'=x' + val pd0_0_1 = SC.RightOr(emptySeq +> (ex1x1 \/ (x1 === y1)), 0, ex1x1, x1 === y1) // |- (x'=x' \/ x'=y') + SCProof(IndexedSeq(pd0_0_0, pd0_0_1)) } // |- (x'=x' \/ x'=y') - val pd0_1 = SCSubproof( + val pd0_1 = SC.SCSubproof( { val pd0_1_m1 = pd0_m1 // ({x,y}={x',y'}) |- (((z=x)∨(z=y))↔((z=x')∨(z=y'))) - val pd0_1_0 = RightForall(emptySeq ++< pd0_1_m1.bot +> forall(z, pd0_1_m1.bot.right.head), -1, pd0_1_m1.bot.right.head, z) - val rd0_1_1 = instantiateForall(Proof(IndexedSeq(pd0_1_0), IndexedSeq(pd0_m1.bot)), x1) // ({x,y}={x',y'}) |- (x'=x \/ x'=y) <=> (x'=x' \/ x'=y') + val pd0_1_0 = SC.RightForall(emptySeq ++< pd0_1_m1.bot +> forall(z, pd0_1_m1.bot.right.head), -1, pd0_1_m1.bot.right.head, z) + val rd0_1_1 = instantiateForall(SCProof(IndexedSeq(pd0_1_0), IndexedSeq(pd0_m1.bot)), x1) // ({x,y}={x',y'}) |- (x'=x \/ x'=y) <=> (x'=x' \/ x'=y') rd0_1_1 }, IndexedSeq(-1) ) // ({x,y}={x',y'}) |- (x'=x \/ x'=y) <=> (x'=x' \/ x'=y') - val pd0_2 = RightSubstIff( + val pd0_2 = SC.RightSubstIff( pd0_1.bot.right |- ((x1 === x) \/ (x1 === y)), 0, List(((x1 === x) \/ (x1 === y), (x1 === x1) \/ (x1 === y1))), LambdaFormulaFormula(Seq(h), h) ) // (x'=x \/ x'=y) <=> (x'=x' \/ x'=y') |- (x'=x \/ x'=y) - val pd0_3 = Cut(pd0_1.bot.left |- pd0_2.bot.right, 1, 2, pd0_1.bot.right.head) // ({x,y}={x',y'}) |- (x=x' \/ y=x') - destructRightOr(Proof(IndexedSeq(pd0_0, pd0_1, pd0_2, pd0_3), IndexedSeq(pd0_m1.bot)), x === x1, y === x1) // ({x,y}={x',y'}) |- x=x', y=x' + val pd0_3 = SC.Cut(pd0_1.bot.left |- pd0_2.bot.right, 1, 2, pd0_1.bot.right.head) // ({x,y}={x',y'}) |- (x=x' \/ y=x') + destructRightOr(SCProof(IndexedSeq(pd0_0, pd0_1, pd0_2, pd0_3), IndexedSeq(pd0_m1.bot)), x === x1, y === x1) // ({x,y}={x',y'}) |- x=x', y=x' }, IndexedSeq(-1) ) // ({x,y}={x',y'}) |- x=x', y=x' -- - val pd1 = SCSubproof( + val pd1 = SC.SCSubproof( { val pd1_m1 = pdm1 - val pd1_0 = SCSubproof { + val pd1_0 = SC.SCSubproof { val exx = x === x - val pd1_0_0 = RightRefl(emptySeq +> exx, exx) // |- x=x - val pd1_0_1 = RightOr(emptySeq +> (exx \/ (x === y)), 0, exx, x === y) // |- (x=x \/ x=y) - Proof(IndexedSeq(pd1_0_0, pd1_0_1)) + val pd1_0_0 = SC.RightRefl(emptySeq +> exx, exx) // |- x=x + val pd1_0_1 = SC.RightOr(emptySeq +> (exx \/ (x === y)), 0, exx, x === y) // |- (x=x \/ x=y) + SCProof(IndexedSeq(pd1_0_0, pd1_0_1)) } // |- (x=x \/ x=y) - val pd1_1 = SCSubproof( + val pd1_1 = SC.SCSubproof( { val pd1_1_m1 = pd1_m1 // ({x,y}={x',y'}) |- (((z=x)∨(z=y))↔((z=x')∨(z=y'))) - val pd1_1_0 = RightForall(emptySeq ++< pd1_1_m1.bot +> forall(z, pd1_1_m1.bot.right.head), -1, pd1_1_m1.bot.right.head, z) - val rd1_1_1 = instantiateForall(Proof(IndexedSeq(pd1_1_0), IndexedSeq(pd1_m1.bot)), x) // ({x,y}={x',y'}) |- (x=x \/ x=y) <=> (x=x' \/ x=y') + val pd1_1_0 = SC.RightForall(emptySeq ++< pd1_1_m1.bot +> forall(z, pd1_1_m1.bot.right.head), -1, pd1_1_m1.bot.right.head, z) + val rd1_1_1 = instantiateForall(SCProof(IndexedSeq(pd1_1_0), IndexedSeq(pd1_m1.bot)), x) // ({x,y}={x',y'}) |- (x=x \/ x=y) <=> (x=x' \/ x=y') rd1_1_1 }, IndexedSeq(-1) ) // // ({x,y}={x',y'}) |- (x=x \/ x=y) <=> (x=x' \/ x=y') val rd1_2 = byEquiv(pd1_1.bot.right.head, pd1_0.bot.right.head)(pd1_1, pd1_0) - val pd1_3 = SCSubproof(Proof(rd1_2.steps, IndexedSeq(pd1_m1.bot)), IndexedSeq(-1)) // // ({x,y}={x',y'}) |- x=x' \/ x=y' - destructRightOr(Proof(IndexedSeq(pd1_0, pd1_1, pd1_3), IndexedSeq(pd1_m1.bot)), x === x1, x === y1) // ({x,y}={x',y'}) |- x=x', x=y' + val pd1_3 = SC.SCSubproof(SCProof(rd1_2.steps, IndexedSeq(pd1_m1.bot)), IndexedSeq(-1)) // // ({x,y}={x',y'}) |- x=x' \/ x=y' + destructRightOr(SCProof(IndexedSeq(pd1_0, pd1_1, pd1_3), IndexedSeq(pd1_m1.bot)), x === x1, x === y1) // ({x,y}={x',y'}) |- x=x', x=y' }, IndexedSeq(-1) ) // ({x,y}={x',y'}) |- x=x', x=y' -- - val pd2 = RightAnd(emptySeq ++< pd1.bot +> (x === x1) +> ((x === y1) /\ (y === x1)), Seq(0, 1), Seq(x === y1, y === x1)) // ({x,y}={x',y'}) |- x=x', (x=y' /\ y=x') --- - val pd3 = LeftNot(emptySeq ++< pd2.bot +< !(x === x1) +> ((x === y1) /\ (y === x1)), 2, x === x1) // ({x,y}={x',y'}), !x===x1 |- (x=y' /\ y=x') - val pd4 = RightOr( + val pd2 = SC.RightAnd(emptySeq ++< pd1.bot +> (x === x1) +> ((x === y1) /\ (y === x1)), Seq(0, 1), Seq(x === y1, y === x1)) // ({x,y}={x',y'}) |- x=x', (x=y' /\ y=x') --- + val pd3 = SC.LeftNot(emptySeq ++< pd2.bot +< !(x === x1) +> ((x === y1) /\ (y === x1)), 2, x === x1) // ({x,y}={x',y'}), !x===x1 |- (x=y' /\ y=x') + val pd4 = SC.RightOr( emptySeq ++< pd3.bot +> (pd3.bot.right.head \/ ((x === x1) /\ (y === y1))), 3, pd3.bot.right.head, (x === x1) /\ (y === y1) ) // ({x,y}={x',y'}), !x===x1 |- (x=x' /\ y=y')\/(x=y' /\ y=x') - Proof(IndexedSeq(pd0, pd1, pd2, pd3, pd4), IndexedSeq(pdm1.bot)) + SCProof(IndexedSeq(pd0, pd1, pd2, pd3, pd4), IndexedSeq(pdm1.bot)) }, IndexedSeq(-1) ) // ({x,y}={x',y'}), !x=x' |- (x=x' /\ y=y')\/(x=y' /\ y=x') @@ -322,12 +322,12 @@ object SetTheory extends lisa.Main { IndexedSeq(0) ) // ({x,y}={x',y'}) |- (x=x' /\ y=y')\/(x=y' /\ y=x') - val p2 = RightImplies(emptySeq +> (p1.bot.left.head ==> p1.bot.right.head), 1, p1.bot.left.head, p1.bot.right.head) // |- ({x,y}={x',y'}) ==> (x=x' /\ y=y')\/(x=y' /\ y=x') - generalizeToForall(Proof(IndexedSeq(p0, p1, p2), IndexedSeq(() |- pairAxiom)), x, y, x1, y1) + val p2 = SC.RightImplies(emptySeq +> (p1.bot.left.head ==> p1.bot.right.head), 1, p1.bot.left.head, p1.bot.right.head) // |- ({x,y}={x',y'}) ==> (x=x' /\ y=y')\/(x=y' /\ y=x') + generalizeToForall(SCProof(IndexedSeq(p0, p1, p2), IndexedSeq(() |- pairAxiom)), x, y, x1, y1) } using ax"pairAxiom" thm"unorderedPair_deconstruction".show - THEOREM("noUniversalSet") of "∀'x. elem('x, 'z) ⊢ " PROOF { + THEOREM("noUniversalSet") of "∀'x. elem('x, 'z) ⊢ " PROOF2 { val x = VariableLabel("x") val y = VariableLabel("y") val z = VariableLabel("z") @@ -336,30 +336,30 @@ object SetTheory extends lisa.Main { // forall(z, exists(y, forall(x, in(x,y) <=> (in(x,y) /\ sPhi(x,z))))) val i1 = () |- comprehensionSchema val i2 = thm"russelParadox" // forall(x1, in(x1,y) <=> !in(x1, x1)) |- () - val p0 = InstPredSchema(() |- forall(z, exists(y, forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x))))), -1, Map(sPhi -> LambdaTermFormula(Seq(x, z), !in(x, x)))) - val s0 = SCSubproof(instantiateForall(Proof(IndexedSeq(p0), IndexedSeq(i1)), z), Seq(-1)) // exists(y1, forall(x1, in(x1,y1) <=> (in(x1,z1) /\ !in(x1, x1)))) + val p0 = SC.InstPredSchema(() |- forall(z, exists(y, forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x))))), -1, Map(sPhi -> LambdaTermFormula(Seq(x, z), !in(x, x)))) + val s0 = SC.SCSubproof(instantiateForall(SCProof(IndexedSeq(p0), IndexedSeq(i1)), z), Seq(-1)) // exists(y1, forall(x1, in(x1,y1) <=> (in(x1,z1) /\ !in(x1, x1)))) val s1 = hypothesis(in(x, y) <=> (in(x, z) /\ !in(x, x))) // in(x,y) <=> (in(x,z) /\ in(x, x)) |- in(x,y) <=> (in(x,z) /\ in(x, x)) - val s2 = RightSubstIff( + val s2 = SC.RightSubstIff( (in(x, z) <=> True, in(x, y) <=> (in(x, z) /\ !in(x, x))) |- in(x, y) <=> (True /\ !in(x, x)), 1, List((in(x, z), And())), LambdaFormulaFormula(Seq(h), in(x, y) <=> (h /\ !in(x, x))) ) // in(x1,y1) <=> (in(x1,z1) /\ in(x1, x1)) |- in(x,y) <=> (True /\ in(x1, x1)) - val s3 = Rewrite((in(x, z), in(x, y) <=> (in(x, z) /\ !in(x, x))) |- in(x, y) <=> !in(x, x), 2) - val s4 = LeftForall((forall(x, in(x, z)), in(x, y) <=> (in(x, z) /\ !in(x, x))) |- in(x, y) <=> !in(x, x), 3, in(x, z), x, x) - val s5 = LeftForall((forall(x, in(x, z)), forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x)))) |- in(x, y) <=> !in(x, x), 4, in(x, y) <=> (in(x, z) /\ !in(x, x)), x, x) - val s6 = RightForall((forall(x, in(x, z)), forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x)))) |- forall(x, in(x, y) <=> !in(x, x)), 5, in(x, y) <=> !in(x, x), x) - val s7 = InstFunSchema(forall(x, in(x, y) <=> !in(x, x)) |- (), -2, Map(y -> LambdaTermTerm(Nil, y))) - val s8 = Cut((forall(x, in(x, z)), forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x)))) |- (), 6, 7, forall(x, in(x, y) <=> !in(x, x))) - val s9 = LeftExists((forall(x, in(x, z)), exists(y, forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x))))) |- (), 8, forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x))), y) - val s10 = Cut(forall(x, in(x, z)) |- (), 0, 9, exists(y, forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x))))) - Proof(steps(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10), imports(i1, i2)) + val s3 = SC.Rewrite((in(x, z), in(x, y) <=> (in(x, z) /\ !in(x, x))) |- in(x, y) <=> !in(x, x), 2) + val s4 = SC.LeftForall((forall(x, in(x, z)), in(x, y) <=> (in(x, z) /\ !in(x, x))) |- in(x, y) <=> !in(x, x), 3, in(x, z), x, x) + val s5 = SC.LeftForall((forall(x, in(x, z)), forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x)))) |- in(x, y) <=> !in(x, x), 4, in(x, y) <=> (in(x, z) /\ !in(x, x)), x, x) + val s6 = SC.RightForall((forall(x, in(x, z)), forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x)))) |- forall(x, in(x, y) <=> !in(x, x)), 5, in(x, y) <=> !in(x, x), x) + val s7 = SC.InstFunSchema(forall(x, in(x, y) <=> !in(x, x)) |- (), -2, Map(y -> LambdaTermTerm(Nil, y))) + val s8 = SC.Cut((forall(x, in(x, z)), forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x)))) |- (), 6, 7, forall(x, in(x, y) <=> !in(x, x))) + val s9 = SC.LeftExists((forall(x, in(x, z)), exists(y, forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x))))) |- (), 8, forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x))), y) + val s10 = SC.Cut(forall(x, in(x, z)) |- (), 0, 9, exists(y, forall(x, in(x, y) <=> (in(x, z) /\ !in(x, x))))) + SCProof(steps(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10), imports(i1, i2)) } using (ax"comprehensionSchema", thm"russelParadox") show private val x = VariableLabel("x") private val y = VariableLabel("y") - val oPair: ConstantFunctionLabel = DEFINE("pair", x, y) as unorderedPair(unorderedPair(x, y), unorderedPair(x, x)) + val oPair: ConstantFunctionLabel = DEFINE("", x, y) as unorderedPair(unorderedPair(x, y), unorderedPair(x, x)) show } diff --git a/src/main/scala/lisa/proven/peano_example/Peano.scala b/src/main/scala/lisa/proven/peano_example/Peano.scala index 47642c624698b6782cfd529af4b1d6a5c9b78132..6cbc144da28866b773eb3f388346e1736c96e52e 100644 --- a/src/main/scala/lisa/proven/peano_example/Peano.scala +++ b/src/main/scala/lisa/proven/peano_example/Peano.scala @@ -27,13 +27,13 @@ object Peano { instantiateForall(SCProof(IndexedSeq(), IndexedSeq(proofImport))) val tempVar = VariableLabel(freshId(formula.freeVariables.map(_.id), "x")) val instantiated = instantiateBinder(forall, t) - val p1 = Hypothesis(instantiated |- instantiated, instantiated) - val p2 = LeftForall(formula |- instantiated, 0, instantiateBinder(forall, tempVar), tempVar, t) - val p3 = Cut(() |- instantiated, -1, 1, formula) - Proof(IndexedSeq(p1, p2, p3), IndexedSeq(proofImport)) + val p1 = SC.Hypothesis(instantiated |- instantiated, instantiated) + val p2 = SC.LeftForall(formula |- instantiated, 0, instantiateBinder(forall, tempVar), tempVar, t) + val p3 = SC.Cut(() |- instantiated, -1, 1, formula) + SCProof(IndexedSeq(p1, p2, p3), IndexedSeq(proofImport)) } - def applyInduction(baseProof: SCSubproof, inductionStepProof: SCSubproof, inductionInstance: SCProofStep): IndexedSeq[SCProofStep] = { + def applyInduction(baseProof: SC.SCSubproof, inductionStepProof: SC.SCSubproof, inductionInstance: SCProofStep): IndexedSeq[SCProofStep] = { require(baseProof.bot.right.size == 1, s"baseProof should prove exactly one formula, got ${Printer.prettySequent(baseProof.bot)}") require(inductionStepProof.bot.right.size == 1, s"inductionStepProof should prove exactly one formula, got ${Printer.prettySequent(inductionStepProof.bot)}") require( @@ -56,21 +56,21 @@ object Peano { val base0 = baseProof val step1 = inductionStepProof val instance2 = inductionInstance - val inductionPremise3 = RightAnd(lhs |- baseFormula /\ stepFormula, Seq(0, 1), Seq(baseFormula, stepFormula)) + val inductionPremise3 = SC.RightAnd(lhs |- baseFormula /\ stepFormula, Seq(0, 1), Seq(baseFormula, stepFormula)) val hypConclusion4 = hypothesis(conclusion) - val inductionInstanceOnTheLeft5 = LeftImplies(lhs + (premise ==> conclusion) |- conclusion, 3, 4, premise, conclusion) - val cutInductionInstance6 = Cut(lhs |- conclusion, 2, 5, premise ==> conclusion) + val inductionInstanceOnTheLeft5 = SC.LeftImplies(lhs + (premise ==> conclusion) |- conclusion, 3, 4, premise, conclusion) + val cutInductionInstance6 = SC.Cut(lhs |- conclusion, 2, 5, premise ==> conclusion) IndexedSeq(base0, step1, instance2, inductionPremise3, hypConclusion4, inductionInstanceOnTheLeft5, cutInductionInstance6) } val (y1, z1) = (VariableLabel("y1"), VariableLabel("z1")) - THEOREM("x + 0 = 0 + x") of "∀'x. +('x, 0) = +(0, 'x)" PROOF { - val refl0: SCProofStep = RightRefl(() |- s(x) === s(x), s(x) === s(x)) - val subst1 = RightSubstEq((x === plus(zero, x)) |- s(x) === s(plus(zero, x)), 0, (x, plus(zero, x)) :: Nil, LambdaTermFormula(Seq(y), s(x) === s(y))) - val implies2 = RightImplies(() |- (x === plus(zero, x)) ==> (s(x) === s(plus(zero, x))), 1, x === plus(zero, x), s(x) === s(plus(zero, x))) - val transform3 = RightSubstEq( + THEOREM("x + 0 = 0 + x") of "∀'x. +('x, 0) = +(0, 'x)" PROOF2 { + val refl0: SCProofStep = SC.RightRefl(() |- s(x) === s(x), s(x) === s(x)) + val subst1 = SC.RightSubstEq((x === plus(zero, x)) |- s(x) === s(plus(zero, x)), 0, (x, plus(zero, x)) :: Nil, LambdaTermFormula(Seq(y), s(x) === s(y))) + val implies2 = SC.RightImplies(() |- (x === plus(zero, x)) ==> (s(x) === s(plus(zero, x))), 1, x === plus(zero, x), s(x) === s(plus(zero, x))) + val transform3 = SC.RightSubstEq( (plus(zero, s(x)) === s(plus(zero, x))) |- (x === plus(zero, x)) ==> (s(x) === plus(zero, s(x))), 2, (plus(zero, s(x)), s(plus(zero, x))) :: Nil, @@ -78,50 +78,50 @@ object Peano { ) // result: ax4plusSuccessor |- 0+Sx = S(0 + x) - val instanceAx4_4 = SCSubproof( + val instanceAx4_4 = SC.SCSubproof( instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", zero), x), Seq(-1) ) - val cut5 = Cut(() |- (x === plus(zero, x)) ==> (s(x) === plus(zero, s(x))), 4, 3, plus(zero, s(x)) === s(plus(zero, x))) + val cut5 = SC.Cut(() |- (x === plus(zero, x)) ==> (s(x) === plus(zero, s(x))), 4, 3, plus(zero, s(x)) === s(plus(zero, x))) - val transform6 = RightSubstEq( + val transform6 = SC.RightSubstEq( Set(plus(x, zero) === x, plus(s(x), zero) === s(x)) |- (plus(x, zero) === plus(zero, x)) ==> (plus(s(x), zero) === plus(zero, s(x))), 5, (plus(x, zero), x) :: (plus(s(x), zero), s(x)) :: Nil, LambdaTermFormula(Seq(y, z), (y === plus(zero, x)) ==> (z === plus(zero, s(x)))) ) - val leftAnd7 = LeftAnd( + val leftAnd7 = SC.LeftAnd( (plus(x, zero) === x) /\ (plus(s(x), zero) === s(x)) |- (plus(x, zero) === plus(zero, x)) ==> (plus(s(x), zero) === plus(zero, s(x))), 6, plus(x, zero) === x, plus(s(x), zero) === s(x) ) - val instancePlusZero8 = SCSubproof( + val instancePlusZero8 = SC.SCSubproof( instantiateForallImport(ax"ax3neutral", x), Seq(-2) ) - val instancePlusZero9 = SCSubproof( + val instancePlusZero9 = SC.SCSubproof( instantiateForallImport(ax"ax3neutral", s(x)), Seq(-2) ) - val rightAnd10 = RightAnd(() |- (plus(x, zero) === x) /\ (plus(s(x), zero) === s(x)), Seq(8, 9), Seq(plus(x, zero) === x, plus(s(x), zero) === s(x))) + val rightAnd10 = SC.RightAnd(() |- (plus(x, zero) === x) /\ (plus(s(x), zero) === s(x)), Seq(8, 9), Seq(plus(x, zero) === x, plus(s(x), zero) === s(x))) - val cut11 = Cut( + val cut11 = SC.Cut( () |- (plus(x, zero) === plus(zero, x)) ==> (plus(s(x), zero) === plus(zero, s(x))), 10, 7, (plus(x, zero) === x) /\ (plus(s(x), zero) === s(x)) ) - val forall12 = RightForall( + val forall12 = SC.RightForall( cut11.bot.left |- forall(x, (plus(x, zero) === plus(zero, x)) ==> (plus(s(x), zero) === plus(zero, s(x)))), 11, (plus(x, zero) === plus(zero, x)) ==> (plus(s(x), zero) === plus(zero, s(x))), x ) - val inductionInstance: SCProofStep = InstPredSchema( + val inductionInstance: SCProofStep = SC.InstPredSchema( () |- ((plus(zero, zero) === plus(zero, zero)) /\ forall(x, (plus(x, zero) === plus(zero, x)) ==> (plus(s(x), zero) === plus(zero, s(x))))) ==> forall( x, plus(x, zero) === plus(zero, x) @@ -132,8 +132,8 @@ object Peano { SCProof( applyInduction( - SCSubproof(SCProof(RightRefl(() |- zero === zero, zero === zero))), - SCSubproof( + SC.SCSubproof(SCProof(SC.RightRefl(() |- zero === zero, zero === zero))), + SC.SCSubproof( SCProof( IndexedSeq(refl0, subst1, implies2, transform3, instanceAx4_4, cut5, transform6, leftAnd7, instancePlusZero8, instancePlusZero9, rightAnd10, cut11, forall12), IndexedSeq(ax"ax4plusSuccessor", ax"ax3neutral") @@ -147,35 +147,35 @@ object Peano { } using (ax"ax4plusSuccessor", ax"ax3neutral", ax"ax7induction") show - THEOREM("switch successor") of "∀'x. ∀'y. +('x, S('y)) = +(S('x), 'y)" PROOF { + THEOREM("switch successor") of "∀'x. ∀'y. +('x, S('y)) = +(S('x), 'y)" PROOF2 { //////////////////////////////////// Base: x + S0 = Sx + 0 /////////////////////////////////////////////// val base0 = { // x + 0 = x - val xEqXPlusZero0 = SCSubproof(instantiateForallImport(ax"ax3neutral", x), IndexedSeq(-1)) + val xEqXPlusZero0 = SC.SCSubproof(instantiateForallImport(ax"ax3neutral", x), IndexedSeq(-1)) // Sx + 0 = Sx - val succXEqSuccXPlusZero1 = SCSubproof(instantiateForallImport(ax"ax3neutral", s(x)), IndexedSeq(-1)) + val succXEqSuccXPlusZero1 = SC.SCSubproof(instantiateForallImport(ax"ax3neutral", s(x)), IndexedSeq(-1)) // x + S0 = S(x + 0) - val xPlusSuccZero2 = SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", x), zero), IndexedSeq(-2)) + val xPlusSuccZero2 = SC.SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", x), zero), IndexedSeq(-2)) // ------------------- x + 0 = x, Sx + 0 = Sx, x + S0 = S(x + 0) |- Sx + 0 = x + S0 --------------------- - val succX3 = RightRefl(() |- s(x) === s(x), s(x) === s(x)) - val substEq4 = RightSubstEq( + val succX3 = SC.RightRefl(() |- s(x) === s(x), s(x) === s(x)) + val substEq4 = SC.RightSubstEq( Set(s(x) === plus(s(x), zero), x === plus(x, zero)) |- plus(s(x), zero) === s(plus(x, zero)), 3, (s(x), plus(s(x), zero)) :: (VariableTerm(x), plus(x, zero)) :: Nil, LambdaTermFormula(Seq(y, z), y === s(z)) ) - val substEq5 = RightSubstEq( + val substEq5 = SC.RightSubstEq( Set(s(x) === plus(s(x), zero), x === plus(x, zero), s(plus(x, zero)) === plus(x, s(zero))) |- plus(s(x), zero) === plus(x, s(zero)), 4, (s(plus(x, zero)), plus(x, s(zero))) :: Nil, LambdaTermFormula(Seq(z), plus(s(x), zero) === z) ) // ------------------------------------------------------------------------------------------------------- - val cut6 = Cut(Set(s(x) === plus(s(x), zero), x === plus(x, zero)) |- plus(s(x), zero) === plus(x, s(zero)), 2, 5, s(plus(x, zero)) === plus(x, s(zero))) - val cut7 = Cut(x === plus(x, zero) |- plus(s(x), zero) === plus(x, s(zero)), 1, 6, s(x) === plus(s(x), zero)) - val cut8 = Cut(() |- plus(s(x), zero) === plus(x, s(zero)), 0, 7, x === plus(x, zero)) - SCSubproof( + val cut6 = SC.Cut(Set(s(x) === plus(s(x), zero), x === plus(x, zero)) |- plus(s(x), zero) === plus(x, s(zero)), 2, 5, s(plus(x, zero)) === plus(x, s(zero))) + val cut7 = SC.Cut(x === plus(x, zero) |- plus(s(x), zero) === plus(x, s(zero)), 1, 6, s(x) === plus(s(x), zero)) + val cut8 = SC.Cut(() |- plus(s(x), zero) === plus(x, s(zero)), 0, 7, x === plus(x, zero)) + SC.SCSubproof( SCProof( IndexedSeq(xEqXPlusZero0, succXEqSuccXPlusZero1, xPlusSuccZero2, succX3, substEq4, substEq5, cut6, cut7, cut8), IndexedSeq(ax"ax3neutral", ax"ax4plusSuccessor") @@ -187,45 +187,45 @@ object Peano { /////////////// Induction step: ?y. (x + Sy === Sx + y) ==> (x + SSy === Sx + Sy) //////////////////// val inductionStep1 = { // x + SSy = S(x + Sy) - val moveSuccessor0 = SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", x), s(y)), IndexedSeq(-2)) + val moveSuccessor0 = SC.SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", x), s(y)), IndexedSeq(-2)) // Sx + Sy = S(Sx + y) - val moveSuccessor1 = SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", s(x)), y), IndexedSeq(-2)) + val moveSuccessor1 = SC.SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", s(x)), y), IndexedSeq(-2)) // ----------- x + SSy = S(x + Sy), x + Sy = Sx + y, S(Sx + y) = Sx + Sy |- x + SSy = Sx + Sy ------------ - val middleEq2 = RightRefl(() |- s(plus(x, s(y))) === s(plus(x, s(y))), s(plus(x, s(y))) === s(plus(x, s(y)))) + val middleEq2 = SC.RightRefl(() |- s(plus(x, s(y))) === s(plus(x, s(y))), s(plus(x, s(y))) === s(plus(x, s(y)))) val substEq3 = - RightSubstEq( + SC.RightSubstEq( Set(plus(x, s(y)) === plus(s(x), y)) |- s(plus(x, s(y))) === s(plus(s(x), y)), 2, (plus(x, s(y)), plus(s(x), y)) :: Nil, LambdaTermFormula(Seq(z1), s(plus(x, s(y))) === s(z1)) ) val substEq4 = - RightSubstEq( + SC.RightSubstEq( Set(plus(x, s(y)) === plus(s(x), y), plus(x, s(s(y))) === s(plus(x, s(y)))) |- plus(x, s(s(y))) === s(plus(s(x), y)), 3, (plus(x, s(s(y))), s(plus(x, s(y)))) :: Nil, LambdaTermFormula(Seq(z1), z1 === s(plus(s(x), y))) ) val substEq5 = - RightSubstEq( + SC.RightSubstEq( Set(plus(x, s(s(y))) === s(plus(x, s(y))), plus(x, s(y)) === plus(s(x), y), s(plus(s(x), y)) === plus(s(x), s(y))) |- plus(x, s(s(y))) === plus(s(x), s(y)), 4, (s(plus(s(x), y)), plus(s(x), s(y))) :: Nil, LambdaTermFormula(Seq(z1), plus(x, s(s(y))) === z1) ) // ------------------------------------------------------------------------------------------------------- - val cut6 = Cut(Set(plus(x, s(y)) === plus(s(x), y), s(plus(s(x), y)) === plus(s(x), s(y))) |- plus(x, s(s(y))) === plus(s(x), s(y)), 0, 5, plus(x, s(s(y))) === s(plus(x, s(y)))) - val cut7 = Cut(plus(x, s(y)) === plus(s(x), y) |- plus(x, s(s(y))) === plus(s(x), s(y)), 1, 6, s(plus(s(x), y)) === plus(s(x), s(y))) - val implies8 = RightImplies(() |- (plus(x, s(y)) === plus(s(x), y)) ==> (plus(x, s(s(y))) === plus(s(x), s(y))), 7, plus(x, s(y)) === plus(s(x), y), plus(x, s(s(y))) === plus(s(x), s(y))) - val forall9 = RightForall( + val cut6 = SC.Cut(Set(plus(x, s(y)) === plus(s(x), y), s(plus(s(x), y)) === plus(s(x), s(y))) |- plus(x, s(s(y))) === plus(s(x), s(y)), 0, 5, plus(x, s(s(y))) === s(plus(x, s(y)))) + val cut7 = SC.Cut(plus(x, s(y)) === plus(s(x), y) |- plus(x, s(s(y))) === plus(s(x), s(y)), 1, 6, s(plus(s(x), y)) === plus(s(x), s(y))) + val implies8 = SC.RightImplies(() |- (plus(x, s(y)) === plus(s(x), y)) ==> (plus(x, s(s(y))) === plus(s(x), s(y))), 7, plus(x, s(y)) === plus(s(x), y), plus(x, s(s(y))) === plus(s(x), s(y))) + val forall9 = SC.RightForall( () |- forall(y, (plus(x, s(y)) === plus(s(x), y)) ==> (plus(x, s(s(y))) === plus(s(x), s(y)))), 8, (plus(x, s(y)) === plus(s(x), y)) ==> (plus(x, s(s(y))) === plus(s(x), s(y))), y ) - SCSubproof( + SC.SCSubproof( SCProof( IndexedSeq(moveSuccessor0, moveSuccessor1, middleEq2, substEq3, substEq4, substEq5, cut6, cut7, implies8, forall9), IndexedSeq(ax"ax3neutral", ax"ax4plusSuccessor") @@ -235,8 +235,8 @@ object Peano { } val inductionInstance = { - val inductionOnY0 = Rewrite(() |- (sPhi(zero) /\ forall(y, sPhi(y) ==> sPhi(s(y)))) ==> forall(y, sPhi(y)), -1) - val inductionInstance1 = InstPredSchema( + val inductionOnY0 = SC.Rewrite(() |- (sPhi(zero) /\ forall(y, sPhi(y) ==> sPhi(s(y)))) ==> forall(y, sPhi(y)), -1) + val inductionInstance1 = SC.InstPredSchema( () |- ((plus(s(x), zero) === plus(x, s(zero))) /\ forall(y, (plus(x, s(y)) === plus(s(x), y)) ==> (plus(x, s(s(y))) === plus(s(x), s(y))))) ==> @@ -244,11 +244,11 @@ object Peano { 0, Map(sPhi -> LambdaTermFormula(Seq(y), plus(x, s(y)) === plus(s(x), y))) ) - SCSubproof(SCProof(IndexedSeq(inductionOnY0, inductionInstance1), IndexedSeq(ax"ax7induction")), Seq(-3)) + SC.SCSubproof(SCProof(IndexedSeq(inductionOnY0, inductionInstance1), IndexedSeq(ax"ax7induction")), Seq(-3)) } val inductionApplication = applyInduction(base0, inductionStep1, inductionInstance) - val addForall = RightForall(() |- forall(x, forall(y, plus(x, s(y)) === plus(s(x), y))), inductionApplication.size - 1, forall(y, plus(x, s(y)) === plus(s(x), y)), x) - val proof: SCProof = Proof( + val addForall = SC.RightForall(() |- forall(x, forall(y, plus(x, s(y)) === plus(s(x), y))), inductionApplication.size - 1, forall(y, plus(x, s(y)) === plus(s(x), y)), x) + val proof: SCProof = SCProof( inductionApplication :+ addForall, IndexedSeq(ax"ax3neutral", ax"ax4plusSuccessor", ax"ax7induction") ) @@ -256,44 +256,45 @@ object Peano { } using (ax"ax3neutral", ax"ax4plusSuccessor", ax"ax7induction") show - THEOREM("additivity of addition") of "∀'x. ∀'y. +('x, 'y) = +('y, 'x)" PROOF { - val base0 = SCSubproof(instantiateForallImport(thm"x + 0 = 0 + x", x), Seq(-3)) + THEOREM("additivity of addition") of "" PROOF2 { + val base0 = SC.SCSubproof(instantiateForallImport(thm"x + 0 = 0 + x", x), Seq(-3)) val inductionStep1 = { - val start0 = RightRefl(() |- plus(x, s(y)) === plus(x, s(y)), plus(x, s(y)) === plus(x, s(y))) + val start0 = SC.RightRefl(() |- plus(x, s(y)) === plus(x, s(y)), plus(x, s(y)) === plus(x, s(y))) val applyPlusSuccAx1 = - RightSubstEq(plus(x, s(y)) === s(plus(x, y)) |- plus(x, s(y)) === s(plus(x, y)), 0, (plus(x, s(y)), s(plus(x, y))) :: Nil, LambdaTermFormula(Seq(z1), plus(x, s(y)) === z1)) + SC.RightSubstEq(plus(x, s(y)) === s(plus(x, y)) |- plus(x, s(y)) === s(plus(x, y)), 0, (plus(x, s(y)), s(plus(x, y))) :: Nil, LambdaTermFormula(Seq(z1), plus(x, s(y)) === z1)) val applyInductionPremise2 = - RightSubstEq( + SC.RightSubstEq( Set(plus(x, s(y)) === s(plus(x, y)), plus(x, y) === plus(y, x)) |- plus(x, s(y)) === s(plus(y, x)), 1, (plus(x, y), plus(y, x)) :: Nil, LambdaTermFormula(Seq(z1), plus(x, s(y)) === s(z1)) ) val applyPlusSuccAx3 = - RightSubstEq( + SC.RightSubstEq( Set(plus(x, s(y)) === s(plus(x, y)), plus(x, y) === plus(y, x), s(plus(y, x)) === plus(y, s(x))) |- plus(x, s(y)) === plus(y, s(x)), 2, (s(plus(y, x)), plus(y, s(x))) :: Nil, LambdaTermFormula(Seq(z1), plus(x, s(y)) === z1) ) val applySwitchSuccessor4 = - RightSubstEq( + SC.RightSubstEq( Set(plus(x, s(y)) === s(plus(x, y)), plus(x, y) === plus(y, x), s(plus(y, x)) === plus(y, s(x)), plus(y, s(x)) === plus(s(y), x)) |- plus(x, s(y)) === plus(s(y), x), 3, (plus(y, s(x)), plus(s(y), x)) :: Nil, LambdaTermFormula(Seq(z1), plus(x, s(y)) === z1) ) - val xPlusSYInstance5 = SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", x), y), Seq(-1)) - val cutXPlusSY6 = Cut(Set(plus(x, y) === plus(y, x), s(plus(y, x)) === plus(y, s(x)), plus(y, s(x)) === plus(s(y), x)) |- plus(x, s(y)) === plus(s(y), x), 5, 4, plus(x, s(y)) === s(plus(x, y))) - val yPlusSXInstance7 = SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", y), x), Seq(-1)) - val cutYPlusSX8 = Cut(Set(plus(x, y) === plus(y, x), plus(y, s(x)) === plus(s(y), x)) |- plus(x, s(y)) === plus(s(y), x), 7, 6, s(plus(y, x)) === plus(y, s(x))) - val swichSuccessorInstance9 = SCSubproof(instantiateForall(instantiateForallImport(thm"switch successor", y), x), Seq(-2)) - val cutSwitchSuccessor10 = Cut(plus(x, y) === plus(y, x) |- plus(x, s(y)) === plus(s(y), x), 9, 8, plus(y, s(x)) === plus(s(y), x)) - val rightImplies11 = RightImplies(() |- (plus(x, y) === plus(y, x)) ==> (plus(x, s(y)) === plus(s(y), x)), 10, plus(x, y) === plus(y, x), plus(x, s(y)) === plus(s(y), x)) - val forall12 = RightForall(() |- forall(y, (plus(x, y) === plus(y, x)) ==> (plus(x, s(y)) === plus(s(y), x))), 11, (plus(x, y) === plus(y, x)) ==> (plus(x, s(y)) === plus(s(y), x)), y) - SCSubproof( - Proof( + val xPlusSYInstance5 = SC.SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", x), y), Seq(-1)) + val cutXPlusSY6 = + SC.Cut(Set(plus(x, y) === plus(y, x), s(plus(y, x)) === plus(y, s(x)), plus(y, s(x)) === plus(s(y), x)) |- plus(x, s(y)) === plus(s(y), x), 5, 4, plus(x, s(y)) === s(plus(x, y))) + val yPlusSXInstance7 = SC.SCSubproof(instantiateForall(instantiateForallImport(ax"ax4plusSuccessor", y), x), Seq(-1)) + val cutYPlusSX8 = SC.Cut(Set(plus(x, y) === plus(y, x), plus(y, s(x)) === plus(s(y), x)) |- plus(x, s(y)) === plus(s(y), x), 7, 6, s(plus(y, x)) === plus(y, s(x))) + val swichSuccessorInstance9 = SC.SCSubproof(instantiateForall(instantiateForallImport(thm"switch successor", y), x), Seq(-2)) + val cutSwitchSuccessor10 = SC.Cut(plus(x, y) === plus(y, x) |- plus(x, s(y)) === plus(s(y), x), 9, 8, plus(y, s(x)) === plus(s(y), x)) + val rightImplies11 = SC.RightImplies(() |- (plus(x, y) === plus(y, x)) ==> (plus(x, s(y)) === plus(s(y), x)), 10, plus(x, y) === plus(y, x), plus(x, s(y)) === plus(s(y), x)) + val forall12 = SC.RightForall(() |- forall(y, (plus(x, y) === plus(y, x)) ==> (plus(x, s(y)) === plus(s(y), x))), 11, (plus(x, y) === plus(y, x)) ==> (plus(x, s(y)) === plus(s(y), x)), y) + SC.SCSubproof( + SCProof( IndexedSeq( start0, applyPlusSuccAx1, @@ -316,8 +317,8 @@ object Peano { } val inductionInstance = { - val inductionOnY0 = Rewrite(() |- (sPhi(zero) /\ forall(y, sPhi(y) ==> sPhi(s(y)))) ==> forall(y, sPhi(y)), -1) - val inductionInstance1 = InstPredSchema( + val inductionOnY0 = SC.Rewrite(() |- (sPhi(zero) /\ forall(y, sPhi(y) ==> sPhi(s(y)))) ==> forall(y, sPhi(y)), -1) + val inductionInstance1 = SC.InstPredSchema( () |- ((plus(x, zero) === plus(zero, x)) /\ forall(y, (plus(x, y) === plus(y, x)) ==> (plus(x, s(y)) === plus(s(y), x)))) ==> @@ -325,11 +326,11 @@ object Peano { 0, Map(sPhi -> LambdaTermFormula(Seq(y), plus(x, y) === plus(y, x))) ) - SCSubproof(SCProof(IndexedSeq(inductionOnY0, inductionInstance1), IndexedSeq(ax"ax7induction")), Seq(-2)) + SC.SCSubproof(SCProof(IndexedSeq(inductionOnY0, inductionInstance1), IndexedSeq(ax"ax7induction")), Seq(-2)) } val inductionApplication = applyInduction(base0, inductionStep1, inductionInstance) - val addForall = RightForall(() |- forall(x, forall(y, plus(x, y) === plus(y, x))), inductionApplication.size - 1, forall(y, plus(x, y) === plus(y, x)), x) - val proof: SCProof = Proof( + val addForall = SC.RightForall(() |- forall(x, forall(y, plus(x, y) === plus(y, x))), inductionApplication.size - 1, forall(y, plus(x, y) === plus(y, x)), x) + val proof: SCProof = SCProof( inductionApplication :+ addForall, IndexedSeq(ax"ax4plusSuccessor", ax"ax7induction", thm"x + 0 = 0 + x", thm"switch successor") ) diff --git a/src/test/scala/lisa/utilities/Transformations.scala b/src/test/scala/lisa/utilities/Transformations.scala index f51cf3aadef181ecdf4fa27f618516fc080f5f19..4fb80659f1065ccaf6491337d1f895e99e784a4d 100644 --- a/src/test/scala/lisa/utilities/Transformations.scala +++ b/src/test/scala/lisa/utilities/Transformations.scala @@ -1,14 +1,16 @@ package lisa.utilities import lisa.automation.kernel.Destructors.* import lisa.automation.kernel.ProofTactics.* -import lisa.kernel.fol.* +import lisa.kernel.fol.FOL +import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof +import lisa.kernel.proof.SequentCalculus.* import lisa.test.ProofCheckerSuite -import lisa.utils.Helpers.given_Conversion_VariableLabel_Term +import lisa.utils.Helpers.{_, given} import lisa.utils.Printer class Transformations extends ProofCheckerSuite { - import lisa.settheory.SetTheoryLibrary.* + // import lisa.settheory.SetTheoryLibrary.* test("Trasnsformation initialises well with empty proof and returns an empty proof") { val nullSCProof = SCProof()