Library ATBR.DKA_Sets



Require Import Common.

Require Export FSets FMaps.
Require FMapAVL.
Require FSetDecide.

Set Implicit Arguments.

Module FSet := FSetList.
Module FMap := FMapList.

Module FSetHide (X : FSetInterface.S).
  Include X.
End FSetHide.

Module FMapHide (X : FMapInterface.S).
  Include X.
End FMapHide.

Module State := Nat_as_OT.
Module StateSet' := FSet.Make(State). Module StateSet := FSetHide StateSet'.
Module StateMap' := FMap.Make(State). Module StateMap := FMapHide StateMap'.

Module StateSetMap' := FMap.Make(StateSet). Module StateSetMap := FMapHide StateSetMap'.
Module Label := State.
Module LabelMap := StateMap.

Module StateSetSet' := FSet.Make(StateSet). Module StateSetSet := FSetHide StateSetSet'.
Module Label_x_StateSet := PairOrderedType Label StateSet.
Module Label_x_StateSetSet' := FSet.Make Label_x_StateSet. Module Label_x_StateSetSet := FSetHide Label_x_StateSetSet'.


Module StateSetProp' := FSetEqProperties.EqProperties StateSet.
Module StateSetProp := StateSetProp'.MP.
Module StateSetFact := StateSetProp.FM.
Module StateSetOrdProp := FSetProperties.OrdProperties(StateSet).
Module StateMapFact := FMapFacts.Facts StateMap.

Module StateSetSetProp' := FSetEqProperties.EqProperties StateSetSet.
Module StateSetSetProp := StateSetSetProp'.MP.
Module StateSetSetFact := StateSetSetProp.FM.
Module StateSetMapProp := FMapFacts.Properties StateSetMap.
Module StateSetMapFact := StateSetMapProp.F.

Module StateSetDecide := FSetDecide.Decide StateSet.
Module StateSetSetDecide := FSetDecide.Decide StateSetSet.

Module Label_x_StateSetSet_Prop' := FSetEqProperties.EqProperties Label_x_StateSetSet.
Module Label_x_StateSetSet_Prop := Label_x_StateSetSet_Prop'.MP.
Module Label_x_StateSetSet_Fact := Label_x_StateSetSet_Prop.FM.

Notation state := nat (only parsing).
Notation stateset := StateSet.t.
Notation label := nat (only parsing).

Ltac stateset_dec := (StateSetDecide.fsetdec).
Ltac statesetset_dec := (StateSetSetDecide.fsetdec).

Section fold_labels.
Fixpoint fold_labels T (f: label -> T -> T) a acc :=
  match a with
    | O => acc
    | S a => fold_labels f a (f a acc)
  end.

Lemma fold_labels_rec_nodep: forall T (P: T -> Prop) f a acc,
  P acc -> (forall acc a, P acc -> P (f a acc)) -> P (fold_labels f a acc).
Proof.
  intros T P f. induction a; simpl; auto.
Qed.


Lemma fold_labels_add_Subset : forall n acc, StateSet.Subset acc (fold_labels StateSet.add n acc).
Proof.
  intros. apply fold_labels_rec_nodep. reflexivity.
  intros. StateSetDecide.fsetdec.
Qed.

Lemma fold_labels_add_union : forall n acc, StateSet.eq (fold_labels StateSet.add n acc) (StateSet.union acc (fold_labels StateSet.add n StateSet.empty)).
Proof.
  assert (forall P, StateSet.Equal P (StateSet.union P StateSet.empty)).
  intros.
  assert (StateSet.Empty StateSet.empty). auto. symmetry; apply StateSetProp.empty_union_2. auto.

  intros. revert acc. induction n.
  simpl. auto.
  simpl. intros. setoid_rewrite IHn at 2. rewrite IHn.
  rewrite StateSetProp.double_inclusion.
  split; intros e He; revert He; StateSetFact.set_iff; intuition. Qed.

