diff --git a/CaseStudies/Gathering/InR2/Algorithm_withLight.v b/CaseStudies/Gathering/InR2/Algorithm_withLight.v
index 924ef899c4a0860bc58509f8185878d884628470..d88ced1fd6c64c7105cd44f1c297dc2257cf4162 100644
--- a/CaseStudies/Gathering/InR2/Algorithm_withLight.v
+++ b/CaseStudies/Gathering/InR2/Algorithm_withLight.v
@@ -164,7 +164,7 @@ refine {|
 Defined.
 
 
-(* We are in a rigid formalism with no other info than the location, so the demon makes no choice. *)
+(* We are in a rigid formalism with no other info than the location and color, so the demon makes no choice. *)
 Instance Loc : Location := make_Location R2.
 Instance VS : RealVectorSpace location := R2_VS.
 Instance ES : EuclideanSpace location := R2_ES.
@@ -172,7 +172,6 @@ Instance RobotChoice : robot_choice (location*L) :=
   { robot_choice_Setoid := prod_Setoid location_Setoid L_Setoid }.
 Instance ActiveChoice : update_choice unit := NoChoice.
 Instance InactiveChoice : inactive_choice unit := { inactive_choice_EqDec := unit_eqdec }.
-(* Instance Info : State location := OnlyLocation (fun _ => True). *)
 
 (* true = white, false = black *)
 Instance St : State (location*L) := @WithMultiplicityLight.St _ Lght.
@@ -884,7 +883,6 @@ Local Existing Instance multiset_observation.
 Typeclasses eauto := (bfs).
 
 (** The target in the triangle case. *)
-(* TODO: replace [isobarycenter_3_pts] with the general [isobarycenter]. *)
 Definition target_triangle (pt1 pt2 pt3 : location) : location :=
   let typ := classify_triangle pt1 pt2 pt3 in
   match typ with
@@ -1102,14 +1100,13 @@ rewrite <- support_spec, Hin. now right; left.
 Qed.
 
 (** The robogram solving the gathering problem in R². *)
-(* Note: If gatherR2_pgm is adapted to this model it should already return a location * L *)
 Definition gatherR2_pgmLight (obs : observation) : location * L :=
   if bivalent_obs obs
   then let other_loc := find_other_loc (fst obs) origin in
        if color_bivalent_obs obs
        then if observer_lght (snd obs)
             then (middle origin other_loc, false)
-            else (origin, true) (* was: (other_loc, true) *)
+            else (origin, true)
        else let maj_black := find_max_black obs origin other_loc in
             (maj_black, observer_lght (snd obs))
   else (gatherR2_old_pgm (fst obs), observer_lght (snd obs)).
@@ -1510,7 +1507,7 @@ Qed.
   - 4''] Dirty scalene triangle: # robots not on SECT
   - 5]   Clean generic case (|SEC| ≥ 4): # robots not on target
   - 6]   Dirty Generic case (|SEC| ≥ 4): # robots not on SECT
-  - 7]   Bivalent case: no need, durect jump to Majority tower of Gathered
+  - 7]   Bivalent case: no need, direct jump to Majority tower of Gathered
   - 8]   Color bivalent case: # black robots
 *)
 
@@ -3704,36 +3701,6 @@ contradiction.
 Qed.
 
 
-Lemma forall_ident pred: Forall pred names <-> forall id:ident, pred id.
-Proof using .
-  split.
-  - intros H id. 
-    eapply Forall_forall in H;eauto.
-    apply In_names.
-  - intros H. 
-    apply Forall_forall.
-    intros x H0. 
-    apply H;auto.
-Qed.
-
-Lemma exists_ident pred: List.Exists pred names <-> exists id:ident, pred id.
-Proof using .
-  split.
-  - intros H. 
-    eapply Exists_exists in H;eauto.
-    destruct H as [x [hx hx']].
-    exists x.
-    assumption.
-  - intros H. 
-    destruct H as [x predx].
-    apply Exists_exists.
-    exists x.
-    split.
-    + apply In_names.
-    + assumption.
-Qed.
-
-
 Lemma Exists_decidable :
   forall [A : Type] (P : A -> Prop),
     (forall x : A, P x \/ ~ P x)
@@ -3804,7 +3771,7 @@ Lemma sub_cb_nb_precondition_wholecolmove_dec id1:
            get_location (config id) == get_location (config id1) ->
            is_moving gatherR2 da config id).
 Proof using .
-  rewrite <- forall_ident.
+  rewrite <- Forall_ident.
   match goal with
     |- Forall ?pred _ \/ _ => destruct (Forall_decidable pred (dec1 id1) names)
   end.
@@ -3822,7 +3789,7 @@ Lemma dec3 x:
               is_moving gatherR2 da config id) /\ is_moving gatherR2 da config id2).
 Proof using .
   red.
