-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathExample.scala
143 lines (124 loc) · 4.68 KB
/
Example.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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")
}