From 572ed12432d034ea55fb9080855f907513dc5565 Mon Sep 17 00:00:00 2001 From: Sankalp Gambhir <sankalp.gambhir47@gmail.com> Date: Tue, 1 Nov 2022 14:07:34 +0100 Subject: [PATCH 1/6] Proof checking at higher abstraction level - Left propositional rules --- .../lisa/utils/tactics/BasicStepTactic.scala | 315 ++++++++++++++---- 1 file changed, 241 insertions(+), 74 deletions(-) diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala index 9c02f590..59f81b59 100644 --- a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala @@ -12,13 +12,34 @@ 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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + val intersectedPivot = bot.left.intersect(bot.right) + + if (!intersectedPivot.isEmpty) + SC.Hypothesis(bot, intersectedPivot.head) + else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "A formula for input to hypothesis could not be inferred from left and right side of sequent." + ) + } } case object Rewrite extends ProofStepWithoutBotNorPrem(1) { - def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = - SC.Rewrite(bot, premises(0)) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + if (premises.length != 1) + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + s"One premise expected, ${premises.length} received." + ) + else if (SC.isSameSequent(bot, currentProof.getSequent(premises(0)))) + SC.Rewrite(bot, premises(0)) + else + ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + "The premise and the conclusion are not trivially equivalent." + ) + } } /** @@ -29,30 +50,54 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val leftSequent = currentProof.getSequent(premises(0)) + lazy val rightSequent = currentProof.getSequent(premises(1)) + + if (premises.length != 2) + invalid(s"Two premises expected, ${premises.length} received.") + else if (!contains(leftSequent.right, phi)) + invalid("Right-hand side of first premise does not contain φ as claimed.") + else if (!contains(rightSequent.left, phi)) + invalid("Left-hand side of second premise does not contain φ as claimed.") + else if (!isSameSet(bot.left, leftSequent.left ++ rightSequent.left.filterNot(isSame(_, phi)))) + invalid("Left-hand side of conclusion + φ is not the union of the left-hand sides of the premises.") + else if (!isSameSet(bot.right, leftSequent.right.filterNot(isSame(_, phi)) ++ rightSequent.right)) + invalid("Right-hand side of conclusion + φ is not the union of the right-hand sides of the premises.") + else + 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val leftSequent = currentProof.getSequent(premises(0)) + lazy val rightSequent = currentProof.getSequent(premises(1)) + lazy 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.") + if (premises.length != 2) + invalid(s"Two premises expected, ${premises.length} received.") + else if (!cutSet.isEmpty) + if (cutSet.tail.isEmpty) + Cut(cutSet.head).asSCProof(bot, premises, currentProof) + else + invalid("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) + Cut(intersectedCutSet.head).asSCProof(bot, premises, currentProof) else - ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - "A consistent cut pivot cannot be inferred from the premises. Possibly a missing or extraneous clause." - ) + invalid("A consistent cut pivot cannot be inferred from the premises. Possibly a missing or extraneous clause.") } } @@ -76,33 +121,57 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val phiAndPsi = ConnectorFormula(And, Seq(phi, psi)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.right, premiseSequent.right)) + invalid("Right-hand sides of the premise and the conclusion must be the same.") + else if ( + !isSameSet(bot.left + phi, premiseSequent.left + phiAndPsi) && + !isSameSet(bot.left + psi, premiseSequent.left + phiAndPsi) && + !isSameSet(bot.left + phi + psi, premiseSequent.left + phiAndPsi) + ) + invalid("Left-hand side of conclusion + φ∧ψ must be same as left-hand side of premise + either φ, ψ or both.") + else + 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = bot.left.diff(premiseSequent.left) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else 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) + LeftAnd(phi, psi).asSCProof(bot, premises, currentProof) 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.") + LeftAnd(psi, phi).asSCProof(bot, premises, currentProof) + case _ => invalid("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." - ) + // try a rewrite, if it works, go ahead with it, otherwise malformed + if (SC.isSameSequent(premiseSequent, bot)) + Rewrite.asSCProof(bot, premises, currentProof) + else + invalid("Left-hand side of conclusion + φ∧ψ must be same as left-hand side of premise + either φ, ψ or both.") } } @@ -125,24 +194,44 @@ object BasicStepTactic { */ 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequents = premises.map(currentProof.getSequent(_)) + lazy val disjunction = ConnectorFormula(Or, disjuncts) + + + if (premises.length == 0) + invalid(s"Premises expected, ${premises.length} received.") + else if (!isSameSet(bot.right, premiseSequents.map(_.right).reduce(_ union _))) + invalid("Right-hand side of conclusion is not the union of the right-hand sides of the premises.") + else if (!isSameSet(disjuncts.foldLeft(bot.left)(_ + _), premiseSequents.map(_.left).reduce(_ union _) + disjunction)) + invalid("Left-hand side of conclusion + disjuncts is not the same as the union of the left-hand sides of the premises + φ∨ψ.") + else + 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))) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequents = premises.map(currentProof.getSequent(_)) + lazy val pivots = premiseSequents.map(_.left.diff(bot.left)) + + if (premises.length == 0) + invalid(s"Premises expected, ${premises.length} received.") + else if (pivots.exists(_.isEmpty)) + Weakening.asSCProof(bot, Seq(premises(pivots.indexWhere(_.isEmpty))), currentProof) else if (pivots.forall(_.tail.isEmpty)) - SC.LeftOr(bot, premises, pivots.map(_.head)) + LeftOr(pivots.map(_.head)).asSCProof(bot, premises, currentProof) 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 + φ∨ψ." - ) + invalid("Left-hand side of conclusion + disjuncts is not the same as the union of the left-hand sides of the premises + φ∨ψ.") } } @@ -164,23 +253,48 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val leftSequent = currentProof.getSequent(premises(0)) + lazy val rightSequent = currentProof.getSequent(premises(1)) + lazy val implication = ConnectorFormula(Implies, Seq(phi, psi)) + + + if (premises.length != 2) + invalid(s"Two premises expected, ${premises.length} received.") + else if (!isSameSet(bot.right + phi, leftSequent.right union rightSequent.right)) + invalid("Right-hand side of conclusion + φ must be identical to union of right-hand sides of premises.") + else if (!isSameSet(bot.left + psi, leftSequent.left union rightSequent.left + implication)) + invalid("Left-hand side of conclusion + ψ must be identical to union of left-hand sides of premises + φ→ψ.") + else + 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val leftSequent = currentProof.getSequent(premises(0)) + lazy val rightSequent = currentProof.getSequent(premises(1)) + lazy val pivotLeft = leftSequent.right.diff(bot.right) lazy val pivotRight = rightSequent.left.diff(bot.left) - if (pivotLeft.isEmpty) - SC.Weakening(bot, premises(0)) + if (premises.length != 2) + invalid(s"Two premises expected, ${premises.length} received.") + else if (pivotLeft.isEmpty) + Weakening.asSCProof(bot, premises, currentProof) else if (pivotRight.isEmpty) - SC.Weakening(bot, premises(1)) + Weakening.asSCProof(bot, premises, currentProof) else if (pivotLeft.tail.isEmpty && pivotRight.tail.isEmpty) - SC.LeftImplies(bot, premises(0), premises(1), pivotLeft.head, pivotRight.head) + LeftImplies(pivotLeft.head, pivotRight.head).asSCProof(bot, premises, currentProof) else ProofStepJudgement.InvalidProofStep( this.asProofStepWithoutBot(premises).asProofStep(bot), @@ -207,21 +321,51 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val implication = ConnectorFormula(Iff, Seq(phi, psi)) + lazy val impLeft = ConnectorFormula(Implies, Seq(phi, psi)) + lazy val impRight = ConnectorFormula(Implies, Seq(psi, phi)) + + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.right, premiseSequent.right)) + invalid("Right-hand sides of premise and conclusion must be the same.") + else if ( + !isSameSet(bot.left + impLeft, premiseSequent.left + implication) && + !isSameSet(bot.left + impRight, premiseSequent.left + implication) && + !isSameSet(bot.left + impLeft + impRight, premiseSequent.left + implication) + ) + invalid("Left-hand side of conclusion + φ↔ψ must be same as left-hand side of premise + either φ→ψ, ψ→φ or both.") + else + 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)) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = premiseSequent.left.diff(bot.left) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (pivot.isEmpty) + Weakening.asSCProof(bot, premises, currentProof) 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 ConnectorFormula(Implies, Seq(phi, psi)) => LeftIff(phi, psi).asSCProof(bot, premises, currentProof) + case _ => invalid("Could not infer a pivot implication from premise.") } } } @@ -244,21 +388,44 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val negation = ConnectorFormula(Neg, Seq(phi)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.right + phi, premiseSequent.right)) + invalid("Right-hand side of conclusion + φ must be the same as right-hand side of premise.") + else if (!isSameSet(bot.left, premiseSequent.left + negation)) + invalid("Left-hand side of conclusion must be the same as left-hand side of premise + ¬φ.") + else + 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)) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = premiseSequent.right.diff(bot.right) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (pivot.isEmpty) + Weakening.asSCProof(bot, premises, currentProof) else if (pivot.tail.isEmpty) - SC.LeftNot(bot, premises(0), pivot.head) + LeftNot(pivot.head).asSCProof(bot, premises, currentProof) else - ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Right-hand side of conclusion + φ must be the same as right-hand side of premise.") + invalid("Right-hand side of conclusion + φ must be the same as right-hand side of premise.") } } -- GitLab From cf2107b186c98c514bc0ce5c0ed03b448df47a07 Mon Sep 17 00:00:00 2001 From: Sankalp Gambhir <sankalp.gambhir47@gmail.com> Date: Tue, 1 Nov 2022 18:24:22 +0100 Subject: [PATCH 2/6] Left rules - proof checking during construction --- .../lisa/utils/tactics/BasicStepTactic.scala | 210 ++++++++++++------ 1 file changed, 144 insertions(+), 66 deletions(-) diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala index 59f81b59..97340316 100644 --- a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala @@ -13,32 +13,35 @@ object BasicStepTactic { case object Hypothesis extends ProofStepWithoutBotNorPrem(0) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { - val intersectedPivot = bot.left.intersect(bot.right) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) - if (!intersectedPivot.isEmpty) - SC.Hypothesis(bot, intersectedPivot.head) + lazy val intersectedPivot = bot.left.intersect(bot.right) + + if (premises.length != 0) + invalid(s"No premises expected, ${premises.length} received.") + else if (intersectedPivot.isEmpty) + invalid("A formula for input to hypothesis could not be inferred from left and right side of sequent.") else - ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - "A formula for input to hypothesis could not be inferred from left and right side of sequent." - ) + SC.Hypothesis(bot, intersectedPivot.head) } } case object Rewrite extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + if (premises.length != 1) - ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - s"One premise expected, ${premises.length} received." - ) - else if (SC.isSameSequent(bot, currentProof.getSequent(premises(0)))) - SC.Rewrite(bot, premises(0)) + invalid(s"One premise expected, ${premises.length} received.") + else if (!SC.isSameSequent(bot, currentProof.getSequent(premises(0)))) + invalid("The premise and the conclusion are not trivially equivalent.") else - ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - "The premise and the conclusion are not trivially equivalent." - ) + SC.Rewrite(bot, premises(0)) } } @@ -139,7 +142,7 @@ object BasicStepTactic { !isSameSet(bot.left + psi, premiseSequent.left + phiAndPsi) && !isSameSet(bot.left + phi + psi, premiseSequent.left + phiAndPsi) ) - invalid("Left-hand side of conclusion + φ∧ψ must be same as left-hand side of premise + either φ, ψ or both.") + invalid("Left-hand side of premise + φ∧ψ must be same as left-hand side of conclusion + either φ, ψ or both.") else SC.LeftAnd(bot, premises(0), phi, psi) } @@ -171,7 +174,7 @@ object BasicStepTactic { if (SC.isSameSequent(premiseSequent, bot)) Rewrite.asSCProof(bot, premises, currentProof) else - invalid("Left-hand side of conclusion + φ∧ψ must be same as left-hand side of premise + either φ, ψ or both.") + invalid("Left-hand side of premise + φ∧ψ must be same as left-hand side of conclusion + either φ, ψ or both.") } } @@ -213,7 +216,7 @@ object BasicStepTactic { SC.LeftOr(bot, premises, disjuncts) } } - case class LeftOrWithoutFormula() extends ProofStepWithoutBotNorPrem(-1) { + case object LeftOrWithoutFormula extends ProofStepWithoutBotNorPrem(-1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( this.asProofStepWithoutBot(premises).asProofStep(bot), @@ -238,7 +241,7 @@ object BasicStepTactic { case object LeftOr extends ProofStepWithoutBotNorPrem(-1) { // default construction: // def apply(disjuncts: Seq[Formula]) = new LeftOr(disjuncts) - def apply() = new LeftOrWithoutFormula() + def apply() = LeftOrWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -296,10 +299,7 @@ object BasicStepTactic { else if (pivotLeft.tail.isEmpty && pivotRight.tail.isEmpty) LeftImplies(pivotLeft.head, pivotRight.head).asSCProof(bot, premises, currentProof) 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." - ) + invalid("Could not infer an implication as a pivot from the premises and conclusion, possible extraneous formulae in premises.") } } @@ -342,13 +342,13 @@ object BasicStepTactic { !isSameSet(bot.left + impRight, premiseSequent.left + implication) && !isSameSet(bot.left + impLeft + impRight, premiseSequent.left + implication) ) - invalid("Left-hand side of conclusion + φ↔ψ must be same as left-hand side of premise + either φ→ψ, ψ→φ or both.") + invalid("Left-hand side of premise + φ↔ψ must be same as left-hand side of conclusion + either φ→ψ, ψ→φ or both.") else SC.LeftIff(bot, premises(0), phi, psi) } } - case class LeftIffWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object LeftIffWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( this.asProofStepWithoutBot(premises).asProofStep(bot), @@ -373,7 +373,7 @@ object BasicStepTactic { case object LeftIff extends ProofStepWithoutBotNorPrem(1) { // default construction: // def apply(phi: Formula, psi: Formula) = new LeftIff(phi, psi) - def apply() = new LeftIffWithoutFormula() + def apply() = LeftIffWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -408,7 +408,7 @@ object BasicStepTactic { } } - case class LeftNotWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object LeftNotWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( this.asProofStepWithoutBot(premises).asProofStep(bot), @@ -433,7 +433,7 @@ object BasicStepTactic { case object LeftNot extends ProofStepWithoutBotNorPrem(1) { // default construction: // def apply(phi: Formula) = new LeftNot(phi) - def apply() = new LeftNotWithoutFormula() + def apply() = LeftNotWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -449,25 +449,49 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val quantified = BinderFormula(Forall, x, phi) + lazy val instantiated = substituteVariables(phi, Map(x -> t)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.right, premiseSequent.right)) + invalid("Right-hand side of conclusion must be the same as right-hand side of premise") + else if (!isSameSet(bot.left + instantiated, premiseSequent.left + quantified)) + invalid("Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ") + else + 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = bot.left.diff(premiseSequent.left) lazy val instantiatedPivot = premiseSequent.left.diff(bot.left) - if (!pivot.isEmpty) + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else 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.") + case BinderFormula(Forall, x, phi) => LeftForall(phi, x, t).asSCProof(bot, premises, currentProof) + case _ => invalid("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)) + invalid("Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ.") + else if (instantiatedPivot.isEmpty) Weakening.asSCProof(bot, premises, currentProof) else if (instantiatedPivot.tail.isEmpty) { // go through conclusion to find a matching quantified formula @@ -480,10 +504,12 @@ object BasicStepTactic { ) 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.") + case Some(BinderFormula(Forall, x, phi)) => LeftForall(phi, x, t).asSCProof(bot, premises, currentProof) + case _ => invalid("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 + invalid("Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ.") } } @@ -510,18 +536,43 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val quantified = BinderFormula(Exists, x, phi) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if ((bot.left union bot.right).exists(_.freeVariables.contains(x))) + invalid("The variable x must not be free in the resulting sequent.") + else if (!isSameSet(bot.right, premiseSequent.right)) + invalid("Right-hand side of conclusion must be the same as right-hand side of premise") + else if (!isSameSet(bot.left + phi, premiseSequent.left + quantified)) + invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ") + else + SC.LeftExists(bot, premises(0), phi, x) + } } - case class LeftExistsWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy 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)) + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (pivot.isEmpty) + if (instantiatedPivot.isEmpty) Rewrite.asSCProof(bot, premises, currentProof) else if (instantiatedPivot.tail.isEmpty) { val in: Formula = instantiatedPivot.head val quantifiedPhi: Option[Formula] = bot.left.find(f => @@ -532,24 +583,26 @@ object BasicStepTactic { ) 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.") + case Some(BinderFormula(Exists, x, phi)) => LeftExists(phi, x).asSCProof(bot, premises, currentProof) + case _ => invalid("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 + invalid("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.") + case BinderFormula(Exists, x, phi) => LeftExists(phi, x).asSCProof(bot, premises, currentProof) + case _ => invalid("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. φ.") + invalid("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() + def apply() = LeftExistsWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -564,34 +617,59 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val y = VariableLabel(freshId(phi.freeVariables.map(_.id) + x.id, "y")) + lazy val instantiated = BinderFormula(Exists, y, BinderFormula(Forall, x, ConnectorFormula(Iff, List(PredicateFormula(equality, List(VariableTerm(x), VariableTerm(y))), phi)))) + lazy val quantified = BinderFormula(ExistsOne, x, phi) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.right, premiseSequent.right)) + invalid("Right-hand side of conclusion must be the same as right-hand side of premise.") + else if (!isSameSet(bot.left + instantiated, premiseSequent.left + quantified)) + invalid("Left-hand side of conclusion + ∃y.∀x. (x=y) ↔ φ must be the same as left-hand side of premise + ∃!x. φ.") + else + 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = bot.left.diff(premiseSequent.left) lazy val instantiatedPivot = premiseSequent.left.diff(bot.left) - if (pivot.isEmpty) + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (pivot.isEmpty) if (instantiatedPivot.isEmpty) - SC.Rewrite(bot, premises(0)) + Rewrite.asSCProof(bot, premises, currentProof) 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 BinderFormula(Exists, _, BinderFormula(Forall, x, ConnectorFormula(Iff, Seq(_, phi)))) => LeftExistsOne(phi, x).asSCProof(bot, premises, currentProof) 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. φ.") + invalid("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.") + case _ => invalid("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. φ.") + invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") } } -- GitLab From da82badb27160493519f60866556bd1ca51dc94d Mon Sep 17 00:00:00 2001 From: Sankalp Gambhir <sankalp.gambhir47@gmail.com> Date: Tue, 1 Nov 2022 20:22:51 +0100 Subject: [PATCH 3/6] Right prop and reflixivity rules, documentation --- .../lisa/utils/tactics/BasicStepTactic.scala | 572 +++++++++++++----- 1 file changed, 423 insertions(+), 149 deletions(-) diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala index 97340316..c1702bef 100644 --- a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala @@ -136,13 +136,13 @@ object BasicStepTactic { if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.right, premiseSequent.right)) - invalid("Right-hand sides of the premise and the conclusion must be the same.") + invalid("Right-hand side of the conclusion is not the same as the right-hand side of the premise.") else if ( !isSameSet(bot.left + phi, premiseSequent.left + phiAndPsi) && !isSameSet(bot.left + psi, premiseSequent.left + phiAndPsi) && !isSameSet(bot.left + phi + psi, premiseSequent.left + phiAndPsi) ) - invalid("Left-hand side of premise + φ∧ψ must be same as left-hand side of conclusion + either φ, ψ or both.") + invalid("Left-hand side of premise + φ∧ψ is not the same as left-hand side of conclusion + either φ, ψ or both.") else SC.LeftAnd(bot, premises(0), phi, psi) } @@ -174,7 +174,7 @@ object BasicStepTactic { if (SC.isSameSequent(premiseSequent, bot)) Rewrite.asSCProof(bot, premises, currentProof) else - invalid("Left-hand side of premise + φ∧ψ must be same as left-hand side of conclusion + either φ, ψ or both.") + invalid("Left-hand side of premise + φ∧ψ is not the same as left-hand side of conclusion + either φ, ψ or both.") } } @@ -270,9 +270,9 @@ object BasicStepTactic { if (premises.length != 2) invalid(s"Two premises expected, ${premises.length} received.") else if (!isSameSet(bot.right + phi, leftSequent.right union rightSequent.right)) - invalid("Right-hand side of conclusion + φ must be identical to union of right-hand sides of premises.") + invalid("Right-hand side of conclusion + φ is not the union of right-hand sides of premises.") else if (!isSameSet(bot.left + psi, leftSequent.left union rightSequent.left + implication)) - invalid("Left-hand side of conclusion + ψ must be identical to union of left-hand sides of premises + φ→ψ.") + invalid("Left-hand side of conclusion + ψ is not the union of left-hand sides of premises + φ→ψ.") else SC.LeftImplies(bot, premises(0), premises(1), phi, psi) } @@ -336,13 +336,13 @@ object BasicStepTactic { if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.right, premiseSequent.right)) - invalid("Right-hand sides of premise and conclusion must be the same.") + invalid("Right-hand side of premise is not the same as right-hand side of conclusion.") else if ( !isSameSet(bot.left + impLeft, premiseSequent.left + implication) && !isSameSet(bot.left + impRight, premiseSequent.left + implication) && !isSameSet(bot.left + impLeft + impRight, premiseSequent.left + implication) ) - invalid("Left-hand side of premise + φ↔ψ must be same as left-hand side of conclusion + either φ→ψ, ψ→φ or both.") + invalid("Left-hand side of premise + φ↔ψ is not the same as left-hand side of conclusion + either φ→ψ, ψ→φ or both.") else SC.LeftIff(bot, premises(0), phi, psi) } @@ -400,9 +400,9 @@ object BasicStepTactic { if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.right + phi, premiseSequent.right)) - invalid("Right-hand side of conclusion + φ must be the same as right-hand side of premise.") + invalid("Right-hand side of conclusion + φ is not the same as right-hand side of premise.") else if (!isSameSet(bot.left, premiseSequent.left + negation)) - invalid("Left-hand side of conclusion must be the same as left-hand side of premise + ¬φ.") + invalid("Left-hand side of conclusion is not the same as left-hand side of premise + ¬φ.") else SC.LeftNot(bot, premises(0), phi) } @@ -425,7 +425,7 @@ object BasicStepTactic { else if (pivot.tail.isEmpty) LeftNot(pivot.head).asSCProof(bot, premises, currentProof) else - invalid("Right-hand side of conclusion + φ must be the same as right-hand side of premise.") + invalid("Right-hand side of conclusion + φ is not the same as right-hand side of premise.") } } @@ -462,9 +462,9 @@ object BasicStepTactic { if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.right, premiseSequent.right)) - invalid("Right-hand side of conclusion must be the same as right-hand side of premise") + invalid("Right-hand side of conclusion is not the same as right-hand side of premise") else if (!isSameSet(bot.left + instantiated, premiseSequent.left + quantified)) - invalid("Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ") + invalid("Left-hand side of conclusion + φ[t/x] is not the same as left-hand side of premise + ∀x. φ") else SC.LeftForall(bot, premises(0), phi, x, t) } @@ -490,7 +490,7 @@ object BasicStepTactic { case _ => invalid("Could not infer a universally quantified pivot from premise and conclusion.") } else - invalid("Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ.") + invalid("Left-hand side of conclusion + φ[t/x] is not the same as left-hand side of premise + ∀x. φ.") else if (instantiatedPivot.isEmpty) Weakening.asSCProof(bot, premises, currentProof) else if (instantiatedPivot.tail.isEmpty) { // go through conclusion to find a matching quantified formula @@ -509,7 +509,7 @@ object BasicStepTactic { } } else - invalid("Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ.") + invalid("Left-hand side of conclusion + φ[t/x] is not the same as left-hand side of premise + ∀x. φ.") } } @@ -550,9 +550,9 @@ object BasicStepTactic { else if ((bot.left union bot.right).exists(_.freeVariables.contains(x))) invalid("The variable x must not be free in the resulting sequent.") else if (!isSameSet(bot.right, premiseSequent.right)) - invalid("Right-hand side of conclusion must be the same as right-hand side of premise") + invalid("Right-hand side of conclusion is not the same as right-hand side of premise") else if (!isSameSet(bot.left + phi, premiseSequent.left + quantified)) - invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ") + invalid("Left-hand side of conclusion + φ is not the same as left-hand side of premise + ∃x. φ") else SC.LeftExists(bot, premises(0), phi, x) } @@ -588,14 +588,14 @@ object BasicStepTactic { } } else - invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") + invalid("Left-hand side of conclusion + φ is not the same as left-hand side of premise + ∃x. φ.") else if (pivot.tail.isEmpty) pivot.head match { case BinderFormula(Exists, x, phi) => LeftExists(phi, x).asSCProof(bot, premises, currentProof) case _ => invalid("Could not infer an existentially quantified pivot from premise and conclusion.") } else - invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") + invalid("Left-hand side of conclusion + φ is not the same as left-hand side of premise + ∃x. φ.") } } @@ -631,15 +631,15 @@ object BasicStepTactic { if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.right, premiseSequent.right)) - invalid("Right-hand side of conclusion must be the same as right-hand side of premise.") + invalid("Right-hand side of conclusion is not the same as right-hand side of premise.") else if (!isSameSet(bot.left + instantiated, premiseSequent.left + quantified)) - invalid("Left-hand side of conclusion + ∃y.∀x. (x=y) ↔ φ must be the same as left-hand side of premise + ∃!x. φ.") + invalid("Left-hand side of conclusion + ∃y.∀x. (x=y) ↔ φ is not the same as left-hand side of premise + ∃!x. φ.") else SC.LeftExistsOne(bot, premises(0), phi, x) } } - case class LeftExistsOneWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object LeftExistsOneWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( this.asProofStepWithoutBot(premises).asProofStep(bot), @@ -662,21 +662,21 @@ object BasicStepTactic { case _ => ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Could not infer an existentially quantified pivot from premise and conclusion.") } } else - invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") + invalid("Left-hand side of conclusion + φ is not 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 _ => invalid("Could not infer an existentially quantified pivot from premise and conclusion.") } else - invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ.") + invalid("Left-hand side of conclusion + φ is not 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() + def apply() = LeftExistsOneWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -691,25 +691,45 @@ object BasicStepTactic { * Γ, Σ |- φ∧ψ∧..., Π, Δ * </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 class RightAnd(conjuncts: Seq[Formula]) extends ProofStepWithoutBotNorPrem(-1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequents = premises.map(currentProof.getSequent(_)) + lazy val conjunction = ConnectorFormula(And, conjuncts) + + if (premises.length == 0) + invalid(s"Premises expected, ${premises.length} received.") + else if (!isSameSet(bot.left, premiseSequents.map(_.left).reduce(_ union _))) + invalid("Left-hand side of conclusion is not the union of the left-hand sides of the premises.") + else if (!isSameSet(conjuncts.foldLeft(bot.right)(_ + _), premiseSequents.map(_.right).reduce(_ union _) + conjunction)) + invalid("Right-hand side of conclusion + conjuncts is not the same as the union of the right-hand sides of the premises + φ∧ψ....") + else + SC.RightAnd(bot, premises, conjuncts) + } } 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)) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequents = premises.map(currentProof.getSequent(_)) + lazy val pivots = premiseSequents.map(_.right.diff(bot.right)) - if (pivots.exists(_.isEmpty)) - SC.Weakening(bot, premises(pivots.indexWhere(_.isEmpty))) + if (premises.length == 0) + invalid(s"Premises expected, ${premises.length} received.") + else if (pivots.exists(_.isEmpty)) + Weakening.asSCProof(bot, Seq(premises(pivots.indexWhere(_.isEmpty))), currentProof) else if (pivots.forall(_.tail.isEmpty)) - SC.RightAnd(bot, premises, pivots.map(_.head)) + RightAnd(pivots.map(_.head)).asSCProof(bot, premises, currentProof) 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 +φ∧ψ." - ) + invalid("Right-hand side of conclusion + φ + ψ is not the same as the union of the right-hand sides of the premises +φ∧ψ.") } } @@ -731,40 +751,64 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val phiAndPsi = ConnectorFormula(Or, Seq(phi, psi)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left, premiseSequent.left)) + invalid("Left-hand side of the premise is not the same as the left-hand side of the conclusion.") + else if ( + !isSameSet(bot.right + phi, premiseSequent.right + phiAndPsi) && + !isSameSet(bot.right + psi, premiseSequent.right + phiAndPsi) && + !isSameSet(bot.right + phi + psi, premiseSequent.right + phiAndPsi) + ) + invalid("Right-hand side of premise + φ∧ψ is not the same as right-hand side of conclusion + either φ, ψ or both.") + else + SC.RightOr(bot, premises(0), phi, psi) + } } - case class RightOrWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = bot.right.diff(premiseSequent.right) - if (!pivot.isEmpty && pivot.tail.isEmpty) + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else 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) + RightOr(phi, psi).asSCProof(bot, premises, currentProof) 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.") + RightOr(psi, phi).asSCProof(bot, premises, currentProof) + case _ => invalid("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)) + Rewrite.asSCProof(bot, premises, currentProof) 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." - ) + invalid("Right-hand side of conclusion + φ∧ψ is not the 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() + def apply() = RightOrWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -779,30 +823,53 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val implication = ConnectorFormula(Implies, Seq(phi, psi)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left + phi, premiseSequent.left)) + invalid("Left-hand side of conclusion + φ is not the same as left-hand side of premise.") + else if (!isSameSet(bot.right + psi, premiseSequent.right + implication)) + invalid("Right-hand side of conclusion + ψ is not the same as right-hand side of premise + φ→ψ.") + else + SC.RightImplies(bot, premises(0), phi, psi) + } } - case class RightImpliesWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val leftPivot = premiseSequent.left.diff(bot.left) + lazy val rightPivot = premiseSequent.right.diff(bot.right) - if ( + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if ( !leftPivot.isEmpty && leftPivot.tail.isEmpty && !rightPivot.isEmpty && rightPivot.tail.isEmpty ) - SC.RightImplies(bot, premises(0), leftPivot.head, rightPivot.head) + RightImplies(leftPivot.head, rightPivot.head).asSCProof(bot, premises, currentProof) else - ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Right-hand side of conclusion + ψ must be same as right-hand side of premise + φ→ψ.") + invalid("Right-hand side of conclusion + ψ is not the 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() + def apply() = RightImpliesWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -817,34 +884,57 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val leftSequent = currentProof.getSequent(premises(0)) + lazy val rightSequent = currentProof.getSequent(premises(1)) + lazy val implication = ConnectorFormula(Iff, Seq(phi, psi)) + lazy val impLeft = ConnectorFormula(Implies, Seq(phi, psi)) + lazy val impRight = ConnectorFormula(Implies, Seq(psi, phi)) + + if (premises.length != 2) + invalid(s"Two premises expected, ${premises.length} received.") + else if (!isSameSet(bot.left, leftSequent.left union rightSequent.left)) + invalid("Left-hand side of conclusion is not the union of the left-hand sides of the premises.") + else if (!isSameSet(bot.right + impLeft + impRight, leftSequent.right union rightSequent.right + implication)) + invalid("Right-hand side of conclusion + φ→ψ + ψ→φ is not the same as the union of the right-hand sides of the premises + φ↔ψ.") + else + SC.RightIff(bot, premises(0), premises(1), phi, psi) + } } - case class RightIffWithoutFormula() extends ProofStepWithoutBotNorPrem(2) { + case object 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) - if (pivot.isEmpty) - SC.Weakening(bot, premises(0)) + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = premiseSequent.right.diff(bot.right) + + if (premises.length != 2) + invalid(s"Two premises expected, ${premises.length} received.") + else if (pivot.isEmpty) + Weakening.asSCProof(bot, Seq(premises(0)), currentProof) 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.") + case ConnectorFormula(Implies, Seq(phi, psi)) => RightIff(phi, psi).asSCProof(bot, premises, currentProof) + case _ => invalid("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 φ↔ψ." - ) + invalid("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() + def apply() = RightIffWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -853,27 +943,50 @@ object BasicStepTactic { /** * <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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val negation = ConnectorFormula(Neg, Seq(phi)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left + phi, premiseSequent.left)) + invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise.") + else if (!isSameSet(bot.right, premiseSequent.right + negation)) + invalid("Right-hand side of conclusion must be the same as right-hand side of premise + ¬φ.") + else + SC.RightNot(bot, premises(0), phi) + } } - case class RightNotWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) - if (pivot.isEmpty) - SC.Weakening(bot, premises(0)) + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = premiseSequent.left.diff(bot.left) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (pivot.isEmpty) + Weakening.asSCProof(bot, Seq(premises(0)), currentProof) else if (pivot.tail.isEmpty) - SC.RightNot(bot, premises(0), pivot.head) + RightNot(pivot.head).asSCProof(bot, premises, currentProof) else - ProofStepJudgement.InvalidProofStep(this.asProofStepWithoutBot(premises).asProofStep(bot), "Left-hand side of conclusion + φ must be the same as left-hand side of premise.") + invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise.") } } @@ -881,7 +994,7 @@ object BasicStepTactic { case object RightNot extends ProofStepWithoutBotNorPrem(1) { // default construction: // def apply(phi: Formula) = new RightNot(phi) - def apply() = new RightNotWithoutFormula() + def apply() = RightNotWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -896,18 +1009,43 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val quantified = BinderFormula(Forall, x, phi) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if ((bot.left union bot.right).exists(_.freeVariables.contains(x))) + invalid("The variable x is free in the resulting sequent.") + else if (!isSameSet(bot.left, premiseSequent.left)) + invalid("Left-hand side of conclusion is not the same as left-hand side of premise.") + else if (!isSameSet(bot.right + phi, premiseSequent.right + quantified)) + invalid("Right-hand side of conclusion + φ is not the same as right-hand side of premise + ∀x. φ.") + else + SC.RightForall(bot, premises(0), phi, x) + } } - case class RightForallWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy 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)) + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (pivot.isEmpty) + if (instantiatedPivot.isEmpty) Rewrite.asSCProof(bot, Seq(premises(0)), currentProof) else if (instantiatedPivot.tail.isEmpty) { val in: Formula = instantiatedPivot.head val quantifiedPhi: Option[Formula] = bot.right.find(f => @@ -918,24 +1056,24 @@ object BasicStepTactic { ) 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.") + case Some(BinderFormula(Forall, x, phi)) => RightForall(phi, x).asSCProof(bot, premises, currentProof) + case _ => invalid("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 invalid("Right-hand side of conclusion + φ is not 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.") + case BinderFormula(Forall, x, phi) => RightForall(phi, x).asSCProof(bot, premises, currentProof) + case _ => invalid("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. φ.") + invalid("Right-hand side of conclusion + φ is not 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() + def apply() = RightForallWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -948,32 +1086,52 @@ object BasicStepTactic { * ------------------- * Γ |- ∃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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val quantified = BinderFormula(Exists, x, phi) + lazy val instantiated = substituteVariables(phi, Map(x -> t)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left, premiseSequent.left)) + invalid("Left-hand side of conclusion is not the same as left-hand side of premise") + else if (!isSameSet(bot.right + instantiated, premiseSequent.right + quantified)) + invalid("Right-hand side of conclusion + φ[t/x] is not the same as right-hand side of premise + ∃x. φ") + else + 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = bot.right.diff(premiseSequent.right) lazy val instantiatedPivot = premiseSequent.right.diff(bot.right) - if (!pivot.isEmpty) + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else 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.") + case BinderFormula(Exists, x, phi) => RightExists(phi, x, t).asSCProof(bot, premises, currentProof) + case _ => invalid("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)) + invalid("Right-hand side of conclusion + φ[t/x] is not the same as right-hand side of premise + ∀x. φ.") + else if (instantiatedPivot.isEmpty) Weakening.asSCProof(bot, premises, currentProof) else if (instantiatedPivot.tail.isEmpty) { // go through conclusion to find a matching quantified formula @@ -986,14 +1144,11 @@ object BasicStepTactic { ) 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.") + case Some(BinderFormula(Exists, x, phi)) => RightExists(phi, x, t).asSCProof(bot, premises, currentProof) + case _ => invalid("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. φ." - ) + invalid("Right-hand side of conclusion + φ[t/x] is not the same as right-hand side of premise + ∀x. φ.") } } @@ -1019,41 +1174,66 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val y = VariableLabel(freshId(phi.freeVariables.map(_.id) + x.id, "y")) + lazy val instantiated = BinderFormula(Exists, y, BinderFormula(Forall, x, ConnectorFormula(Iff, List(PredicateFormula(equality, List(VariableTerm(x), VariableTerm(y))), phi)))) + lazy val quantified = BinderFormula(ExistsOne, x, phi) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left, premiseSequent.left)) + invalid("Left-hand side of conclusion is not the same as left-hand side of premise.") + else if (!isSameSet(bot.right + instantiated, premiseSequent.right + quantified)) + invalid("Right-hand side of conclusion + ∃y.∀x. (x=y) ↔ φ is not the same as right-hand side of premise + ∃!x. φ.") + else + SC.RightExistsOne(bot, premises(0), phi, x) + } } - case class RightExistsOneWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { + case object 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) + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = bot.right.diff(premiseSequent.right) lazy val instantiatedPivot = premiseSequent.right.diff(bot.right) - if (pivot.isEmpty) + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (pivot.isEmpty) if (instantiatedPivot.isEmpty) - SC.Rewrite(bot, premises(0)) + Rewrite.asSCProof(bot, premises, currentProof) 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.") + case BinderFormula(Exists, _, BinderFormula(Forall, x, ConnectorFormula(Iff, Seq(_, phi)))) => RightExistsOne(phi, x).asSCProof(bot, premises, currentProof) + case _ => invalid("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. φ.") + invalid("Right-hand side of conclusion + φ is not 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.") + case BinderFormula(ExistsOne, x, phi) => RightExistsOne(phi, x).asSCProof(bot, premises, currentProof) + case _ => invalid("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. φ.") + invalid("Right-hand side of conclusion + φ is not 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() + def apply() = RightExistsOneWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -1069,8 +1249,23 @@ object BasicStepTactic { * </pre> */ case object Weakening extends ProofStepWithoutBotNorPrem(1) { - def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = - SC.Weakening(bot, premises(0)) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSubset(premiseSequent.left, bot.left)) + invalid("Left-hand side of conclusion is not the same as left-hand side of premise.") + else if (!isSubset(premiseSequent.right, bot.right)) + invalid("Left-hand side of premise is not a subset of left-hand side of conclusion.") + else + SC.Weakening(bot, premises(0)) + } } // Equality Rules @@ -1081,20 +1276,56 @@ object BasicStepTactic { * Γ |- Δ * </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 LeftRefl(phi: Formula) extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left + phi, premiseSequent.left)) + invalid("Left-hand sides of the conclusion + φ is not the same as left-hand side of the premise.") + else if (!isSameSet(bot.right, premiseSequent.right)) + invalid("Right-hand side of the premise is not the same as the right-hand side of the conclusion.") + else + phi match { + case PredicateFormula(`equality`, Seq(left, right)) => + if (isSame(left, right)) + SC.LeftRefl(bot, premises(0), phi) + else + invalid("φ is not an instance of reflexivity.") + case _ => invalid("φ is not an equality.") + } + } } - case class LeftReflWithoutFormula() extends ProofStepWithoutBotNorPrem(1) { - def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = - SC.Rewrite(bot, premises(0)) + case object LeftReflWithoutFormula extends ProofStepWithoutBotNorPrem(1) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val pivot = premiseSequent.left.diff(bot.left) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if(!pivot.isEmpty && pivot.tail.isEmpty) + LeftRefl(pivot.head).asSCProof(bot, premises, currentProof) + else + invalid("Could not infer an equality as pivot from premise and conclusion.") + } } case object LeftRefl extends ProofStepWithoutBotNorPrem(1) { // default construction: // def apply(fa: Formula) = new LeftRefl(fa) - def apply() = new LeftReflWithoutFormula() + def apply() = LeftReflWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = @@ -1108,20 +1339,63 @@ object BasicStepTactic { * |- 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 RightRefl(phi: Formula) extends ProofStepWithoutBotNorPrem(0) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + if (premises.length != 0) + invalid(s"No premises expected, ${premises.length} received.") + else if (!contains(bot.right, phi)) + invalid("Right-hand side of conclusion does not contain φ.") + else + phi match { + case PredicateFormula(`equality`, Seq(left, right)) => + if (isSame(left, right)) + SC.RightRefl(bot, phi) + else + invalid("φ is not an instance of reflexivity.") + case _ => invalid("φ is not an equality.") + } + } } - case class RightReflWithoutFormula() extends ProofStepWithoutBotNorPrem(0) { - def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = - SC.RewriteTrue(bot) + case object RightReflWithoutFormula extends ProofStepWithoutBotNorPrem(0) { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + if (premises.length != 0) + invalid(s"No premises expected, ${premises.length} received.") + else if(bot.right.isEmpty) + invalid("Right-hand side of conclusion does not contain an instance of reflexivity.") + else { + // go through conclusion to see if you can find an reflexive formula + val pivot: Option[Formula] = bot.right.find(f => + f match { + case PredicateFormula(`equality`, Seq(l, r)) => isSame(l, r) + case _ => false + } + ) + + pivot match { + case Some(phi) => RightRefl(phi).asSCProof(bot, premises, currentProof) + case _ => invalid("Could not infer an equality as pivot from conclusion.") + } + + } + + } } case object RightRefl extends ProofStepWithoutBotNorPrem(0) { // default construction: // def apply(fa: Formula) = new RightRefl(fa) - def apply() = new RightReflWithoutFormula() + def apply() = RightReflWithoutFormula // usage without an argument list def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = -- GitLab From 9b873594e1c8a59095b46c056223dc8e0ebf9023 Mon Sep 17 00:00:00 2001 From: Sankalp Gambhir <sankalp.gambhir47@gmail.com> Date: Wed, 2 Nov 2022 12:44:01 +0100 Subject: [PATCH 4/6] Proof checking for substitution rules --- .../lisa/utils/tactics/BasicStepTactic.scala | 104 ++++++++++++++++-- 1 file changed, 96 insertions(+), 8 deletions(-) diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala index c1702bef..9fd096e3 100644 --- a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala @@ -1410,8 +1410,30 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val (s_es, t_es) = equals.unzip + lazy val phi_s = lambdaPhi(s_es) + lazy val phi_t = lambdaPhi(t_es) + lazy val equalities = equals map { case (s, t) => PredicateFormula(equality, Seq(s, t)) } + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.right, premiseSequent.right)) + invalid("Right-hand side of the premise is not the same as the right-hand side of the conclusion.") + else if ( + !isSameSet(bot.left + phi_s, premiseSequent.left ++ equalities + phi_t) && + !isSameSet(bot.left + phi_t, premiseSequent.left ++ equalities + phi_s) + ) + invalid("Left-hand side of the conclusion + φ(s_) is not the same as left-hand side of the premise + (s=t)_ + φ(t_) (or with s_ and t_ swapped).") + else + SC.LeftSubstEq(bot, premises(0), equals, lambdaPhi) + } } /** @@ -1422,8 +1444,30 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val (s_es, t_es) = equals.unzip + lazy val phi_s = lambdaPhi(s_es) + lazy val phi_t = lambdaPhi(t_es) + lazy val equalities = equals map { case (s, t) => PredicateFormula(equality, Seq(s, t)) } + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left, premiseSequent.left ++ equalities)) + invalid("Left-hand side of the conclusion is not the same as the left-hand side of the premise + (s=t)_.") + else if ( + !isSameSet(bot.left + phi_s, premiseSequent.left + phi_t) && + !isSameSet(bot.left + phi_t, premiseSequent.left + phi_s) + ) + invalid("Right-hand side of the conclusion + φ(s_) is not the same as right-hand side of the premise + φ(t_) (or with s_ and t_ swapped).") + else + SC.RightSubstEq(bot, premises(0), equals, lambdaPhi) + } } /** @@ -1434,8 +1478,30 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val (psi_es, tau_es) = equals.unzip + lazy val phi_psi = lambdaPhi(psi_es) + lazy val phi_tau = lambdaPhi(tau_es) + lazy val implications = equals map { case (s, t) => ConnectorFormula(Iff, Seq(s, t)) } + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.right, premiseSequent.right)) + invalid("Right-hand side of the premise is not the same as the right-hand side of the conclusion.") + else if ( + !isSameSet(bot.left + phi_psi, premiseSequent.left ++ implications + phi_tau) && + !isSameSet(bot.left + phi_tau, premiseSequent.left ++ implications + phi_psi) + ) + invalid("Left-hand side of the conclusion + φ(ψ_) is not the same as left-hand side of the premise + (ψ ↔ τ)_ + φ(τ_) (or with ψ_ and τ_ swapped).") + else + SC.LeftSubstIff(bot, premises(0), equals, lambdaPhi) + } } /** @@ -1446,8 +1512,30 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + lazy val (psi_es, tau_es) = equals.unzip + lazy val phi_psi = lambdaPhi(psi_es) + lazy val phi_tau = lambdaPhi(tau_es) + lazy val implications = equals map { case (s, t) => ConnectorFormula(Iff, Seq(s, t)) } + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left, premiseSequent.left ++ implications)) + invalid("Left-hand side of the conclusion is not the same as the left-hand side of the premise + (ψ ↔ τ)_.") + else if ( + !isSameSet(bot.left + phi_psi, premiseSequent.left + phi_tau) && + !isSameSet(bot.left + phi_tau, premiseSequent.left + phi_psi) + ) + invalid("Right-hand side of the conclusion + φ(ψ_) is not the same as right-hand side of the premise + φ(τ_) (or with ψ_ and τ_ swapped).") + else + SC.RightSubstIff(bot, premises(0), equals, lambdaPhi) + } } /** -- GitLab From 3295ca673bfb88f481f0b89f34169662bef802cf Mon Sep 17 00:00:00 2001 From: Sankalp Gambhir <sankalp.gambhir47@gmail.com> Date: Wed, 2 Nov 2022 15:08:23 +0100 Subject: [PATCH 5/6] Checking for abstracted instantiation steps --- .../lisa/utils/tactics/BasicStepTactic.scala | 66 +++++++++++++++---- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala index 9fd096e3..b66cea87 100644 --- a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala @@ -961,16 +961,16 @@ object BasicStepTactic { if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.left + phi, premiseSequent.left)) - invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise.") + invalid("Left-hand side of conclusion + φ is not the same as left-hand side of premise.") else if (!isSameSet(bot.right, premiseSequent.right + negation)) - invalid("Right-hand side of conclusion must be the same as right-hand side of premise + ¬φ.") + invalid("Right-hand side of conclusion is not the same as right-hand side of premise + ¬φ.") else SC.RightNot(bot, premises(0), phi) } } case object RightNotWithoutFormula extends ProofStepWithoutBotNorPrem(1) { - def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( this.asProofStepWithoutBot(premises).asProofStep(bot), msg @@ -986,7 +986,7 @@ object BasicStepTactic { else if (pivot.tail.isEmpty) RightNot(pivot.head).asSCProof(bot, premises, currentProof) else - invalid("Left-hand side of conclusion + φ must be the same as left-hand side of premise.") + invalid("Left-hand side of conclusion + φ is not the same as left-hand side of premise.") } } @@ -1546,8 +1546,23 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left, premiseSequent.left.map(instantiateTermSchemas(_, insts)))) + invalid("Left-hand side of premise instantiated with the map 'insts' is not the same as left-hand side of conclusion.") + else if (!isSameSet(bot.right, premiseSequent.right.map(instantiateTermSchemas(_, insts)))) + invalid("Right-hand side of premise instantiated with the map 'insts' is not the same as right-hand side of conclusion.") + else + SC.InstFunSchema(bot, premises(0), insts) + } } /** @@ -1558,16 +1573,43 @@ object BasicStepTactic { * </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) + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + + lazy val premiseSequent = currentProof.getSequent(premises(0)) + + if (premises.length != 1) + invalid(s"One premise expected, ${premises.length} received.") + else if (!isSameSet(bot.left, premiseSequent.left.map(instantiatePredicateSchemas(_, insts)))) + invalid("Left-hand side of premise instantiated with the map 'insts' is not the same as left-hand side of conclusion.") + else if (!isSameSet(bot.right, premiseSequent.right.map(instantiatePredicateSchemas(_, insts)))) + invalid("Right-hand side of premise instantiated with the map 'insts' is not the same as right-hand side of conclusion.") + else + 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) - } + def asSCProof(currentProof: Library#Proof): ProofStepJudgement = { + def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( + this, + msg + ) + + lazy val premiseSequents = premises.map(currentProof.getSequent(_)) + lazy val invalidPremise = premises.zipWithIndex.find( (no, p) => !SC.isSameSequent(premiseSequents(no), sp.imports(p))) + + if (premises.length != sp.imports.length) + invalid(s"Subproof expected ${sp.imports.length} premises, ${premises.length} received.") + else if (!invalidPremise.isEmpty) + invalid(s"Premise number ${invalidPremise.get._1} (refering to step ${invalidPremise.get}) is not the same as import number ${invalidPremise.get._1} of the subproof.") + else + SC.SCSubproof(sp, premises) + } } } -- GitLab From 5149ae2a85d688bba20f2d26e6370c22e2232e32 Mon Sep 17 00:00:00 2001 From: Sankalp Gambhir <sankalp.gambhir47@gmail.com> Date: Wed, 2 Nov 2022 15:10:56 +0100 Subject: [PATCH 6/6] scalafmt --- .../lisa/utils/tactics/BasicStepTactic.scala | 396 +++++++++--------- 1 file changed, 192 insertions(+), 204 deletions(-) diff --git a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala index b66cea87..23e9e616 100644 --- a/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala +++ b/lisa-utils/src/main/scala/lisa/utils/tactics/BasicStepTactic.scala @@ -14,9 +14,9 @@ object BasicStepTactic { case object Hypothesis extends ProofStepWithoutBotNorPrem(0) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val intersectedPivot = bot.left.intersect(bot.right) @@ -32,10 +32,10 @@ object BasicStepTactic { case object Rewrite extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) - + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!SC.isSameSequent(bot, currentProof.getSequent(premises(0)))) @@ -55,9 +55,9 @@ object BasicStepTactic { case class Cut(phi: Formula) extends ProofStepWithoutBotNorPrem(2) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val leftSequent = currentProof.getSequent(premises(0)) lazy val rightSequent = currentProof.getSequent(premises(1)) @@ -80,9 +80,9 @@ object BasicStepTactic { case object CutWithoutFormula extends ProofStepWithoutBotNorPrem(2) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val leftSequent = currentProof.getSequent(premises(0)) lazy val rightSequent = currentProof.getSequent(premises(1)) @@ -126,9 +126,9 @@ object BasicStepTactic { case class LeftAnd(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val phiAndPsi = ConnectorFormula(And, Seq(phi, psi)) @@ -151,10 +151,10 @@ object BasicStepTactic { case object LeftAndWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) - + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) + lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = bot.left.diff(premiseSequent.left) @@ -170,11 +170,11 @@ object BasicStepTactic { case _ => invalid("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)) - Rewrite.asSCProof(bot, premises, currentProof) - else - invalid("Left-hand side of premise + φ∧ψ is not the same as left-hand side of conclusion + either φ, ψ or both.") + // try a rewrite, if it works, go ahead with it, otherwise malformed + if (SC.isSameSequent(premiseSequent, bot)) + Rewrite.asSCProof(bot, premises, currentProof) + else + invalid("Left-hand side of premise + φ∧ψ is not the same as left-hand side of conclusion + either φ, ψ or both.") } } @@ -198,13 +198,12 @@ object BasicStepTactic { case class LeftOr(disjuncts: Seq[Formula]) extends ProofStepWithoutBotNorPrem(-1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequents = premises.map(currentProof.getSequent(_)) lazy val disjunction = ConnectorFormula(Or, disjuncts) - if (premises.length == 0) invalid(s"Premises expected, ${premises.length} received.") @@ -219,9 +218,9 @@ object BasicStepTactic { case object LeftOrWithoutFormula extends ProofStepWithoutBotNorPrem(-1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequents = premises.map(currentProof.getSequent(_)) lazy val pivots = premiseSequents.map(_.left.diff(bot.left)) @@ -258,14 +257,13 @@ object BasicStepTactic { case class LeftImplies(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(2) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val leftSequent = currentProof.getSequent(premises(0)) lazy val rightSequent = currentProof.getSequent(premises(1)) lazy val implication = ConnectorFormula(Implies, Seq(phi, psi)) - if (premises.length != 2) invalid(s"Two premises expected, ${premises.length} received.") @@ -281,9 +279,9 @@ object BasicStepTactic { case object LeftImpliesWithoutFormula extends ProofStepWithoutBotNorPrem(2) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val leftSequent = currentProof.getSequent(premises(0)) lazy val rightSequent = currentProof.getSequent(premises(1)) @@ -323,25 +321,24 @@ object BasicStepTactic { case class LeftIff(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val implication = ConnectorFormula(Iff, Seq(phi, psi)) lazy val impLeft = ConnectorFormula(Implies, Seq(phi, psi)) lazy val impRight = ConnectorFormula(Implies, Seq(psi, phi)) - if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.right, premiseSequent.right)) invalid("Right-hand side of premise is not the same as right-hand side of conclusion.") else if ( - !isSameSet(bot.left + impLeft, premiseSequent.left + implication) && - !isSameSet(bot.left + impRight, premiseSequent.left + implication) && - !isSameSet(bot.left + impLeft + impRight, premiseSequent.left + implication) - ) + !isSameSet(bot.left + impLeft, premiseSequent.left + implication) && + !isSameSet(bot.left + impRight, premiseSequent.left + implication) && + !isSameSet(bot.left + impLeft + impRight, premiseSequent.left + implication) + ) invalid("Left-hand side of premise + φ↔ψ is not the same as left-hand side of conclusion + either φ→ψ, ψ→φ or both.") else SC.LeftIff(bot, premises(0), phi, psi) @@ -351,9 +348,9 @@ object BasicStepTactic { case object LeftIffWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = premiseSequent.left.diff(bot.left) @@ -390,13 +387,13 @@ object BasicStepTactic { case class LeftNot(phi: Formula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val negation = ConnectorFormula(Neg, Seq(phi)) - + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.right + phi, premiseSequent.right)) @@ -411,9 +408,9 @@ object BasicStepTactic { case object LeftNotWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = premiseSequent.right.diff(bot.right) @@ -451,14 +448,14 @@ object BasicStepTactic { case class LeftForall(phi: Formula, x: VariableLabel, t: Term) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val quantified = BinderFormula(Forall, x, phi) lazy val instantiated = substituteVariables(phi, Map(x -> t)) - + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.right, premiseSequent.right)) @@ -473,16 +470,15 @@ object BasicStepTactic { case class LeftForallWithoutFormula(t: Term) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = bot.left.diff(premiseSequent.left) lazy val instantiatedPivot = premiseSequent.left.diff(bot.left) - if (premises.length != 1) - invalid(s"One premise expected, ${premises.length} received.") + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!pivot.isEmpty) if (pivot.tail.isEmpty) pivot.head match { @@ -507,9 +503,7 @@ object BasicStepTactic { case Some(BinderFormula(Forall, x, phi)) => LeftForall(phi, x, t).asSCProof(bot, premises, currentProof) case _ => invalid("Could not infer a universally quantified pivot from premise and conclusion.") } - } - else - invalid("Left-hand side of conclusion + φ[t/x] is not the same as left-hand side of premise + ∀x. φ.") + } else invalid("Left-hand side of conclusion + φ[t/x] is not the same as left-hand side of premise + ∀x. φ.") } } @@ -538,13 +532,13 @@ object BasicStepTactic { case class LeftExists(phi: Formula, x: VariableLabel) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val quantified = BinderFormula(Exists, x, phi) - + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if ((bot.left union bot.right).exists(_.freeVariables.contains(x))) @@ -561,9 +555,9 @@ object BasicStepTactic { case object LeftExistsWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = bot.left.diff(premiseSequent.left) @@ -586,9 +580,7 @@ object BasicStepTactic { case Some(BinderFormula(Exists, x, phi)) => LeftExists(phi, x).asSCProof(bot, premises, currentProof) case _ => invalid("Could not infer an existensially quantified pivot from premise and conclusion.") } - } - else - invalid("Left-hand side of conclusion + φ is not the same as left-hand side of premise + ∃x. φ.") + } else invalid("Left-hand side of conclusion + φ is not the same as left-hand side of premise + ∃x. φ.") else if (pivot.tail.isEmpty) pivot.head match { case BinderFormula(Exists, x, phi) => LeftExists(phi, x).asSCProof(bot, premises, currentProof) @@ -619,9 +611,9 @@ object BasicStepTactic { case class LeftExistsOne(phi: Formula, x: VariableLabel) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val y = VariableLabel(freshId(phi.freeVariables.map(_.id) + x.id, "y")) @@ -642,9 +634,9 @@ object BasicStepTactic { case object LeftExistsOneWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = bot.left.diff(premiseSequent.left) @@ -694,9 +686,9 @@ object BasicStepTactic { case class RightAnd(conjuncts: Seq[Formula]) extends ProofStepWithoutBotNorPrem(-1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequents = premises.map(currentProof.getSequent(_)) lazy val conjunction = ConnectorFormula(And, conjuncts) @@ -714,9 +706,9 @@ object BasicStepTactic { case object RightAndWithoutFormula extends ProofStepWithoutBotNorPrem(-1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequents = premises.map(currentProof.getSequent(_)) lazy val pivots = premiseSequents.map(_.right.diff(bot.right)) @@ -753,9 +745,9 @@ object BasicStepTactic { case class RightOr(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val phiAndPsi = ConnectorFormula(Or, Seq(phi, psi)) @@ -778,9 +770,9 @@ object BasicStepTactic { case object RightOrWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = bot.right.diff(premiseSequent.right) @@ -825,13 +817,13 @@ object BasicStepTactic { case class RightImplies(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val implication = ConnectorFormula(Implies, Seq(phi, psi)) - + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.left + phi, premiseSequent.left)) @@ -846,9 +838,9 @@ object BasicStepTactic { case object RightImpliesWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val leftPivot = premiseSequent.left.diff(bot.left) @@ -886,16 +878,16 @@ object BasicStepTactic { case class RightIff(phi: Formula, psi: Formula) extends ProofStepWithoutBotNorPrem(2) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val leftSequent = currentProof.getSequent(premises(0)) lazy val rightSequent = currentProof.getSequent(premises(1)) lazy val implication = ConnectorFormula(Iff, Seq(phi, psi)) lazy val impLeft = ConnectorFormula(Implies, Seq(phi, psi)) lazy val impRight = ConnectorFormula(Implies, Seq(psi, phi)) - + if (premises.length != 2) invalid(s"Two premises expected, ${premises.length} received.") else if (!isSameSet(bot.left, leftSequent.left union rightSequent.left)) @@ -910,9 +902,9 @@ object BasicStepTactic { case object RightIffWithoutFormula extends ProofStepWithoutBotNorPrem(2) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = premiseSequent.right.diff(bot.right) @@ -951,13 +943,13 @@ object BasicStepTactic { case class RightNot(phi: Formula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val negation = ConnectorFormula(Neg, Seq(phi)) - + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.left + phi, premiseSequent.left)) @@ -970,11 +962,11 @@ object BasicStepTactic { } case object RightNotWithoutFormula extends ProofStepWithoutBotNorPrem(1) { - def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { + def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = premiseSequent.left.diff(bot.left) @@ -1011,13 +1003,13 @@ object BasicStepTactic { case class RightForall(phi: Formula, x: VariableLabel) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val quantified = BinderFormula(Forall, x, phi) - + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if ((bot.left union bot.right).exists(_.freeVariables.contains(x))) @@ -1034,9 +1026,9 @@ object BasicStepTactic { case object RightForallWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = bot.right.diff(premiseSequent.right) @@ -1091,14 +1083,14 @@ object BasicStepTactic { case class RightExists(phi: Formula, x: VariableLabel, t: Term) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val quantified = BinderFormula(Exists, x, phi) lazy val instantiated = substituteVariables(phi, Map(x -> t)) - + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!isSameSet(bot.left, premiseSequent.left)) @@ -1113,16 +1105,15 @@ object BasicStepTactic { case class RightExistsWithoutFormula(t: Term) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = bot.right.diff(premiseSequent.right) lazy val instantiatedPivot = premiseSequent.right.diff(bot.right) - if (premises.length != 1) - invalid(s"One premise expected, ${premises.length} received.") + if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") else if (!pivot.isEmpty) if (pivot.tail.isEmpty) pivot.head match { @@ -1147,8 +1138,7 @@ object BasicStepTactic { case Some(BinderFormula(Exists, x, phi)) => RightExists(phi, x, t).asSCProof(bot, premises, currentProof) case _ => invalid("Could not infer an existentially quantified pivot from premise and conclusion.") } - } else - invalid("Right-hand side of conclusion + φ[t/x] is not the same as right-hand side of premise + ∀x. φ.") + } else invalid("Right-hand side of conclusion + φ[t/x] is not the same as right-hand side of premise + ∀x. φ.") } } @@ -1176,9 +1166,9 @@ object BasicStepTactic { case class RightExistsOne(phi: Formula, x: VariableLabel) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val y = VariableLabel(freshId(phi.freeVariables.map(_.id) + x.id, "y")) @@ -1199,9 +1189,9 @@ object BasicStepTactic { case object RightExistsOneWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = bot.right.diff(premiseSequent.right) @@ -1251,9 +1241,9 @@ object BasicStepTactic { case object Weakening extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) @@ -1279,9 +1269,9 @@ object BasicStepTactic { case class LeftRefl(phi: Formula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) @@ -1293,10 +1283,10 @@ object BasicStepTactic { invalid("Right-hand side of the premise is not the same as the right-hand side of the conclusion.") else phi match { - case PredicateFormula(`equality`, Seq(left, right)) => - if (isSame(left, right)) + case PredicateFormula(`equality`, Seq(left, right)) => + if (isSame(left, right)) SC.LeftRefl(bot, premises(0), phi) - else + else invalid("φ is not an instance of reflexivity.") case _ => invalid("φ is not an equality.") } @@ -1306,16 +1296,16 @@ object BasicStepTactic { case object LeftReflWithoutFormula extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val pivot = premiseSequent.left.diff(bot.left) if (premises.length != 1) invalid(s"One premise expected, ${premises.length} received.") - else if(!pivot.isEmpty && pivot.tail.isEmpty) + else if (!pivot.isEmpty && pivot.tail.isEmpty) LeftRefl(pivot.head).asSCProof(bot, premises, currentProof) else invalid("Could not infer an equality as pivot from premise and conclusion.") @@ -1342,9 +1332,9 @@ object BasicStepTactic { case class RightRefl(phi: Formula) extends ProofStepWithoutBotNorPrem(0) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) if (premises.length != 0) invalid(s"No premises expected, ${premises.length} received.") @@ -1352,10 +1342,10 @@ object BasicStepTactic { invalid("Right-hand side of conclusion does not contain φ.") else phi match { - case PredicateFormula(`equality`, Seq(left, right)) => - if (isSame(left, right)) + case PredicateFormula(`equality`, Seq(left, right)) => + if (isSame(left, right)) SC.RightRefl(bot, phi) - else + else invalid("φ is not an instance of reflexivity.") case _ => invalid("φ is not an equality.") } @@ -1365,14 +1355,12 @@ object BasicStepTactic { case object RightReflWithoutFormula extends ProofStepWithoutBotNorPrem(0) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) - if (premises.length != 0) - invalid(s"No premises expected, ${premises.length} received.") - else if(bot.right.isEmpty) - invalid("Right-hand side of conclusion does not contain an instance of reflexivity.") + if (premises.length != 0) invalid(s"No premises expected, ${premises.length} received.") + else if (bot.right.isEmpty) invalid("Right-hand side of conclusion does not contain an instance of reflexivity.") else { // go through conclusion to see if you can find an reflexive formula val pivot: Option[Formula] = bot.right.find(f => @@ -1386,7 +1374,7 @@ object BasicStepTactic { case Some(phi) => RightRefl(phi).asSCProof(bot, premises, currentProof) case _ => invalid("Could not infer an equality as pivot from conclusion.") } - + } } @@ -1412,9 +1400,9 @@ object BasicStepTactic { case class LeftSubstEq(equals: List[(Term, Term)], lambdaPhi: LambdaTermFormula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val (s_es, t_es) = equals.unzip @@ -1427,9 +1415,9 @@ object BasicStepTactic { else if (!isSameSet(bot.right, premiseSequent.right)) invalid("Right-hand side of the premise is not the same as the right-hand side of the conclusion.") else if ( - !isSameSet(bot.left + phi_s, premiseSequent.left ++ equalities + phi_t) && - !isSameSet(bot.left + phi_t, premiseSequent.left ++ equalities + phi_s) - ) + !isSameSet(bot.left + phi_s, premiseSequent.left ++ equalities + phi_t) && + !isSameSet(bot.left + phi_t, premiseSequent.left ++ equalities + phi_s) + ) invalid("Left-hand side of the conclusion + φ(s_) is not the same as left-hand side of the premise + (s=t)_ + φ(t_) (or with s_ and t_ swapped).") else SC.LeftSubstEq(bot, premises(0), equals, lambdaPhi) @@ -1446,9 +1434,9 @@ object BasicStepTactic { case class RightSubstEq(equals: List[(Term, Term)], lambdaPhi: LambdaTermFormula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val (s_es, t_es) = equals.unzip @@ -1461,9 +1449,9 @@ object BasicStepTactic { else if (!isSameSet(bot.left, premiseSequent.left ++ equalities)) invalid("Left-hand side of the conclusion is not the same as the left-hand side of the premise + (s=t)_.") else if ( - !isSameSet(bot.left + phi_s, premiseSequent.left + phi_t) && - !isSameSet(bot.left + phi_t, premiseSequent.left + phi_s) - ) + !isSameSet(bot.left + phi_s, premiseSequent.left + phi_t) && + !isSameSet(bot.left + phi_t, premiseSequent.left + phi_s) + ) invalid("Right-hand side of the conclusion + φ(s_) is not the same as right-hand side of the premise + φ(t_) (or with s_ and t_ swapped).") else SC.RightSubstEq(bot, premises(0), equals, lambdaPhi) @@ -1480,9 +1468,9 @@ object BasicStepTactic { case class LeftSubstIff(equals: List[(Formula, Formula)], lambdaPhi: LambdaFormulaFormula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val (psi_es, tau_es) = equals.unzip @@ -1495,9 +1483,9 @@ object BasicStepTactic { else if (!isSameSet(bot.right, premiseSequent.right)) invalid("Right-hand side of the premise is not the same as the right-hand side of the conclusion.") else if ( - !isSameSet(bot.left + phi_psi, premiseSequent.left ++ implications + phi_tau) && - !isSameSet(bot.left + phi_tau, premiseSequent.left ++ implications + phi_psi) - ) + !isSameSet(bot.left + phi_psi, premiseSequent.left ++ implications + phi_tau) && + !isSameSet(bot.left + phi_tau, premiseSequent.left ++ implications + phi_psi) + ) invalid("Left-hand side of the conclusion + φ(ψ_) is not the same as left-hand side of the premise + (ψ ↔ τ)_ + φ(τ_) (or with ψ_ and τ_ swapped).") else SC.LeftSubstIff(bot, premises(0), equals, lambdaPhi) @@ -1514,9 +1502,9 @@ object BasicStepTactic { case class RightSubstIff(equals: List[(Formula, Formula)], lambdaPhi: LambdaFormulaFormula) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) lazy val (psi_es, tau_es) = equals.unzip @@ -1529,9 +1517,9 @@ object BasicStepTactic { else if (!isSameSet(bot.left, premiseSequent.left ++ implications)) invalid("Left-hand side of the conclusion is not the same as the left-hand side of the premise + (ψ ↔ τ)_.") else if ( - !isSameSet(bot.left + phi_psi, premiseSequent.left + phi_tau) && - !isSameSet(bot.left + phi_tau, premiseSequent.left + phi_psi) - ) + !isSameSet(bot.left + phi_psi, premiseSequent.left + phi_tau) && + !isSameSet(bot.left + phi_tau, premiseSequent.left + phi_psi) + ) invalid("Right-hand side of the conclusion + φ(ψ_) is not the same as right-hand side of the premise + φ(τ_) (or with ψ_ and τ_ swapped).") else SC.RightSubstIff(bot, premises(0), equals, lambdaPhi) @@ -1548,9 +1536,9 @@ object BasicStepTactic { case class InstFunSchema(insts: Map[SchematicTermLabel, LambdaTermTerm]) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) @@ -1575,9 +1563,9 @@ object BasicStepTactic { case class InstPredSchema(insts: Map[SchematicVarOrPredLabel, LambdaTermFormula]) extends ProofStepWithoutBotNorPrem(1) { def asSCProof(bot: Sequent, premises: Seq[Int], currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this.asProofStepWithoutBot(premises).asProofStep(bot), - msg - ) + this.asProofStepWithoutBot(premises).asProofStep(bot), + msg + ) lazy val premiseSequent = currentProof.getSequent(premises(0)) @@ -1596,12 +1584,12 @@ object BasicStepTactic { case class SCSubproof(sp: SCProof, premises: Seq[Int] = Seq.empty, display: Boolean = true) extends ProofStep { def asSCProof(currentProof: Library#Proof): ProofStepJudgement = { def invalid(msg: String) = ProofStepJudgement.InvalidProofStep( - this, - msg - ) + this, + msg + ) lazy val premiseSequents = premises.map(currentProof.getSequent(_)) - lazy val invalidPremise = premises.zipWithIndex.find( (no, p) => !SC.isSameSequent(premiseSequents(no), sp.imports(p))) + lazy val invalidPremise = premises.zipWithIndex.find((no, p) => !SC.isSameSequent(premiseSequents(no), sp.imports(p))) if (premises.length != sp.imports.length) invalid(s"Subproof expected ${sp.imports.length} premises, ${premises.length} received.") -- GitLab