-  rewrite <- exists_ident.
+  rewrite <- Exists_ident.
   apply Exists_decidable.
   intros x0. 
   apply Decidable.dec_and.
@@ -3830,7 +3797,7 @@ Proof using .
     destruct ((get_location (config x0) =?= get_location (config x)));intuition.
   - apply Decidable.dec_and.
     + red.
-      rewrite <- forall_ident.
+      rewrite <- Forall_ident.
       apply Forall_decidable.
       apply dec1.
     + apply is_moving_dec.
@@ -3841,7 +3808,7 @@ Lemma cb_nb_precondition_wholecolmove_dec:
   cb_nb_precondition_wholecolmove \/ ~ cb_nb_precondition_wholecolmove .
 Proof using .
   unfold cb_nb_precondition_wholecolmove.
-  setoid_rewrite <- exists_ident.
+  setoid_rewrite <- Exists_ident.
   apply Exists_decidable.
   intro x.
   apply dec3.
@@ -4029,8 +3996,8 @@ destruct (active da) as [| id l] eqn:Hactive.
     2:{ red. apply sub_cb_nb_precondition_wholecolmove_dec. }
     destruct H.
     - left.
-      rewrite <- exists_ident.
-      rewrite <- forall_ident in H.
+      rewrite <- Exists_ident.
+      rewrite <- Forall_ident in H.
       rewrite <- Exists_Forall_neg in H.
       + revert H.
         apply Exists_impl.