Lemma fold_labels_add n : forall x, x < n <-> StateSet.In x (fold_labels StateSet.add n StateSet.empty).
Proof.
  intros. induction n. split; intros; [omega_false | StateSetDecide.fsetdec].
  simpl. destruct (eq_nat_dec x n). rewrite e. intuition. apply fold_labels_add_Subset. StateSetDecide.fsetdec.
  split; intros.

  assert (x < n). clear IHn. omega. apply -> IHn in H0. clear - H0. rewrite fold_labels_add_union. StateSetDecide.fsetdec.
  rewrite fold_labels_add_union in *.
  revert H. StateSetFact.set_iff. intuition.
Qed.

End fold_labels.

Fixpoint set_of_ones (f: nat -> bool) k: stateset :=
  match k with
    | 0 => StateSet.empty
    | S k =>
      if f k
        then StateSet.add k (set_of_ones f k)
        else set_of_ones f k
  end.

Lemma nmem_set_of_ones: forall f n i, n<=i -> StateSet.mem i (set_of_ones f n) = false.
Proof.
  induction n; simpl; intros i Hi.
  apply StateSetProp'.empty_mem.
  case (f n). rewrite StateSetProp'.add_mem_2; auto with omega.
  auto with omega.
Qed.

Lemma mem_set_of_ones: forall f n i, i<n -> StateSet.mem i (set_of_ones f n) = f i.
Proof.
  induction n; intros i Hi.
  inversion Hi.
  simpl. destruct (eq_nat_dec i n). subst.
  case (f n). apply StateSetProp'.add_mem_1.
  apply nmem_set_of_ones. trivial.
  case (f n). rewrite StateSetProp'.add_mem_2; auto with omega.
  auto with omega.
Qed.

Lemma In_set_of_ones_lt: forall n i f, StateSet.In i (set_of_ones f n) -> i < n.
Proof.
  induction n; simpl.
  stateset_dec.
  intros i f. case (f n); intro H.
  destruct (eq_nat_dec n i). omega.
  apply StateSet.add_3 in H; trivial.
  apply IHn in H. omega.
  apply IHn in H. omega.
Qed.

Definition merge_plus n := StateSet.fold (fun x acc => StateSet.add (x + n)%nat acc).

Definition below s n := StateSet.For_all (fun i => i<n) s.

Lemma _mem_merge_aux_0: Equivalence StateSet.Equal.
Proof. constructor; repeat intro; stateset_dec. Qed.

Lemma _mem_merge_aux_1: forall n, compat_op (@eq nat) StateSet.Equal (fun (x : nat) acc => StateSet.add (x + n)%nat acc).
Proof. repeat intro. subst. stateset_dec. Qed.

Lemma _mem_merge_aux_2: forall n, transpose StateSet.Equal (fun x acc => StateSet.add (x + n)%nat acc).
Proof. repeat intro. stateset_dec. Qed.

Lemma mem_merge_1: forall s i n t, i<n ->
  StateSet.mem i (merge_plus n s t) = StateSet.mem i t.
Proof.
  unfold merge_plus.
  intros. apply StateSetProp.fold_rec_nodep. reflexivity.
  intros.
  remember (StateSet.mem i t) as b.
  destruct b.
     rewrite <- StateSetFact.mem_iff in *.
     StateSetFact.set_iff. right. assumption.

     rewrite <- StateSetFact.not_mem_iff in *.
     intro. apply H1. revert H2.
     StateSetFact.set_iff. intros [H' | H']; [omega_false | stateset_dec].
Qed.

Lemma below_false : forall t n i, below t n -> n <= i -> ~ StateSet.In i t. Proof.
  intros.
  unfold below in H. unfold StateSet.For_all in H. intro.
  apply H in H1. omega_false.
Qed.

