-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.lean
277 lines (248 loc) · 13.9 KB
/
Main.lean
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
import «CertifyingDatalog»
section CollectTreeModels
def collectModel {helper: ParseArityHelper} (l: List (ProofTreeSkeleton helper.toSignature)): CheckableModel helper.toSignature :=
match l with
| [] => []
| hd::tl => hd.elements ++ collectModel tl
lemma collectModelHasTreeElements {helper: ParseArityHelper} (l: List (ProofTreeSkeleton helper.toSignature)) (ga: GroundAtom helper.toSignature): ga ∈ collectModel l ↔ ∃ (t: ProofTreeSkeleton helper.toSignature), t ∈ l ∧ t.elem ga := by
induction l with
| nil =>
unfold collectModel
simp
| cons hd tl ih =>
unfold collectModel
simp
rw [ih,Tree.elem_iff_memElements]
lemma collectModelToSetIsSetOfTreesElements {helper: ParseArityHelper} (l: List (ProofTreeSkeleton helper.toSignature)): List.toSet (collectModel l) = {ga: GroundAtom helper.toSignature | ∃ t, t ∈ l ∧ t.elem ga} := by
apply Set.ext
intro ga
rw [← List.toSet_mem, collectModelHasTreeElements]
simp
end CollectTreeModels
section TreeListValidity
def checkTreeListValidityWithUnivDatabase (problem: TreeVerificationProblem): Except String Unit :=
let db := univDatabase problem.helper.toSignature
let kb : KnowledgeBase problem.helper.toSignature := { prog := problem.program, db }
ProofTreeSkeleton.checkValidityOfList problem.trees kb
theorem checkTreeListValidityWithUnivDatabaseUnitIffAllTreesValid (problem: TreeVerificationProblem): checkTreeListValidityWithUnivDatabase problem = Except.ok () ↔ ((∀ t ∈ problem.trees, t.isValid {prog := problem.program, db := univDatabase problem.helper.toSignature})
∧ ((collectModel problem.trees).toSet ⊆ {prog := problem.program, db := univDatabase problem.helper.toSignature : KnowledgeBase problem.helper.toSignature}.proofTheoreticSemantics)) := by
unfold checkTreeListValidityWithUnivDatabase
simp
rw [collectModelToSetIsSetOfTreesElements]
rw [← ProofTreeSkeleton.checkValidityOfListOkIffAllValidIffAllValidAndSubsetSemantics]
def checkTreeListModelhood (problem: TreeVerificationProblem) (safe: problem.program.isSafe): Except String Unit :=
let model := collectModel problem.trees
model.checkProgram problem.program safe
theorem checkTreeListModelHoodUnitIffModel (problem: TreeVerificationProblem) (safe: problem.program.isSafe) :
checkTreeListModelhood problem safe = Except.ok () ↔ Interpretation.models (List.toSet (collectModel problem.trees)) {prog := problem.program, db := emptyDatabase problem.helper.toSignature} := by
unfold checkTreeListModelhood
simp
rw [CheckableModel.checkProgramIsOkIffAllRulesAreSatisfied]
unfold Interpretation.models
simp
end TreeListValidity
section DagValidity
def checkDagValidityWithUnivDatabase (problem: GraphVerificationProblem): Except String Unit :=
let m := problem.program.toSymbolSequenceMap
let d:= univDatabase problem.helper.toSignature
problem.graph.checkValidity m d
theorem checkDagValidityWithUnivDatabaseUnitIffAcyclicAndAllValid (problem: GraphVerificationProblem) : checkDagValidityWithUnivDatabase problem = Except.ok () ↔ ((problem.graph.isAcyclic ∧ (∀ a ∈ problem.graph.vertices, problem.graph.locallyValid_for_kb {prog := problem.program, db := univDatabase problem.helper.toSignature} a))
∧ (problem.graph.vertices.toSet ⊆ {prog := problem.program, db := univDatabase problem.helper.toSignature : KnowledgeBase problem.helper.toSignature}.proofTheoreticSemantics)) := by
unfold checkDagValidityWithUnivDatabase
simp
rw [problem.graph.checkValidityIsOkIffAcyclicAndAllValid {prog := problem.program, db := univDatabase problem.helper.toSignature}]
simp
intro acyclic all_valid
apply Graph.verticesOfLocallyValidAcyclicGraphAreInProofTheoreticSemantics
exact acyclic; exact all_valid
def checkDagModelhood (problem: GraphVerificationProblem) (safe: problem.program.isSafe): Except String Unit :=
let model : CheckableModel problem.helper.toSignature := problem.graph.vertices
model.checkProgram problem.program safe
theorem checkDagModelhoodUnitIffModel (problem: GraphVerificationProblem) (safe: problem.program.isSafe) :
checkDagModelhood problem safe = Except.ok () ↔ Interpretation.models (List.toSet problem.graph.vertices) {prog := problem.program, db := emptyDatabase problem.helper.toSignature} := by
unfold checkDagModelhood
simp
rw [CheckableModel.checkProgramIsOkIffAllRulesAreSatisfied]
unfold Interpretation.models
simp
end DagValidity
section OrderedProofGraphValidity
def checkOrderedGraphValidityWithUnivDatabase (problem: OrderedGraphVerificationProblem): Except String Unit :=
let m := problem.program.toSymbolSequenceMap
let d:= univDatabase problem.helper.toSignature
problem.graph.checkValidity m d
theorem checkOrderedGraphValidityWithUnivDatabaseUnitIffValid (problem: OrderedGraphVerificationProblem) : checkOrderedGraphValidityWithUnivDatabase problem = Except.ok () ↔ ((problem.graph.isValid {prog := problem.program, db := univDatabase problem.helper.toSignature})
∧ (problem.graph.labels.toSet ⊆ {prog := problem.program, db := univDatabase problem.helper.toSignature : KnowledgeBase problem.helper.toSignature}.proofTheoreticSemantics)) := by
unfold checkOrderedGraphValidityWithUnivDatabase
simp
rw [problem.graph.checkValidity_semantics {prog := problem.program, db := univDatabase problem.helper.toSignature}]
simp
intro isValid
apply OrderedProofGraph.verticesValidOrderedProofGraphAreInProofTheoreticSemantics
exact isValid
def checkOrderedGraphModelhood (problem: OrderedGraphVerificationProblem) (safe: problem.program.isSafe): Except String Unit :=
let model : CheckableModel problem.helper.toSignature := problem.graph.labels
model.checkProgram problem.program safe
theorem checkOrderedGraphModelhoodUnitIffModel (problem: OrderedGraphVerificationProblem) (safe: problem.program.isSafe) :
checkOrderedGraphModelhood problem safe = Except.ok () ↔ Interpretation.models (List.toSet problem.graph.labels) {prog := problem.program, db := emptyDatabase problem.helper.toSignature} := by
unfold checkOrderedGraphModelhood
simp
rw [CheckableModel.checkProgramIsOkIffAllRulesAreSatisfied]
unfold Interpretation.models
simp
end OrderedProofGraphValidity
inductive InputFormat where
| trees: InputFormat
| graph: InputFormat
| orderedGraph: InputFormat
structure ArgsParsed where
(programFileName: String)
(complete: Bool)
(help: Bool)
(format: InputFormat)
def parseArgsHelper (args: List String) (curr: ArgsParsed) : Except String ArgsParsed :=
match args with
| [] =>
if curr.programFileName == ""
then Except.error "No program file name provided"
else Except.ok curr
| hd::tl =>
if hd ∈ ["-h", "--help"]
then Except.ok {programFileName := "", complete := false, help := true, format:= InputFormat.trees}
else if hd ∈ ["-c", "-g", "-o"]
then
if hd == "-c"
then parseArgsHelper tl {programFileName := "", complete := true, help := false, format:= curr.format}
else
if hd == "-g"
then parseArgsHelper tl {programFileName := "", complete := curr.complete , help := false, format:= InputFormat.graph}
else
if hd == "-o"
then parseArgsHelper tl {programFileName := "", complete := curr.complete , help := false, format:= InputFormat.orderedGraph}
else
Except.error ("Unknown argument " ++ hd)
else
if tl == []
then Except.ok {programFileName := hd, complete := curr.complete, help := false, format:= curr.format}
else Except.error "Too many arguments"
def parseArgs (args: List String): Except String ArgsParsed := parseArgsHelper args {programFileName := "", complete := false, help:= false, format:= InputFormat.trees}
def printHelp: IO Unit := do
IO.println "Datalog results validity checker"
IO.println "Input [Options] <problemFile>"
IO.println "Arguments"
IO.println " <problemFile>: contains a json description of the program and the proof trees"
IO.println "Options"
IO.println " -h --help Help (displayed right now)"
IO.println " -g Use a graph instead of a list of trees as an input via a list of edges (start -- end)"
IO.println " -o Use an topologically ordered graph instead of a list of trees as an input via a list atom and list of natural numbers of predecessors"
IO.println " -c Completeness check: instead of validating the proof, check if the facts form a model. (Can be combined with -g or -o.)"
def parseTreeProblemFromJson (fileName: String): IO (Except String TreeVerificationProblem) := do
let filePath := System.FilePath.mk fileName
if ← filePath.pathExists
then
match Lean.Json.parse (← IO.FS.readFile filePath) with
| Except.error msg => pure (Except.error ("Error parsing JSON " ++ msg))
| Except.ok json =>
match Lean.fromJson? (α:=TreeProblemInput) json with
| Except.error msg => pure (Except.error ("Json does not match problem description" ++ msg))
| Except.ok parsedProblem =>
pure (TreeVerificationProblem.fromProblemInput parsedProblem)
else pure (Except.error "File does not exist")
def main_trees (argsParsed: ArgsParsed): IO Unit := do
match ← parseTreeProblemFromJson argsParsed.programFileName with
| Except.error e => IO.println e
| Except.ok problem =>
if argsParsed.complete = true
then
IO.println "Checking Modelhood..."
match safe: problem.program.checkSafety with
| Except.error msg => IO.println msg
| Except.ok _ =>
have safe': ∀ (r: Rule problem.helper.toSignature), r ∈ problem.program → r.isSafe := by
rw [Program.checkSafety_iff_isSafe] at safe
apply safe
match checkTreeListModelhood problem safe' with
| Except.error msg => IO.println ("Invalid result due to: " ++ msg )
| Except.ok _ => IO.println "Valid result"
else
IO.println "Checking Proof Validity..."
match checkTreeListValidityWithUnivDatabase problem with
| Except.error msg => IO.println ("Invalid result due to: " ++ msg )
| Except.ok _ => IO.println "Valid result"
def parseDagProblemFromJson (fileName: String): IO (Except String GraphVerificationProblem) := do
let filePath := System.FilePath.mk fileName
if ← filePath.pathExists
then
match Lean.Json.parse (← IO.FS.readFile filePath) with
| Except.error msg => pure (Except.error ("Error parsing JSON " ++ msg))
| Except.ok json =>
match Lean.fromJson? (α:=GraphProblemInput) json with
| Except.error msg => pure (Except.error ("Json does not match problem description" ++ msg))
| Except.ok parsedProblem =>
pure (GraphVerificationProblem.fromProblemInput parsedProblem)
else pure (Except.error "File does not exist")
def main_dag (argsParsed: ArgsParsed): IO Unit := do
match ← parseDagProblemFromJson argsParsed.programFileName with
| Except.error e => IO.println e
| Except.ok problem =>
if argsParsed.complete = true
then
IO.println "Checking Modelhood..."
match safe: problem.program.checkSafety with
| Except.error msg => IO.println msg
| Except.ok _ =>
have safe': ∀ (r: Rule problem.helper.toSignature), r ∈ problem.program → r.isSafe := by
rw [Program.checkSafety_iff_isSafe] at safe
apply safe
match checkDagModelhood problem safe' with
| Except.error msg => IO.println ("Invalid result due to: " ++ msg )
| Except.ok _ => IO.println "Valid result"
else
IO.println "Checking Proof Validity..."
match checkDagValidityWithUnivDatabase problem with
| Except.error msg => IO.println ("Invalid result due to: " ++ msg )
| Except.ok _ => IO.println "Valid result"
def parseOrderedDagProblemFromJson (fileName: String): IO (Except String OrderedGraphVerificationProblem) := do
let filePath := System.FilePath.mk fileName
if ← filePath.pathExists
then
match Lean.Json.parse (← IO.FS.readFile filePath) with
| Except.error msg => pure (Except.error ("Error parsing JSON " ++ msg))
| Except.ok json =>
match Lean.fromJson? (α:=OrderedGraphProblemInput) json with
| Except.error msg => pure (Except.error ("Json does not match problem description" ++ msg))
| Except.ok parsedProblem =>
pure (OrderedGraphVerificationProblem.fromProblemInput parsedProblem)
else pure (Except.error "File does not exist")
def main_ordered_dag (argsParsed: ArgsParsed): IO Unit := do
match ← parseOrderedDagProblemFromJson argsParsed.programFileName with
| Except.error e => IO.println e
| Except.ok problem =>
if argsParsed.complete = true
then
IO.println "Checking Modelhood..."
match safe: problem.program.checkSafety with
| Except.error msg => IO.println msg
| Except.ok _ =>
have safe': ∀ (r: Rule problem.helper.toSignature), r ∈ problem.program → r.isSafe := by
rw [Program.checkSafety_iff_isSafe] at safe
apply safe
match checkOrderedGraphModelhood problem safe' with
| Except.error msg => IO.println ("Invalid result due to: " ++ msg )
| Except.ok _ => IO.println "Valid result"
else
IO.println "Checking Proof Validity..."
match checkOrderedGraphValidityWithUnivDatabase problem with
| Except.error msg => IO.println ("Invalid result due to: " ++ msg )
| Except.ok _ => IO.println "Valid result"
def main(args: List String): IO Unit := do
match parseArgs args with
| Except.error e => IO.println e
| Except.ok argsParsed =>
if argsParsed.help = true
then printHelp
else
match argsParsed.format with
| InputFormat.trees => main_trees argsParsed
| InputFormat.graph => main_dag argsParsed
| InputFormat.orderedGraph => main_ordered_dag argsParsed