Skip to content
Snippets Groups Projects
Select Git revision
  • 6c91f6bc706291c5229d9e06d8ed59978e360d66
  • public default protected
2 results

WithMultiplicity.v

Blame
  • WithMultiplicity.v 10.53 KiB
    (**************************************************************************)
    (*   Mechanised Framework for Local Interactions & Distributed Algorithms *)
    (*   T. Balabonski, P. Courtieu, L. Rieg, X. Urbain                       *)
    (*   PACTOLE project                                                      *)
    (*                                                                        *)
    (*   This file is distributed under the terms of the CeCILL-C licence.    *)
    (*                                                                        *)
    (**************************************************************************)
    
    (**************************************************************************)
    (**  Mechanised Framework for Local Interactions & Distributed Algorithms   
                                                                                
         T. Balabonski, P. Courtieu, L. Rieg, X. Urbain                         
                                                                                
         PACTOLE project                                                        
                                                                                
         This file is distributed under the terms of the CeCILL-C licence.      
                                                                              *)
    (**************************************************************************)
    
    
    Require Import Lia PeanoNat.
    Require Import SetoidList.
    Require Export Pactole.CaseStudies.Gathering.Definitions.
    Require Export Pactole.Observations.MultisetObservation.
    Close Scope R_scope.
    Close Scope VectorSpace_scope.
    Set Implicit Arguments.
    Typeclasses eauto := (bfs) 5.
    (* Require Even. *)
    
    (** Gathering Definitions specific to a setting with multiplicities, i.e. a multiset observation. *)
    
    Section MultisetGathering.
    
    (** Here, we restrict the state to only contain the location. *)
    Context `{Location}.
    (* TODO: add the existence of a similarity here *)
    #[export]Instance Info : State location := OnlyLocation (fun _ => True).
    Context {VS : RealVectorSpace location}.
    Context {RMS : RealMetricSpace location}.
    Context `{Names}.
    Context `{robot_choice}.
    Context `{update_choice}.
    Context `{inactive_choice}.
    Context {UpdFun : update_function _ _ _}.
    Context {InaFun : inactive_function _}.
    
    #[export] Existing Instance multiset_observation.
    
    Notation "!! config" :=
      (@obs_from_config location _ _ _ multiset_observation config origin : observation) (at level 10).
    
    Lemma no_info : forall x y, get_location x == get_location y -> x == y.
    Proof using . now intros. Qed.
    
    (** When all robots are on two towers of the same height, there is no solution to the gathering problem.
        Therefore, we define these configurations as [invalid]. *)
    Definition invalid (config : configuration) :=
         Nat.Even nG /\ nG >=2 /\ exists pt1 pt2 : location, pt1 =/= pt2
      /\ (!! config)[pt1] = Nat.div2 nG /\ (!! config)[pt2] = Nat.div2 nG.
    
    Global Instance invalid_compat : Proper (equiv ==> iff) invalid.
    Proof using .
    intros ? ? Heq. split; intros [HnG [Hle [pt1 [pt2 [Hneq Hpt]]]]];
    repeat split; trivial; exists pt1, pt2; split; trivial; now rewrite Heq in *.
    Qed.
    
    (** [ValidsolGathering r d] means that any possible (infinite)
        execution, generated by demon [d] and robogram [r] and any intial
        configuration not [invalid], will *eventually* be [Gather]ed.
        This is the statement used for the correctness proof of the algorithms. *)
    Definition ValidSolGathering (r : robogram) (d : demon) :=
      forall config : configuration, ~invalid config -> WillGather (execute r d config).
    
    (** **  Generic properties  **)
    
    (* We need to unfold [obs_is_ok] for rewriting *)
    Definition obs_from_config_spec : forall (config : configuration) (pt : location),
      (!! config)[pt] = countA_occ _ equiv_dec pt (List.map get_location (config_list config))
      := fun config => obs_from_config_spec config origin.
    
    Lemma obs_non_nil : 2 <= nG -> forall config,
      !! config =/= MMultisetInterface.empty.
    Proof using .
    simpl obs_from_config. intros HnG config Heq.
    assert (Hlgth:= config_list_length config).
    assert (Hl : config_list config = nil).
    { apply List.map_eq_nil with _ get_location.
      rewrite <- make_multiset_empty.
      now intro; rewrite Heq. }
    rewrite Hl in Hlgth.
    simpl in *.
    lia.
    Qed.
    
    Lemma invalid_size : nB = 0 ->
      forall config : configuration, invalid config -> size (!! config) = 2.
    Proof using .
    intros HnB config [Heven [HsizeG [pt1 [pt2 [Hdiff [Hpt1 Hpt2]]]]]].
    rewrite <- (@cardinal_total_sub_eq _ _ _ _ _ (add pt2 (Nat.div2 nG) (singleton pt1 (Nat.div2 nG)))).
    + rewrite size_add.
      destruct (In_dec pt2 (singleton pt1 (Nat.div2 nG))) as [Hin | Hin].
      - exfalso. rewrite In_singleton in Hin.
        destruct Hin. now contradiction Hdiff.
      - rewrite size_singleton; trivial; [].
        apply Exp_prop.div2_not_R0. apply HsizeG.
      - apply Exp_prop.div2_not_R0. apply HsizeG.
    + intro pt. destruct (pt =?= pt2) as [Heq2 | Heq2], (pt =?= pt1) as [Heq1 | Heq1].
      - rewrite Heq1, Heq2 in *. now contradiction Hdiff.
      - rewrite add_spec, singleton_spec.
        do 2 destruct_match; try contradiction; [].
        simpl.
        rewrite Heq2.
        now apply Nat.eq_le_incl.
      - rewrite add_other, singleton_spec; auto; [].
        destruct_match; try contradiction; [].
        rewrite Heq1.
        now apply Nat.eq_le_incl.
      - rewrite add_other, singleton_spec; auto; [].
        destruct_match; try contradiction; [].
        auto with arith.
    + rewrite cardinal_add, cardinal_singleton, cardinal_obs_from_config.
      rewrite HnB, Nat.add_0_r. now apply even_div2.
    Qed.
    
    Lemma invalid_strengthen : nB = 0 -> forall config, invalid config ->
      { pt1 : location & { pt2 : location | pt1 =/= pt2 & !! config == add pt1 (Nat.div2 nG) (singleton pt2 (Nat.div2 nG)) } }.
    Proof using .
    intros HnB config Hconfig.
    (* Because we want a computational goal and the hypothesis is not,
       we first destruct the support to get the elements and only then
       prove that they are the same as the one given in [invalid]. *)
    assert (Hlen := invalid_size HnB Hconfig). rewrite size_spec in Hlen.
    destruct (support (!! config)) as [| pt1 [| pt2 [| ? ?]]] eqn:Hsupp; try discriminate; [].
    (* Transforming sig2 into sig to have only one goal after instanciating pt1 and pt2 *)
    cut {pt1 : location & {pt2 : location
         | pt1 =/= pt2 /\ obs_from_config config origin == add pt1 (Nat.div2 nG) (singleton pt2 (Nat.div2 nG))}}.
    { intros [? [? [? ?]]]. eauto. }
    exists pt1, pt2.
    destruct Hconfig as [Heven [Hge2 [pt1' [pt2' [Hdiff [Hpt1' Hpt2']]]]]].
    (* Both couples of points are the same *)
    assert (Hcase : pt1' == pt1 /\ pt2' == pt2 \/ pt1' == pt2 /\ pt2' == pt1).
    { assert (Hin1 : InA equiv pt1' (pt1 :: pt2 :: nil)).
      { rewrite <- Hsupp, support_spec. unfold In. rewrite Hpt1'.
        destruct nG as [| [| nG]]; simpl; solve [ auto with arith | lia]. }
      assert (Hin2 : InA equiv pt2' (pt1 :: pt2 :: nil)).
      { rewrite <- Hsupp, support_spec. unfold In. rewrite Hpt2'.
        destruct nG as [| [| nG]]; simpl; solve [ auto with arith | lia]. }
      rewrite 2 InA_cons, InA_nil in Hin1, Hin2. clear -Hin1 Hin2 Hdiff.
      decompose [or] Hin1; decompose [or] Hin2; tauto || contradiction Hdiff; etransitivity; eauto. }
    split.
    + intro. apply Hdiff.
      decompose [and or] Hcase; repeat (etransitivity; eauto; symmetry).
    + symmetry. apply cardinal_total_sub_eq.
      - intro pt. rewrite add_spec, singleton_spec.
        repeat destruct_match;
        destruct Hcase as [[Heq1 Heq2] | [Heq1 Heq2]];
        rewrite Heq1 in *; rewrite Heq2 in *;
        try match goal with H : pt == _ |- _ => rewrite H in *; clear H end;
        rewrite ?Hpt1', ?Hpt2'; lia || now contradiction Hdiff.
      - rewrite cardinal_add, cardinal_singleton, cardinal_obs_from_config, even_div2; auto; lia.
    Qed.
    
    Lemma invalid_same_location : nB = 0 -> forall config pt1 pt2 pt3, invalid config ->
      In pt1 (!! config) -> In pt2 (!! config) -> In pt3 (!! config) ->
      pt1 =/= pt3 -> pt2 =/= pt3 -> pt1 == pt2.
    Proof using .
    intros HnB config pt1 pt2 pt3 Hinvalid Hin1 Hin2 Hin3 Hdiff13 Hdiff23.
    destruct (invalid_strengthen HnB Hinvalid) as [pta [ptb Hdiff Hobs]].
    rewrite Hobs, add_In, In_singleton in Hin1, Hin2, Hin3.
    destruct Hin1 as [[] | []], Hin2 as [[] | []], Hin3 as [[] | []];
    solve [ etransitivity; eauto
          | contradiction Hdiff13; etransitivity; eauto
          | contradiction Hdiff23; etransitivity; eauto ].
    Qed.
    Arguments invalid_same_location _ config {pt1} {pt2} pt3 _ _ _ _ _.
    
    Lemma invalid_dec : nB = 0 -> forall config, {invalid config} + {~invalid config}.
    Proof using .
    intros HnB config.
    destruct (size (!! config)) as [| [| [| n]]] eqn:Hsize;
    try (right; intro Habs; apply invalid_size in Habs; lia); [].
    rewrite size_elements in Hsize.
    destruct (elements (!! config)) as [| [pt1 n1] [| [pt2 n2] [| ? ?]]] eqn:Helem;
    try discriminate; [].
    destruct (n1 =?= n2) as [Hn | Hn].
    * left.
      assert (2 * n1 = nG).
      { assert (Hcardinal := cardinal_obs_from_config config origin).
        rewrite cardinal_fold_elements, Helem in Hcardinal. simpl in Hcardinal.
        rewrite <- Hn, HnB in Hcardinal. lia. }
      assert (n1 = Nat.div2 nG). { rewrite <- (Exp_prop.div2_double n1). now f_equal. }
      split; [| split].
      + now exists n1.
      + cut (0 < n1); try lia; [].
        assert (Hin : InA eq_pair (pt1, n1) (elements (!! config))).
        { rewrite Helem. now left. }
        rewrite elements_spec in Hin. simpl in Hin. lia.
      + exists pt1, pt2.
        hnf in Hn. subst n1 n2.
        repeat split.
        - assert (Hnodup := elements_NoDupA (!! config)).
          rewrite Helem in Hnodup. inv Hnodup. rewrite InA_cons, InA_nil in *.
          unfold eq_elt in *. simpl in *. tauto.
        - change pt1 with (fst (pt1, Nat.div2 nG)). change (Nat.div2 nG) with (snd (pt1, Nat.div2 nG)) at 2.
          eapply proj1. rewrite <- elements_spec.
          rewrite Helem. now left.
        - change pt2 with (fst (pt2, Nat.div2 nG)). change (Nat.div2 nG) with (snd (pt2, Nat.div2 nG)) at 2.
          eapply proj1. rewrite <- elements_spec.
          rewrite Helem. now right; left.
    * right.
      intro Hvalid. contradiction Hn.
      assert (Hhalf : 0 < Nat.div2 nG).
      { destruct Hvalid as [_ [Hle _]]. destruct nG as [| [| ?]]; simpl; solve [ auto with arith | lia]. }
      destruct (invalid_strengthen HnB Hvalid) as [pt1' [pt2' Hdiff Hobs]].
      assert (Hperm : PermutationA eq_pair ((pt1, n1) :: (pt2, n2) :: nil)
                                           ((pt1', Nat.div2 nG) :: (pt2', Nat.div2 nG) :: nil)).
      { rewrite <- Helem, Hobs. rewrite elements_add, elements_singleton; auto; [].
        cbn [removeA]. rewrite singleton_other; trivial; [].
        constructor.
        + split; simpl; reflexivity || lia.
        + destruct_match.
          - contradiction Hdiff. hnf in * |-; simpl in *. auto.
          - reflexivity. }
      rewrite PermutationA_2 in Hperm; autoclass; [].
      clear -Hperm. destruct Hperm as [[[] []] | [[] []]]; compute in *; congruence.
    Qed.
    
    End MultisetGathering.