Lemma mem_In : forall a b x y, (StateSet.In x a <-> StateSet.In y b) <-> (StateSet.mem x a = StateSet.mem y b).
Proof.
  intros. case_eq (StateSet.mem x a); intros;
  intuition
  repeat
    match goal with
      | H : true = StateSet.mem _ _ |- _ => symmetry in H
      | H : StateSet.mem _ _ = true |- _ => rewrite <- StateSetFact.mem_iff in H
      | H : false = StateSet.mem _ _ |- _ => symmetry in H
      | H : StateSet.mem _ _ = false |- _ => rewrite <- StateSetFact.not_mem_iff in H
      | |- true = StateSet.mem _ _=> symmetry
      | |- false = StateSet.mem _ _=> symmetry
      | |- StateSet.mem _ _ = true => rewrite <- StateSetFact.mem_iff
      | |- StateSet.mem _ _ = false=> rewrite <- StateSetFact.not_mem_iff

    end; intuition.
Qed.

Lemma mem_merge_2: forall s i n t, n<=i -> below t n ->
  StateSet.mem i (merge_plus n s t) = StateSet.mem (i-n) s.
Proof.
  unfold merge_plus.
  intros.
  set (Pred := fun Q acc => StateSet.In i acc <-> StateSet.In (i - n) Q).
  assert (Pred s (StateSet.fold (fun x acc => StateSet.add (x + n) acc) s t)).
  apply StateSetProp.fold_rec_bis; subst Pred; cbv beta.
    intros. rewrite <- H1. apply H2.

    split; intros. apply False_ind. eapply (below_false H0). apply H. apply H1.
    apply False_ind. eapply StateSet.empty_1. apply H1.


    intros. StateSetFact.set_iff. intuition.

  subst Pred; cbv beta in H1.
  apply -> mem_In. apply H1.
Qed.

Lemma merge_below: forall n m s t, below t n -> below s m -> below (merge_plus n s t) (n+m).
Proof.
  unfold merge_plus. intros.
  apply StateSetProp.fold_rec_nodep.
    unfold below, StateSet.For_all in *.
    intuition. specialize (H x H1). omega.

    unfold below, StateSet.For_all in *.
    intuition. specialize (H0 x H1). revert H3. StateSetFact.set_iff. intuition.
Qed.

Section lemmes_set_of_ones.

  Lemma _set_of_ones_le f n m : n <= m -> StateSet.Subset (set_of_ones f n) (set_of_ones f m ).
  Proof.
    intros.
    induction H. stateset_dec.

    simpl. destruct (f m). eapply StateSetProp.subset_trans. apply IHle. stateset_dec.
    assumption.
  Qed.

  Lemma _set_of_ones_correction1 f n : forall x, x < n -> (f x = true -> StateSet.In x (set_of_ones f n)).
  Proof.
    induction n. intros; inversion H.
    intros. destruct (eq_nat_dec x n). subst. simpl. rewrite H0. stateset_dec.
    eapply _set_of_ones_le; [| apply IHn]. auto. omega. auto.
  Qed.

  Lemma _set_of_ones_correction2 f n x : StateSet.In x (set_of_ones f n ) -> (x < n /\ f x = true).
  Proof.
    revert x; induction n.
      intros; simpl in H. stateset_dec.
      intros; simpl in H.
      destruct (eq_nat_dec x n). subst.
      Set Printing Coercions. destruct (f n). auto.

      specialize (IHn n). intuition (omega_false).
      assert ( x < n /\ f x = true). apply IHn.
      destruct (f n). eapply StateSet.add_3. intro. apply n0. symmetry. apply H0. assumption. assumption.
      split; intuition (omega).
   Qed.

  Lemma set_of_ones_correction f n : forall x, x < n -> (StateSet.In x (set_of_ones f n) <-> f x = true).
  Proof.
    intros.
    intuition (auto using _set_of_ones_correction1).
    destruct (@_set_of_ones_correction2 f n x H0); trivial.
  Qed.

  Lemma set_of_ones_correction' f n : forall x, StateSet.In x (set_of_ones f n) -> x < n.
  Proof.
    intros. elim (@_set_of_ones_correction2 f n x); intros.
    tauto.
    apply H.
  Qed.

  Lemma set_of_ones_compat' n f g :
    (forall x, x < n -> f x = g x ) -> StateSet.eq (set_of_ones f n) (set_of_ones g n).
  Proof.
    intros.
    rewrite StateSetProp.double_inclusion. split; repeat intro.
    assert (a < n) by eauto using set_of_ones_correction';
    destruct (f a); destruct (g a);rewrite set_of_ones_correction in *;
      solve [ assumption | rewrite <- H; assumption | rewrite -> H; assumption].
    assert (a < n) by eauto using set_of_ones_correction';
    destruct (f a); destruct (g a);rewrite set_of_ones_correction in *;
      solve [ assumption | rewrite <- H; assumption | rewrite -> H; assumption].
  Qed.

