2015-12-31 20:44:34 +00:00
|
|
|
Require Import Classical FunctionalExtensionality List.
|
|
|
|
|
|
|
|
Set Implicit Arguments.
|
|
|
|
|
|
|
|
|
|
|
|
Axiom prop_ext : forall P Q : Prop,
|
|
|
|
(P <-> Q) -> P = Q.
|
|
|
|
|
|
|
|
Section set.
|
|
|
|
Variable A : Type.
|
|
|
|
|
|
|
|
Definition set := A -> Prop.
|
|
|
|
Definition In (x : A) (s : set) := s x.
|
|
|
|
|
|
|
|
Definition constant (ls : list A) : set := fun x => List.In x ls.
|
|
|
|
Definition universe : set := fun _ => True.
|
|
|
|
Definition check (P : Prop) : set := fun _ => P.
|
|
|
|
|
|
|
|
Definition union (s1 s2 : set) : set := fun x => s1 x \/ s2 x.
|
|
|
|
Definition intersection (s1 s2 : set) : set := fun x => s1 x /\ s2 x.
|
2016-02-14 22:55:59 +00:00
|
|
|
Definition minus (s1 s2 : set) : set := fun x => s1 x /\ ~s2 x.
|
2015-12-31 20:44:34 +00:00
|
|
|
Definition complement (s : set) : set := fun x => ~s x.
|
|
|
|
|
|
|
|
Definition subseteq (s1 s2 : set) := forall x, s1 x -> s2 x.
|
|
|
|
Definition subset (s1 s2 : set) := subseteq s1 s2 /\ ~subseteq s2 s1.
|
|
|
|
|
|
|
|
Definition scomp (P : A -> Prop) : set := P.
|
|
|
|
|
|
|
|
Theorem sets_equal : forall s1 s2 : set, (forall x, s1 x <-> s2 x) -> s1 = s2.
|
|
|
|
Proof.
|
|
|
|
intros.
|
|
|
|
apply functional_extensionality; intros.
|
|
|
|
apply prop_ext; auto.
|
|
|
|
Qed.
|
|
|
|
End set.
|
|
|
|
|
|
|
|
Infix "\in" := In (at level 70).
|
|
|
|
Notation "[ P ]" := (check P).
|
|
|
|
Infix "\cup" := union (at level 40).
|
|
|
|
Infix "\cap" := intersection (at level 40).
|
2016-04-26 17:46:48 +00:00
|
|
|
Infix "\setminus" := minus (at level 40).
|
2015-12-31 20:44:34 +00:00
|
|
|
Infix "\subseteq" := subseteq (at level 70).
|
|
|
|
Infix "\subset" := subset (at level 70).
|
|
|
|
Notation "[ x | P ]" := (scomp (fun x => P)).
|
|
|
|
|
2017-03-21 23:27:36 +00:00
|
|
|
Module Type EMPTY.
|
|
|
|
End EMPTY.
|
|
|
|
Module SetNotations(M : EMPTY).
|
|
|
|
Notation "{ }" := (constant nil).
|
|
|
|
Notation "{ x1 , .. , xN }" := (constant (cons x1 (.. (cons xN nil) ..))).
|
|
|
|
End SetNotations.
|
|
|
|
|
|
|
|
|
2015-12-31 20:44:34 +00:00
|
|
|
Ltac sets' tac :=
|
2016-04-22 23:11:42 +00:00
|
|
|
unfold In, constant, universe, check, union, intersection, minus, complement, subseteq, subset, scomp in *;
|
2015-12-31 20:44:34 +00:00
|
|
|
tauto || intuition tac.
|
|
|
|
|
|
|
|
Ltac sets tac :=
|
|
|
|
try match goal with
|
|
|
|
| [ |- @eq (set _) _ _ ] => apply sets_equal; intro; split
|
|
|
|
end; sets' tac.
|
|
|
|
|
|
|
|
|
|
|
|
(** * Some of the usual properties of set operations *)
|
|
|
|
|
|
|
|
Section properties.
|
|
|
|
Variable A : Type.
|
|
|
|
Variable x : A.
|
|
|
|
Variables s1 s2 s3 : set A.
|
|
|
|
|
|
|
|
Theorem union_comm : s1 \cup s2 = s2 \cup s1.
|
|
|
|
Proof.
|
|
|
|
sets idtac.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem union_assoc : (s1 \cup s2) \cup s3 = s1 \cup (s2 \cup s3).
|
|
|
|
Proof.
|
|
|
|
sets idtac.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem intersection_comm : s1 \cap s2 = s2 \cap s1.
|
|
|
|
Proof.
|
|
|
|
sets idtac.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem intersection_assoc : (s1 \cap s2) \cap s3 = s1 \cap (s2 \cap s3).
|
|
|
|
Proof.
|
|
|
|
sets idtac.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem not_union : complement (s1 \cup s2) = complement s1 \cap complement s2.
|
|
|
|
Proof.
|
|
|
|
sets idtac.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem not_intersection : complement (s1 \cap s2) = complement s1 \cup complement s2.
|
|
|
|
Proof.
|
|
|
|
sets idtac.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem subseteq_refl : s1 \subseteq s1.
|
|
|
|
Proof.
|
|
|
|
unfold subseteq; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem subseteq_In : s1 \subseteq s2 -> x \in s1 -> x \in s2.
|
|
|
|
Proof.
|
|
|
|
unfold subseteq, In; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem cap_split : forall (P1 P2 : A -> Prop),
|
|
|
|
(forall s, P1 s \/ P2 s)
|
|
|
|
-> s1 \cap [s | P1 s] \subseteq s2
|
|
|
|
-> s1 \cap [s | P2 s] \subseteq s3
|
|
|
|
-> s1 \subseteq (s2 \cap [s | P1 s]) \cup (s3 \cap [s | P2 s]).
|
|
|
|
Proof.
|
|
|
|
intros; sets eauto.
|
|
|
|
specialize (H x0).
|
|
|
|
specialize (H0 x0).
|
|
|
|
specialize (H1 x0).
|
|
|
|
tauto.
|
|
|
|
Qed.
|
2016-02-14 22:13:25 +00:00
|
|
|
|
|
|
|
Variables ss1 ss2 : list A.
|
|
|
|
|
|
|
|
Theorem union_constant : constant ss1 \cup constant ss2 = constant (ss1 ++ ss2).
|
|
|
|
Proof.
|
|
|
|
unfold constant, union; simpl.
|
|
|
|
|
|
|
|
apply sets_equal; simpl; intuition.
|
|
|
|
Qed.
|
2015-12-31 20:44:34 +00:00
|
|
|
End properties.
|
|
|
|
|
|
|
|
Hint Resolve subseteq_refl subseteq_In.
|
2016-02-14 22:13:25 +00:00
|
|
|
|
2017-03-06 01:46:53 +00:00
|
|
|
(*Hint Rewrite union_constant.*)
|
2016-02-14 22:33:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
(** * Removing duplicates from constant sets *)
|
|
|
|
|
|
|
|
Inductive removeDups A : list A -> list A -> Prop :=
|
|
|
|
| RdNil : removeDups nil nil
|
|
|
|
| RdNew : forall x ls ls',
|
|
|
|
~List.In x ls
|
|
|
|
-> removeDups ls ls'
|
|
|
|
-> removeDups (x :: ls) (x :: ls')
|
|
|
|
| RdDup : forall x ls ls',
|
|
|
|
List.In x ls
|
|
|
|
-> removeDups ls ls'
|
|
|
|
-> removeDups (x :: ls) ls'.
|
|
|
|
|
|
|
|
Theorem removeDups_fwd : forall A x (ls ls' : list A),
|
|
|
|
removeDups ls ls'
|
|
|
|
-> List.In x ls
|
|
|
|
-> List.In x ls'.
|
|
|
|
Proof.
|
|
|
|
induction 1; simpl; intuition.
|
|
|
|
subst; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem removeDups_bwd : forall A x (ls ls' : list A),
|
|
|
|
removeDups ls ls'
|
|
|
|
-> List.In x ls'
|
|
|
|
-> List.In x ls.
|
|
|
|
Proof.
|
|
|
|
induction 1; simpl; intuition.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem removeDups_ok : forall A (ls ls' : list A),
|
|
|
|
removeDups ls ls'
|
|
|
|
-> constant ls = constant ls'.
|
|
|
|
Proof.
|
|
|
|
intros.
|
|
|
|
apply sets_equal.
|
|
|
|
unfold constant; intuition eauto using removeDups_fwd, removeDups_bwd.
|
|
|
|
Qed.
|
|
|
|
|
2016-02-18 22:51:58 +00:00
|
|
|
Ltac someMatch ls :=
|
|
|
|
match ls with
|
|
|
|
| ?x :: ?ls' =>
|
|
|
|
let rec someMatch' ls :=
|
|
|
|
match ls with
|
|
|
|
| x :: _ => idtac
|
|
|
|
| _ :: ?ls' => someMatch' ls'
|
|
|
|
end
|
|
|
|
in someMatch' ls'
|
|
|
|
| _ :: ?ls' => someMatch ls'
|
|
|
|
end.
|
|
|
|
|
2016-02-14 22:33:46 +00:00
|
|
|
Ltac removeDups :=
|
|
|
|
match goal with
|
|
|
|
| [ |- context[constant ?ls] ] =>
|
2016-02-18 22:51:58 +00:00
|
|
|
someMatch ls;
|
2016-02-14 22:33:46 +00:00
|
|
|
erewrite (@removeDups_ok _ ls)
|
|
|
|
by repeat (apply RdNil
|
|
|
|
|| (apply RdNew; [ simpl; intuition congruence | ])
|
|
|
|
|| (apply RdDup; [ simpl; intuition congruence | ]))
|
|
|
|
end.
|
2016-02-14 22:55:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
(** * Simplifying set subtraction with constant sets *)
|
|
|
|
|
|
|
|
Inductive doSubtract A : list A -> list A -> list A -> Prop :=
|
|
|
|
| DsNil : forall ls, doSubtract nil ls nil
|
|
|
|
| DsKeep : forall x ls ls0 ls',
|
|
|
|
~List.In x ls0
|
|
|
|
-> doSubtract ls ls0 ls'
|
|
|
|
-> doSubtract (x :: ls) ls0 (x :: ls')
|
|
|
|
| DsDrop : forall x ls ls0 ls',
|
2016-04-21 17:42:30 +00:00
|
|
|
List.In x ls0
|
2016-02-14 22:55:59 +00:00
|
|
|
-> doSubtract ls ls0 ls'
|
|
|
|
-> doSubtract (x :: ls) ls0 ls'.
|
|
|
|
|
|
|
|
Theorem doSubtract_fwd : forall A x (ls ls0 ls' : list A),
|
|
|
|
doSubtract ls ls0 ls'
|
|
|
|
-> List.In x ls
|
|
|
|
-> ~List.In x ls0
|
|
|
|
-> List.In x ls'.
|
|
|
|
Proof.
|
|
|
|
induction 1; simpl; intuition.
|
|
|
|
subst; eauto.
|
2016-04-21 17:42:30 +00:00
|
|
|
tauto.
|
2016-02-14 22:55:59 +00:00
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem doSubtract_bwd1 : forall A x (ls ls0 ls' : list A),
|
|
|
|
doSubtract ls ls0 ls'
|
|
|
|
-> List.In x ls'
|
|
|
|
-> List.In x ls.
|
|
|
|
Proof.
|
|
|
|
induction 1; simpl; intuition.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem doSubtract_bwd2 : forall A x (ls ls0 ls' : list A),
|
|
|
|
doSubtract ls ls0 ls'
|
|
|
|
-> List.In x ls'
|
|
|
|
-> List.In x ls0
|
|
|
|
-> False.
|
|
|
|
Proof.
|
|
|
|
induction 1; simpl; intuition.
|
|
|
|
subst; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem doSubtract_ok : forall A (ls ls0 ls' : list A),
|
|
|
|
doSubtract ls ls0 ls'
|
|
|
|
-> constant ls \setminus constant ls0 = constant ls'.
|
|
|
|
Proof.
|
|
|
|
unfold minus.
|
|
|
|
intros.
|
|
|
|
apply sets_equal.
|
|
|
|
unfold constant; intuition eauto using doSubtract_fwd, doSubtract_bwd1, doSubtract_bwd2.
|
|
|
|
Qed.
|
|
|
|
|
2016-04-21 17:42:30 +00:00
|
|
|
Ltac fancy_neq :=
|
|
|
|
solve [ repeat match goal with
|
|
|
|
| [ H : @eq (nat -> _) _ _ |- _ ] => apply (f_equal (fun f => f 0)) in H
|
|
|
|
| [ H : _ = _ |- _ ] => inversion H; clear H; subst
|
|
|
|
end ].
|
|
|
|
|
2016-02-14 22:55:59 +00:00
|
|
|
Ltac doSubtract :=
|
|
|
|
match goal with
|
2018-03-17 23:35:43 +00:00
|
|
|
| [ |- context[@minus ?A (@constant ?A1 ?ls) (@constant ?A2 ?ls0)] ] =>
|
|
|
|
match A with
|
|
|
|
| A1 => idtac
|
|
|
|
| _ => change (@constant A1 ls) with (@constant A ls)
|
|
|
|
end;
|
|
|
|
match A with
|
|
|
|
| A2 => idtac
|
|
|
|
| _ => change (@constant A2 ls0) with (@constant A ls0)
|
|
|
|
end;
|
|
|
|
erewrite (@doSubtract_ok A ls ls0)
|
2016-02-14 22:55:59 +00:00
|
|
|
by repeat (apply DsNil
|
2016-04-21 17:42:30 +00:00
|
|
|
|| (apply DsKeep; [ simpl; intuition (congruence || fancy_neq) | ])
|
2016-02-14 22:55:59 +00:00
|
|
|
|| (apply DsDrop; [ simpl; intuition congruence | ]))
|
|
|
|
end.
|
2016-02-15 00:23:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
(** Undetermined set variables in fixed points should be turned into the empty set. *)
|
|
|
|
Ltac unifyTails :=
|
|
|
|
match goal with
|
|
|
|
| [ |- context[_ \cup ?x] ] => is_evar x;
|
|
|
|
match type of x with
|
|
|
|
| set ?A => unify x (constant (@nil A))
|
|
|
|
| ?A -> Prop => unify x (constant (@nil A))
|
|
|
|
end
|
|
|
|
end.
|
2017-03-06 01:46:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
(** * But wait... there's a reflective way to do some of this, too. *)
|
|
|
|
|
|
|
|
Require Import Arith.
|
|
|
|
Import List ListNotations.
|
|
|
|
|
|
|
|
Section setexpr.
|
|
|
|
Variable A : Type.
|
|
|
|
|
|
|
|
Inductive setexpr :=
|
|
|
|
| Literal (vs : list nat)
|
|
|
|
| Constant (s : set A)
|
|
|
|
| Union (e1 e2 : setexpr).
|
|
|
|
|
|
|
|
Fixpoint interp_setexpr (env : list A) (e : setexpr) : set A :=
|
|
|
|
match e with
|
|
|
|
| Literal vs =>
|
|
|
|
match env with
|
2017-03-21 23:27:36 +00:00
|
|
|
| [] => constant []
|
2017-03-06 01:46:53 +00:00
|
|
|
| x :: _ => constant (map (nth_default x env) vs)
|
|
|
|
end
|
|
|
|
| Constant s => s
|
|
|
|
| Union e1 e2 => interp_setexpr env e1 \cup interp_setexpr env e2
|
|
|
|
end.
|
|
|
|
|
|
|
|
Record normal_form := {
|
|
|
|
Elements : list nat;
|
|
|
|
Other : option (set A)
|
|
|
|
}.
|
|
|
|
|
|
|
|
Fixpoint member (n : nat) (ls : list nat) : bool :=
|
|
|
|
match ls with
|
|
|
|
| [] => false
|
|
|
|
| m :: ls' => (n =? m) || member n ls'
|
|
|
|
end.
|
|
|
|
|
|
|
|
Fixpoint dedup (ls : list nat) : list nat :=
|
|
|
|
match ls with
|
|
|
|
| [] => []
|
|
|
|
| n :: ls =>
|
|
|
|
let ls' := dedup ls in
|
|
|
|
if member n ls' then ls' else n :: ls'
|
|
|
|
end.
|
|
|
|
|
|
|
|
Fixpoint setmerge (ls1 ls2 : list nat) : list nat :=
|
|
|
|
match ls1 with
|
|
|
|
| [] => ls2
|
|
|
|
| n :: ls1' =>
|
|
|
|
if member n ls2 then setmerge ls1' ls2 else n :: setmerge ls1' ls2
|
|
|
|
end.
|
|
|
|
|
|
|
|
Fixpoint normalize_setexpr (e : setexpr) : normal_form :=
|
|
|
|
match e with
|
|
|
|
| Literal vs => {| Elements := dedup vs; Other := None |}
|
|
|
|
| Constant s => {| Elements := []; Other := Some s |}
|
|
|
|
| Union e1 e2 =>
|
|
|
|
let nf1 := normalize_setexpr e1 in
|
|
|
|
let nf2 := normalize_setexpr e2 in
|
|
|
|
{| Elements := setmerge nf1.(Elements) nf2.(Elements);
|
|
|
|
Other := match nf1.(Other), nf2.(Other) with
|
|
|
|
| None, None => None
|
|
|
|
| o, None => o
|
|
|
|
| None, o => o
|
|
|
|
| Some s1, Some s2 => Some (s1 \cup s2)
|
|
|
|
end |}
|
|
|
|
end.
|
|
|
|
|
|
|
|
Definition interp_normal_form (env : list A) (nf : normal_form) : set A :=
|
|
|
|
let cs := match env with
|
2017-03-21 23:27:36 +00:00
|
|
|
| [] => constant []
|
2017-03-06 01:46:53 +00:00
|
|
|
| x :: _ => constant (map (nth_default x env) nf.(Elements))
|
|
|
|
end in
|
|
|
|
match nf.(Other) with
|
|
|
|
| None => cs
|
|
|
|
| Some o => cs \cup o
|
|
|
|
end.
|
|
|
|
|
|
|
|
Lemma member_ok : forall n ns,
|
|
|
|
if member n ns then In n ns else ~In n ns.
|
|
|
|
Proof.
|
|
|
|
induction ns; simpl; intuition.
|
|
|
|
case_eq (n =? a); simpl; intros.
|
|
|
|
apply beq_nat_true in H; auto.
|
|
|
|
apply beq_nat_false in H.
|
|
|
|
destruct (member n ns); intuition.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma In_dedup_fwd : forall n ns,
|
|
|
|
In n (dedup ns)
|
|
|
|
-> In n ns.
|
|
|
|
Proof.
|
|
|
|
induction ns; simpl; intuition.
|
|
|
|
pose proof (member_ok a (dedup ns)).
|
|
|
|
destruct (member a (dedup ns)); simpl in *; intuition.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma In_dedup_bwd : forall n ns,
|
|
|
|
In n ns
|
|
|
|
-> In n (dedup ns).
|
|
|
|
Proof.
|
|
|
|
induction ns; simpl; intuition.
|
|
|
|
pose proof (member_ok a (dedup ns)).
|
|
|
|
destruct (member a (dedup ns)); simpl in *; intuition congruence.
|
|
|
|
pose proof (member_ok a (dedup ns)).
|
|
|
|
destruct (member a (dedup ns)); simpl in *; intuition congruence.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma constant_dedup : forall (f : _ -> A) vs,
|
|
|
|
constant (map f (dedup vs)) = constant (map f vs).
|
|
|
|
Proof.
|
|
|
|
induction vs; simpl; intuition.
|
|
|
|
pose proof (member_ok a (dedup vs)).
|
|
|
|
case_eq (member a (dedup vs)); intro.
|
|
|
|
rewrite IHvs.
|
|
|
|
rewrite H0 in H.
|
|
|
|
apply In_dedup_fwd in H.
|
|
|
|
apply sets_equal.
|
|
|
|
unfold constant.
|
|
|
|
simpl.
|
|
|
|
intuition.
|
|
|
|
apply in_map_iff.
|
|
|
|
eauto.
|
|
|
|
simpl.
|
|
|
|
apply sets_equal.
|
|
|
|
simpl.
|
|
|
|
intuition congruence.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma constant_map_setmerge : forall (f : _ -> A) ns2 ns1,
|
|
|
|
constant (map f (setmerge ns1 ns2)) = constant (map f ns1) \cup constant (map f ns2).
|
|
|
|
Proof.
|
|
|
|
induction ns1; simpl; intros.
|
|
|
|
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
|
|
|
|
pose proof (member_ok a ns2).
|
|
|
|
destruct (member a ns2).
|
|
|
|
rewrite IHns1.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
right.
|
|
|
|
eapply in_map_iff; eauto.
|
|
|
|
|
|
|
|
simpl.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
change (In x (map f (setmerge ns1 ns2))) with ((fun x => In x (map f (setmerge ns1 ns2))) x) in H1.
|
|
|
|
rewrite IHns1 in H1.
|
|
|
|
tauto.
|
|
|
|
change (In x (map f (setmerge ns1 ns2))) with ((fun x => In x (map f (setmerge ns1 ns2))) x).
|
|
|
|
rewrite IHns1.
|
|
|
|
tauto.
|
|
|
|
change (In x (map f (setmerge ns1 ns2))) with ((fun x => In x (map f (setmerge ns1 ns2))) x).
|
|
|
|
rewrite IHns1.
|
|
|
|
tauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem normalize_setexpr_ok : forall env e,
|
|
|
|
interp_normal_form env (normalize_setexpr e) = interp_setexpr env e.
|
|
|
|
Proof.
|
|
|
|
induction e; simpl; intros.
|
|
|
|
|
|
|
|
unfold interp_normal_form; simpl.
|
|
|
|
destruct env; trivial.
|
|
|
|
apply constant_dedup.
|
|
|
|
|
|
|
|
unfold interp_normal_form; simpl.
|
|
|
|
destruct env; sets ltac:(simpl in *; intuition).
|
|
|
|
|
|
|
|
unfold interp_normal_form in *; simpl in *.
|
|
|
|
destruct (Other (normalize_setexpr e1)), (Other (normalize_setexpr e2)).
|
|
|
|
destruct env.
|
|
|
|
rewrite <- IHe1.
|
|
|
|
rewrite <- IHe2.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
rewrite <- IHe1.
|
|
|
|
rewrite <- IHe2.
|
|
|
|
rewrite constant_map_setmerge.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
destruct env.
|
|
|
|
rewrite <- IHe1.
|
|
|
|
rewrite <- IHe2.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
rewrite constant_map_setmerge.
|
|
|
|
rewrite <- IHe1.
|
|
|
|
rewrite <- IHe2.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
destruct env.
|
|
|
|
rewrite <- IHe1.
|
|
|
|
rewrite <- IHe2.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
rewrite constant_map_setmerge.
|
|
|
|
rewrite <- IHe1.
|
|
|
|
rewrite <- IHe2.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
destruct env.
|
|
|
|
rewrite <- IHe1.
|
|
|
|
rewrite <- IHe2.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
rewrite constant_map_setmerge.
|
|
|
|
rewrite <- IHe1.
|
|
|
|
rewrite <- IHe2.
|
|
|
|
sets ltac:(simpl in *; intuition).
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Fixpoint included (ns1 ns2 : list nat) : bool :=
|
|
|
|
match ns1 with
|
|
|
|
| [] => true
|
|
|
|
| n :: ns1' => member n ns2 && included ns1' ns2
|
|
|
|
end.
|
|
|
|
|
|
|
|
Lemma included_true : forall ns2 ns1,
|
|
|
|
included ns1 ns2 = true
|
|
|
|
-> (forall x, In x ns1 -> In x ns2).
|
|
|
|
Proof.
|
|
|
|
induction ns1; simpl; intuition subst.
|
|
|
|
|
|
|
|
pose proof (member_ok x ns2).
|
|
|
|
destruct (member x ns2); simpl in *; auto; congruence.
|
|
|
|
|
|
|
|
pose proof (member_ok a ns2).
|
|
|
|
destruct (member a ns2); simpl in *; auto; congruence.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Require Import Bool.
|
|
|
|
|
|
|
|
Theorem compare_sets : forall env e1 e2,
|
|
|
|
let nf1 := normalize_setexpr e1 in
|
|
|
|
let nf2 := normalize_setexpr e2 in
|
|
|
|
match Other nf1, Other nf2 with
|
|
|
|
| None, None => included nf1.(Elements) nf2.(Elements)
|
|
|
|
&& included nf2.(Elements) nf1.(Elements) = true
|
|
|
|
| _, _ => False
|
|
|
|
end
|
|
|
|
-> interp_setexpr env e1 = interp_setexpr env e2.
|
|
|
|
Proof.
|
|
|
|
intros.
|
|
|
|
do 2 rewrite <- normalize_setexpr_ok.
|
|
|
|
subst nf1.
|
|
|
|
subst nf2.
|
|
|
|
unfold interp_normal_form.
|
|
|
|
destruct (Other (normalize_setexpr e1)), (Other (normalize_setexpr e2)); intuition.
|
|
|
|
destruct env; trivial.
|
|
|
|
apply andb_true_iff in H; intuition.
|
|
|
|
specialize (included_true _ _ H0).
|
|
|
|
specialize (included_true _ _ H1).
|
|
|
|
clear H0 H1.
|
|
|
|
intros.
|
|
|
|
apply sets_equal.
|
|
|
|
unfold constant; simpl; intuition.
|
|
|
|
apply in_map_iff.
|
|
|
|
apply in_map_iff in H1.
|
|
|
|
firstorder.
|
|
|
|
apply in_map_iff.
|
|
|
|
apply in_map_iff in H1.
|
|
|
|
firstorder.
|
|
|
|
Qed.
|
|
|
|
End setexpr.
|
|
|
|
|
|
|
|
Ltac quote E env k :=
|
|
|
|
let T := type of E in
|
|
|
|
match eval hnf in T with
|
|
|
|
| ?A -> Prop =>
|
|
|
|
let rec lookup E env k :=
|
|
|
|
match env with
|
|
|
|
| [] => k 0 [E]
|
|
|
|
| E :: _ => k 0 env
|
|
|
|
| ?E' :: ?env' =>
|
|
|
|
lookup E env' ltac:(fun pos env'' => k (S pos) (E' :: env''))
|
|
|
|
end in
|
|
|
|
|
|
|
|
let rec lookups Es env k :=
|
|
|
|
match Es with
|
|
|
|
| [] => k (@nil nat) env
|
|
|
|
| ?E :: ?Es' =>
|
|
|
|
lookup E env ltac:(fun pos env' =>
|
|
|
|
lookups Es' env' ltac:(fun poss env'' =>
|
|
|
|
k (pos :: poss) env''))
|
|
|
|
end in
|
|
|
|
|
|
|
|
let rec quote' E env k :=
|
|
|
|
match E with
|
|
|
|
| constant ?Es =>
|
|
|
|
lookups Es env ltac:(fun poss env' => k (Literal A poss) env')
|
|
|
|
| ?E1 \cup ?E2 =>
|
|
|
|
quote' E1 env ltac:(fun e1 env' =>
|
|
|
|
quote' E2 env' ltac:(fun e2 env'' =>
|
|
|
|
k (Union e1 e2) env''))
|
|
|
|
| _ =>
|
2017-03-21 23:27:36 +00:00
|
|
|
(let pf := constr:(eq_refl : E = constant []) in
|
2017-03-06 01:46:53 +00:00
|
|
|
k (Literal A []) env)
|
|
|
|
|| k (Constant E) env
|
|
|
|
end in
|
|
|
|
|
|
|
|
quote' E env k
|
|
|
|
end.
|
|
|
|
|
2017-03-07 19:59:56 +00:00
|
|
|
Ltac sets_cbv := cbv beta iota zeta delta [interp_normal_form normalize_setexpr nth_default
|
|
|
|
setmerge Elements Other nth_error map dedup member beq_nat orb
|
|
|
|
andb included].
|
2017-03-13 01:27:59 +00:00
|
|
|
|
|
|
|
Ltac sets_cbv_in H := cbv beta iota zeta delta [interp_normal_form normalize_setexpr nth_default
|
|
|
|
setmerge Elements Other nth_error map dedup member beq_nat orb
|
|
|
|
andb included] in H.
|
2017-03-07 19:59:56 +00:00
|
|
|
|
2017-03-06 01:46:53 +00:00
|
|
|
Ltac normalize_set :=
|
|
|
|
match goal with
|
|
|
|
| [ |- context[@union ?A ?X ?Y] ] =>
|
|
|
|
quote (@union A X Y) (@nil A) ltac:(fun e env =>
|
2017-03-07 19:59:56 +00:00
|
|
|
change (@union A X Y) with (interp_setexpr env e));
|
|
|
|
rewrite <- normalize_setexpr_ok; sets_cbv
|
2017-03-13 01:27:59 +00:00
|
|
|
| [ H : context[@union ?A ?X ?Y] |- _ ] =>
|
|
|
|
quote (@union A X Y) (@nil A) ltac:(fun e env =>
|
|
|
|
change (@union A X Y) with (interp_setexpr env e) in H);
|
|
|
|
rewrite <- normalize_setexpr_ok in H; sets_cbv_in H
|
2017-03-06 01:46:53 +00:00
|
|
|
end.
|
|
|
|
|
|
|
|
Ltac compare_sets :=
|
|
|
|
match goal with
|
|
|
|
| [ |- @eq ?T ?X ?Y ] =>
|
|
|
|
match eval hnf in T with
|
|
|
|
| ?A -> _ =>
|
|
|
|
quote X (@nil A) ltac:(fun x env =>
|
|
|
|
quote Y env ltac:(fun y env' =>
|
2017-03-07 19:59:56 +00:00
|
|
|
change (interp_setexpr env' x = interp_setexpr env' y)));
|
|
|
|
apply compare_sets; sets_cbv; reflexivity
|
2017-03-06 01:46:53 +00:00
|
|
|
end
|
|
|
|
end.
|