aboutsummaryrefslogtreecommitdiffstats
path: root/src/State.v
blob: 953c8ee9a6a895dd871b86bea1819c876ce5b1df (plain)
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
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
(**************************************************************************)
(*                                                                        *)
(*     SMTCoq                                                             *)
(*     Copyright (C) 2011 - 2021                                          *)
(*                                                                        *)
(*     See file "AUTHORS" for the list of authors                         *)
(*                                                                        *)
(*   This file is distributed under the terms of the CeCILL-C licence     *)
(*                                                                        *)
(**************************************************************************)


Require Import List Bool Int63 PArray Omega.

(* Require Import AxiomesInt. *)

Local Open Scope int63_scope.
Local Open Scope array_scope.

Coercion is_true : bool >-> Sortclass.

Set Vm Optimize.

Notation var := int (only parsing).

(* Variables interpretation *)
Module Valuation.
(* TODO : Should be var -> Prop *)
  Definition t := var -> bool.
  Definition wf (rho : t) : Prop := rho 0 /\ ~ rho 1.

End Valuation.


Module Var.

  Definition _true : var := 0. (* true *)
  (* Register _true as PrimInline. *)

  Definition _false : var := 1. (* false *)

  Definition interp (rho:Valuation.t) (x:var) : bool := rho x.

  Lemma interp_true : forall rho, Valuation.wf rho -> interp rho _true.
  Proof. intros rho [H _];exact H. Qed.

  Lemma interp_false : forall rho, Valuation.wf rho -> ~ interp rho _false.
  Proof. intros rho [_ H];exact H. Qed.

End Var.

Notation _lit := int (only parsing).