End lemmes_set_of_ones.


Various lemmas used elsewhere in the development.

Essentially, an add-on to the FSet library
Section Attic.
Lemma compat_bool_neg A f : compat_bool (@eq A) f -> compat_bool (@eq A) (fun x => negb (f x)).
  repeat intro. subst. auto.
Qed.

Implicit Arguments compat_bool_neg [A].

Lemma negb_f A (f : A -> bool) (x : A) : false = f x -> negb (f x) = true.
  repeat intro. rewrite <- H. reflexivity.
Qed.

Implicit Arguments negb_f [A].

Hint Resolve
  compat_bool_neg (@compat_bool_neg StateSet.t) (@compat_bool_neg StateSet.elt)
  negb_f (@negb_f StateSet.t) (@negb_f StateSet.elt) .

Lemma cpl_fst_snd : forall A B (u : A) (v : B) (x : A *B), (u,v) = x -> (u = fst x) /\ (v = snd x).
Proof.
  intros.
  split; destruct H; reflexivity.
Qed.

Lemma union_partition : forall f x t u, compat_bool (@eq StateSet.elt ) f -> (t,u) = StateSet.partition f x -> StateSet.Equal x (StateSet.union t u).
Proof.
  intros f x t u Hf Htu.
  apply cpl_fst_snd in Htu. destruct Htu as [Ht Hu].
  rewrite Ht, Hu.
  rewrite StateSet.partition_1, StateSet.partition_2; auto.
  repeat intro; intuition StateSetFact.set_iff.
  remember (f a) as b; destruct b. left. auto with set.
  right. apply (StateSet.filter_3 (f:= fun x => negb (f x))); auto.
  revert H. StateSetFact.set_iff. intuition (eapply StateSet.filter_1; [| eassumption]; repeat intro; subst; auto).
Qed.

Lemma inter_partition : forall f x t u, compat_bool (@eq StateSet.elt ) f ->
  StateSet.eq (fst (StateSet.partition f x)) t ->
  StateSet.eq (snd (StateSet.partition f x)) u
  -> StateSet.Empty (StateSet.inter t u).
Proof.
  intros f x t u Hf Ht Hu.

  rewrite StateSet.partition_1 in Ht by auto.
  rewrite StateSet.partition_2 in Hu by auto.
  repeat intro. revert H. StateSetFact.set_iff.
  repeat intro.
  rewrite <- Ht, <-Hu in H. clear Ht Hu.
  set (g := fun x => negb (f x)).

  assert (Hdiscr : f a = true /\ g a = true).
  destruct H as [Haf Hag]; split; eapply StateSet.filter_2; subst g; eauto.
  subst g. destruct Hdiscr as [Haf Hag]. destruct Haf. destruct (f a); simpl in Hag; discriminate.
Qed.

Lemma inter_filter : forall (f : StateSet.elt -> bool) p, compat_bool StateSet.E.eq f ->
  StateSet.Empty
  (StateSet.inter
    (StateSet.filter f p)
    (StateSet.filter (fun x => negb (f x)) p)
    ).
Proof.
  intros. eapply inter_partition.
  apply H.
  apply StateSet.partition_1; auto.
  apply StateSet.partition_2; auto.
Qed.