@@ -4066,7 +4033,7 @@ destruct (active da) as [| id l] eqn:Hactive.
                  \/ get_location (config id2) == get_location (config id1))).
     { intros id0 id2.
       specialize (h_cb_nb_wm id0 id2).
-      rewrite <-exists_ident in h_cb_nb_wm.
+      rewrite <-Exists_ident in h_cb_nb_wm.
       destruct (Exists_decidable ((fun id : ident =>
                   get_location (config id) == get_location (config id0) /\ ~ is_moving gatherR2 da config id))) with (l:=names).
       { intros id'.
@@ -4074,16 +4041,16 @@ destruct (active da) as [| id l] eqn:Hactive.
         - apply get_location_dec.
         - apply Decidable.dec_not.
           destruct (is_moving_dec gatherR2 da config id'); now left + right. }
-      + left; apply exists_ident;auto.
+      + left; apply Exists_ident;auto.
       + destruct  h_cb_nb_wm as [h | [h | h]].
         * contradiction.
         * right.
           split.
-          -- rewrite <- exists_ident;auto.
+          -- rewrite <- Exists_ident;auto.
           -- now left.
         * right.
           split.
-          -- rewrite <- exists_ident;auto.
+          -- rewrite <- Exists_ident;auto.
           -- now right. }
 
     intros id1. 
@@ -4260,7 +4227,7 @@ destruct (active da) as [| id l] eqn:Hactive.
               \/ ~(exists id'', get_location (config id'') = get_location (config id_move)
                                 /\ ~ is_moving gatherR2 da config id''))
         as [[id'' [h_id''_loc h_id''_move]]| h].
-      { setoid_rewrite <- exists_ident.
+      { setoid_rewrite <- Exists_ident.
         apply Exists_decidable.
         intros x. 
         apply Decidable.dec_and.
@@ -4273,7 +4240,7 @@ destruct (active da) as [| id l] eqn:Hactive.
           assumption.
         * now apply stationary_moving.
         * now apply stationary_moving.
-      + rewrite <- exists_ident in h.
+      + rewrite <- Exists_ident in h.
         rewrite <- Forall_Exists_neg in h.
         changeR2.
         assert (Forall (fun x : ident =>
@@ -4414,7 +4381,7 @@ destruct (active da) as [| id l] eqn:Hactive.
               \/ ~(exists id'', get_location (config id'') = get_location (config id_move)
                                 /\ ~ is_moving gatherR2 da config id''))
         as [[id'' [h_id''_loc h_id''_move]]| h].
-      { setoid_rewrite <- exists_ident.
+      { setoid_rewrite <- Exists_ident.
         apply Exists_decidable.
         intros x. 
         apply Decidable.dec_and.
@@ -4427,7 +4394,7 @@ destruct (active da) as [| id l] eqn:Hactive.
           assumption.
         * now apply stationary_moving.
         * now apply stationary_moving.
-      + rewrite <- exists_ident in h.
+      + rewrite <- Exists_ident in h.
         rewrite <- Forall_Exists_neg in h.
         changeR2.
         assert (Forall (fun x : ident =>
@@ -4496,7 +4463,7 @@ destruct (active da) as [| id l] eqn:Hactive.
                      /\ get_location (config id_counterexample) = get_location (config id')) as [id_counter [h_counter1 h_counter2]].
           { apply Decidable.dec_not_not.
             { red.
-              setoid_rewrite <- exists_ident.
+              setoid_rewrite <- Exists_ident.
               apply Exists_decidable.
               intros x. 
               apply Decidable.dec_and.
@@ -7096,6 +7063,75 @@ destruct (gathered_at_dec config (get_location (config (Good g1)))) as [Hmove |
 Qed.
 
 
+(* *********** UNFAIR DEMON ************** *)
+
+(* Unfairness in terms of gathering: someone always moves if robots
+   are not gathered (and position is valid). *)
+Definition unfair_da_gathering r da config :=
+    (forall pt, ~gathered_at pt config) ->
+    changing r da config <> nil.
+
+Definition unfair_gathering r d config :=
+  Stream.forever2 (Stream.instant2 (unfair_da_gathering r)) d (execute r d config).
+
+(* We link this definition to the usual notion of unfairness:
+   if a robot can move, then some robot moves. *)
+
+Definition sim_da_with_all_activated da : similarity_da.
+Proof using .
+exists (da_with_all_activated da).
+apply (proj2_sig da).
+Defined.
+
+Lemma unfair_da_gather_impl: forall da config,
+    unfair_da gatherR2 (proj_sim_da da) config ->
+    unfair_da_gathering gatherR2 da config.
+Proof using .
+unfold unfair_da, unfair_da_gathering.
+intros da config Hunfair Hgather.
+apply Hunfair.
+destruct (OneMustChange (Good g1) (Hgather (get_location (config (Good g1)))))
+  as [gmove Hgmove].
+assert (Hall : List.In gmove (active (proj_sim_da (sim_da_with_all_activated da)))).
+{ unfold active. simpl. rewrite List.filter_In. auto using In_names. }
+specialize (Hgmove (sim_da_with_all_activated da)
+                   (FSYNC_SSYNC_da (da_with_all_activated_FSYNC_da da)) Hall).
+rewrite changing_spec in Hgmove.
+intro Habs. apply no_changing_same_config in Habs. apply Hgmove, Habs.
+Qed.
+
+Lemma unfair_gather_impl : forall d config,
+  unfair gatherR2 (similarity_demon2demon d) config ->
+  unfair_gathering gatherR2 d config.
+Proof using .
+coinduction cfsd.
++ destruct H. clear -H. simpl in *. now apply unfair_da_gather_impl.
++ now destruct H.
+Qed.
+
+(* Final theorem for unfair demons. *)
+Theorem unfair_Gathering_in_R2 : forall (d : similarity_demon) config,
+  SSYNC (d : demon) ->
+  unfair gatherR2 (d : demon) config ->
+  WillGather (execute gatherR2 d config).
+Proof using .
+intros d config Hssync Hunfair'.
+assert (Hunfair : unfair_gathering gatherR2 d config) by now apply unfair_gather_impl.
+clear Hunfair'.
+revert d Hssync Hunfair. pattern config.
+apply (well_founded_ind wf_lt_config). clear config.
+intros config Hind d Hssync Hunfair.
+(* Are we already gathered? *)
+destruct (gathered_at_dec config (get_location (config (Good g1)))) as [Hmove | Hmove].
++ (* If so, not much to do *)
+  apply Stream.Now. exists (get_location (config (Good g1))). now apply gathered_at_OK.
++ (* Otherwise, by assumption on the demon, a robot should move
+     so we can use our well-founded induction hypothesis. *)
+  destruct Hunfair as [Hactive Hunfair], Hssync. hnf in Hactive.
+  apply Stream.Later, Hind; trivial; try (now apply never_bivalent); [].
+  apply round_lt_config; trivial; [].
+  apply Hactive; trivial; []. intros pt Habs. apply Hmove. eapply gathered_precise, Habs.
+Qed.
 End GatheringInR2.
 
 (* We prefer calling this from another file, see Algorithm_withLight_ASsumptions.v. *)
diff --git a/CaseStudies/Gathering/InR2/Algorithm_withLight_Assumptions.v b/CaseStudies/Gathering/InR2/Algorithm_withLight_Assumptions.v
index fb7e777e87409836d2e01111551e21e2689a4ae6..ae1cefaf8348e8a000416d087013a51a9affe287 100644
--- a/CaseStudies/Gathering/InR2/Algorithm_withLight_Assumptions.v
+++ b/CaseStudies/Gathering/InR2/Algorithm_withLight_Assumptions.v
@@ -1,2 +1,3 @@
 Require Pactole.CaseStudies.Gathering.InR2.Algorithm_withLight.
 Print Assumptions InR2.Algorithm_withLight.Gathering_in_R2.
+Print Assumptions InR2.Algorithm_withLight.unfair_Gathering_in_R2.
diff --git a/CaseStudies/Gathering/WithMultiplicityLight.v b/CaseStudies/Gathering/WithMultiplicityLight.v
index 09ea4ea62b35f4a321bf102855c280c0ebaf3811..e003a4a98dafcb47db8889d7458ee0a1bea58e03 100644
--- a/CaseStudies/Gathering/WithMultiplicityLight.v
+++ b/CaseStudies/Gathering/WithMultiplicityLight.v
@@ -46,9 +46,8 @@ Class Lights := {
 
 Section MultisetGathering.
 
-(** Here, we restrict the state to only contain the location. *)
+(** Here, the state contain the location and the color. *)
 Context `{Loc:Location}.
-(* TODO: add the existence of a similarity here *)
 Context {Lght : Lights}.
 
 Local Instance St : State (location*L) := AddInfo L (OnlyLocation (fun _ => True)).
@@ -1183,18 +1182,14 @@ specialize (@obs_from_config_fst st config (fst (!!! (config, st))) (snd (!!! (c
 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 hfst.
-    rewrite Hpt1'.
-    destruct (nG+nB) as [| [| nG]] eqn:heqnB ; simpl; try lia.
-    set (d := (Nat.div2 nG)).
-    lia. }
+    rewrite hfst, Hpt1'.
+    destruct (nG+nB) as [| [| nG]] eqn:heqnB ; simpl;
+    lia || (set (d := (Nat.div2 nG)); lia). }
   assert (Hin2 : InA equiv pt2' (pt1 :: pt2 :: nil)).
   { rewrite <- Hsupp, support_spec. unfold In.
-    rewrite hfst.
-    rewrite Hpt2'.
-    destruct (nG+nB) as [| [| nG]] eqn:heqnB; simpl; try lia.
-    set (d := (Nat.div2 nG)).
-    lia. }
+    rewrite hfst, Hpt2'.
+    destruct (nG+nB) as [| [| nG]] eqn:heqnB; simpl;
+    lia || (set (d := (Nat.div2 nG)); lia). }
   rewrite 2 InA_cons, InA_nil in Hin1, Hin2. clear -Hin1 Hin2 Hdiff.
   decompose [or] Hin1; decompose [or] Hin2; tauto || elim Hdiff; etransitivity; eauto. }
 split.
diff --git a/Core/Formalism.v b/Core/Formalism.v
index 10159f49916154701b9b9c439ad679e4dc0e385c..c3ff4b95fea717649423670796d4cedbd367b991 100644
--- a/Core/Formalism.v
+++ b/Core/Formalism.v
@@ -794,9 +794,9 @@ Proof using . now intros da id. Qed.
 
 (** An unfair demon activates at least one activable robot if such a robot exists. *)
 Definition unfair_da r da config :=
-  (* If assuming all robots are activated, a robot can move *)
+  (* If assuming all robots are activated, a robot can evolve *)
   changing r (da_with_all_activated da) config <> nil ->
-  (* then at least a robot moves *)
+  (* then at least a robot evolves *)
   changing r da config <> nil.
 
 Definition unfair r d config :=
diff --git a/Core/Identifiers.v b/Core/Identifiers.v
index d6a61b02be35b598c7ca4a47e95addcf00234b1b..6e0f1691f0338358c34ebdc91cc640819065f45f 100644
--- a/Core/Identifiers.v
+++ b/Core/Identifiers.v
@@ -70,6 +70,16 @@ intro r. cbn. unfold names. rewrite in_app_iff. destruct r as [g | b].
 - right. apply in_map, In_Bnames.
 Qed.
 
+Corollary Forall_ident `{Names} : forall P, Forall P names <-> forall id, P id.
+Proof using . intro P. rewrite Forall_forall. generalize In_names. intuition. Qed.
+
+Corollary Exists_ident `{Names} : forall P, List.Exists P names <-> exists id, P id.
+Proof using .
+intro P.
+rewrite Exists_exists.
+split; intro Hex; decompose [ex and] Hex; eauto using In_names.
+Qed.
+
 Lemma names_NoDup `{Names} : NoDup names.
 Proof using .
 unfold names. rewrite <- NoDupA_Leibniz. apply (NoDupA_app _).
diff --git a/Observations/MultisetObservation.v b/Observations/MultisetObservation.v
index 73b74e3f98ef4f6530de357a6a6fab4ac5c51305..8e9f7718eabed16205d72177676c3b432824db91 100644
--- a/Observations/MultisetObservation.v
+++ b/Observations/MultisetObservation.v
@@ -241,7 +241,7 @@ Qed.
 
 Lemma obs_from_config_on_loc : forall config st pt,
   (obs_from_config config st)[pt] = length (on_loc pt config).
-Proof.
+Proof using .
 intros config st pt.
 unfold obs_from_config, on_loc. cbn.
 rewrite config_list_spec, map_map.
@@ -254,11 +254,11 @@ Qed.
 
 Lemma In_occupied : forall config st pt,
   In pt (obs_from_config config st) <-> InA equiv pt (occupied config).
-Proof. intros. now rewrite occupied_spec, obs_from_config_In. Qed.
+Proof using . intros. now rewrite occupied_spec, obs_from_config_In. Qed.
 
 Lemma support_occupied : forall config st,
   PermutationA equiv (support (obs_from_config config st)) (occupied config).
-Proof.
+Proof using .
 intros. apply NoDupA_equivlistA_PermutationA.
 + autoclass.
 + apply support_NoDupA.
diff --git a/Util/ListComplements.v b/Util/ListComplements.v
index 3bd8d16287945e05154b008300e689b8334013ec..4783c9573bb166489c28f0e935c856839fbb66e6 100644
--- a/Util/ListComplements.v
+++ b/Util/ListComplements.v
@@ -2066,7 +2066,7 @@ Qed.
 
 Global Instance removeA_dups_compat : forall eqA_dec,
   Proper (PermutationA eqA ==> PermutationA eqA) (removeA_dups eqA_dec).
-Proof.
+Proof using HeqA.
 intros eqA_dec l1 l2 Hperm.
 apply NoDupA_equivlistA_PermutationA; trivial; try apply removeA_dups_spec; [].
 transitivity l1.