import lisa.automation.Congruence import lisa.automation.Substitution.{ApplyRules as Substitute} import lisa.automation.Tableau import lisa.automation.atp.Goeland object Example extends lisa.Main: draft() val x = variable val y = variable val P = predicate[1] val f = function[1] // Simple proof with LISA's DSL val fixedPointDoubleApplication = Theorem(∀(x, P(x) ==> P(f(x))) |- P(x) ==> P(f(f(x)))) { val a1 = assume(∀(x, P(x) ==> P(f(x)))) have(thesis) by Tautology.from(a1 of x, a1 of f(x)) } // Example of set theoretic development /** * Theorem --- The empty set is a subset of every set. * * `|- ∅ ⊆ x` */ val emptySetIsASubset = Theorem( ∅ ⊆ x ) { have((y ∈ ∅) ==> (y ∈ x)) by Weakening(emptySetAxiom of (x := y)) val rhs = thenHave(∀(y, (y ∈ ∅) ==> (y ∈ x))) by RightForall have(thesis) by Tautology.from(subsetAxiom of (x := ∅, y := x), rhs) } /** * Theorem --- If a set has an element, then it is not the empty set. * * `y ∈ x ⊢ ! x = ∅` */ val setWithElementNonEmpty = Theorem( (y ∈ x) |- x =/= ∅ ) { have((x === ∅) |- !(y ∈ x)) by Substitute(x === ∅)(emptySetAxiom of (x := y)) } /** * Theorem --- A power set is never empty. * * `|- !powerAxiom(x) = ∅` */ val powerSetNonEmpty = Theorem( powerSet(x) =/= ∅ ) { have(thesis) by Tautology.from( setWithElementNonEmpty of (y := ∅, x := powerSet(x)), powerAxiom of (x := ∅, y := x), emptySetIsASubset ) } val buveurs = Theorem(exists(x, P(x) ==> forall(y, P(y)))) { have(thesis) by Tableau } // val a = variable // val one = variable // val two = variable // val * = SchematicFunctionLabel("*", 2) // val << = SchematicFunctionLabel("<<", 2) // val / = SchematicFunctionLabel("/", 2) // private val star: SchematicFunctionLabel[2] = * // private val shift: SchematicFunctionLabel[2] = << // private val divide: SchematicFunctionLabel[2] = / // extension (t:Term) { // def *(u:Term) = star(t, u) // def <<(u:Term) = shift(t, u) // def /(u:Term) = divide(t, u) // } // val congruence = Theorem(((a*two) === (a<<one), a*(two/two) === (a*two)/two, (two/two) === one, (a*one) === a) |- ((a<<one)/two) === a) { // have(thesis) by Congruence // } // import lisa.mathematics.settheory.SetTheory.* // Examples of definitions // val succ = DEF(x) --> union(unorderedPair(x, singleton(x))) // show // val inductiveSet = DEF(x) --> in(∅, x) /\ forall(y, in(y, x) ==> in(succ(y), x)) // show // Simple tactic definition for LISA DSL // object SimpleTautology extends ProofTactic { // def solveFormula(using proof: library.Proof)(f: Formula, decisionsPos: List[Formula], decisionsNeg: List[Formula]): proof.ProofTacticJudgement = { // val redF = reducedForm(f) // if (redF == ⊤) { // Restate(decisionsPos |- f :: decisionsNeg) // } else if (redF == ⊥) { // proof.InvalidProofTactic("Sequent is not a propositional tautology") // } else { // val atom = findBestAtom(redF).get // def substInRedF(f: Formula) = redF.substituted(atom -> f) // TacticSubproof { // have(solveFormula(substInRedF(⊤), atom :: decisionsPos, decisionsNeg)) // val step2 = thenHave(atom :: decisionsPos |- redF :: decisionsNeg) by Substitution2(⊤ <=> atom) // have(solveFormula(substInRedF(⊥), decisionsPos, atom :: decisionsNeg)) // val step4 = thenHave(decisionsPos |- redF :: atom :: decisionsNeg) by Substitution2(⊥ <=> atom) // have(decisionsPos |- redF :: decisionsNeg) by Cut(step4, step2) // thenHave(decisionsPos |- f :: decisionsNeg) by Restate // } // } // } // def solveSequent(using proof: library.Proof)(bot: Sequent) = // TacticSubproof { // Since the tactic above works on formulas, we need an extra step to convert an arbitrary sequent to an equivalent formula // have(solveFormula(sequentToFormula(bot), Nil, Nil)) // thenHave(bot) by Restate.from // } // } // val a = formulaVariable // val b = formulaVariable // val c = formulaVariable // val testTheorem = Lemma((a /\ (b \/ c)) <=> ((a /\ b) \/ (a /\ c))) { // have(thesis) by SimpleTautology.solveSequent // } // show /** * Example showing discharge of proofs using the Goeland theorem prover. Will * fail if Goeland is not available on PATH. */ object GoelandExample extends lisa.Main: val x = variable val y = variable val P = predicate[1] val f = function[1] val buveurs2 = Theorem(exists(x, P(x) ==> forall(y, P(y)))) { have(thesis) by Goeland // ("goeland/Example.buveurs2_sol") }