Definition eq_option_stateset_X_stateset (a b : (option (StateSet.t * StateSet.t))) : Prop :=
  match (a,b) with
    | (Some a, Some b) => StateSet.eq (fst a) (fst b) /\ StateSet.eq (snd a) (snd b)
    | (None , None) => True
    | _ => False
  end.

Hint Unfold eq_option_stateset_X_stateset.
Hint Extern 5 (StateSet.eq _ _) => now symmetry.
Hint Unfold compat_bool.

Global Instance eq_option_stateset_X_stateset_compat : Equivalence eq_option_stateset_X_stateset.
Opaque StateSet.eq. unfold eq_option_stateset_X_stateset.
split; red; intros.
destruct x; intuition auto.
destruct y; destruct x; intuition auto.
destruct z; destruct y; destruct x; intuition auto.
  transitivity (fst p0); auto.
  transitivity (snd p0); auto.
Defined.

Global Instance stateset_is_empty_compat : Proper (StateSet.eq ==> @eq bool) (StateSet.is_empty).
Proof.
  repeat intro. rewrite H. reflexivity.
Qed.

Definition stateset_X_stateset_eq a b : Prop :=
  StateSet.eq (fst a) (fst b) /\
  StateSet.eq (snd a) (snd b).

Global Instance partition_compat :
Proper ((pointwise_relation StateSet.elt (@eq bool) ) ==> StateSet.eq ==> stateset_X_stateset_eq) (StateSet.partition).
Proof.
  unfold stateset_X_stateset_eq.
  repeat intro.
  split. rewrite 2 StateSet.partition_1; auto.
  apply StateSetFact.filter_ext; auto.
  rewrite 2 StateSet.partition_2; auto.
  apply StateSetFact.filter_ext; auto. intro. intros. subst. auto.
  intros. rewrite H. reflexivity.
Qed.

Lemma partition_predicate p f : compat_bool StateSet.E.eq f ->
  (forall i, StateSet.In i (fst (StateSet.partition f p)) -> f i = true)
  /\ (forall i, StateSet.In i (snd (StateSet.partition f p)) -> f i = false)

.
Proof.
  intros.
  split; intros.

  setoid_rewrite StateSet.partition_1 in H0; auto.
  eapply StateSet.filter_2; [| apply H0]; auto.
  setoid_rewrite StateSet.partition_2 in H0; auto.
  set (g := (fun x => negb (f x))) in *.
  setoid_replace (f i = false) with (g i = true) using relation iff.

  eapply StateSet.filter_2; [| apply H0]; auto.

  subst g; simpl.
  case_eq (f i); intuition; compute.
Qed.

Lemma partition_union f p : compat_bool StateSet.E.eq f ->
  StateSet.Equal p (StateSet.union (fst (StateSet.partition f p)) (snd (StateSet.partition f p))).
Proof.
  intros Hf.
  rewrite StateSet.partition_1; auto. rewrite StateSet.partition_2; auto.
  repeat intro; intuition StateSetFact.set_iff.
  remember (f a) as b; destruct b.
    left. auto with set.
    right. eapply StateSet.filter_3; auto.

  revert H. StateSetFact.set_iff. intuition (eapply StateSet.filter_1; [| eassumption]; repeat intro; subst; auto).
Qed.

Lemma partition_inter f p : compat_bool StateSet.E.eq f ->
  StateSet.Empty (StateSet.inter (fst (StateSet.partition f p)) (snd (StateSet.partition f p))).
Proof.
  intros Hf.
  rewrite StateSet.partition_1; auto.
  rewrite StateSet.partition_2; auto.
  repeat intro. revert H. StateSetFact.set_iff. repeat intro.
  set (g := fun x => negb (f x)).

  assert (Hdiscr : f a = true /\ g a = true). destruct H as [Haf Hag]; split; eapply StateSet.filter_2; eauto.
  subst g. destruct Hdiscr as [Haf Hag]. destruct Haf. destruct (f a); simpl in Hag; discriminate.
Qed.

End Attic.