-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconstraints.v
287 lines (243 loc) · 7.75 KB
/
constraints.v
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
Require Import bbv.Word.
Require Import Nat.
Require Import Coq.NArith.NArith.
Require Import FORVES2.constants.
Import Constants.
Require Import FORVES2.program.
Import Program.
Require Import List.
Import ListNotations.
Module Constraints.
(*
Literals
{{{*)
(* INFO: STABLE API *)
Inductive cliteral : Type :=
| C_VAR (n : nat) (* x *)
| C_VAL (n : N) (* c *)
| C_VAR_DELTA (n: nat)(delta : N) (* x + c *)
.
Definition eq_clit (c c': cliteral): bool :=
match c, c' with
| C_VAR n, C_VAR n' => n =? n'
| C_VAL n, C_VAL n' => (n =? n')%N
| C_VAR_DELTA n d, C_VAR_DELTA n' d' => (n =? n') && (d =? d')%N
| _, _ => false
end.
Theorem eq_clit_refl: forall c: cliteral, eq_clit c c = true.
Proof.
intros c.
destruct c;
try apply Bool.andb_true_iff;
try split;
try apply N.eqb_refl;
try apply PeanoNat.Nat.eqb_refl.
Qed.
Theorem eq_clit_snd: forall c c': cliteral,((eq_clit c c' = true) <-> c = c').
Proof.
intros c c'.
split.
- intro c_eq_c'.
destruct c.
-- destruct c'; try discriminate.
--- simpl in c_eq_c'.
apply PeanoNat.Nat.eqb_eq in c_eq_c'.
rewrite c_eq_c'.
reflexivity.
-- destruct c'; try discriminate.
--- simpl in c_eq_c'.
apply N.eqb_eq in c_eq_c'.
rewrite c_eq_c'.
reflexivity.
-- destruct c'; try discriminate.
simpl in c_eq_c'.
try apply Bool.andb_true_iff in c_eq_c'.
destruct c_eq_c' as [n_eq_n' d_eq_d'].
apply PeanoNat.Nat.eqb_eq in n_eq_n'.
apply N.eqb_eq in d_eq_d'.
rewrite <- n_eq_n'. rewrite <- d_eq_d'. reflexivity.
- intro c_is_c'.
rewrite c_is_c'.
apply eq_clit_refl.
Qed.
Theorem eq_clit_comm: forall c c': cliteral, eq_clit c c' = eq_clit c' c.
Proof.
intros [n | n | n d] [n' | n' | n' d'];
try (apply N.eqb_sym || apply PeanoNat.Nat.eqb_sym) || reflexivity.
- simpl.
rewrite (PeanoNat.Nat.eqb_sym n n').
rewrite (N.eqb_sym d d').
reflexivity.
Qed.
(*}}} End Literals *)
(*
Constraints
{{{*)
Inductive constraint : Type :=
| C_LT (l r : cliteral)
| C_EQ (l r : cliteral)
| C_LE (l r : cliteral)
.
Definition eqc (c c': constraint): bool :=
match c, c' with
| C_LT l r , C_LT l' r'
| C_EQ l r , C_EQ l' r'
| C_LE l r , C_LE l' r' => eq_clit l l' && eq_clit r r'
| _, _ => false
end.
Theorem eqc_refl(c: constraint): eqc c c = true.
Proof.
destruct c;
apply andb_true_intro;
split;
apply eq_clit_refl.
Qed.
Theorem eqc_snd(c c' : constraint): eqc c c' = true <-> c = c'.
Proof.
split.
- intro c_eq_c'.
destruct c;
destruct c' as [l' r'|l' r' |l' r']; try discriminate;
simpl in c_eq_c';
symmetry in c_eq_c';
apply Bool.andb_true_eq in c_eq_c';
destruct c_eq_c' as [l_eq_l' r_eq_r'];
symmetry in l_eq_l';
symmetry in r_eq_r';
apply eq_clit_snd in l_eq_l';
apply eq_clit_snd in r_eq_r';
rewrite l_eq_l';
rewrite r_eq_r';
reflexivity.
- intros c_is_c'.
rewrite c_is_c'.
apply eqc_refl.
Qed.
Theorem eqc_comm: forall c c', eqc c c' = eqc c' c.
Proof.
intros [l r | l r | l r] [l' r' | l' r' | l' r'];
simpl;
try rewrite (eq_clit_comm l l');
try rewrite (eq_clit_comm r r');
reflexivity.
Qed.
Notation conjunction := (list constraint).
Notation disjunction := (list conjunction).
Definition constraints : Type := disjunction.
(** A [constraints] is a disjunctive normal form representation of hypothesis. *)
(*}}} end Constraints *)
(*
Satisfiability of constraints
{{{*)
Definition assignment : Type := nat -> EVMWord.
(** Maps variable indexes to concrete values *)
Definition cliteral_to_nat (model: assignment) (c: cliteral): N :=
(** The value of the literal [c] under the assigment [model]. *)
match c with
| C_VAL n => n
| C_VAR i => wordToN (model i)
| C_VAR_DELTA i delta => wordToN (model i) + delta
end.
(* INFO: STABLE API *)
Definition satisfies_single_constraint (model: assignment) (c: constraint) : bool :=
let get_value := cliteral_to_nat model in
match c with
| C_EQ l r => (get_value l =? get_value r)%N
| C_LT l r => (get_value l <? get_value r)%N
| C_LE l r => (get_value l <=? get_value r)%N
end.
Definition satisfies_conjunction (model: assignment) (conj: conjunction): bool :=
forallb (satisfies_single_constraint model) conj.
Definition satisfies_constraints (model: assignment) (cs: constraints): bool :=
existsb (satisfies_conjunction model) cs.
Definition is_model (cs : constraints) (model : assignment) : bool := satisfies_constraints model cs.
(** A model of some constraints is a model which satisfies the constraints *)
Definition is_sat (cs : constraints) : Prop :=
exists (model : assignment), is_model cs model = true.
Definition imply(cs: constraints)(c: constraint) := forall (m: assignment),
satisfies_constraints m cs = true -> satisfies_single_constraint m c = true.
Definition conj_imply(cs: conjunction)(c: constraint) := forall (m: assignment),
satisfies_conjunction m cs = true -> satisfies_single_constraint m c = true.
(*}}} End of Satisfiability of constraints*)
(*
Implication checkers
{{{ *)
Record imp_checker: Type :=
{ imp_checker_fun: constraints -> constraint -> bool
; imp_checker_snd: forall (cs: constraints) (c: constraint),
imp_checker_fun cs c = true -> imply cs c
}.
Record conj_imp_checker: Type :=
{ conj_imp_checker_fun: conjunction -> constraint -> bool
; conj_imp_checker_snd: forall (cs: conjunction) (c: constraint),
conj_imp_checker_fun cs c = true -> conj_imply cs c
}.
Program Definition mk_imp_checker (checker: conj_imp_checker): imp_checker := {|
imp_checker_fun (cs : constraints) c :=
match cs with
| [] => false
| _ => forallb (fun conj => conj_imp_checker_fun checker conj c) cs
end
|}.
Next Obligation.
unfold imply; intros model.
destruct checker as [checker checker_snd].
rename H into full_checker__cs_imp_c.
induction cs as [|c' cs']; try discriminate.
simpl in *.
apply Bool.andb_true_iff in full_checker__cs_imp_c
as [checker__c'_imp_c checker__cs'_imp_c].
intros h; apply Bool.orb_true_iff in h as [c'_sat | cs'_sat].
- exact (checker_snd _ _ checker__c'_imp_c model c'_sat).
- unfold is_model in cs'_sat.
destruct cs' as [|c'' cs'']; try discriminate.
exact (IHcs' checker__cs'_imp_c cs'_sat).
Qed.
(* }}} Implication checkers *)
(*
Inclusion implication checker
{{{ *)
Program Definition inclusion_conj_imp_checker: conj_imp_checker := {|
conj_imp_checker_fun := fun cs c => existsb (eqc c) cs
|}.
Next Obligation.
unfold conj_imply; intros model cs_sat.
unfold imp_checker_snd.
induction cs as [|c' cs' IHcs']; try discriminate.
simpl in H.
destruct (eqc c' c) eqn:c'_is_c.
- apply eqc_snd in c'_is_c.
simpl in *.
apply Bool.andb_true_iff in cs_sat.
destruct cs_sat as [c'_sat _].
rewrite c'_is_c in c'_sat.
exact c'_sat.
- simpl.
rewrite (eqc_comm c' c) in c'_is_c.
simpl in cs_sat.
apply Bool.andb_true_iff in cs_sat.
destruct cs_sat as [_ cs'_sat].
rewrite c'_is_c in H.
simpl in H.
exact (IHcs' H cs'_sat).
Qed.
Definition inclusion_imp_checker := mk_imp_checker inclusion_conj_imp_checker.
(*}}} End Inclusion implication checker *)
Program Definition dummy_imp_checker : imp_checker := {|
imp_checker_fun (cs : constraints) c := false
|}.
Record sat_checker : Type :=
{ sat_checker_fun : constraints -> bool
(* TODO: Perhaps [option assigment] over [bool]?
Provides a witness that the constraints are provable *)
; sat_checker_snd : forall (cs : constraints),
sat_checker_fun cs = true -> is_sat cs
}.
Program Definition chk_is_sat : sat_checker := {|
sat_checker_fun (cs: constraints) := true
|}.
Next Obligation.
Admitted.
(* Compute sat_checker_fun chk_is_sat. *)
End Constraints.
(* vim: set foldmethod=marker: *)