Skip to content
Snippets Groups Projects
Select Git revision
  • 1881101799f9f4f328503e80b06fb8981c3b24d5
  • noetic-devel default protected
  • liris
  • rolling-devel
  • melodic-devel
  • kinetic-devel
  • 0.7.8
  • 0.8.1
  • 0.7.7
  • 0.8.0
  • 0.7.6
  • 0.7.5
  • 0.7.4
  • 0.7.3
  • 0.7.2
  • 0.7.1
  • 0.7.0
17 results

hand.xacro

Blame
  • Tower.v 13.10 KiB
    (**************************************************************************)
    (*   Mechanised Framework for Local Interactions & Distributed Algorithms *)
    (*   T. Balabonski, P. Courtieu, R. Pelle, 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, R. Pelle, L. Rieg, X. Urbain               
         PACTOLE project                                                        
                                                                                
         This file is distributed under the terms of the CeCILL-C licence.      
                                                                              *)
    (**************************************************************************)
    
    Require Import Utf8.
    Require Import List SetoidList.
    Require Import Arith_base Lia.
    Require Import Pactole.Util.Stream.
    Require Import Pactole.Util.Enum.
    Require Import Pactole.Util.Fin.
    Require Import Pactole.Models.NoByzantine.
    Require Import Pactole.Models.RingSSync.
    Require Import Pactole.CaseStudies.Exploration.ExplorationDefs.
    
    Open Scope list_scope.
    Set Implicit Arguments.
    (* Typeclasses eauto := (bfs). *)
    
    Section Tower.
    
    (** Given an abitrary ring *)
    Context {n : nat} {ltc_2_n : 2 <c n}.
    (** There are k good robots and no byzantine ones. *)
    Context {k : nat} {ltc_0_k : 0 <c k}.
    Instance Robots : Names := Robots k 0.
    
    (** Assumptions on the number of robots: it is non zero and strictly divides the ring size. *)
    Hypothesis kdn : (n mod k = 0).
    Hypothesis k_inf_n : (k < n).
    
    (** There is no byzantine robot. *)
    Instance NoByz : NoByzantine.
    Proof using . now split. Qed.
    
    Notation "!! config" :=
      (@obs_from_config _ _ _ _ multiset_observation config fin0) (at level 0).
    Notation execute := (execute (UpdFun := UpdFun)).
    
    (** In order to prove that at least one position is occupied, we define the list of positions. *)
    Definition Vlist := enum (n).
    
    Lemma Vlist_NoDup : NoDupA equiv Vlist.
    Proof using . rewrite NoDupA_Leibniz. apply enum_NoDup. Qed.
    
    Lemma Vlist_length : length Vlist = n.
    Proof using . apply enum_length. Qed.
    
    (** As there is strictly less robots than location, there is an empty location. *)
    Lemma ConfigExistsEmpty : ∀ config, ¬ (∀ pt, In pt (!! config)).
    Proof using k_inf_n kdn.
      generalize k_inf_n; intros Hkin config Hall.
      assert (Hsize : size (!! config) < n).
      { apply Nat.le_lt_trans with (cardinal (!! config)). apply size_cardinal.
        cut (cardinal (!! config) = k). intros H. rewrite H. apply k_inf_n.
        change (cardinal (make_multiset (List.map get_location
        (config_list config))) = k). rewrite cardinal_make_multiset,
        config_list_spec, map_map, map_length, names_length. simpl.
        rewrite Nat.add_0_r. reflexivity. }
      assert (Hle : n <= size (!! config)).
      { rewrite size_spec. assert (Hobs : ∀ pt, InA equiv pt (support (!! config))).
        { intro pt. specialize (Hall pt). now rewrite support_spec. }
        rewrite <- Vlist_length at 1. apply (Preliminary.inclA_length setoid_equiv).
        apply Vlist_NoDup. repeat intro. apply Hobs. } lia.
    Qed.
    
    Lemma Stopped_same : ∀ e, Stopped e -> e == Stream.tl e.
    Proof using .
      cofix Hcoind. intros e Hstop. constructor.
      + clear Hcoind. apply Hstop.
      + apply Hcoind. apply Hstop.
    Qed.
    
    Lemma Will_stop_tl : ∀ e, Will_stop e -> Will_stop (Stream.tl e).
    Proof using .
      intros e He. induction He.
      + left. match goal with H : Stopped _ |- _ => apply H end.
      + right. apply IHHe.
    Qed.
    
    (** Acceptable starting configurations contain no tower,
        that is, all robots are at different locations. *)
    Definition Valid_starting_config config : Prop :=
      Util.Preliminary.injective (@Logic.eq ident) (@equiv _ state_Setoid) config.
    
    Definition Explore_and_Stop (r : robogram) :=
      forall d config, Fair d -> Valid_starting_config config ->
      ExplorationStop (execute r d config).
    
    (** No algorithm can stop on a starting configuration. *)
    Theorem no_stop_on_starting_config : ∀ r d config,
      Fair d -> Explore_and_Stop r -> Valid_starting_config config ->
      ~ Stopped (execute r d config).
    Proof using k_inf_n kdn.
      intros r d config.
      generalize (@reflexivity execution equiv _ (execute r d config)).
      generalize (execute r d config) at -2.
      intros e Heqe Hfair Hsol Hvalid Hsto.
      destruct (Hsol d config Hfair Hvalid) as [Hvisit Hstop].
      assert (Hfalse :=  ConfigExistsEmpty config).
      (* TODO: remove the use of classical logic: everything is decidable here *)
      apply Logic.Classical_Pred_Type.not_all_ex_not in Hfalse.
      destruct Hfalse as [loc Hfalse]. specialize (Hvisit loc).
      rewrite <- Heqe in *. induction Hvisit.
      + rewrite Heqe in *.
        match goal with H : Stream.instant _ _ |- _ => destruct H as [g Hg] end.
        rewrite (obs_from_config_In config fin0) in Hfalse; destruct Hfalse.
        exists (Good g). apply Hg.
      + apply IHHvisit.
        - rewrite <- Heqe. symmetry. now apply Stopped_same.
        - apply Hsto.
        - now apply Will_stop_tl.
    Qed.
    
    (** In particular, there is a tower on any final configuration. *)
    Lemma tower_on_final_config : ∀ r d config, Fair d -> Explore_and_Stop r
      -> Stopped (execute r d config) -> ∃ loc, (!! config)[loc] > 1.
    Proof using k_inf_n kdn.
      intros r d config Hfair Hsol Hstop.
      assert (Hequiv := @no_stop_on_starting_config r d config Hfair Hsol).
      assert (Hvalid : ~Valid_starting_config config) by tauto.
      apply config_not_injective in Hvalid. destruct Hvalid as [id [id' [Hid Heq]]].
      exists (config id).
      assert (Hobs := obs_from_config_spec config fin0 (config id)).
      assert (Hperm : exists l, PermutationA equiv (config_list config)
        (config id :: config id' :: l)).
      { assert (Hin : List.In id names) by apply In_names.
        assert (Hin' : List.In id' names) by apply In_names.
        assert (Hperm : exists l, PermutationA eq names (id :: id' :: l)).
        { rewrite <- InA_Leibniz in Hin, Hin'.
          apply PermutationA_split in Hin; autoclass; [].
          destruct Hin as [l' Hperm']. rewrite Hperm', InA_cons in Hin'.
          destruct Hin' as [| Hin']; try congruence; [].
          apply PermutationA_split in Hin'; autoclass; [].
          destruct Hin' as [l Hperm]. exists l. now rewrite Hperm', Hperm. }
        destruct Hperm as [l Hperm]. exists (List.map config l).
        now rewrite config_list_spec, Hperm. }
      destruct Hperm as [l Hperm]. rewrite Hobs.
      (* FIXME: why does [rewrite Hperm] fail here? *)
      rewrite (countA_occ_compat _ equiv_dec _ _ (reflexivity (config id))
                (PermutationA_map _ _ Hperm)).
      simpl List.map. rewrite List.map_id. unfold Datatypes.id. simpl.
      repeat destruct_match; solve [lia | exfalso; auto].
    Qed.
    
    Lemma exec_stopped (r : robogram) :
      ∀ (d : demon) (c : configuration), Fair d -> Will_stop (execute r d c)
      -> exists d' c', Fair d'/\ Stopped (execute r d' c').
    Proof using .
      intros d' config' Hfair Hstop. remember (execute r d' config') as e'.
      revert Heqe'. revert d' config' Hfair.
      induction Hstop as [e' Hstop | e' Hstop IHstop].
      + intros d' config' Hfair Heq. exists d', config'; now rewrite Heq in *.
      + intros d' config' Hfair Heq.
        apply (IHstop (tl d') (hd (tl e'))).
        - destruct Hfair as [_ Hfair]. constructor; apply Hfair.
        - now rewrite Heq, execute_tail.
    Qed.
    
    Lemma no_exploration_k_inf_2 : ∀ r d config,
      Fair d -> Explore_and_Stop r -> Valid_starting_config config -> k > 1.
    Proof using k_inf_n kdn.
      intros r d config Hfair Hsol Hvalid. assert (Hexr := exec_stopped r).
      assert (Htower := tower_on_final_config).
      destruct (Hsol d config Hfair Hvalid) as [Hvisit Hstop].
      destruct (Hexr d config Hfair Hstop) as [d' [config' [Hfair' Hstop']]].
      specialize (Htower r d' config' Hfair' Hsol Hstop'). destruct Htower.
      assert (Hcard := cardinal_lower x (!! config')).
      rewrite cardinal_obs_from_config in Hcard. unfold nG, nB in *.
      unfold Robots in *. simpl in *. lia.
    Qed.
    
    End Tower.
    
    (* Prefer not to leave this here, so that make -vos does not fail here.
    See Tower_Assumptions.v *)
    (* Print Assumptions no_exploration_k_inf_2. *)
    
    (*
    (** Stronger result: in any successful sequential execution,
        the last starting configuration was seen at least [ring_size - kG + 1] rounds ago. *)
    
    Fixpoint last_init_conf (l : list configuration) (a : configuration) :=
      match l with
      | nil => (False, nil)
      | config :: l' => if a =?= config
                        then (((List.Forall (fun x => ~ Valid_starting_config x ) l')
                              /\ Valid_starting_config a),l')
                        else last_init_conf l' a
      end.
    
    (* Definition SequencialExecution (e : execution) : Prop :=
      Stream.forever
        (fun e' => forall r d conf,
             e' == execute r d conf /\
             (exists id, forall id', id' <> id /\ step (Stream.hd d) id' (conf id')
                                                  = Moving false)) e. *)
    Definition SequencialExecution : execution -> Prop :=
      Stream.forever (Stream.instant
        (fun config => forall da, exists id, forall id', id' <> id -> activate da id' = false)).
    
    Fixpoint Biggest_list_of_exe (l : list configuration) (e : execution) : Prop :=
      match l with
      | nil => Stopped e
      | x :: nil => x == Stream.hd e /\ Stopped e
      | x :: y => x == Stream.hd e /\ ~ Stream.hd e == Stream.hd (Stream.tl e)
                                   /\  Biggest_list_of_exe y (Stream.tl (Stream.tl e))
      end.
    
    (* Lemma stop_tl : forall e, Stopped e -> Stopped (Stream.tl e).
    Proof. intros e He. apply He. Qed. *)
    
    Theorem TowerOnFinalConf : forall l r d config (e : execution) x,
        Valid_starting_config config ->
        e == execute r d config ->
        Biggest_list_of_exe l e ->
        let (P, l') := last_init_conf l config in
        P ->
        Explore_and_Stop r ->
        SequencialExecution e ->
        (forall config, List.In config l' ->
           exists pt, (!! config)[pt] = x -> (1 < x)%nat  -> (x < kG)%nat) ->
        (ring_size - kG + 1 <= length l')%nat.
    Proof.
    intros l r d config e x Hconfig Heq_e Hlist.
    destruct (last_init_conf l config) as (P, l') eqn : Hlic.
    intros HP Hvalid Hsequ Hl_conf.
    assert ((length l' < ring_size - kG + 1)%nat
           -> False).
    { intros Hf.
      unfold last_init_conf in Hlic.
      induction l.
      * simpl in *.
        rewrite surjective_pairing in Hlic.
        simpl in *.
        assert (P = fst (P, l')) by intuition.
        rewrite <- Hlic in *.
        simpl in *.
        now rewrite <- H.
      * destruct (config =?=  a).
        + assert (HeqP : P = fst (P, l')) by intuition.
          assert (l' = snd (P, l')) by intuition.
          rewrite <- Hlic in *; cbn -[equiv] in *.
          rewrite HeqP in HP.
          intuition.
          assert (Valid_starting_config a).
          { revert_one @equiv. intro Heq. now rewrite <- Heq. }
          destruct (last_init_conf l) eqn : Hl.
          
        split.
        - intros.
          destruct Hsequ.
          specialize (H0 r d conf). 
          destruct H0 as (He_conf, (id,Hid)).
          destruct l eqn : Hl.
        - simpl in *.
          destruct (Hvalid c Hconf) as (Hvisit, Hstop).
          assert (Hfalse :=  ConfExistsEmpty c).
          unfold is_visited in *.
          rewrite Heq_e in Hlist.
          now generalize (test Hvalid Heq_e Hconf Hlist).
        - destruct l0 eqn : Hl'.
           + simpl in *.
             destruct Hlist as (Hceq, Hstp).
             generalize (test Hvalid Heq_e Hconf).
             intros Htest.
             assert (Hval_t: ValidStartingConf t).
             rewrite Hceq.
             rewrite Heq_e.
             now simpl in *.
             assert (He_eq : eeq e (execute r d t)).
             rewrite Hceq.
             now rewrite Heq_e.
             generalize (test Hvalid He_eq Hval_t).
             intros Htest'.
             destruct Htest.
             now rewrite <- Heq_e.
           + destruct (Classical_Prop.classic (ValidStartingConf (last (t :: t0 :: l1) c)))
               as [Hv|Hnv].
             simpl in *.
             destruct ( Config.eq_dec (Stream.hd e) (Stream.hd (Stream.tl (Stream.tl e))));
               try easy.
             destruct Hlist as (Hceq, Hlist).
             assert (Hse : ~Stopped e).
             intros Hs.
             destruct Hs as (Hse, Hs).
             now unfold stop_now in Hse.
             destruct l1.
             * destruct (Classical_Prop.classic
                           (ValidStartingConfSolExplorationStop
                           r (Stream.tl (Stream.tl d)))) as [Hvrd|Hnvrd].
               assert (Heeq_to : eeq (Stream.tl (Stream.tl e)) (execute r (Stream.tl (Stream.tl d)) t0)).
               { rewrite Heq_e.
                 destruct Hlist as (Hlist, Hstp).
                 rewrite Heq_e in Hlist.
                 repeat rewrite execute_tail in *.
                 apply execute_compat; try easy.
               }
               destruct (test Hvrd Heeq_to Hv).
               now rewrite <- Heeq_to.
               unfold ValidStartingConfSolExplorationStop in *.
               apply Classical_Prop.NNPP.
               intro.
               apply Hnvrd.
               intros.
               destruct (Hvrd t0 Hv).  Heeq_to).
               admit.
             apply Classical_Pred_Type.not_all_not_ex.
             intros Hf.
             destruct Hnv.
             unfold ValidStartingConf.
             intros (ex, Hex).
             now specialize (Hf ex).
    Qed.
     *)