diff --git a/src/main/scala/Example.scala b/src/main/scala/Example.scala index 49a5bf92ffff0b5f1e26d4bb7bea2468b88e3c87..a207d70a21196821ae8c6b4cea45c4817e3f18f8 100644 --- a/src/main/scala/Example.scala +++ b/src/main/scala/Example.scala @@ -1,11 +1,11 @@ -import lisa.kernel.Printer.* import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof import lisa.kernel.proof.SCProofChecker import lisa.kernel.proof.SCProofChecker.* import lisa.kernel.proof.SequentCalculus.* import proven.tactics.SimplePropositionalSolver.solveSequent -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} +import utilities.Printer.* import utilities.tptp.KernelParser.* import utilities.tptp.ProblemGatherer.* import utilities.tptp.* @@ -140,10 +140,6 @@ object Example { println("SPC: " + p.spc.mkString(", ")) p.formulas.foreach(printAnnotatedFormula) } - private def checkProof(proof: SCProof): Unit = { - val error = SCProofChecker.checkSCProof(proof) - println(prettySCProof(proof, error)) - } val P = SchematicPredicateLabel("P", 1) diff --git a/src/main/scala/lisa/kernel/Printer.scala b/src/main/scala/lisa/kernel/Printer.scala deleted file mode 100644 index 044c181af93298f6b417766f488985bdd860a746..0000000000000000000000000000000000000000 --- a/src/main/scala/lisa/kernel/Printer.scala +++ /dev/null @@ -1,333 +0,0 @@ -package lisa.kernel - -import lisa.kernel.fol.FOL.* -import lisa.kernel.proof.SCProof -import lisa.kernel.proof.SCProofCheckerJudgement -import lisa.kernel.proof.SCProofCheckerJudgement.* -import lisa.kernel.proof.SequentCalculus.* - -/** - * A set of methods to pretty-print kernel trees. - */ -object Printer { - - private def spaceSeparator(compact: Boolean): String = if (compact) "" else " " - private def commaSeparator(compact: Boolean, symbol: String = ","): String = s"$symbol${spaceSeparator(compact)}" - - private def prettyParentheses(content: String): String = s"(${content})" - - private def prettyFunction(name: String, args: Seq[String], compact: Boolean, dropParentheses: Boolean = true): String = { - if (dropParentheses && args.isEmpty) name else s"$name(${args.mkString(commaSeparator(compact))})" - } - - private def prettyInfix(operator: String, left: String, right: String, compact: Boolean): String = - Seq(left, operator, right).mkString(spaceSeparator(compact)) - - // Special symbols that aren't defined in this theory - private val (membership, subsetOf, sameCardinality) = ( - ConstantPredicateLabel("set_membership", 2), - ConstantPredicateLabel("subset_of", 2), - ConstantPredicateLabel("same_cardinality", 2) - ) - private val (emptySet, unorderedPair, orderedPair, singleton, powerSet, unionSet) = ( - ConstantFunctionLabel("empty_set", 0), - ConstantFunctionLabel("unordered_pair", 2), - ConstantFunctionLabel("ordered_pair", 2), - ConstantFunctionLabel("singleton", 1), - ConstantFunctionLabel("power_set", 1), - ConstantFunctionLabel("union", 1) - ) - private val nonAtomicPredicates: Set[PredicateLabel] = Set(equality, membership, subsetOf, sameCardinality) // Predicates which require parentheses (for readability) - - private def prettyFormulaInternal(formula: Formula, isRightMost: Boolean, compact: Boolean): String = formula match { - case PredicateFormula(label, args) => - label match { - case `equality` => - args match { - case Seq(l, r) => prettyInfix(label.id, prettyTerm(l), prettyTerm(r), compact) - case _ => throw new Exception - } - case `membership` => - args match { - case Seq(l, r) => prettyInfix("∈", prettyTerm(l), prettyTerm(r), compact) - case _ => throw new Exception - } - case `subsetOf` => - args match { - case Seq(l, r) => prettyInfix("⊆", prettyTerm(l), prettyTerm(r), compact) - case _ => throw new Exception - } - case `sameCardinality` => - args match { - case Seq(l, r) => prettyInfix("~", prettyTerm(l), prettyTerm(r), compact) - case _ => throw new Exception - } - case _ => - val labelString = label match { - case ConstantPredicateLabel(id, _) => id - case SchematicPredicateLabel(id, _) => s"?$id" - } - prettyFunction(labelString, args.map(prettyTerm(_, compact)), compact) - } - case ConnectorFormula(label, args) => - (label, args) match { - case (Neg, Seq(arg)) => - val isAtomic = arg match { - case PredicateFormula(label, _) => !nonAtomicPredicates.contains(label) - case ConnectorFormula(Neg, _) => true - case _ => false - } - val bodyString = prettyFormulaInternal(arg, isRightMost, compact) - val bodyParenthesized = if (isAtomic) bodyString else prettyParentheses(bodyString) - s"${label.id}${bodyParenthesized}" - case (binary @ (Implies | Iff | And | Or), Seq(l, r)) => - val precedences: Map[ConnectorLabel, Int] = Map( - And -> 1, - Or -> 2, - Implies -> 3, - Iff -> 4 - ) - val precedence = precedences(binary) - val isLeftParentheses = l match { - case _: BinderFormula => true - case PredicateFormula(leftLabel, _) => nonAtomicPredicates.contains(leftLabel) - case ConnectorFormula(leftLabel, _) => precedences.get(leftLabel).exists(_ >= precedence) - } - val isRightParentheses = r match { - case _: BinderFormula => !isRightMost - case PredicateFormula(leftLabel, _) => nonAtomicPredicates.contains(leftLabel) - case ConnectorFormula(rightLabel, _) => precedences.get(rightLabel).exists(_ > precedence) - } - val (leftString, rightString) = (prettyFormulaInternal(l, isLeftParentheses, compact), prettyFormulaInternal(r, isRightMost || isRightParentheses, compact)) - val leftParenthesized = if (isLeftParentheses) prettyParentheses(leftString) else leftString - val rightParenthesized = if (isRightParentheses) prettyParentheses(rightString) else rightString - prettyInfix(label.id, leftParenthesized, rightParenthesized, compact) - case (nary @ (And | Or), args) if args.nonEmpty => - // Rewriting to match the above case; namely op(a) --> a, and op(a, ...rest) --> op(a, op(...rest)) - // Empty args aren't allowed here - // Invariant: args.size > 2 - if (args.sizeIs == 1) { - prettyFormulaInternal(args.head, isRightMost, compact) - } else { - prettyFormulaInternal(ConnectorFormula(nary, Seq(args.head, ConnectorFormula(nary, args.tail))), isRightMost, compact) - } - case _ => prettyFunction(label.id, args.map(a => prettyFormulaInternal(a, isRightMost, compact)), compact) - } - case BinderFormula(label, bound, inner) => - def accumulateNested(f: Formula, acc: Seq[VariableLabel]): (Seq[VariableLabel], Formula) = f match { - case BinderFormula(`label`, nestBound, nestInner) => accumulateNested(nestInner, nestBound +: acc) - case _ => (acc, f) - } - val (bounds, innerNested) = accumulateNested(inner, Seq(bound)) - Seq(s"${label.id}${bounds.reverse.map(_.id).mkString(commaSeparator(compact))}.", prettyFormulaInternal(innerNested, true, compact)).mkString(spaceSeparator(compact)) - } - - /** - * Returns a string representation of this formula. See also [[prettyTerm]]. - * Example output: - * <pre> - * ∀x, y. (∀z. (z ∈ x) ↔ (z ∈ y)) ↔ (x = y) - * </pre> - * @param formula the formula - * @param compact whether spaces should be omitted between tokens - * @return the string representation of this formula - */ - def prettyFormula(formula: Formula, compact: Boolean = false): String = prettyFormulaInternal(formula, true, compact) - - /** - * Returns a string representation of this term. See also [[prettyFormula]]. - * Example output: - * <pre> - * f({w, (x, y)}, z) - * </pre> - * @param term the term - * @param compact whether spaces should be omitted between tokens - * @return the string representation of this term - */ - def prettyTerm(term: Term, compact: Boolean = false): String = term match { - case VariableTerm(label) => label.id - case FunctionTerm(label, args) => - label match { - case `emptySet` => - args match { - case Seq() => prettyFunction("∅", Seq.empty, compact, dropParentheses = true) - case _ => throw new Exception - } - case `unorderedPair` => - args match { - case Seq(l, r) => s"{${Seq(l, r).map(prettyTerm(_, compact)).mkString(commaSeparator(compact))}}" - case _ => throw new Exception - } - case `orderedPair` => - args match { - case Seq(l, r) => s"(${Seq(l, r).map(prettyTerm(_, compact)).mkString(commaSeparator(compact))})" - case _ => throw new Exception - } - case `singleton` => - args match { - case Seq(s) => s"{${prettyTerm(s)}}" - case _ => throw new Exception - } - case `powerSet` => - args match { - case Seq(s) => prettyFunction("P", Seq(prettyTerm(s)), compact) - case _ => throw new Exception - } - case `unionSet` => - args match { - case Seq(s) => prettyFunction("U", Seq(prettyTerm(s)), compact) - case _ => throw new Exception - } - case _ => - val labelString = label match { - case ConstantFunctionLabel(id, _) => id - case SchematicFunctionLabel(id, _) => s"?$id" - } - prettyFunction(labelString, args.map(prettyTerm(_, compact)), compact) - } - } - - /** - * Returns a string representation of this sequent. - * Example output: - * <pre> - * ⊢ ∀x, y. (∀z. (z ∈ x) ↔ (z ∈ y)) ↔ (x = y) - * </pre> - * @param sequent the sequent - * @param compact whether spaces should be omitted between tokens - * @return the string representation of this sequent - */ - def prettySequent(sequent: Sequent, compact: Boolean = false): String = { - def prettyFormulas(set: Set[Formula]): String = set.toSeq.map(prettyFormula(_, compact)).sorted.mkString(commaSeparator(compact, ";")) - Seq(prettyFormulas(sequent.left), "⊢", prettyFormulas(sequent.right)).filter(_.nonEmpty).mkString(spaceSeparator(compact)) - } - - /** - * Returns a string representation of the line number in a proof. - * Example output: - * <pre> - * 0:2:1 - * </pre> - * @param line the line number - * @return the string representation of this line number - */ - def prettyLineNumber(line: Seq[Int]): String = line.mkString(":") - - /** - * Returns a string representation of this proof. - * @param proof the proof - * @param judgement optionally provide a proof checking judgement that will mark a particular step in the proof - * (`->`) as an error. The proof is considered to be valid by default - * @return a string where each indented line corresponds to a step in the proof - */ - def prettySCProof(proof: SCProof, judgement: SCProofCheckerJudgement = SCValidProof, forceDisplaySubproofs: Boolean = false): String = { - def computeMaxNumberingLengths(proof: SCProof, level: Int, result: IndexedSeq[Int]): IndexedSeq[Int] = { - val resultWithCurrent = result.updated( - level, - (Seq((proof.steps.size - 1).toString.length, result(level)) ++ (if (proof.imports.nonEmpty) Seq((-proof.imports.size).toString.length) else Seq.empty)).max - ) - proof.steps.collect { case sp: SCSubproof => sp }.foldLeft(resultWithCurrent)((acc, sp) => computeMaxNumberingLengths(sp.sp, level + 1, if (acc.size <= level + 1) acc :+ 0 else acc)) - } - val maxNumberingLengths = computeMaxNumberingLengths(proof, 0, IndexedSeq(0)) // The maximum value for each number column - val maxLevel = maxNumberingLengths.size - 1 - - def leftPadSpaces(v: Any, n: Int): String = { - val s = String.valueOf(v) - if (s.length < n) (" " * (n - s.length)) + s else s - } - def rightPadSpaces(v: Any, n: Int): String = { - val s = String.valueOf(v) - if (s.length < n) s + (" " * (n - s.length)) else s - } - def prettySCProofRecursive(proof: SCProof, level: Int, tree: IndexedSeq[Int], topMostIndices: IndexedSeq[Int]): Seq[(Boolean, String, String, String)] = { - val printedImports = proof.imports.zipWithIndex.reverse.flatMap { case (imp, i) => - val currentTree = tree :+ (-i - 1) - val showErrorForLine = judgement match { - case SCValidProof => false - case SCInvalidProof(position, _) => currentTree.startsWith(position) && currentTree.drop(position.size).forall(_ == 0) - } - val prefix = (Seq.fill(level - topMostIndices.size)(None) ++ Seq.fill(topMostIndices.size)(None) :+ Some(-i - 1)) ++ Seq.fill(maxLevel - level)(None) - val prefixString = prefix.map(_.map(_.toString).getOrElse("")).zipWithIndex.map { case (v, i1) => leftPadSpaces(v, maxNumberingLengths(i1)) }.mkString(" ") - def pretty(stepName: String, topSteps: Int*): (Boolean, String, String, String) = - ( - showErrorForLine, - prefixString, - Seq(stepName, topSteps.mkString(commaSeparator(compact = false))).filter(_.nonEmpty).mkString(" "), - prettySequent(imp) - ) - - Seq(pretty("Import", 0)) - } - printedImports ++ proof.steps.zipWithIndex.flatMap { case (step, i) => - val currentTree = tree :+ i - val showErrorForLine = judgement match { - case SCValidProof => false - case SCInvalidProof(position, _) => currentTree.startsWith(position) && currentTree.drop(position.size).forall(_ == 0) - } - val prefix = (Seq.fill(level - topMostIndices.size)(None) ++ Seq.fill(topMostIndices.size)(None) :+ Some(i)) ++ Seq.fill(maxLevel - level)(None) - val prefixString = prefix.map(_.map(_.toString).getOrElse("")).zipWithIndex.map { case (v, i1) => leftPadSpaces(v, maxNumberingLengths(i1)) }.mkString(" ") - def pretty(stepName: String, topSteps: Int*): (Boolean, String, String, String) = - ( - showErrorForLine, - prefixString, - Seq(stepName, topSteps.mkString(commaSeparator(compact = false))).filter(_.nonEmpty).mkString(" "), - prettySequent(step.bot) - ) - step match { - case sp @ SCSubproof(_, _, display) if display || forceDisplaySubproofs => - pretty("Subproof", sp.premises*) +: prettySCProofRecursive(sp.sp, level + 1, currentTree, (if (i == 0) topMostIndices else IndexedSeq.empty) :+ i) - case other => - val line = other match { - case Rewrite(_, t1) => pretty("Rewrite", t1) - case Hypothesis(_, _) => pretty("Hypo.") - case Cut(_, t1, t2, _) => pretty("Cut", t1, t2) - case LeftAnd(_, t1, _, _) => pretty("Left ∧", t1) - case LeftNot(_, t1, _) => pretty("Left ¬", t1) - case RightOr(_, t1, _, _) => pretty("Right ∨", t1) - case RightNot(_, t1, _) => pretty("Right ¬", t1) - case LeftExists(_, t1, _, _) => pretty("Left ∃", t1) - case LeftForall(_, t1, _, _, _) => pretty("Left ∀", t1) - case LeftExistsOne(_, t1, _, _) => pretty("Left ∃!", t1) - case LeftOr(_, l, _) => pretty("Left ∨", l*) - case RightExists(_, t1, _, _, _) => pretty("Right ∃", t1) - case RightForall(_, t1, _, _) => pretty("Right ∀", t1) - case RightExistsOne(_, t1, _, _) => pretty("Right ∃!", t1) - case RightAnd(_, l, _) => pretty("Right ∧", l*) - case RightIff(_, t1, t2, _, _) => pretty("Right ↔", t1, t2) - case RightImplies(_, t1, _, _) => pretty("Right →", t1) - case Weakening(_, t1) => pretty("Weakening", t1) - case LeftImplies(_, t1, t2, _, _) => pretty("Left →", t1, t2) - case LeftIff(_, t1, _, _) => pretty("Left ↔", t1) - case LeftRefl(_, t1, _) => pretty("L. Refl", t1) - case RightRefl(_, _) => pretty("R. Refl") - case LeftSubstEq(_, t1, _, _) => pretty("L. SubstEq", t1) - case RightSubstEq(_, t1, _, _) => pretty("R. SubstEq", t1) - case LeftSubstIff(_, t1, _, _) => pretty("L. SubstIff", t1) - case RightSubstIff(_, t1, _, _) => pretty("R. SubstIff", t1) - case InstFunSchema(_, t1, _) => pretty("?Fun Instantiation", t1) - case InstPredSchema(_, t1, _) => pretty("?Pred Instantiation", t1) - case SCSubproof(_, _, false) => pretty("Subproof (hidden)") - case other => throw new Exception(s"No available method to print this proof step, consider updating Printer.scala\n$other") - } - Seq(line) - } - } - } - - val marker = "->" - - val lines = prettySCProofRecursive(proof, 0, IndexedSeq.empty, IndexedSeq.empty) - val maxStepNameLength = lines.map { case (_, _, stepName, _) => stepName.length }.maxOption.getOrElse(0) - lines - .map { case (isMarked, indices, stepName, sequent) => - val suffix = Seq(indices, rightPadSpaces(stepName, maxStepNameLength), sequent) - val full = if (!judgement.isValid) (if (isMarked) marker else leftPadSpaces("", marker.length)) +: suffix else suffix - full.mkString(" ") - } - .mkString("\n") + (judgement match { - case SCValidProof => "" - case SCInvalidProof(path, message) => s"\nProof checker has reported an error at line ${path.mkString(".")}: $message" - }) - } - -} diff --git a/src/main/scala/lisa/kernel/proof/Judgement.scala b/src/main/scala/lisa/kernel/proof/Judgement.scala index 680d70b42f6d504076b1481848d6f308136d20c7..56137f419ed9924e3593bc26f538c0c07ff42c2a 100644 --- a/src/main/scala/lisa/kernel/proof/Judgement.scala +++ b/src/main/scala/lisa/kernel/proof/Judgement.scala @@ -8,6 +8,7 @@ import lisa.kernel.proof.RunningTheory */ sealed abstract class SCProofCheckerJudgement { import SCProofCheckerJudgement.* + val proof: SCProof /** * Whether this judgement is positive -- the proof is concluded to be valid; @@ -15,7 +16,7 @@ sealed abstract class SCProofCheckerJudgement { * @return An instance of either [[SCValidProof]] or [[SCInvalidProof]] */ def isValid: Boolean = this match { - case SCValidProof => true + case _: SCValidProof => true case _: SCInvalidProof => false } } @@ -25,14 +26,14 @@ object SCProofCheckerJudgement { /** * A positive judgement. */ - case object SCValidProof extends SCProofCheckerJudgement + case class SCValidProof(proof: SCProof) extends SCProofCheckerJudgement /** * A negative judgement. * @param path The path of the error, expressed as indices * @param message The error message that hints about the first error encountered */ - case class SCInvalidProof(path: Seq[Int], message: String) extends SCProofCheckerJudgement + case class SCInvalidProof(proof: SCProof, path: Seq[Int], message: String) extends SCProofCheckerJudgement } /** diff --git a/src/main/scala/lisa/kernel/proof/RunningTheory.scala b/src/main/scala/lisa/kernel/proof/RunningTheory.scala index 70f54f3c8ef1bf39d828f65d0bc4d082229503c3..dd307f14d42d81a0dcbba30c28c4dca355ea9d90 100644 --- a/src/main/scala/lisa/kernel/proof/RunningTheory.scala +++ b/src/main/scala/lisa/kernel/proof/RunningTheory.scala @@ -62,21 +62,26 @@ class RunningTheory { private[proof] val theoryAxioms: mMap[String, Axiom] = mMap.empty private[proof] val theorems: mMap[String, Theorem] = mMap.empty - private[proof] val definitions: mMap[ConstantLabel, Option[Definition]] = mMap(equality -> None) + private[proof] val funDefinitions: mMap[ConstantFunctionLabel, Option[FunctionDefinition]] = mMap.empty + private[proof] val predDefinitions: mMap[ConstantPredicateLabel, Option[PredicateDefinition]] = mMap(equality -> None) /** * Check if a label is a symbol of the theory */ - def isSymbol(label: ConstantLabel): Boolean = definitions.contains(label) - /** - * From a given proof, if it is true in the Running theory, add that theorem to the theory and returns it. - * The proof's imports must be justified by the list of justification, and the conclusion of the theorem - * can't contain symbols that do not belong to the theory. - * @param justifications The list of justifications of the proof's imports. - * @param proof The proof of the desired Theorem. - * @return A Theorem if the proof is correct, None else - */ + def isSymbol(label: ConstantLabel): Boolean = label match + case c: ConstantFunctionLabel => funDefinitions.contains(c) + case c: ConstantPredicateLabel => predDefinitions.contains(c) + + /** + * From a given proof, if it is true in the Running theory, add that theorem to the theory and returns it. + * The proof's imports must be justified by the list of justification, and the conclusion of the theorem + * can't contain symbols that do not belong to the theory. + * + * @param justifications The list of justifications of the proof's imports. + * @param proof The proof of the desired Theorem. + * @return A Theorem if the proof is correct, None else + */ def makeTheorem(name: String, statement: Sequent, proof: SCProof, justifications: Seq[Justification]): RunningTheoryJudgement[this.Theorem] = { if (proof.conclusion == statement) proofToTheorem(name, proof, justifications) else InvalidJustification("The proof does not prove the claimed statement", None) @@ -87,11 +92,11 @@ class RunningTheory { if (belongsToTheory(proof.conclusion)) val r = SCProofChecker.checkSCProof(proof) r match { - case SCProofCheckerJudgement.SCValidProof => + case SCProofCheckerJudgement.SCValidProof(_) => val thm = Theorem(name, proof.conclusion) theorems.update(name, thm) ValidJustification(thm) - case r @ SCProofCheckerJudgement.SCInvalidProof(path, message) => + case r @ SCProofCheckerJudgement.SCInvalidProof(_, _, message) => InvalidJustification("The given proof is incorrect: " + message, Some(r)) } else InvalidJustification("All symbols in the conclusion of the proof must belong to the theory. You need to add missing symbols to the theory.", None) @@ -100,9 +105,10 @@ class RunningTheory { /** * Introduce a new definition of a predicate in the theory. The symbol must not already exist in the theory * and the formula can't contain symbols that are not in the theory. + * * @param label The desired label. - * @param args The variables representing the arguments of the predicate in the formula phi. - * @param phi The formula defining the predicate. + * @param args The variables representing the arguments of the predicate in the formula phi. + * @param phi The formula defining the predicate. * @return A definition object if the parameters are correct, */ def makePredicateDefinition(label: ConstantPredicateLabel, args: Seq[VariableLabel], phi: Formula): RunningTheoryJudgement[this.PredicateDefinition] = { @@ -110,7 +116,7 @@ class RunningTheory { if (!isSymbol(label)) if (phi.freeVariables.subsetOf(args.toSet) && phi.schematicFunctions.isEmpty && phi.schematicPredicates.isEmpty) val newDef = PredicateDefinition(label, args, phi) - definitions.update(label, Some(newDef)) + predDefinitions.update(label, Some(newDef)) RunningTheoryJudgement.ValidJustification(newDef) else InvalidJustification("The definition is not allowed to contain schematic symbols or free variables.", None) else InvalidJustification("The specified symbol is already part of the theory and can't be redefined.", None) @@ -123,12 +129,13 @@ class RunningTheory { * satisfying the definition's formula must first be proven. This is easy if the formula behaves as a shortcut, * for example f(x,y) = 3x+2y * but is much more general. The proof's conclusion must be of the form: |- ∀args. ∃!out. phi - * @param proof The proof of existence and uniqueness + * + * @param proof The proof of existence and uniqueness * @param justifications The justifications of the proof. - * @param label The desired label. - * @param args The variables representing the arguments of the predicate in the formula phi. - * @param out The variable representing the function's result in the formula - * @param phi The formula defining the predicate. + * @param label The desired label. + * @param args The variables representing the arguments of the predicate in the formula phi. + * @param out The variable representing the function's result in the formula + * @param phi The formula defining the predicate. * @return A definition object if the parameters are correct, */ def makeFunctionDefinition( @@ -145,19 +152,19 @@ class RunningTheory { if (proof.imports.forall(i => justifications.exists(j => isSameSequent(i, sequentFromJustification(j))))) val r = SCProofChecker.checkSCProof(proof) r match { - case SCProofCheckerJudgement.SCValidProof => + case SCProofCheckerJudgement.SCValidProof(_) => proof.conclusion match { case Sequent(l, r) if l.isEmpty && r.size == 1 => val subst = bindAll(Forall, args, BinderFormula(ExistsOne, out, phi)) val subst2 = bindAll(Forall, args.reverse, BinderFormula(ExistsOne, out, phi)) if (isSame(r.head, subst) || isSame(r.head, subst2)) { val newDef = FunctionDefinition(label, args, out, phi) - definitions.update(label, Some(newDef)) + funDefinitions.update(label, Some(newDef)) RunningTheoryJudgement.ValidJustification(newDef) } else InvalidJustification("The proof is correct but its conclusion does not correspond to a definition for the formula phi.", None) case _ => InvalidJustification("The conclusion of the proof must have an empty left hand side, and a single formula on the right hand side.", None) } - case r @ SCProofCheckerJudgement.SCInvalidProof(path, message) => InvalidJustification("The given proof is incorrect: " + message, Some(r)) + case r @ SCProofCheckerJudgement.SCInvalidProof(_, path, message) => InvalidJustification("The given proof is incorrect: " + message, Some(r)) } else InvalidJustification("Not all imports of the proof are correctly justified.", None) else InvalidJustification("The definition is not allowed to contain schematic symbols or free variables.", None) @@ -194,6 +201,7 @@ class RunningTheory { /** * Verify if a given formula belongs to some language + * * @param phi The formula to check * @return Weather phi belongs to the specified language */ @@ -214,6 +222,7 @@ class RunningTheory { /** * Verify if a given term belongs to some language + * * @param t The term to check * @return Weather t belongs to the specified language */ @@ -229,6 +238,7 @@ class RunningTheory { /** * Verify if a given sequent belongs to some language + * * @param s The sequent to check * @return Weather s belongs to the specified language */ @@ -244,6 +254,7 @@ class RunningTheory { * Add a new axiom to the Theory. For example, if the theory contains the language and theorems * of Zermelo-Fraenkel Set Theory, this function can add the axiom of choice to it. * If the axiom belongs to the language of the theory, adds it and return true. Else, returns false. + * * @param f the new axiom to be added. * @return true if the axiom was added to the theory, false else. */ @@ -260,28 +271,38 @@ class RunningTheory { * For example, This function can add the empty set symbol to a theory, and then an axiom asserting * the it is empty can be introduced as well. */ - def addSymbol(s: ConstantLabel): Unit = definitions.update(s, None) + + def addSymbol(s: ConstantLabel): Unit = s match + case c: ConstantFunctionLabel => funDefinitions.update(c, None) + case c: ConstantPredicateLabel => predDefinitions.update(c, None) /** * Public accessor to the set of symbol currently in the theory's language. + * * @return the set of symbol currently in the theory's language. */ - def language: List[(ConstantLabel, Option[Definition])] = definitions.toList + + def language: List[(ConstantLabel, Option[Definition])] = funDefinitions.toList ++ predDefinitions.toList /** * Public accessor to the current set of axioms of the theory + * * @return the current set of axioms of the theory */ def axiomsList: Iterable[Axiom] = theoryAxioms.values /** * Verify if a given formula is an axiom of the theory + * * @param f the candidate axiom * @return wether f is an axiom of the theory */ def isAxiom(f: Formula): Boolean = theoryAxioms.exists(a => isSame(a._2.ax, f)) + def getAxiom(f: Formula): Option[Axiom] = theoryAxioms.find(a => isSame(a._2.ax, f)).map(_._2) + def getAxiom(name: String): Option[Axiom] = theoryAxioms.get(name) + def getTheorem(name: String): Option[Theorem] = theorems.get(name) } diff --git a/src/main/scala/lisa/kernel/proof/SCProofChecker.scala b/src/main/scala/lisa/kernel/proof/SCProofChecker.scala index ad72abfe303ef53d79351c0b4422f30b2f96961a..1ae79196707b059f70495a60d36ca7831c4e60ad 100644 --- a/src/main/scala/lisa/kernel/proof/SCProofChecker.scala +++ b/src/main/scala/lisa/kernel/proof/SCProofChecker.scala @@ -1,9 +1,9 @@ package lisa.kernel.proof -import lisa.kernel.Printer import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProofCheckerJudgement.* import lisa.kernel.proof.SequentCalculus.* +import utilities.Printer object SCProofChecker { @@ -28,9 +28,9 @@ object SCProofChecker { val r: SCProofCheckerJudgement = if (false_premise.nonEmpty) - SCInvalidProof(Nil, s"Step no $no can't refer to higher number ${false_premise.get} as a premise.") + SCInvalidProof(SCProof(step), Nil, s"Step no $no can't refer to higher number ${false_premise.get} as a premise.") else if (false_premise2.nonEmpty) - SCInvalidProof(Nil, s"A step can't refer to step ${false_premise2.get}, imports only contains ${importsSize.get} elements.") + SCInvalidProof(SCProof(step), Nil, s"A step can't refer to step ${false_premise2.get}, imports only contains ${importsSize.get} elements.") else step match { /* @@ -39,7 +39,7 @@ object SCProofChecker { * Γ |- Δ */ case Rewrite(s, t1) => - if (isSameSequent(s, ref(t1))) SCValidProof else SCInvalidProof(Nil, s"The premise and the conclusion are not trivially equivalent.") + if (isSameSequent(s, ref(t1))) SCValidProof(SCProof(step)) else SCInvalidProof(SCProof(step), Nil, s"The premise and the conclusion are not trivially equivalent.") /* * * -------------- @@ -47,9 +47,9 @@ object SCProofChecker { */ case Hypothesis(Sequent(left, right), phi) => if (contains(left, phi)) - if (contains(right, phi)) SCValidProof - else SCInvalidProof(Nil, s"Right-hand side does not contain formula φ") - else SCInvalidProof(Nil, s"Left-hand side does not contain formula φ") + if (contains(right, phi)) SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, s"Right-hand side does not contain formula φ") + else SCInvalidProof(SCProof(step), Nil, s"Left-hand side does not contain formula φ") /* * Γ |- Δ, φ φ, Σ |- Π * ------------------------ @@ -60,11 +60,11 @@ object SCProofChecker { if (isSameSet(b.right, ref(t2).right union ref(t1).right.filterNot(isSame(_, phi)))) if (contains(ref(t2).left, phi)) if (contains(ref(t1).right, phi)) - SCValidProof - else SCInvalidProof(Nil, s"Right-hand side of first premise does not contain φ as claimed.") - else SCInvalidProof(Nil, s"Left-hand side of second premise does not contain φ as claimed.") - else SCInvalidProof(Nil, s"Right-hand side of conclusion + φ is not the union of the right-hand sides of the premises.") - else SCInvalidProof(Nil, s"Left-hand side of conclusion + φ is not the union of the left-hand sides of the premises.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, s"Right-hand side of first premise does not contain φ as claimed.") + else SCInvalidProof(SCProof(step), Nil, s"Left-hand side of second premise does not contain φ as claimed.") + else SCInvalidProof(SCProof(step), Nil, s"Right-hand side of conclusion + φ is not the union of the right-hand sides of the premises.") + else SCInvalidProof(SCProof(step), Nil, s"Left-hand side of conclusion + φ is not the union of the left-hand sides of the premises.") // Left rules /* @@ -80,9 +80,9 @@ object SCProofChecker { isSameSet(b.left + psi, ref(t1).left + phiAndPsi) || isSameSet(b.left + phi + psi, ref(t1).left + phiAndPsi) ) - SCValidProof - else SCInvalidProof(Nil, "Left-hand side of conclusion + φ∧ψ must be same as left-hand side of premise + either φ, ψ or both.") - else SCInvalidProof(Nil, "Right-hand sides of the premise and the conclusion must be the same.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of conclusion + φ∧ψ must be same as left-hand side of premise + either φ, ψ or both.") + else SCInvalidProof(SCProof(step), Nil, "Right-hand sides of the premise and the conclusion must be the same.") /* * Γ, φ |- Δ Σ, ψ |- Π * ------------------------ @@ -92,9 +92,9 @@ object SCProofChecker { if (isSameSet(b.right, t.map(ref(_).right).reduce(_ union _))) val phiOrPsi = ConnectorFormula(Or, disjuncts) if (isSameSet(disjuncts.foldLeft(b.left)(_ + _), t.map(ref(_).left).reduce(_ union _) + phiOrPsi)) - SCValidProof - else SCInvalidProof(Nil, s"Left-hand side of conclusion + disjuncts is not the same as the union of the left-hand sides of the premises + φ∨ψ.") - else SCInvalidProof(Nil, s"Right-hand side of conclusion is not the union of the right-hand sides of the premises.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, s"Left-hand side of conclusion + disjuncts is not the same as the union of the left-hand sides of the premises + φ∨ψ.") + else SCInvalidProof(SCProof(step), Nil, s"Right-hand side of conclusion is not the union of the right-hand sides of the premises.") /* * Γ |- φ, Δ Σ, ψ |- Π * ------------------------ @@ -104,9 +104,9 @@ object SCProofChecker { val phiImpPsi = ConnectorFormula(Implies, Seq(phi, psi)) if (isSameSet(b.right + phi, ref(t1).right union ref(t2).right)) if (isSameSet(b.left + psi, ref(t1).left union ref(t2).left + phiImpPsi)) - SCValidProof - else SCInvalidProof(Nil, s"Left-hand side of conclusion + ψ must be identical to union of left-hand sides of premisces + φ→ψ.") - else SCInvalidProof(Nil, s"Right-hand side of conclusion + φ must be identical to union of right-hand sides of premisces.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, s"Left-hand side of conclusion + ψ must be identical to union of left-hand sides of premisces + φ→ψ.") + else SCInvalidProof(SCProof(step), Nil, s"Right-hand side of conclusion + φ must be identical to union of right-hand sides of premisces.") /* * Γ, φ→ψ |- Δ Γ, φ→ψ, ψ→φ |- Δ * -------------- or --------------- @@ -122,9 +122,9 @@ object SCProofChecker { isSameSet(b.left + psiImpPhi, ref(t1).left + phiIffPsi) || isSameSet(b.left + phiImpPsi + psiImpPhi, ref(t1).left + phiIffPsi) ) - SCValidProof - else SCInvalidProof(Nil, "Left-hand side of conclusion + φ↔ψ must be same as left-hand side of premise + either φ→ψ, ψ→φ or both.") - else SCInvalidProof(Nil, "Right-hand sides of premise and conclusion must be the same.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of conclusion + φ↔ψ must be same as left-hand side of premise + either φ→ψ, ψ→φ or both.") + else SCInvalidProof(SCProof(step), Nil, "Right-hand sides of premise and conclusion must be the same.") /* * Γ |- φ, Δ @@ -135,9 +135,9 @@ object SCProofChecker { val nPhi = ConnectorFormula(Neg, Seq(phi)) if (isSameSet(b.left, ref(t1).left + nPhi)) if (isSameSet(b.right + phi, ref(t1).right)) - SCValidProof - else SCInvalidProof(Nil, "Right-hand side of conclusion + φ must be the same as right-hand side of premise") - else SCInvalidProof(Nil, "Left-hand side of conclusion must be the same as left-hand side of premise + ¬φ") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion + φ must be the same as right-hand side of premise") + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of conclusion must be the same as left-hand side of premise + ¬φ") /* * Γ, φ[t/x] |- Δ @@ -147,9 +147,9 @@ object SCProofChecker { case LeftForall(b, t1, phi, x, t) => if (isSameSet(b.right, ref(t1).right)) if (isSameSet(b.left + substituteVariables(phi, Map(x -> t)), ref(t1).left + BinderFormula(Forall, x, phi))) - SCValidProof - else SCInvalidProof(Nil, "Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ") - else SCInvalidProof(Nil, "Right-hand side of conclusion must be the same as right-hand side of premise") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of conclusion + φ[t/x] must be the same as left-hand side of premise + ∀x. φ") + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion must be the same as right-hand side of premise") /* * Γ, φ |- Δ @@ -160,10 +160,10 @@ object SCProofChecker { if (isSameSet(b.right, ref(t1).right)) if (isSameSet(b.left + phi, ref(t1).left + BinderFormula(Exists, x, phi))) if ((b.left union b.right).forall(f => !f.freeVariables.contains(x))) - SCValidProof - else SCInvalidProof(Nil, "The variable x must not be free in the resulting sequent.") - else SCInvalidProof(Nil, "Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ") - else SCInvalidProof(Nil, "Right-hand side of conclusion must be the same as right-hand side of premise") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "The variable x must not be free in the resulting sequent.") + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of conclusion + φ must be the same as left-hand side of premise + ∃x. φ") + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion must be the same as right-hand side of premise") /* * Γ, ∃y.∀x. (x=y) ↔ φ |- Δ @@ -175,9 +175,9 @@ object SCProofChecker { val temp = BinderFormula(Exists, y, BinderFormula(Forall, x, ConnectorFormula(Iff, List(PredicateFormula(equality, List(VariableTerm(x), VariableTerm(y))), phi)))) if (isSameSet(b.right, ref(t1).right)) if (isSameSet(b.left + temp, ref(t1).left + BinderFormula(ExistsOne, x, phi))) - SCValidProof - else SCInvalidProof(Nil, "Left-hand side of conclusion + ∃y.∀x. (x=y) ↔ φ must be the same as left-hand side of premise + ∃!x. φ") - else SCInvalidProof(Nil, "Right-hand side of conclusion must be the same as right-hand side of premise") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of conclusion + ∃y.∀x. (x=y) ↔ φ must be the same as left-hand side of premise + ∃!x. φ") + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion must be the same as right-hand side of premise") // Right rules /* @@ -189,9 +189,9 @@ object SCProofChecker { val phiAndPsi = ConnectorFormula(And, cunjuncts) if (isSameSet(b.left, t.map(ref(_).left).reduce(_ union _))) if (isSameSet(cunjuncts.foldLeft(b.right)(_ + _), t.map(ref(_).right).reduce(_ union _) + phiAndPsi)) - SCValidProof - else SCInvalidProof(Nil, s"Right-hand side of conclusion + φ + ψ is not the same as the union of the right-hand sides of the premises φ∧ψ.") - else SCInvalidProof(Nil, s"Left-hand side of conclusion is not the union of the left-hand sides of the premises.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, s"Right-hand side of conclusion + φ + ψ is not the same as the union of the right-hand sides of the premises φ∧ψ.") + else SCInvalidProof(SCProof(step), Nil, s"Left-hand side of conclusion is not the union of the left-hand sides of the premises.") /* * Γ |- φ, Δ Γ |- φ, ψ, Δ * -------------- or --------------- @@ -205,9 +205,9 @@ object SCProofChecker { isSameSet(b.right + psi, ref(t1).right + phiOrPsi) || isSameSet(b.right + phi + psi, ref(t1).right + phiOrPsi) ) - SCValidProof - else SCInvalidProof(Nil, "Right-hand side of conclusion + φ∧ψ must be same as right-hand side of premise + either φ, ψ or both.") - else SCInvalidProof(Nil, "Left-hand sides of the premise and the conclusion must be the same.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion + φ∧ψ must be same as right-hand side of premise + either φ, ψ or both.") + else SCInvalidProof(SCProof(step), Nil, "Left-hand sides of the premise and the conclusion must be the same.") /* * Γ, φ |- ψ, Δ * -------------- @@ -217,9 +217,9 @@ object SCProofChecker { val phiImpPsi = ConnectorFormula(Implies, Seq(phi, psi)) if (isSameSet(ref(t1).left, b.left + phi)) if (isSameSet(b.right + psi, ref(t1).right + phiImpPsi)) - SCValidProof - else SCInvalidProof(Nil, "Right-hand side of conclusion + ψ must be same as right-hand side of premise + φ→ψ.") - else SCInvalidProof(Nil, "Left-hand side of conclusion + psi must be same as left-hand side of premise.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion + ψ must be same as right-hand side of premise + φ→ψ.") + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of conclusion + psi must be same as left-hand side of premise.") /* * Γ |- a→ψ, Δ Σ |- ψ→φ, Π * ---------------------------- @@ -231,9 +231,9 @@ object SCProofChecker { val phiIffPsi = ConnectorFormula(Iff, Seq(phi, psi)) if (isSameSet(b.left, ref(t1).left union ref(t2).left)) if (isSameSet(b.right + phiImpPsi + psiImpPhi, ref(t1).right union ref(t2).right + phiIffPsi)) - SCValidProof - else SCInvalidProof(Nil, s"Right-hand side of conclusion + a→ψ + ψ→φ is not the same as the union of the right-hand sides of the premises φ↔b.") - else SCInvalidProof(Nil, s"Left-hand side of conclusion is not the union of the left-hand sides of the premises.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, s"Right-hand side of conclusion + a→ψ + ψ→φ is not the same as the union of the right-hand sides of the premises φ↔b.") + else SCInvalidProof(SCProof(step), Nil, s"Left-hand side of conclusion is not the union of the left-hand sides of the premises.") /* * Γ, φ |- Δ * -------------- @@ -243,9 +243,9 @@ object SCProofChecker { val nPhi = ConnectorFormula(Neg, Seq(phi)) if (isSameSet(b.right, ref(t1).right + nPhi)) if (isSameSet(b.left + phi, ref(t1).left)) - SCValidProof - else SCInvalidProof(Nil, "Left-hand side of conclusion + φ must be the same as left-hand side of premise") - else SCInvalidProof(Nil, "Right-hand side of conclusion must be the same as right-hand side of premise + ¬φ") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of conclusion + φ must be the same as left-hand side of premise") + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion must be the same as right-hand side of premise + ¬φ") /* * Γ |- φ, Δ * ------------------- if x is not free in the resulting sequent @@ -255,10 +255,10 @@ object SCProofChecker { if (isSameSet(b.left, ref(t1).left)) if (isSameSet(b.right + phi, ref(t1).right + BinderFormula(Forall, x, phi))) if ((b.left union b.right).forall(f => !f.freeVariables.contains(x))) - SCValidProof - else SCInvalidProof(Nil, "The variable x must not be free in the resulting sequent.") - else SCInvalidProof(Nil, "Right-hand side of conclusion + φ must be the same as right-hand side of premise + ∀x. φ") - else SCInvalidProof(Nil, "Left-hand sides of conclusion and premise must be the same.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "The variable x must not be free in the resulting sequent.") + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion + φ must be the same as right-hand side of premise + ∀x. φ") + else SCInvalidProof(SCProof(step), Nil, "Left-hand sides of conclusion and premise must be the same.") /* * Γ |- φ[t/x], Δ * ------------------- @@ -267,9 +267,9 @@ object SCProofChecker { case RightExists(b, t1, phi, x, t) => if (isSameSet(b.left, ref(t1).left)) if (isSameSet(b.right + substituteVariables(phi, Map(x -> t)), ref(t1).right + BinderFormula(Exists, x, phi))) - SCValidProof - else SCInvalidProof(Nil, "Right-hand side of the conclusion + φ[t/x] must be the same as right-hand side of the premise + ∃x. φ") - else SCInvalidProof(Nil, "Left-hand sides or conclusion and premise must be the same.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of the conclusion + φ[t/x] must be the same as right-hand side of the premise + ∃x. φ") + else SCInvalidProof(SCProof(step), Nil, "Left-hand sides or conclusion and premise must be the same.") /** * <pre> @@ -283,9 +283,9 @@ object SCProofChecker { val temp = BinderFormula(Exists, y, BinderFormula(Forall, x, ConnectorFormula(Iff, List(PredicateFormula(equality, List(VariableTerm(x), VariableTerm(y))), phi)))) if (isSameSet(b.left, ref(t1).left)) if (isSameSet(b.right + temp, ref(t1).right + BinderFormula(ExistsOne, x, phi))) - SCValidProof - else SCInvalidProof(Nil, "Right-hand side of conclusion + ∃y.∀x. (x=y) ↔ φ must be the same as right-hand side of premise + ∃!x. φ") - else SCInvalidProof(Nil, "Left-hand sides of conclusion and premise must be the same") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of conclusion + ∃y.∀x. (x=y) ↔ φ must be the same as right-hand side of premise + ∃!x. φ") + else SCInvalidProof(SCProof(step), Nil, "Left-hand sides of conclusion and premise must be the same") // Structural rules /* @@ -296,9 +296,9 @@ object SCProofChecker { case Weakening(b, t1) => if (isSubset(ref(t1).left, b.left)) if (isSubset(ref(t1).right, b.right)) - SCValidProof - else SCInvalidProof(Nil, "Right-hand side of premise must be a subset of right-hand side of conclusion") - else SCInvalidProof(Nil, "Left-hand side of premise must be a subset of left-hand side of conclusion") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of premise must be a subset of right-hand side of conclusion") + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of premise must be a subset of left-hand side of conclusion") // Equality Rules /* @@ -312,11 +312,11 @@ object SCProofChecker { if (isSame(left, right)) if (isSameSet(b.right, ref(t1).right)) if (isSameSet(b.left + phi, ref(t1).left)) - SCValidProof - else SCInvalidProof(Nil, s"Left-hand sides of the conclusion + φ must be the same as left-hand side of the premise.") - else SCInvalidProof(Nil, s"Right-hand sides of the premise and the conclusion aren't the same.") - else SCInvalidProof(Nil, s"φ is not an instance of reflexivity.") - case _ => SCInvalidProof(Nil, "φ is not an equality") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, s"Left-hand sides of the conclusion + φ must be the same as left-hand side of the premise.") + else SCInvalidProof(SCProof(step), Nil, s"Right-hand sides of the premise and the conclusion aren't the same.") + else SCInvalidProof(SCProof(step), Nil, s"φ is not an instance of reflexivity.") + case _ => SCInvalidProof(SCProof(step), Nil, "φ is not an equality") } /* @@ -329,10 +329,10 @@ object SCProofChecker { case PredicateFormula(`equality`, Seq(left, right)) => if (isSame(left, right)) if (contains(b.right, phi)) - SCValidProof - else SCInvalidProof(Nil, s"Right-Hand side of conclusion does not contain φ") - else SCInvalidProof(Nil, s"φ is not an instance of reflexivity.") - case _ => SCInvalidProof(Nil, s"φ is not an equality.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, s"Right-Hand side of conclusion does not contain φ") + else SCInvalidProof(SCProof(step), Nil, s"φ is not an instance of reflexivity.") + case _ => SCInvalidProof(SCProof(step), Nil, s"φ is not an equality.") } /* @@ -351,9 +351,14 @@ object SCProofChecker { isSameSet(b.left + phi_t_for_f, ref(t1).left ++ sEqT_es + phi_s_for_f) || isSameSet(b.left + phi_s_for_f, ref(t1).left ++ sEqT_es + phi_t_for_f) ) - SCValidProof - else SCInvalidProof(Nil, "Left-hand sides of the conclusion + φ(s_) must be the same as left-hand side of the premise + (s=t)_ + φ(t_) (or with s_ and t_ swapped).") - else SCInvalidProof(Nil, "Right-hand sides of the premise and the conclusion aren't the same.") + SCValidProof(SCProof(step)) + else + SCInvalidProof( + SCProof(step), + Nil, + "Left-hand sides of the conclusion + φ(s_) must be the same as left-hand side of the premise + (s=t)_ + φ(t_) (or with s_ and t_ swapped)." + ) + else SCInvalidProof(SCProof(step), Nil, "Right-hand sides of the premise and the conclusion aren't the same.") /* * Γ |- φ(s_), Δ @@ -370,9 +375,14 @@ object SCProofChecker { isSameSet(b.right + phi_s_for_f, ref(t1).right + phi_t_for_f) || isSameSet(b.right + phi_t_for_f, ref(t1).right + phi_s_for_f) ) - SCValidProof - else SCInvalidProof(Nil, s"Right-hand side of the premise and the conclusion should be the same with each containing one of φ(s_) φ(t_), but it isn't the case.") - else SCInvalidProof(Nil, "Left-hand sides of the premise + (s=t)_ must be the same as left-hand side of the premise.") + SCValidProof(SCProof(step)) + else + SCInvalidProof( + SCProof(step), + Nil, + s"Right-hand side of the premise and the conclusion should be the same with each containing one of φ(s_) φ(t_), but it isn't the case." + ) + else SCInvalidProof(SCProof(step), Nil, "Left-hand sides of the premise + (s=t)_ must be the same as left-hand side of the premise.") /* * Γ, φ(ψ_) |- Δ * --------------------- @@ -388,9 +398,14 @@ object SCProofChecker { isSameSet(ref(t1).left ++ psiIffTau + phi_tau_for_q, b.left + phi_psi_for_q) || isSameSet(ref(t1).left ++ psiIffTau + phi_psi_for_q, b.left + phi_tau_for_q) ) - SCValidProof - else SCInvalidProof(Nil, "Left-hand sides of the conclusion + φ(ψ_) must be the same as left-hand side of the premise + (ψ↔τ)_ + φ(τ_) (or with ψ and τ swapped).") - else SCInvalidProof(Nil, "Right-hand sides of the premise and the conclusion aren't the same.") + SCValidProof(SCProof(step)) + else + SCInvalidProof( + SCProof(step), + Nil, + "Left-hand sides of the conclusion + φ(ψ_) must be the same as left-hand side of the premise + (ψ↔τ)_ + φ(τ_) (or with ψ and τ swapped)." + ) + else SCInvalidProof(SCProof(step), Nil, "Right-hand sides of the premise and the conclusion aren't the same.") /* * Γ |- φ[ψ/?p], Δ @@ -407,9 +422,14 @@ object SCProofChecker { isSameSet(b.right + phi_tau_for_q, ref(t1).right + phi_psi_for_q) || isSameSet(b.right + phi_psi_for_q, ref(t1).right + phi_tau_for_q) ) - SCValidProof - else SCInvalidProof(Nil, s"Right-hand side of the premise and the conclusion should be the same with each containing one of φ[τ/?q] and φ[ψ/?q], but it isn't the case.") - else SCInvalidProof(Nil, "Left-hand sides of the premise + ψ↔τ must be the same as left-hand side of the premise.") + SCValidProof(SCProof(step)) + else + SCInvalidProof( + SCProof(step), + Nil, + s"Right-hand side of the premise and the conclusion should be the same with each containing one of φ[τ/?q] and φ[ψ/?q], but it isn't the case." + ) + else SCInvalidProof(SCProof(step), Nil, "Left-hand sides of the premise + ψ↔τ must be the same as left-hand side of the premise.") /** * <pre> @@ -422,9 +442,9 @@ object SCProofChecker { val expected = (ref(t1).left.map(phi => instantiateFunctionSchemas(phi, insts)), ref(t1).right.map(phi => instantiateFunctionSchemas(phi, insts))) if (isSameSet(bot.left, expected._1)) if (isSameSet(bot.right, expected._2)) - SCValidProof - else SCInvalidProof(Nil, "Right-hand side of premise instantiated with the map 'insts' must be the same as right-hand side of conclusion.") - else SCInvalidProof(Nil, "Left-hand side of premise instantiated with the map 'insts' must be the same as left-hand side of conclusion.") + SCValidProof(SCProof(step)) + else SCInvalidProof(SCProof(step), Nil, "Right-hand side of premise instantiated with the map 'insts' must be the same as right-hand side of conclusion.") + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of premise instantiated with the map 'insts' must be the same as left-hand side of conclusion.") /** * <pre> @@ -437,18 +457,23 @@ object SCProofChecker { val expected = (ref(t1).left.map(phi => instantiatePredicateSchemas(phi, insts)), ref(t1).right.map(phi => instantiatePredicateSchemas(phi, insts))) if (isSameSet(bot.left, expected._1)) if (isSameSet(bot.right, expected._2)) - SCValidProof + SCValidProof(SCProof(step)) else - SCInvalidProof(Nil, "Right-hand side of premise instantiated with the map 'insts' must be the same as right-hand side of conclusion.") - else SCInvalidProof(Nil, "Left-hand side of premise instantiated with the map 'insts' must be the same as left-hand side of conclusion.") + SCInvalidProof(SCProof(step), Nil, "Right-hand side of premise instantiated with the map 'insts' must be the same as right-hand side of conclusion.") + else SCInvalidProof(SCProof(step), Nil, "Left-hand side of premise instantiated with the map 'insts' must be the same as left-hand side of conclusion.") case SCSubproof(sp, premises, _) => if (premises.size == sp.imports.size) { val invalid = premises.zipWithIndex.find((no, p) => !isSameSequent(ref(no), sp.imports(p))) if (invalid.isEmpty) { checkSCProof(sp) - } else SCInvalidProof(Nil, s"Premise number ${invalid.get._1} (refering to step ${invalid.get}) is not the same as import number ${invalid.get._1} of the subproof.") - } else SCInvalidProof(Nil, "Number of premises and imports don't match: " + premises.size + " " + sp.imports.size) + } else + SCInvalidProof( + SCProof(step), + Nil, + s"Premise number ${invalid.get._1} (refering to step ${invalid.get}) is not the same as import number ${invalid.get._1} of the subproof." + ) + } else SCInvalidProof(SCProof(step), Nil, "Number of premises and imports don't match: " + premises.size + " " + sp.imports.size) } r @@ -459,19 +484,19 @@ object SCProofChecker { * If the proof is not correct, the functrion will report the faulty line and a brief explanation. * * @param proof A SC proof to check - * @return SCValidProof if the proof is correct, else SCInvalidProof with the path to the incorrect proof step + * @return SCValidProof(SCProof(step)) if the proof is correct, else SCInvalidProof with the path to the incorrect proof step * and an explanation. */ def checkSCProof(proof: SCProof): SCProofCheckerJudgement = { val possibleError = proof.steps.view.zipWithIndex .map((step, no) => checkSingleSCStep(no, step, (i: Int) => proof.getSequent(i), Some(proof.imports.size)) match { - case SCInvalidProof(path, message) => SCInvalidProof(no +: path, message) - case SCValidProof => SCValidProof + case SCInvalidProof(_, path, message) => SCInvalidProof(proof, no +: path, message) + case SCValidProof(_) => SCValidProof(proof) } ) .find(j => !j.isValid) - if (possibleError.isEmpty) SCValidProof + if (possibleError.isEmpty) SCValidProof(proof) else possibleError.get } diff --git a/src/main/scala/lisa/settheory/SetTheoryDefinitions.scala b/src/main/scala/lisa/settheory/SetTheoryDefinitions.scala index cb030de9e9c2c4b51b05155aa472ebd5571ad3dc..0bb0cbc8a3a781d573ecc08194284e2be414ba5e 100644 --- a/src/main/scala/lisa/settheory/SetTheoryDefinitions.scala +++ b/src/main/scala/lisa/settheory/SetTheoryDefinitions.scala @@ -2,7 +2,7 @@ package lisa.settheory import lisa.kernel.fol.FOL._ import lisa.kernel.proof.RunningTheory -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} /** * Base trait for set theoretical axiom systems. diff --git a/src/main/scala/lisa/settheory/SetTheoryTGAxioms.scala b/src/main/scala/lisa/settheory/SetTheoryTGAxioms.scala index 6bd499c09a36a31806a92614699e05dea8ee4db0..81b81922de16ce5817a0add565bcf61d31477fe3 100644 --- a/src/main/scala/lisa/settheory/SetTheoryTGAxioms.scala +++ b/src/main/scala/lisa/settheory/SetTheoryTGAxioms.scala @@ -1,6 +1,7 @@ package lisa.settheory + import lisa.kernel.fol.FOL._ -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} /** * Axioms for the Tarski-Grothendieck theory (TG) diff --git a/src/main/scala/lisa/settheory/SetTheoryZAxioms.scala b/src/main/scala/lisa/settheory/SetTheoryZAxioms.scala index 5a47aad939e8c2afd84ad1f154820f7b308990b1..11fde4e4eb4e2dd94f99511f88123fd1a7394ed2 100644 --- a/src/main/scala/lisa/settheory/SetTheoryZAxioms.scala +++ b/src/main/scala/lisa/settheory/SetTheoryZAxioms.scala @@ -2,7 +2,7 @@ package lisa.settheory import lisa.kernel.fol.FOL.* import lisa.kernel.proof.RunningTheory -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} /** * Axioms for the Zermelo theory (Z) diff --git a/src/main/scala/lisa/settheory/SetTheoryZFAxioms.scala b/src/main/scala/lisa/settheory/SetTheoryZFAxioms.scala index 13221cc12f60f84b53fae1d358bb3d602919001a..e89ea065be30ad3354e1b7bbfa1049f754e52d3e 100644 --- a/src/main/scala/lisa/settheory/SetTheoryZFAxioms.scala +++ b/src/main/scala/lisa/settheory/SetTheoryZFAxioms.scala @@ -1,7 +1,7 @@ package lisa.settheory import lisa.kernel.fol.FOL._ -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} /** * Axioms for the Zermelo-Fraenkel theory (ZF) diff --git a/src/main/scala/proven/DSetTheory/Part1.scala b/src/main/scala/proven/DSetTheory/Part1.scala index 3d674ce858f4fd76b1d2005003dffcb54e1052a1..331916cc558db0ac818f310f44a056b95a79cf1f 100644 --- a/src/main/scala/proven/DSetTheory/Part1.scala +++ b/src/main/scala/proven/DSetTheory/Part1.scala @@ -1,8 +1,5 @@ package proven.DSetTheory -import lisa.kernel.Printer -import lisa.kernel.Printer.prettyFormula -import lisa.kernel.Printer.prettySCProof -import lisa.kernel.Printer.prettySequent + import lisa.kernel.fol.FOL import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof @@ -14,8 +11,11 @@ import proven.ElementsOfSetTheory.oPair import proven.ElementsOfSetTheory.orderedPairDefinition import proven.tactics.Destructors.* import proven.tactics.ProofTactics.* -import utilities.KernelHelpers.{_, given} -import utilities.TheoriesHelpers.{_, given} +import utilities.Helpers.{_, given} +import utilities.Printer +import utilities.Printer.prettyFormula +import utilities.Printer.prettySCProof +import utilities.Printer.prettySequent import scala.collection.immutable import scala.collection.immutable.SortedSet @@ -397,8 +397,6 @@ object Part1 { /* val lemma2 = SCProof({ - - // goal ∀b. (b ∈ ?B) ⇒ ∀a. (a ∈ ?A) ⇒ ∃!x. ?psi(x, a, b) ⊢ ∃!Z. ∃X. Z=UX /\ ∀x. (x ∈ X) ↔ ∃b. (b ∈ ?B) ∧ ∀x1. (x1 ∈ x) ↔ ∃a. (a ∈ ?A) ∧ ?psi(x1, a, b) // redGoal ∀b. (b ∈ ?B) ⇒ ∀a. (a ∈ ?A) ⇒ ∃!x. ?psi(x, a, b) ⊢ ∃Z1. ∀Z. Z=Z1 <=> ∃X. Z=UX /\ ∀x. (x ∈ X) ↔ ∃b. (b ∈ ?B) ∧ ∀x1. (x1 ∈ x) ↔ ∃a. (a ∈ ?A) ∧ ?psi(x1, a, b) // redGoal ∀b. (b ∈ ?B) ⇒ ∀a. (a ∈ ?A) ⇒ ∃!x. ?psi(x, a, b) ⊢ ∀Z. Z=UX <=> ∃X. Z=UX /\ ∀x. (x ∈ X) ↔ ∃b. (b ∈ ?B) ∧ ∀x1. (x1 ∈ x) ↔ ∃a. (a ∈ ?A) ∧ ?psi(x1, a, b) @@ -572,13 +570,10 @@ object Part1 { } /* val thm_lemmaCartesianProduct = theory.proofToTheorem("lemmaCartesianProduct", lemmaCartesianProduct, Seq(thm_lemmaMapTwoArguments)).get - val vA = VariableLabel("A") val vB = VariableLabel("B") val cart_product = ConstantFunctionLabel("cart_cross", 2) val def_oPair = theory.makeFunctionDefinition(lemmaCartesianProduct, Seq(thm_lemmaMapTwoArguments), cart_product, Seq(vA, vB), VariableLabel("z"), innerOfDefinition(lemmaCartesianProduct.conclusion.right.head)).get - - */ def innerOfDefinition(f: Formula): Formula = f match { @@ -600,10 +595,7 @@ object Part1 { } def main(args: Array[String]): Unit = { - def checkProof(proof: SCProof): Unit = { - val error = SCProofChecker.checkSCProof(proof) - println(prettySCProof(proof, error)) - } + println("\nthmMapFunctional") checkProof(thmMapFunctional) println("\nlemma1") diff --git a/src/main/scala/proven/ElementsOfSetTheory.scala b/src/main/scala/proven/ElementsOfSetTheory.scala index c1fd97c4000bee26b07bb7cd885d3a5a41d2396f..e5c83222a4a9f693bd518f27ea6646a8f2e74f2f 100644 --- a/src/main/scala/proven/ElementsOfSetTheory.scala +++ b/src/main/scala/proven/ElementsOfSetTheory.scala @@ -1,20 +1,17 @@ package proven -import lisa.kernel.Printer -import lisa.kernel.Printer.* + import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof import lisa.kernel.proof.SCProofChecker import lisa.kernel.proof.SequentCalculus.* import lisa.settheory.AxiomaticSetTheory import lisa.settheory.AxiomaticSetTheory.* -import lisa.settheory.AxiomaticSetTheory.* import proven.ElementsOfSetTheory.theory import proven.tactics.Destructors.* -import proven.tactics.Destructors.* import proven.tactics.ProofTactics.* -import proven.tactics.ProofTactics.* -import utilities.KernelHelpers.{_, given} -import utilities.TheoriesHelpers.{_, given} +import utilities.Helpers.{_, given} +import utilities.Printer +import utilities.Printer.* import scala.collection.immutable import scala.collection.immutable.SortedSet @@ -72,7 +69,7 @@ object ElementsOfSetTheory { val fin4 = generalizeToForall(fin3, fin3.conclusion.right.head, y) fin4.copy(imports = imps) } // |- ∀∀({x$1,y$2}={y$2,x$1}) - println(prettySequent(proofUnorderedPairSymmetry.conclusion)) + val thm_proofUnorderedPairSymmetry: theory.Theorem = theory.theorem("proofUnorderedPairSymmetry", "⊢ ∀y, x. {x, y} = {y, x}", proofUnorderedPairSymmetry, Seq(axiom(extensionalityAxiom), axiom(pairAxiom))).get @@ -324,7 +321,7 @@ object ElementsOfSetTheory { val p2 = RightImplies(emptySeq +> (p1.bot.left.head ==> p1.bot.right.head), 1, p1.bot.left.head, p1.bot.right.head) // |- ({x,y}={x',y'}) ==> (x=x' /\ y=y')\/(x=y' /\ y=x') generalizeToForall(SCProof(IndexedSeq(p0, p1, p2), IndexedSeq(() |- pairAxiom)), x, y, x1, y1) } // |- ∀∀∀∀(({x$4,y$3}={x'$2,y'$1})⇒(((y'$1=y$3)∧(x'$2=x$4))∨((x$4=y'$1)∧(y$3=x'$2)))) - println(prettySequent(proofUnorderedPairDeconstruction.conclusion)) + val thm_proofUnorderedPairDeconstruction = theory .theorem( "proofUnorderedPairDeconstruction", @@ -342,7 +339,6 @@ object ElementsOfSetTheory { /* val proofOrderedPairDeconstruction: SCProof = { - val opairxy = pair(pair(x, y), pair(x, x)) val opairxx = pair(pair(x, x), pair(x, x)) val opairxy1 = pair(pair(x1, y1), pair(x1, x1)) @@ -351,11 +347,8 @@ object ElementsOfSetTheory { val pairxx = pair(x, x) val pairxy1 = pair(x1, y1) val pairxx1 = pair(x1, x1) - - val p0 = SCSubproof(orderedPairDefinition, display = false) val p1 = SCSubproof(proofUnorderedPairDeconstruction) // |- ∀∀∀∀(({x$4,y$3}={x'$2,y'$1})⇒(((y'$1=y$3)∧(x'$2=x$4))∨((x$4=y'$1)∧(y$3=x'$2)))) - val p2: SCSubproof = SCSubproof(SCProof(byCase(x === y)( { val p2_0 = SCSubproof(SCProof({ @@ -388,7 +381,6 @@ object ElementsOfSetTheory { }, IndexedSeq(-2)) // {x',y'}={x,x}, x=y |- x=x' /\ x=y' val p2_2 = Cut(emptySeq ++< p2_0.bot ++> p2_1.bot, 0, 1, p2_0.bot.right.head) // ((x,y)=(x',y')), x=y |- x=x' /\ x=y' val p2_3 = RightSubstEq(emptySeq +< (oPair(x, y) === oPair(x1, y1)) +< (x === y) +> ((x === x1) /\ (y === y1)), 2, x, y, (x === x1) /\ (z === y1), z) - SCSubproof(SCProof(IndexedSeq(p2_0, p2_1, p2_2, p2_3), IndexedSeq(p0, p1)), IndexedSeq(-1, -2)) } // ((x,y)=(x',y')), x=y |- x=x' /\ y=y' , @@ -398,10 +390,8 @@ object ElementsOfSetTheory { val p2_0_1 = UseFunctionDefinition(emptySeq +> (oPair(x1, y1) === opairxy1), oPair, Seq(x1, y1)) // |- (x1, y1) === {{x1,y1}, {x1,x1}} val p2_0_2 = RightSubstEq(emptySeq +< (oPair(x, y) === oPair(x1, y1)) +> (oPair(x1, y1) === pair(pair(x, y), pair(x, x))), 0, oPair(x, y), oPair(x1, y1), z === pair(pair(x, y), pair(x, x)), z) // (x1,y1)=(x,y) |- ((x1,y1)={{x,y},{x,x}}) - val p2_0_3 = RightSubstEq(emptySeq +< (oPair(x, y) === oPair(x1, y1)) +< (opairxy1 === oPair(x1, y1)) +> (pair(pair(x, y), pair(x, x)) === pair(pair(x1, y1), pair(x1, x1))), 2, opairxy1, oPair(x1, y1), z === pair(pair(x, y), pair(x, x)), z) // (x1,y1)=(x,y), (x1,y1)={{x1,y1}, {x1,x1}} |- {{x1,y1}, {x1,x1}}={{x,y},{x,x}}) - val p2_0_4 = Cut(emptySeq +< (oPair(x, y) === oPair(x1, y1)) +> (pair(pair(x, y), pair(x, x)) === pair(pair(x1, y1), pair(x1, x1))), 1, 3, opairxy1 === oPair(x1, y1)) SCProof(IndexedSeq(p2_0_0, p2_0_1, p2_0_2, p2_0_3, p2_0_4), IndexedSeq(p0)) @@ -414,7 +404,6 @@ object ElementsOfSetTheory { case BinaryConnectorFormula(`or`, l, r) => (l, r) } val pr2_1: SCProof = destructRightOr(pr2_0, f, g) // ((x,y)=(x',y')) |- (({x',x'}={x,y})∧({x',y'}={x,x})), (({x,x}={x',x'})∧({x,y}={x',y'})) - val pb2_0 = SCSubproof({ val prb2_0_0 = instantiateForall(SCProof(IndexedSeq(), IndexedSeq(p1)), x, y, x1, x1) // |- (({x,y}={x',x'}) ⇒ (((x'=y)∧(x'=x))∨((x=x')∧(y=x')))) val f = (x1 === y) /\ (x1 === x) @@ -427,10 +416,8 @@ object ElementsOfSetTheory { SCProof(IndexedSeq(pb3_0_0, pb3_0_1, pb3_0_2, pb3_0_3, pb3_0_4), IndexedSeq(p1)) }, IndexedSeq(-2)) // {x',x'}={x,y} |- x=y val pb2_1 = SCSubproof(destructRightAnd(pr2_1, pairxx1 === pairxy, pairxx === pairxy1), IndexedSeq(-1, -2)) // ((x,y)=(x',y')) |- (({x',x'}={x,y}), (({x,x}={x',x'})∧({x,y}={x',y'})) - val pb2_2 = Cut(pb2_1.bot -> pb2_0.bot.left.head +> (x === y), 1, 0, pb2_0.bot.left.head) // ((x,y)=(x',y')) |- x=y, (({x,x}={x',x'})∧({x,y}={x',y'})) val pc2_0 = SCSubproof(SCProof(IndexedSeq(pb2_0, pb2_1, pb2_2), IndexedSeq(p0, p1)), IndexedSeq(-1, -2)) // ((x,y)=(x',y')) |- x=y, (({x,x}={x',x'})∧({x,y}={x',y'})) - val pc2_1 = SCSubproof({ val pc2_1_0 = SCSubproof(destructRightAnd(SCProof(IndexedSeq(), IndexedSeq(pc2_0)), pairxy === pairxy1, pairxx === pairxx1), IndexedSeq(-2)) // ((x,y)=(x',y')) |- x=y, {x,y}={x',y'} val pc2_1_1 = SCSubproof(instantiateForall(SCProof(IndexedSeq(), IndexedSeq(p1)), x, y, x1, y1), IndexedSeq(-1)) // (({x,y}={x',y'})⇒(((y'=y)∧(x'=x))∨((x=y')∧(y=x')))) @@ -450,7 +437,6 @@ object ElementsOfSetTheory { val prc2_2_4 = destructRightAnd(prc2_2_3, x === x1, x === x1) // ((x,y)=(x',y')) |- x=y, x'=x SCProof(prc2_2_4.steps, IndexedSeq(p1, pc2_0)) }, IndexedSeq(-2, 0)) // ((x,y)=(x',y')) |- x=y, x'=x - val pc2_3 = RightSubstEq(pc2_1.bot -> (x1 === y) +> (x === y) +< (x1 === x), 1, x, x1, z === y, z) // ((x,y)=(x',y')), x=x' |- x=y, ((y=y')∧(x=x'))) val pc2_4 = Cut(pc2_3.bot -< (x === x1), 2, 3, x === x1) // ((x,y)=(x',y')) |- x=y, ((y=y')∧(x=x'))) val pc2_5 = LeftNot(pc2_4.bot +< !(x === y) -> (x === y), 4, x === y) // ((x,y)=(x',y')), !x=y |- ((y=y')∧(x=x'))) @@ -458,16 +444,12 @@ object ElementsOfSetTheory { } // ((x,y)=(x',y')), !x=y |- x=x' /\ y=y' ).steps, IndexedSeq(p0, p1)), IndexedSeq(0, 1)) // ((x,y)=(x',y')) |- x=x' /\ y=y' SCProof(p0, p1, p2) - ??? } // |- (x,y)=(x', y') ===> x=x' /\ y=y' */ def main(args: Array[String]): Unit = { - def checkProof(proof: SCProof): Unit = { - val error = SCProofChecker.checkSCProof(proof) - println(prettySCProof(proof, error)) - } + println("\nproofUnorderedPairSymmetry") checkProof(proofUnorderedPairSymmetry) println("\nproofUnorderedPairDeconstruction") diff --git a/src/main/scala/proven/tactics/Destructors.scala b/src/main/scala/proven/tactics/Destructors.scala index 86fdd967d7c9383e43e1cb964f79f90e6b8cbdb2..39f2c6cd06d1dec8647e96ae3a19c5726ae52963 100644 --- a/src/main/scala/proven/tactics/Destructors.scala +++ b/src/main/scala/proven/tactics/Destructors.scala @@ -5,7 +5,7 @@ import lisa.kernel.proof.SCProof import lisa.kernel.proof.SequentCalculus.* import lisa.kernel.proof.SequentCalculus.* import proven.tactics.ProofTactics.hypothesis -import utilities.KernelHelpers.* +import utilities.Helpers.* object Destructors { def destructRightOr(p: SCProof, a: Formula, b: Formula): SCProof = { diff --git a/src/main/scala/proven/tactics/ProofTactics.scala b/src/main/scala/proven/tactics/ProofTactics.scala index 50b4d61a962826d74b41eec90a03b8e13be4e080..5ac98af434b313e80c47228e53f150a98b4c187d 100644 --- a/src/main/scala/proven/tactics/ProofTactics.scala +++ b/src/main/scala/proven/tactics/ProofTactics.scala @@ -1,10 +1,10 @@ package proven.tactics -import lisa.kernel.Printer.* import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof import lisa.kernel.proof.SequentCalculus.* -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} +import utilities.Printer.* import scala.collection.immutable.Set diff --git a/src/main/scala/proven/tactics/SimplePropositionalSolver.scala b/src/main/scala/proven/tactics/SimplePropositionalSolver.scala index a48c558fed8dbe7f1c7de0ba64bdad2d2fc8f3ea..69e75d73ac08756a9c2c05181bdcd0a4d780fdb4 100644 --- a/src/main/scala/proven/tactics/SimplePropositionalSolver.scala +++ b/src/main/scala/proven/tactics/SimplePropositionalSolver.scala @@ -3,7 +3,7 @@ package proven.tactics import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof import lisa.kernel.proof.SequentCalculus.* -import utilities.KernelHelpers.* +import utilities.Helpers.* import scala.collection.mutable.Set as mSet diff --git a/src/main/scala/utilities/KernelHelpers.scala b/src/main/scala/utilities/KernelHelpers.scala index 2e7ac7364a3e23b52d8f79683a01cf8f5cbb7bdd..f9967ba8727b4a433214976450b49f62c15ccb8b 100644 --- a/src/main/scala/utilities/KernelHelpers.scala +++ b/src/main/scala/utilities/KernelHelpers.scala @@ -14,7 +14,7 @@ import lisa.kernel.proof.SequentCalculus.isSameSequent * import lisa.KernelHelpers.* * </pre> */ -object KernelHelpers { +trait KernelHelpers { import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SequentCalculus.Sequent diff --git a/src/main/scala/utilities/TheoriesHelpers.scala b/src/main/scala/utilities/TheoriesHelpers.scala index e0f9864e76803c937d3dd528cc121170203bc497..9d6c32d2dec5f6db0ca7f1e0ce103a0f80c3b2f0 100644 --- a/src/main/scala/utilities/TheoriesHelpers.scala +++ b/src/main/scala/utilities/TheoriesHelpers.scala @@ -1,13 +1,12 @@ package utilities -import lisa.kernel.proof.RunningTheory -import lisa.kernel.proof.RunningTheoryJudgement +import lisa.kernel.fol.FOL.* import lisa.kernel.proof.RunningTheoryJudgement.InvalidJustification -import lisa.kernel.proof.SCProof -import lisa.kernel.proof.SequentCalculus.Rewrite -import lisa.kernel.proof.SequentCalculus.isSameSequent +import lisa.kernel.proof.SequentCalculus.* +import lisa.kernel.proof.* +import utilities.Printer -object TheoriesHelpers { +trait TheoriesHelpers extends KernelHelpers { // for when the kernel will have a dedicated parser extension (theory: RunningTheory) @@ -18,4 +17,39 @@ object TheoriesHelpers { else InvalidJustification("The proof does not prove the claimed statement", None) } + extension (just: RunningTheory#Justification) + def show(output: String => Unit = println): just.type = { + just match + case thm: RunningTheory#Theorem => output(s"Theorem ${thm.name} := ${Printer.prettySequent(thm.proposition)}") + case axiom: RunningTheory#Axiom => output(s"Axiom ${axiom.name} := ${Printer.prettyFormula(axiom.ax)}") + case d: RunningTheory#Definition => + d match + case pd: RunningTheory#PredicateDefinition => + output(s"Definition of predicate symbol ${pd.label.id} := ${Printer.prettyFormula(pd.label(pd.args.map(VariableTerm(_))*) <=> pd.phi)}") // (label, args, phi) + case fd: RunningTheory#FunctionDefinition => + output(s"Definition of function symbol ${fd.label.id} := ${Printer.prettyFormula((fd.label(fd.args.map(VariableTerm(_))*) === fd.out) <=> fd.phi)})") + // output(Printer.prettySequent(thm.proposition)) + // thm + just + } + + extension [J <: RunningTheory#Justification](theoryJudgement: RunningTheoryJudgement[J]) { + + def showAndGet(output: String => Unit = println): J = { + theoryJudgement match + case RunningTheoryJudgement.ValidJustification(just) => + just.show(output) + case InvalidJustification(message, error) => + output(s"$message\n${error match + case Some(judgement) => Printer.prettySCProof(judgement) + case None => "" + }") + theoryJudgement.get + } + } + + def checkProof(proof: SCProof, output: String => Unit = println): Unit = { + val judgement = SCProofChecker.checkSCProof(proof) + output(Printer.prettySCProof(judgement)) + } } diff --git a/src/main/scala/utilities/tptp/KernelParser.scala b/src/main/scala/utilities/tptp/KernelParser.scala index 3f7d2fe05c1c40c482291212c7bb75cf2c6d9f35..215e85d79f370b762bea599561a3a5354b5f9378 100644 --- a/src/main/scala/utilities/tptp/KernelParser.scala +++ b/src/main/scala/utilities/tptp/KernelParser.scala @@ -6,7 +6,7 @@ import leo.datastructures.TPTP.FOF import leo.modules.input.TPTPParser as Parser import lisa.kernel.fol.FOL as K import lisa.kernel.proof.SequentCalculus as LK -import utilities.KernelHelpers.* +import utilities.Helpers.* import utilities.tptp.* import java.io.File diff --git a/src/test/scala/lisa/kernel/EquivalenceCheckerTests.scala b/src/test/scala/lisa/kernel/EquivalenceCheckerTests.scala index 2576c9c9a4863c35b97ee62760b0ff958ea14bf2..c499619ec8712709280d0e31206fcc5ca0dbb748 100644 --- a/src/test/scala/lisa/kernel/EquivalenceCheckerTests.scala +++ b/src/test/scala/lisa/kernel/EquivalenceCheckerTests.scala @@ -1,10 +1,10 @@ package lisa.kernel -import lisa.kernel.Printer +import utilities.Printer import lisa.kernel.fol.FOL import lisa.kernel.fol.FOL.* import org.scalatest.funsuite.AnyFunSuite -import utilities.KernelHelpers.* +import utilities.Helpers.* import scala.collection.MapView import scala.collection.mutable.ArrayBuffer diff --git a/src/test/scala/lisa/kernel/FolTests.scala b/src/test/scala/lisa/kernel/FolTests.scala index 7ebe445cc788ee09fb913207d4f049260dede3ba..42e6caed9f3a9dd861be9db59162238fee6484d7 100644 --- a/src/test/scala/lisa/kernel/FolTests.scala +++ b/src/test/scala/lisa/kernel/FolTests.scala @@ -1,6 +1,6 @@ package lisa.kernel -import lisa.kernel.Printer +import utilities.Printer import lisa.kernel.fol.FOL.* import lisa.kernel.proof.RunningTheory import lisa.kernel.proof.RunningTheory.* @@ -8,7 +8,7 @@ import lisa.kernel.proof.SCProof import lisa.kernel.proof.SCProofChecker import lisa.kernel.proof.SequentCalculus.* import org.scalatest.funsuite.AnyFunSuite -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} import scala.collection.immutable.SortedSet import scala.util.Random diff --git a/src/test/scala/lisa/kernel/IncorrectProofsTests.scala b/src/test/scala/lisa/kernel/IncorrectProofsTests.scala index 840dbd5d3082f434a50fb957b5231781afc2de46..3d7aa18bf839e0e322f083663d889198d303b746 100644 --- a/src/test/scala/lisa/kernel/IncorrectProofsTests.scala +++ b/src/test/scala/lisa/kernel/IncorrectProofsTests.scala @@ -5,7 +5,7 @@ import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof import lisa.kernel.proof.SequentCalculus.* import test.ProofCheckerSuite -import utilities.KernelHelpers.* +import utilities.Helpers.* import scala.collection.immutable.SortedSet import scala.language.implicitConversions diff --git a/src/test/scala/lisa/kernel/PrinterTest.scala b/src/test/scala/lisa/kernel/PrinterTest.scala index cf6a4899b65440498135e5996e7a7547791543eb..67e91f29c1ca1820f2804de870b44f3359ca0dce 100644 --- a/src/test/scala/lisa/kernel/PrinterTest.scala +++ b/src/test/scala/lisa/kernel/PrinterTest.scala @@ -1,6 +1,6 @@ package lisa.kernel -import lisa.kernel.Printer._ +import utilities.Printer._ import lisa.kernel.fol.FOL._ import org.scalatest.funsuite.AnyFunSuite diff --git a/src/test/scala/lisa/kernel/ProofTests.scala b/src/test/scala/lisa/kernel/ProofTests.scala index fc559c9a75105307136b7fd0b6d6620da60589f1..d5704b084af2fccf9bf8fd0f39e8a7d009cab378 100644 --- a/src/test/scala/lisa/kernel/ProofTests.scala +++ b/src/test/scala/lisa/kernel/ProofTests.scala @@ -1,6 +1,6 @@ package lisa.kernel -import lisa.kernel.Printer +import utilities.Printer import lisa.kernel.fol.FOL.* import lisa.kernel.proof.RunningTheory import lisa.kernel.proof.RunningTheory.* @@ -8,7 +8,7 @@ import lisa.kernel.proof.SCProof import lisa.kernel.proof.SCProofChecker import lisa.kernel.proof.SequentCalculus.* import org.scalatest.funsuite.AnyFunSuite -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} import scala.util.Random diff --git a/src/test/scala/lisa/proven/ElementsOfSetTheoryTests.scala b/src/test/scala/lisa/proven/ElementsOfSetTheoryTests.scala index b9e09182ecdb26f35689f42134711a4ef1ae6798..36a3fb11e37022c4827d795d20d53fefddc173a2 100644 --- a/src/test/scala/lisa/proven/ElementsOfSetTheoryTests.scala +++ b/src/test/scala/lisa/proven/ElementsOfSetTheoryTests.scala @@ -1,6 +1,6 @@ -package proven +package lisa.proven -import lisa.kernel.Printer +import utilities.Printer import lisa.kernel.fol.FOL.* import lisa.kernel.fol.FOL.* import lisa.kernel.proof.SCProof @@ -10,8 +10,8 @@ import lisa.settheory.AxiomaticSetTheory.* import proven.ElementsOfSetTheory.* import proven.tactics.ProofTactics import test.ProofCheckerSuite -import utilities.KernelHelpers.{_, given} -import utilities.KernelHelpers.{_, given} +import utilities.Helpers.{_, given} +import utilities.Helpers.{_, given} class ElementsOfSetTheoryTests extends ProofCheckerSuite { diff --git a/src/test/scala/lisa/proven/SimpleProverTests.scala b/src/test/scala/lisa/proven/SimpleProverTests.scala index e0b99c734ee9091a7e5daad84562aabfe017f3a3..8598562aa8dd742ca7fee37d2314905d9f47c1ba 100644 --- a/src/test/scala/lisa/proven/SimpleProverTests.scala +++ b/src/test/scala/lisa/proven/SimpleProverTests.scala @@ -1,14 +1,14 @@ -package proven +package lisa.proven -import lisa.kernel.Printer -import lisa.kernel.Printer.* +import utilities.Printer +import utilities.Printer.* import lisa.kernel.fol.FOL.* import lisa.kernel.proof.RunningTheory import lisa.kernel.proof.RunningTheory.PredicateLogic import lisa.kernel.proof.SCProofChecker import org.scalatest.funsuite.AnyFunSuite import proven.tactics.SimplePropositionalSolver as SPS -import utilities.KernelHelpers.* +import utilities.Helpers.* import utilities.tptp.KernelParser.* import utilities.tptp.ProblemGatherer.getPRPproblems diff --git a/src/test/scala/test/ProofCheckerSuite.scala b/src/test/scala/test/ProofCheckerSuite.scala index 8a6011d729cf0cdd1a0409d4028a9555a82327fe..caaee39fda0749d07d6b38c21e122b36cdd2c422 100644 --- a/src/test/scala/test/ProofCheckerSuite.scala +++ b/src/test/scala/test/ProofCheckerSuite.scala @@ -1,14 +1,14 @@ package test -import lisa.kernel.Printer +import utilities.Printer import lisa.kernel.proof.SCProof import lisa.kernel.proof.SCProofChecker._ import lisa.kernel.proof.SequentCalculus.Sequent import lisa.kernel.proof.SequentCalculus.isSameSequent import lisa.settheory.AxiomaticSetTheory import org.scalatest.funsuite.AnyFunSuite -import utilities.KernelHelpers._ -import utilities.KernelHelpers.given_Conversion_Boolean_List_String_Option +import utilities.Helpers._ +import utilities.Helpers.given_Conversion_Boolean_List_String_Option abstract class ProofCheckerSuite extends AnyFunSuite { import lisa.kernel.fol.FOL.* @@ -39,14 +39,14 @@ abstract class ProofCheckerSuite extends AnyFunSuite { val axioms = AxiomaticSetTheory.axioms def checkProof(proof: SCProof): Unit = { - val error = checkSCProof(proof) - println(Printer.prettySCProof(proof, error)) + val judgement = checkSCProof(proof) + println(Printer.prettySCProof(judgement)) println(s"\n(${proof.totalLength} proof steps in total)") } def checkProof(proof: SCProof, expected: Sequent): Unit = { val judgement = checkSCProof(proof) - assert(judgement.isValid, "\n" + Printer.prettySCProof(proof, judgement)) + assert(judgement.isValid, "\n" + Printer.prettySCProof( judgement)) assert(isSameSequent(proof.conclusion, expected), s"(${Printer.prettySequent(proof.conclusion)} did not equal ${Printer.prettySequent(expected)})") }