-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathmcisProgScript.sml
478 lines (440 loc) · 12.8 KB
/
mcisProgScript.sml
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
(*
MCIS (unconnected) encode and checker
*)
open preamble basis pbc_normaliseTheory graphProgTheory mcisTheory graph_basicTheory;
val _ = new_theory "mcisProg"
val _ = translation_extends"graphProg";
val xlet_autop = xlet_auto >- (TRY( xcon) >> xsimpl)
(* The encoder *)
val res = translate enc_string_def;
val res = translate pbcTheory.map_obj_def;
val res = translate unmapped_obj_def;
val res = translate FOLDN_def;
val res = translate full_encode_mcis_eq;
(* parse input from f1 f2 and run encoder into pbc *)
val parse_and_enc = (append_prog o process_topdecs) `
fun parse_and_enc f1 f2 =
case parse_lad f1 of
Inl err => Inl err
| Inr gp =>
(case parse_lad f2 of
Inl err => Inl err
| Inr gt =>
Inr (fst gp, full_encode_mcis gp gt))`
Theorem parse_and_enc_spec:
STRING_TYPE f1 f1v ∧
STRING_TYPE f2 f2v ∧
validArg f1 ∧
validArg f2 ∧
hasFreeFD fs
⇒
app (p:'ffi ffi_proj) ^(fetch_v"parse_and_enc"(get_ml_prog_state()))
[f1v;f2v]
(STDIO fs)
(POSTv v.
STDIO fs *
& ∃res.
SUM_TYPE STRING_TYPE
(PAIR_TYPE NUM (PAIR_TYPE
(OPTION_TYPE (PAIR_TYPE
(LIST_TYPE (PAIR_TYPE INT (PBC_LIT_TYPE STRING_TYPE)))
INT))
(LIST_TYPE (PAIR_TYPE PBC_PBOP_TYPE (PAIR_TYPE (LIST_TYPE (PAIR_TYPE INT (PBC_LIT_TYPE STRING_TYPE))) INT)))
)) res v ∧
case res of
INL err =>
get_graph_lad fs f1 = NONE ∨
get_graph_lad fs f2 = NONE
| INR (n,objf) =>
∃gp gt.
get_graph_lad fs f1 = SOME gp ∧
get_graph_lad fs f2 = SOME gt ∧
full_encode_mcis gp gt = objf ∧
FST gp = n)
Proof
rw[]>>
xcf"parse_and_enc"(get_ml_prog_state())>>
xlet_autop>>
every_case_tac>>fs[SUM_TYPE_def]>>xmatch
>- (
xcon>>xsimpl>>
qexists_tac`INL err`>>simp[SUM_TYPE_def])>>
xlet_autop>>
every_case_tac>>fs[SUM_TYPE_def]>>xmatch
>- (
xcon>>xsimpl>>
qexists_tac`INL err`>>simp[SUM_TYPE_def])>>
rpt xlet_autop>>
xcon>>xsimpl >>
rename1`_ (full_encode_mcis gpp gtt)`>>
qexists_tac`INR (FST gpp,full_encode_mcis gpp gtt)`>>
simp[SUM_TYPE_def,PAIR_TYPE_def]
QED
(* Pretty print conclusion *)
Definition mcis_eq_str_def:
mcis_eq_str (n:num) =
strlit "s VERIFIED MAX CIS SIZE |CIS| = " ^
toString n ^ strlit"\n"
End
Definition mcis_bound_str_def:
mcis_bound_str (l:num) (u:num) =
strlit "s VERIFIED MAX CIS SIZE BOUND "^
toString l ^ strlit " <= |CIS| <= " ^
toString u ^ strlit"\n"
End
Definition print_mcis_str_def:
print_mcis_str (lbg:num,ubg:num) =
if lbg = ubg
then mcis_eq_str ubg
else mcis_bound_str lbg ubg
End
Definition mcis_sem_def:
mcis_sem gp gt (lbg,ubg) ⇔
if lbg = ubg then
max_cis_size gp gt = ubg
else
(∀vs. is_cis vs gp gt ⇒ CARD vs ≤ ubg) ∧
(∃vs. is_cis vs gp gt ∧ lbg ≤ CARD vs)
End
Definition check_unsat_3_sem_def:
check_unsat_3_sem fs f1 f2 out ⇔
(out ≠ strlit"" ⇒
∃gp gt bounds.
get_graph_lad fs f1 = SOME gp ∧
get_graph_lad fs f2 = SOME gt ∧
out = print_mcis_str bounds ∧
mcis_sem gp gt bounds)
End
Definition map_concl_to_string_def:
(map_concl_to_string n (INL s) = (INL s)) ∧
(map_concl_to_string n (INR (out,bnd,c)) =
case conv_concl n c of
SOME bounds => INR (print_mcis_str bounds)
| NONE => INL (strlit "c Unexpected conclusion for MCIS problem.\n"))
End
val res = translate (conv_concl_def |> REWRITE_RULE [GSYM sub_check_def]) ;
val conv_concl_side = Q.prove(
`∀x y. conv_concl_side x y <=> T`,
EVAL_TAC>>
rw[]>>
intLib.ARITH_TAC) |> update_precondition;
val res = translate mcis_eq_str_def;
val res = translate mcis_bound_str_def;
val res = translate print_mcis_str_def;
val res = translate map_concl_to_string_def;
Definition mk_prob_def:
mk_prob objf = (NONE,objf):mlstring list option #
((int # mlstring lit) list # int) option #
(pbop # (int # mlstring lit) list # int) list
End
val res = translate mk_prob_def;
val check_unsat_3 = (append_prog o process_topdecs) `
fun check_unsat_3 f1 f2 f3 =
case parse_and_enc f1 f2 of
Inl err => TextIO.output TextIO.stdErr err
| Inr (n,objf) =>
let val probt = default_prob in
(case
map_concl_to_string n
(check_unsat_top_norm False (mk_prob objf) probt f3) of
Inl err => TextIO.output TextIO.stdErr err
| Inr s => TextIO.print s)
end`
Theorem check_unsat_3_spec:
STRING_TYPE f1 f1v ∧ validArg f1 ∧
STRING_TYPE f2 f2v ∧ validArg f2 ∧
STRING_TYPE f3 f3v ∧ validArg f3 ∧
hasFreeFD fs
⇒
app (p:'ffi ffi_proj) ^(fetch_v"check_unsat_3"(get_ml_prog_state()))
[f1v; f2v; f3v]
(STDIO fs)
(POSTv uv. &UNIT_TYPE () uv *
SEP_EXISTS out err.
STDIO (add_stdout (add_stderr fs err) out) *
&(check_unsat_3_sem fs f1 f2 out))
Proof
rw[check_unsat_3_sem_def]>>
xcf "check_unsat_3" (get_ml_prog_state ())>>
reverse (Cases_on `STD_streams fs`) >- (fs [TextIOProofTheory.STDIO_def] \\ xpull) >>
xlet_autop>>
Cases_on`res`>>fs[SUM_TYPE_def]
>- (
xmatch>>
xapp_spec output_stderr_spec \\ xsimpl>>
asm_exists_tac>>xsimpl>>
qexists_tac`emp`>>xsimpl>>
qexists_tac`fs`>>xsimpl>>
rw[]>>
qexists_tac`x`>>xsimpl>>rw[]>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
xsimpl)
>- (
xmatch>>
xapp_spec output_stderr_spec \\ xsimpl>>
asm_exists_tac>>xsimpl>>
qexists_tac`emp`>>xsimpl>>
qexists_tac`fs`>>xsimpl>>
rw[]>>
qexists_tac`x`>>xsimpl>>rw[]>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
xsimpl)>>
Cases_on`y`>>fs[PAIR_TYPE_def]>>
xmatch>>
assume_tac npbc_parseProgTheory.default_prob_v_thm>>
xlet`POSTv v.
STDIO fs *
&prob_TYPE default_prob v`
>-
(xvar>>xsimpl)>>
xlet_autop>>
xlet`POSTv v. STDIO fs * &BOOL F v`
>-
(xcon>>xsimpl)>>
drule npbc_parseProgTheory.check_unsat_top_norm_spec>>
qpat_x_assum`prob_TYPE (mk_prob _) _`assume_tac>>
disch_then drule>>
qpat_x_assum`prob_TYPE default_prob _`assume_tac>>
disch_then drule>>
strip_tac>>
xlet_auto
>- (
xsimpl>>
fs[validArg_def]>>
metis_tac[])>>
xlet_autop>>
every_case_tac>>gvs[SUM_TYPE_def]
>- (
fs[map_concl_to_string_def,SUM_TYPE_def]>>
xmatch>>
xapp_spec output_stderr_spec \\ xsimpl>>
asm_exists_tac>>xsimpl>>
qexists_tac`emp`>>xsimpl>>
qexists_tac`fs`>>xsimpl>>
rw[]>>
qexists_tac`strlit ""`>>
rename1`add_stderr _ err`>>
qexists_tac`err`>>xsimpl>>rw[]>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
xsimpl)>>
fs[map_concl_to_string_def]>>
every_case_tac>>fs[SUM_TYPE_def]>>xmatch
>- (
xapp_spec output_stderr_spec \\ xsimpl>>
asm_exists_tac>>xsimpl>>
qexists_tac`emp`>>xsimpl>>
qexists_tac`fs`>>xsimpl>>
rw[]>>
qexists_tac`strlit ""`>>
rename1`add_stderr _ err`>>
qexists_tac`err`>>xsimpl>>rw[]>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
xsimpl)
>- (
xapp>>xsimpl>>
asm_exists_tac>>simp[]>>
qexists_tac`emp`>>qexists_tac`fs`>>xsimpl>>
rw[]>>
qexists_tac`print_mcis_str x`>>simp[]>>
qexists_tac`strlit ""`>>
rw[]>>simp[STD_streams_stderr,add_stdo_nil]>>
xsimpl>>
(drule_at Any) full_encode_mcis_sem_concl>>
fs[]>>
Cases_on`x`>> disch_then (drule_at Any)>>
disch_then(qspec_then`gt'` mp_tac)>>
impl_tac>-
fs[get_graph_lad_def,AllCaseEqs(),mk_prob_def]>>
rw[]>>
qexists_tac`(q,r)`>>
simp[mcis_sem_def]>>
metis_tac[])
QED
Definition check_unsat_2_sem_def:
check_unsat_2_sem fs f1 f2 out ⇔
case get_graph_lad fs f1 of
NONE => out = strlit ""
| SOME gpp =>
case get_graph_lad fs f2 of
NONE => out = strlit ""
| SOME gtt =>
out = concat (print_prob
(mk_prob (full_encode_mcis gpp gtt)))
End
val check_unsat_2 = (append_prog o process_topdecs) `
fun check_unsat_2 f1 f2 =
case parse_and_enc f1 f2 of
Inl err => TextIO.output TextIO.stdErr err
| Inr (n,objf) =>
TextIO.print_list (print_prob (mk_prob objf))`
Theorem check_unsat_2_spec:
STRING_TYPE f1 f1v ∧ validArg f1 ∧
STRING_TYPE f2 f2v ∧ validArg f2 ∧
hasFreeFD fs
⇒
app (p:'ffi ffi_proj) ^(fetch_v"check_unsat_2"(get_ml_prog_state()))
[f1v;f2v]
(STDIO fs)
(POSTv uv. &UNIT_TYPE () uv *
SEP_EXISTS out err.
STDIO (add_stdout (add_stderr fs err) out) *
&(check_unsat_2_sem fs f1 f2 out))
Proof
rw[check_unsat_2_sem_def]>>
xcf "check_unsat_2" (get_ml_prog_state ())>>
reverse (Cases_on `STD_streams fs`) >- (fs [TextIOProofTheory.STDIO_def] \\ xpull) >>
xlet_autop>>
Cases_on`res`>>fs[SUM_TYPE_def]
>- (
xmatch>>
xapp_spec output_stderr_spec \\ xsimpl>>
asm_exists_tac>>xsimpl>>
qexists_tac`emp`>>qexists_tac`fs`>>xsimpl>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
rw[]>>
qexists_tac`x`>>xsimpl)
>- (
xmatch>>
xapp_spec output_stderr_spec \\ xsimpl>>
asm_exists_tac>>xsimpl>>
qexists_tac`emp`>>qexists_tac`fs`>>xsimpl>>
every_case_tac>>xsimpl>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
rw[]>>
qexists_tac`x`>>xsimpl)>>
Cases_on`y`>>gvs[PAIR_TYPE_def]>>
xmatch>>
xlet_autop>>
xlet_autop>>
xapp_spec print_list_spec>>xsimpl>>
asm_exists_tac>>xsimpl>>
qexists_tac`emp`>>qexists_tac`fs`>>xsimpl>>
rw[]>>
qexists_tac`strlit ""`>>
simp[STD_streams_stderr,add_stdo_nil]>>
xsimpl
QED
Definition usage_string_def:
usage_string = strlit "Usage: cake_pb_mcis <LAD file (pattern)> <LAD file (target)> <optional: PB proof file>\n"
End
val r = translate usage_string_def;
val main = (append_prog o process_topdecs) `
fun main u =
case CommandLine.arguments () of
[f1,f2] => check_unsat_2 f1 f2
| [f1,f2,f3] => check_unsat_3 f1 f2 f3
| _ => TextIO.output TextIO.stdErr usage_string`
Definition main_sem_def:
main_sem fs cl out =
if LENGTH cl = 3 then
check_unsat_2_sem fs (EL 1 cl) (EL 2 cl) out
else if LENGTH cl = 4 then
check_unsat_3_sem fs (EL 1 cl) (EL 2 cl) out
else out = strlit ""
End
Theorem STDIO_refl:
STDIO A ==>>
STDIO A * GC
Proof
xsimpl
QED
Theorem main_spec:
hasFreeFD fs
⇒
app (p:'ffi ffi_proj) ^(fetch_v"main"(get_ml_prog_state()))
[Conv NONE []]
(COMMANDLINE cl * STDIO fs)
(POSTv uv. &UNIT_TYPE () uv *
COMMANDLINE cl *
SEP_EXISTS out err.
STDIO (add_stdout (add_stderr fs err) out) *
&(main_sem fs cl out))
Proof
rw[main_sem_def]>>
xcf"main"(get_ml_prog_state())>>
reverse (Cases_on `STD_streams fs`) >- (fs [TextIOProofTheory.STDIO_def] \\ xpull) >>
reverse(Cases_on`wfcl cl`) >- (fs[COMMANDLINE_def] \\ xpull)>>
rpt xlet_autop >>
Cases_on `cl` >- fs[wfcl_def] >>
Cases_on`t`>>fs[LIST_TYPE_def]
>- (
xmatch>>
xapp_spec output_stderr_spec \\ xsimpl>>
rename1`COMMANDLINE cl`>>
qexists_tac`COMMANDLINE cl`>>xsimpl>>
qexists_tac `usage_string` >>
simp [theorem "usage_string_v_thm"] >>
qexists_tac`fs`>>xsimpl>>
rw[]>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
metis_tac[STDIO_refl])>>
Cases_on`t'`>>fs[LIST_TYPE_def]
>- (
xmatch>>
xapp_spec output_stderr_spec \\ xsimpl>>
rename1`COMMANDLINE cl`>>
qexists_tac`COMMANDLINE cl`>>xsimpl>>
qexists_tac `usage_string` >>
simp [theorem "usage_string_v_thm"] >>
qexists_tac`fs`>>xsimpl>>
rw[]>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
metis_tac[STDIO_refl])>>
Cases_on`t`>>fs[LIST_TYPE_def]
>- (
xmatch>>
xapp>>rw[]>>
rpt(first_x_assum (irule_at Any)>>xsimpl)>>
fs[wfcl_def]>>
rw[]>>metis_tac[STDIO_refl])>>
Cases_on`t'`>>fs[LIST_TYPE_def]
>- (
xmatch>>
xapp>>rw[]>>
rpt(first_x_assum (irule_at Any)>>xsimpl)>>
fs[wfcl_def]>>
rw[]>>metis_tac[STDIO_refl])>>
xmatch>>
xapp_spec output_stderr_spec \\ xsimpl>>
rename1`COMMANDLINE cl`>>
qexists_tac`COMMANDLINE cl`>>xsimpl>>
qexists_tac `usage_string` >>
simp [theorem "usage_string_v_thm"] >>
qexists_tac`fs`>>xsimpl>>
rw[]>>
fs[STD_streams_add_stderr, STD_streams_stdout,add_stdo_nil]>>
metis_tac[STDIO_refl]
QED
Theorem main_whole_prog_spec2:
hasFreeFD fs ⇒
whole_prog_spec2 main_v cl fs NONE
(λfs'. ∃out err.
fs' = add_stdout (add_stderr fs err) out ∧
main_sem fs cl out)
Proof
rw[basis_ffiTheory.whole_prog_spec2_def]
\\ match_mp_tac (MP_CANON (DISCH_ALL (MATCH_MP app_wgframe (UNDISCH main_spec))))
\\ xsimpl
\\ rw[PULL_EXISTS]
\\ qexists_tac`add_stdout (add_stderr fs x') x`
\\ xsimpl
\\ qexists_tac`x`
\\ qexists_tac`x'`
\\ xsimpl
\\ simp[GSYM add_stdo_with_numchars,with_same_numchars]
QED
local
val name = "main"
val (sem_thm,prog_tm) =
whole_prog_thm (get_ml_prog_state()) name (UNDISCH main_whole_prog_spec2)
Definition main_prog_def:
main_prog = ^prog_tm
End
in
Theorem main_semantics =
sem_thm
|> REWRITE_RULE[GSYM main_prog_def]
|> DISCH_ALL
|> SIMP_RULE(srw_ss())[GSYM CONJ_ASSOC,AND_IMP_INTRO];
end
val _ = export_theory();