Module Lit.

  Definition is_pos (l:_lit) := is_even l.
  (* Register is_pos as PrimInline. *)

  Definition blit (l:_lit) : var := l >> 1.
  (* Register blit as PrimInline. *)

  Definition lit (x:var) : _lit := x << 1.
  (* Register lit as PrimInline. *)

  Definition neg (l:_lit) : _lit := l lxor 1.
  (* Register neg as PrimInline. *)

  Definition nlit (x:var) : _lit := neg (lit x).
  (* Register nlit as PrimInline. *)

  Definition _true : _lit := Eval compute in lit Var._true.
  (* Register _true as PrimInline. *)

  Lemma lit_true : _true = lit Var._true.
  Proof. reflexivity. Qed.

  Definition _false : _lit := Eval compute in lit Var._false.
  (* Register _false as PrimInline. *)

  Lemma lit_false : _false = lit Var._false.
  Proof. reflexivity. Qed.

  Definition eqb (l l' : _lit) := l == l'.
  (* Register eqb as PrimInline. *)

  Lemma eqb_spec : forall l l', eqb l l' = true <-> l = l'.
  Proof eqb_spec.

  Lemma neg_involutive : forall l,  neg (neg l) = l.
  Proof.
    unfold neg;intros; rewrite <- lxor_assoc;change (1 lxor 1) with 0;rewrite lxor_0_r;trivial.
  Qed.

  Lemma blit_neg : forall l, blit (neg l) = blit l.
  Proof.
    unfold blit, neg;intros l.
    rewrite lxor_lsr, lxor_0_r;trivial.
  Qed.

  Lemma lit_blit: forall l,
    is_pos l = true -> lit (blit l) = l.
  Proof.
    unfold is_pos, lit, blit;intros.
    rewrite (bit_xor_split l) at 2.
    rewrite is_even_bit, negb_true_iff in H;rewrite H.
    symmetry;apply lxor_0_r.
  Qed.

  Lemma lit_blit_neg: forall l,
    is_pos l = false -> lit (blit l) = neg l.
  Proof.
    unfold is_pos, lit, blit;intros.
    rewrite (bit_xor_split l) at 2.
    rewrite is_even_bit, negb_false_iff in H;rewrite H.
    rewrite <- (neg_involutive ((l >> 1) << 1)) at 1;trivial.
  Qed.

  Lemma nlit_blit: forall l,
    is_pos l = false -> nlit (blit l) = l.
  Proof.
    unfold nlit;intros;rewrite lit_blit_neg;auto using neg_involutive.
  Qed.

  Lemma nlit_blit_neg: forall l,
    is_pos l = true -> nlit (blit l) = neg l.
  Proof.
    unfold nlit;intros;rewrite lit_blit;auto using neg_involutive.
  Qed.

  Lemma is_pos_lit : forall l,
    is_pos (lit l) = true.
  Proof.
    unfold is_pos, lit;apply is_even_lsl_1.
  Qed.

  Lemma is_pos_neg : forall l,
    is_pos (neg l) = negb (is_pos l).
  Proof.
    unfold neg, is_pos;intros l.
    rewrite is_even_xor, xorb_false_r;trivial.
  Qed.

  Lemma is_pos_nlit : forall l,
    is_pos (nlit l) = false.
  Proof.
    unfold nlit;intros l;rewrite is_pos_neg, is_pos_lit;trivial.
  Qed.

  Lemma is_pos_true : is_pos _true.
  Proof. reflexivity. Qed.

  Lemma is_pos_false : is_pos _false.
  Proof. reflexivity. Qed.

  Lemma blit_pos :forall a b,
    Lit.blit a = Lit.blit b -> Lit.is_pos a = Lit.is_pos b ->
    a = b.
  Proof lsr_is_even_eq.

  Lemma blit_lit : forall l, blit (lit (blit l)) = blit l.
  Proof.
    intros l;case_eq (is_pos l);intros.
    rewrite lit_blit;trivial.
    rewrite lit_blit_neg, blit_neg;trivial.
  Qed.

  Lemma blit_nlit : forall l, blit (nlit (blit l)) = blit l.
  Proof.
    intros l;case_eq (is_pos l);intros.
    rewrite nlit_blit_neg, blit_neg;trivial.
    rewrite nlit_blit;trivial.
  Qed.

  Lemma blit_true : blit _true = Var._true.
  Proof. reflexivity. Qed.

  Lemma blit_false : blit _false = Var._false.
  Proof. reflexivity. Qed.

                        (* Interpretation of a literal *)
  Definition interp rho (l:_lit) :=
    if is_pos l then Var.interp rho (blit l)
      else negb (Var.interp rho (blit l)).

  Lemma interp_true : forall rho, Valuation.wf rho -> interp rho _true.
  Proof.
    intros rho Hwf;unfold interp;rewrite is_pos_true, blit_true.
    apply Var.interp_true;trivial.
  Qed.

  Lemma interp_false : forall rho, Valuation.wf rho -> ~interp rho _false.
  Proof.
    intros rho Hwf;unfold interp;rewrite is_pos_false, blit_false.
    apply Var.interp_false;trivial.
  Qed.

  Lemma interp_neg : forall rho l, interp rho (neg l) = negb (interp rho l).
  Proof.
    intros rho l;unfold interp;rewrite is_pos_neg, blit_neg.
    destruct (is_pos l);simpl;auto using negb_involutive.
  Qed.

  Lemma interp_lit : forall rho l, interp rho (lit (blit l)) = Var.interp rho (blit l).
  Proof.
    intros;unfold interp;rewrite is_pos_lit, blit_lit;trivial.
  Qed.

  Lemma interp_nlit : forall rho l, interp rho (nlit (blit l)) = negb (Var.interp rho (blit l)).
  Proof.
    unfold nlit;intros rho l;rewrite interp_neg, interp_lit;trivial.
  Qed.

  Lemma interp_eq_compat : forall rho1 rho2 l,
    rho1 (blit l) = rho2 (blit l) ->
    interp rho1 l = interp rho2 l.
  Proof.
    unfold interp, Var.interp;intros rho1 rho2 l Heq;rewrite Heq;trivial.
  Qed.

  Lemma lxor_neg : forall l1 l2, (l1 lxor l2 == 1) = true -> l1 = Lit.neg l2.
  Proof.
    unfold Lit.neg; intros l1 l2;rewrite eqb_spec;intros Heq;rewrite <- Heq.
    rewrite lxor_comm, <- lxor_assoc, lxor_nilpotent, lxor_0_r;trivial.
  Qed.

End Lit.


Lemma compare_spec' : forall x y,
    match x ?= y with
    | Lt => x < y
    | Eq => x = y
    | Gt => y < x
    end.
Proof.
  intros x y;rewrite compare_def_spec;unfold compare_def.
  case_eq (x < y);intros;[reflexivity | ].
  case_eq (x == y);intros.
  rewrite <- eqb_spec;trivial.
  rewrite <- not_true_iff_false in H, H0.
  unfold is_true in *;rewrite ltb_spec in H |- *;rewrite eqb_spec in H0.
  assert ([|x|] <> [|y|]) by (intros Heq;apply H0, to_Z_inj;trivial);omega.
Qed.


Module C.

  Definition t := list _lit.

  Definition interp (rho:Valuation.t) (l:t) :=
    List.existsb (Lit.interp rho) l.

  Definition valid rho c :=
    interp rho c = true.

  Definition _true : t := Lit._true :: nil.

  Definition is_false (c:t) :=
    match c with
      | nil => true
      | _ => false
    end.

  Fixpoint has_true (c:t) :=
    match c with
      | nil => false
      | l :: c => (l == Lit._true) || has_true c
    end.
  

  Section OR.

    Variable or : t -> t -> t.
    Variable l1 : _lit.
    Variable c1 : t.

    Fixpoint or_aux (c2:t) :=
      match c2 with
      | nil => l1 :: c1
      | l2::c2' =>
        match l1 ?= l2 with
        | Eq => l1 :: or c1 c2'
        | Lt => l1 :: or c1 c2
        | Gt => l2 :: or_aux c2'
        end
      end.

    Variable rho : Valuation.t.
    Hypothesis or_correct : forall c2,
        interp rho (or c1 c2) = interp rho c1 || interp rho c2.

    Lemma or_aux_correct : forall c2,
      interp rho (or_aux c2) = interp rho (l1::c1) || interp rho c2.
    Proof.
      induction c2;simpl.
      rewrite orb_false_r;trivial.
      generalize (compare_spec' l1 a);destruct (l1 ?= a);intros H;simpl.
      rewrite H;destruct (Lit.interp rho a);trivial.
      rewrite !orb_false_l, or_correct;trivial.
      rewrite or_correct;simpl;rewrite orb_assoc;trivial.
      rewrite IHc2;simpl.
      destruct (Lit.interp rho a);simpl;trivial.
      rewrite orb_true_r;trivial.
    Qed.

  End OR.

  Fixpoint or (c1 c2:t) {struct c1} : t :=
    match c1, c2 with
    | nil, _ => c2
    | _, nil => c1
    | l1::c1, l2::c2' =>
      match compare l1 l2 with
      | Eq => l1 :: or c1 c2'
      | Lt => l1 :: or c1 c2
      | Gt => l2 :: or_aux or l1 c1 c2'
      end
    end.

  Lemma or_correct : forall rho c1 c2,
    interp rho (or c1 c2) = interp rho c1 || interp rho c2.
  Proof.
    induction c1;simpl;trivial.
    destruct c2;simpl.
    rewrite orb_false_r;trivial.
    generalize (compare_spec' a i);destruct (a ?= i);intros H;simpl.
    rewrite H, IHc1;simpl;destruct (Lit.interp rho i);simpl;trivial.
    rewrite IHc1, orb_assoc;trivial.
    rewrite or_aux_correct;simpl;trivial.
    destruct (Lit.interp rho i);trivial.
    simpl;rewrite !orb_true_r;trivial.
  Qed.

  Section RESOLVE.

    Variable resolve : t -> t -> t.
    Variable l1 : _lit.
    Variable c1 : t.

    Fixpoint resolve_aux (c2:t) : t :=
      match c2 with
      | nil => _true
      | l2::c2' =>
        match compare l1 l2 with
        | Eq => l1 :: resolve c1 c2'
        | Lt => if l1 lxor l2 == 1 then or c1 c2' else l1 :: resolve c1 c2
        | Gt =>
          if l1 lxor l2 == 1 then or c1 c2' else l2 :: resolve_aux c2'
        end
      end.

    Lemma resolve_aux_correct : forall rho,
      (forall c2, interp rho c1 -> interp rho c2 -> interp rho (resolve c1 c2)) ->
      interp rho (l1 :: c1) ->
      forall c2, interp rho c2 ->
      interp rho (resolve_aux c2).
    Proof.
      intros rho resolve_correct Hc1;simpl in Hc1.
      induction c2;simpl;try discriminate.
      generalize (compare_spec' l1 a);destruct (l1 ?= a);intros;subst;simpl.
      simpl in Hc1;destruct (Lit.interp rho a);simpl in *;auto.
      generalize (Lit.lxor_neg l1 a);destruct (l1 lxor a == 1);intros.
      rewrite or_correct.
      rewrite H1, Lit.interp_neg in Hc1;trivial;destruct (Lit.interp rho a).
      simpl in Hc1;rewrite Hc1;trivial.
      simpl in H0;rewrite H0, orb_true_r;trivial.
      simpl;destruct (Lit.interp rho l1);simpl;auto.
      generalize (Lit.lxor_neg l1 a);destruct (l1 lxor a == 1);intros.
      rewrite or_correct.
      rewrite H1, Lit.interp_neg in Hc1;trivial;destruct (Lit.interp rho a).
      simpl in Hc1;rewrite Hc1;trivial.
      simpl in H0;rewrite H0, orb_true_r;trivial.
      simpl;destruct (Lit.interp rho a);simpl;auto.
    Qed.

  End RESOLVE.

  Fixpoint resolve (c1 c2:t) {struct c1} : t :=
    match c1, c2 with
    | nil, _ => _true
    | _, nil => _true
    | l1::c1, l2::c2' =>
      match compare l1 l2 with
      | Eq => l1 :: resolve c1 c2'
      | Lt => if l1 lxor l2 == 1 then or c1 c2' else l1 :: resolve c1 c2
      | Gt =>
        if l1 lxor l2 == 1 then or c1 c2' else l2 :: resolve_aux resolve l1 c1 c2'
      end
    end.

  Lemma resolve_correct : forall rho c1 c2,
    interp rho c1 -> interp rho c2 ->
    interp rho (resolve c1 c2).
  Proof.
    induction c1;simpl;try discriminate.
    destruct c2;simpl;try discriminate.
    intros Hc1 Hc2.
    generalize (compare_spec' a i);destruct (a ?= i);intros;subst;simpl.
    destruct (Lit.interp rho i);simpl in *;auto.
    generalize (Lit.lxor_neg a i);destruct (a lxor i == 1);intros.
    rewrite or_correct.
    rewrite H0, Lit.interp_neg in Hc1;trivial;destruct (Lit.interp rho i).
    simpl in Hc1;rewrite Hc1;trivial.
    simpl in Hc2;rewrite Hc2, orb_true_r;trivial.
    simpl;destruct (Lit.interp rho a);simpl;auto.
    generalize (Lit.lxor_neg a i);destruct (a lxor i == 1);intros.
    rewrite or_correct.
    rewrite H0, Lit.interp_neg in Hc1;trivial;destruct (Lit.interp rho i).
    simpl in Hc1;rewrite Hc1;trivial.
    simpl in Hc2;rewrite Hc2, orb_true_r;trivial.
    simpl;destruct (Lit.interp rho i);simpl;auto using resolve_aux_correct.
  Qed.

  Lemma interp_true : forall rho, Valuation.wf rho -> interp rho _true = true.
  Proof.
    unfold _true, interp;intros rho Hwf;simpl.
    rewrite Lit.interp_true;trivial.
  Qed.

  Lemma is_false_correct :
    forall c, is_false c = true ->
      forall rho, ~valid rho c.
  Proof.
    unfold valid, interp;destruct c;simpl; auto;discriminate.
  Qed.

  Lemma Cinterp_neg rho cl :
    interp rho (List.map Lit.neg cl) = negb (List.forallb (Lit.interp rho) cl).
  Proof.
    induction cl as [ |l cl IHcl]; auto.
    simpl. now rewrite negb_andb, IHcl, Lit.interp_neg.
  Qed.

End C.


Notation clause_id := int (only parsing).

Notation resolution := (array clause_id) (only parsing).

Module S.

  Definition t := array C.t.

  Definition get (s:t) (cid:clause_id) := s.[cid].
  (* Register get as PrimInline. *)

  (* Do not use this function outside this module *)
  (* expect if you are sure that [c = sort_uniq c] *)
  Definition internal_set (s:t) (cid:clause_id) (c:C.t) : t := s.[cid <- c].
  (* Register internal_set as PrimInline. *)

  Definition make (nclauses : int) : t :=
    PArray.make nclauses C._true.

  Definition valid rho s :=
    forall id, C.valid rho (get s id).


  (* Specification of make *)

  Lemma valid_make : forall rho nclauses,
    Valuation.wf rho ->
    valid rho (make nclauses).
  Proof.
    unfold valid, make, get;intros.
    rewrite PArray.get_make; apply C.interp_true;trivial.
  Qed.


  (* Specification of get *)

  Lemma valid_get : forall rho s, valid rho s ->
    forall id, C.valid rho (get s id).
  Proof. intros rho s H id. unfold valid in H. unfold Valuation.t in rho. apply H. Qed.
  (** Proof. auto. Qed. **)


  (* Specification of internal_set *)

  Lemma valid_internal_set :
    forall rho s, valid rho s ->
      forall c, C.valid rho c ->
        forall id, valid rho (set s id c).
  Proof.
    unfold valid, get;simpl;intros.
    destruct (Int63Properties.reflect_eqb id id0);subst.
    case_eq (id0 < length s);intros.
    rewrite PArray.get_set_same;trivial.
    rewrite PArray.get_outofbound.
    rewrite PArray.default_set.
    rewrite <- (PArray.get_outofbound _ _ (length s)); trivial.
    rewrite <- not_true_iff_false, ltb_spec;auto with zarith.
    rewrite PArray.length_set;trivial.
    rewrite get_set_other;trivial.
  Qed.

  (* Building clause *)
  (* Same as set but without precondition *)

  (* TODO: It can be a good idea to change the insertion sort algorithm *)

  Fixpoint insert l1 c :=
   match c with
   | nil => l1:: nil
   | l2 :: c' =>
     match l1 ?= l2 with
     | Lt => if l1 lxor l2 == 1 then C._true else l1 :: c
     | Eq => c
     | Gt => if l1 lxor l2 == 1 then C._true else l2 :: insert l1 c'
     end
   end.

  Fixpoint insert_no_simpl l1 c :=
   match c with
   | nil => l1:: nil
   | l2 :: c' =>
     match l1 ?= l2 with
     | Lt => l1 :: c
     | Eq => c
     | Gt => l2 :: insert_no_simpl l1 c'
     end
   end.

  Fixpoint insert_keep l1 c :=
   match c with
   | nil => l1:: nil
   | l2 :: c' =>
     match l1 ?= l2 with
     | Lt | Eq => l1 :: c
     | Gt => l2 :: insert_keep l1 c'
     end
   end.

  Fixpoint sort c :=
    match c with
    | nil => nil
    | l1 :: c => insert_no_simpl l1 (sort c)
    end.

  
  Fixpoint sort_uniq c :=
    match c with
    | nil => nil
    | l1 :: c => insert l1 (sort_uniq c)
    end.

  Fixpoint sort_keep c :=
    match c with
    | nil => nil
    | l1 :: c => insert_keep l1 (sort_keep c)
    end.

  
  Lemma insert_correct : forall rho (Hwf:Valuation.wf rho) l1 c,
    C.interp rho (insert l1 c) = C.interp rho (l1 :: c).
  Proof.
    intros rho Hwf l1;induction c;simpl;trivial.
    generalize (compare_spec' l1 a);destruct (l1 ?= a);intros;subst;simpl.
    destruct (Lit.interp rho a);simpl in *;auto.
    generalize (Lit.lxor_neg l1 a);destruct (l1 lxor a == 1);intros;trivial.
    rewrite C.interp_true;trivial.
    rewrite H0, Lit.interp_neg;trivial;destruct (Lit.interp rho a);trivial.
    generalize (Lit.lxor_neg l1 a);destruct (l1 lxor a == 1);intros.
    rewrite C.interp_true;trivial.
    rewrite H0, Lit.interp_neg;trivial;destruct (Lit.interp rho a);trivial.
    simpl;rewrite orb_assoc,(orb_comm (Lit.interp rho l1)),<-orb_assoc,IHc;trivial.
  Qed.

  
  Lemma insert_no_simpl_correct : forall rho (Hwf:Valuation.wf rho) l1 c,
    C.interp rho (insert_no_simpl l1 c) = C.interp rho (l1 :: c).
  Proof.
    intros rho Hwf l1;induction c;simpl;trivial.
    generalize (compare_spec' l1 a);destruct (l1 ?= a);intros;subst;simpl;auto.
    destruct (Lit.interp rho a);simpl in *;auto.
    simpl;rewrite orb_assoc,(orb_comm (Lit.interp rho l1)),<-orb_assoc,IHc;trivial.
  Qed.

  Lemma insert_keep_correct : forall rho (Hwf:Valuation.wf rho) l1 c,
      C.interp rho (insert_keep l1 c) = C.interp rho (l1 :: c).
  Proof.
    intros rho Hwf l1;induction c;simpl;trivial.
    generalize (compare_spec' l1 a);destruct (l1 ?= a);intros;subst;simpl;auto.
    destruct (Lit.interp rho a);simpl in *;auto. rewrite orb_true_r; auto.
  Qed.

    
  Lemma sort_uniq_correct : forall rho (Hwf:Valuation.wf rho) c,
    C.interp rho (sort_uniq c) = C.interp rho c.
  Proof.
    intros rho Hwf;induction c;simpl;trivial.
    rewrite insert_correct;trivial;simpl;rewrite IHc;trivial.
  Qed.

      
  Lemma sort_correct : forall rho (Hwf:Valuation.wf rho) c,
    C.interp rho (sort c) = C.interp rho c.
  Proof.
    intros rho Hwf;induction c;simpl;trivial.
    rewrite insert_no_simpl_correct;trivial;simpl;rewrite IHc;trivial.
  Qed.

        
  Lemma sort_keep_correct : forall rho (Hwf:Valuation.wf rho) c,
    C.interp rho (sort_keep c) = C.interp rho c.
  Proof.
    intros rho Hwf;induction c;simpl;trivial.
    rewrite insert_keep_correct;trivial;simpl;rewrite IHc;trivial.
  Qed.

  
  (* Definition set_clause (s:t) pos (c:C.t) : t := *)
  (*   set s pos (sort_uniq c). *)
  
  (* Version that does not simplify ~a \/ a *)
  Definition set_clause (s:t) pos (c:C.t) : t :=
    set s pos (sort c).

  Lemma valid_set_clause :
    forall rho s, Valuation.wf rho -> valid rho s -> forall pos c,
                 C.valid rho c -> valid rho (set_clause s pos c).
  Proof.
    unfold valid, get, set_clause. intros rho s Hrho Hs pos c Hc id.
    destruct (Int63Properties.reflect_eqb pos id);subst.
    case_eq (id < length s); intro H.
    unfold get;rewrite PArray.get_set_same; trivial.
    unfold C.valid;rewrite sort_correct;trivial.
    generalize (Hs id);rewrite !PArray.get_outofbound, PArray.default_set;trivial.
    rewrite length_set;trivial.
    rewrite get_set_other;trivial.
  Qed.

  Definition set_clause_keep (s:t) pos (c:C.t) : t :=
    set s pos (sort_keep c).


  Lemma valid_set_clause_keep :
    forall rho s, Valuation.wf rho -> valid rho s -> forall pos c,
                 C.valid rho c -> valid rho (set_clause_keep s pos c).
  Proof.
    unfold valid, get, set_clause_keep. intros rho s Hrho Hs pos c Hc id.
    destruct (Int63Properties.reflect_eqb pos id);subst.
    case_eq (id < length s); intro H.
    unfold get;rewrite PArray.get_set_same; trivial.
    unfold C.valid;rewrite sort_keep_correct;trivial.
    generalize (Hs id);rewrite !PArray.get_outofbound, PArray.default_set;trivial.
    rewrite length_set;trivial.
    rewrite get_set_other;trivial.
  Qed.

  (* Resolution *)

  Open Scope int63_scope.

  Definition set_resolve (s:t) pos (r:resolution) : t :=
    let len := PArray.length r in
    if len == 0 then s
    else
      let c := foldi (fun i c' => (C.resolve (get s (r.[i])) c')) 1 (len - 1) (get s (r.[0])) in
      (* S.set_clause *) internal_set s pos c.

  Lemma valid_set_resolve :
    forall rho s, Valuation.wf rho -> valid rho s ->
      forall pos r, valid rho (set_resolve s pos r).
  Proof.
    unfold set_resolve; intros rho s Hrho Hv pos r.
    destruct (Int63Properties.reflect_eqb (length r) 0);[trivial | ].
    apply valid_internal_set;trivial.
    (* apply S.valid_set_clause; auto. *)
    apply foldi_ind;auto.
    intros i c _ _ Hc. apply C.resolve_correct;auto;apply Hv.
  Qed.


  (* Weakening *)


  Definition subclause (cl1 cl2 : list _lit) :=
    List.forallb (fun l1 =>
                    (l1 == Lit._false) || (l1 == Lit.neg Lit._true) ||
                    List.existsb (fun l2 => l1 == l2) cl2) cl1.
  
  Definition check_weaken (s:t) (cid:clause_id) (cl:list _lit) : C.t :=
    if subclause (get s cid) cl then cl else C._true.


  Lemma check_weaken_valid : forall rho s (cid:clause_id) (cl:list _lit),
      Valuation.wf rho ->
      valid rho s ->
      C.valid rho (check_weaken s cid cl).
  Proof.
    intros rho s cid cl Hw Hs.
    unfold check_weaken, C.valid.
    case_eq (subclause (get s cid) cl); try (intros; now apply C.interp_true).
    specialize (Hs cid).
    unfold C.valid, C.interp in Hs.
    apply existsb_exists in Hs.
    intro.
    unfold subclause in H.
    rewrite forallb_forall in H.
    unfold C.valid, C.interp.
    apply existsb_exists.
    destruct Hs as (x, (Hi, Hax)).
    specialize (H x Hi).
    rewrite !orb_true_iff in H.
    rewrite !eqb_spec in H.
    destruct H as [[H | H] | H].
    - contradict Hax. subst. apply Lit.interp_false; trivial.
    - contradict Hax. subst. rewrite Lit.interp_neg.
      rewrite not_true_iff_false, negb_false_iff, Lit.interp_true; trivial.
    - apply existsb_exists in H.
      destruct H as (x', (Hcl, Hxx')).
      rewrite eqb_spec in Hxx'.
      subst x'.
      exists x. auto.
  Qed.
  
  Definition set_weaken (s:t) pos (cid:clause_id) (cl:list _lit) : t :=
      S.set_clause_keep s pos (check_weaken s cid cl).

  
      
  Lemma valid_set_weaken :
    forall rho s, Valuation.wf rho -> valid rho s ->
      forall pos cid w, valid rho (set_weaken s pos cid w).
  Proof.
    intros.
    apply S.valid_set_clause_keep; auto.
    apply check_weaken_valid; auto.
  Qed.

  
End S.