Library AMM11262.unicode_format.utf_AMM11262


Require Import Arith.

Require OrderedTypeEx.
Require FSetList.
Module NatSet := FSetList.Make(OrderedTypeEx.Nat_as_OT).
Import NatSet.

Notation " A ⇒ B " := (A -> B) (at level 90, right associativity) : type_scope.
Notation " ∀ x , B " := (forall x:_, B ) (at level 200, x at level 0, no associativity) : type_scope.
Notation " ∀ x y , B " := (forall (x:_) (y:_), B ) (at level 200, x at level 0, y at level 0, no associativity) : type_scope.
Notation " ∀ x y z , B " := (forall (x:_) (y:_) (z:_), B ) (at level 200, x at level 0, y at level 0, z at level 0, no associativity) : type_scope.
Notation " ¬ x " := (not x) (at level 75, right associativity) : type_scope.
Notation " A ∧ B " := (A /\ B) (at level 80, right associativity) : type_scope.
Notation " A ∨ B " := (sumor A B) (at level 85, right associativity) : type_scope.
Notation " A \/ B " := (sumbool A B) (at level 85, right associativity) : type_scope.
Notation " ∃ x , B " := (sig (fun x:_=>B) ) (at level 0, x at level 99, no associativity) : type_scope.
Notation " A × B " := (A * B) (at level 40, left associativity) : type_scope.
Notation " 'ℕ' " := nat : type_scope.
Infix " ≤ " := le (at level 70, right associativity): nat_scope.
Notation "s ≐ t" := (Equal s t) (at level 70, no associativity).
Infix "∈" := In (at level 30, no associativity).
Infix "⊆" := Subset (at level 70, right associativity).
Infix "\" := diff (at level 40, left associativity).
Notation "| A |" := (cardinal A) (at level 10, no associativity).
Infix "≡" := E.eq (at level 70, no associativity).
Infix "∩" := inter (at level 40, left associativity).
Infix "∪" := union (at level 50, left associativity).
Notation " { x } ∪ X " := (add x X).
Notation " X \ { x } " := (remove x X).
Notation "∅" := empty.

Require FSetFacts FSetProperties.

Module GeneralProperties := FSetProperties.Properties NatSet.
Import GeneralProperties.

Section problem_knows_not_refl.

Variable town: t.
Variable n:.
Variable cardinality: | town | = 2×n+1.

Variable knows: elt elt Prop.
Infix "ℛ" := knows (at level 70, no associativity).

Variable knows_sym: m n, m n n m.
Variable knows_extensional:m n p, np m n m p.

Variable property: B, B town |B| = n
           d, d∈(town\B) /\ (b, bB d b).

Lemma extendible_by_one: B', |B'| |town| -1 d, dtown ¬(dB').
Proof.
 clear knows knows_sym knows_extensional property.
 intros B' H_cardinal_town.
 assert (H_town:1 |town|); [omega|].
 rewrite <- (diff_inter_cardinal town B') in H_cardinal_town.
 rewrite <- (diff_inter_cardinal town B') in H_town.
 assert (H_inter:|townB'| |B'|);
  [apply (subset_cardinal);apply (inter_subset_2)|].
 generalize (le_trans _ _ _ H_inter H_cardinal_town); intro H1.
 assert (H2:1|town\B'|); [omega|].
 assert (H3:=(S_pred _ _ H2)).
 destruct (cardinal_inv_2 H3) as [d Hd].
 exists d; split.
  apply diff_1 with B'; assumption.
  apply diff_2 with town; assumption.
Qed.

Lemma extendible_to_n: B', B'town |B'| n B, |B| = n B'B Btown.
Proof.
 intros B' H_sub H_B'_cardinal.
 assert (H_cardinal_aux_3:2×n |town| -1);[apply le_trans with (2×n); omega|].
 clear cardinality property.
 induction n.
 generalize (sym_eq (le_n_O_eq _ H_B'_cardinal)); intro H_eq.
 generalize (empty_is_empty_1 (cardinal_inv_1 H_eq)).
 intro H_B'.
 exists ; repeat split.
  rewrite H_B'; apply subset_empty.
  apply subset_empty.
 destruct (le_lt_eq_dec _ _ H_B'_cardinal) as [H_lt|H_le].
  generalize (lt_n_Sm_le _ _ H_lt); clear H_lt; intro H_le.
  assert (H_cardinal_town_2:2 * n0 |town| - 1);[omega|].
  destruct (IHn0 H_le H_cardinal_town_2) as [C [HC1 [HC2 HC3]]].
  assert (HC5:|C| |town| - 1).
   rewrite HC1; apply le_trans with (2×(S n0));[omega| assumption].
  destruct (extendible_by_one C HC5) as [d [Hd1 Hd2]].
  exists ({d} C).
  repeat split.
   rewrite (add_cardinal_2 Hd2); rewrite HC1; reflexivity.
   apply subset_add_2; assumption.
   apply subset_add_3; assumption.

  exists B'.
  repeat split; trivial; apply subset_refl.
Qed.

The following property, proven by induction, is the heart of the solution, and is due to Tonny Hurkens.
Lemma inductive_invariant: m, m n
                B', B'town |B'| = m b'₀ b'₁, b'₀B' b'₁B' ¬(b'₀b'₁) b'₀ b'₁.
Proof.
 intros m.
 induction m; intros H_le.
  exists .
  repeat split.
   apply subset_empty.
   intros b'₀ b'₁ H0 H1; apply False_ind.
   elim (FM.empty_iff b'₀); intros H2 _; apply H2; assumption.
  assert (H_le0:=le_Sn_le _ _ H_le).
  destruct (IHm H_le0) as [B' [H3' [H1 H2]]].
  rewrite <- H1 in H_le0.
  destruct (extendible_to_n B' H3' H_le0) as [B [HB1 [HB2 HB3]]].
  destruct (property B HB3 HB1) as [d [Hd1 Hd2]].
  exists ({d}∪ B'); repeat split.
   apply subset_add_3.
   apply diff_1 with B; assumption.
   apply subset_trans with B; assumption.
   rewrite <- H1.
   apply add_cardinal_2.
   intro Hd4.
   generalize (in_subset Hd4 HB2).
   apply diff_2 with town; assumption.
   intros b'₀ b'₁ H_b'₀ H_b'₁ H_neq.
   destruct ((proj1 (FM.add_iff B' d b'₀)) H_b'₀) as [H3|H3].
    apply knows_sym; apply knows_extensional with d; trivial.
    destruct ((proj1 (FM.add_iff B' d b'₁)) H_b'₁) as [H4|H4].
     apply False_ind; apply H_neq; rewrite <- H3; assumption.
     apply knows_sym.
     apply Hd2; apply in_subset with B'; trivial.
    destruct ((proj1 (FM.add_iff B' d b'₁)) H_b'₁) as [H4|H4].
     apply knows_extensional with d; trivial.
     apply knows_sym.
     apply Hd2; apply in_subset with B'; trivial.
     apply H2; assumption.
Qed.

Theorem AMM11262: e,etown u, utown ¬(ue) e u.
Proof.
 destruct (inductive_invariant n (le_refl n)) as [B [HB1 [HB2 HB3]]].
 destruct (property B HB1 HB2) as [d [Hd1 Hd2]].
 set (C:=(town\({d}∪B))).
 assert (H_susbset_C:Ctown);
 [ subst C; apply subset_diff; apply subset_refl
 | ].
 assert (H_inter_town: (town ({d}∪B)) {d} B).
  rewrite inter_sym; apply inter_subset_equal;
  apply subset_add_3; trivial; apply diff_1 with B; assumption.
 assert (H_d_nin_B:¬dB); [apply diff_2 with town; assumption|].
 assert (H_cardinal_C:|C| =n).
  assert (H_aux:|town∩({d}∪B)|=S n).
   rewrite (@Equal_cardinal (town∩({d}∪B)) ({d}∪B) H_inter_town);
   rewrite (add_cardinal_2 H_d_nin_B); rewrite HB2; reflexivity.
  generalize (diff_inter_cardinal town ({d}∪B));
  fold C; rewrite H_aux; rewrite cardinality; omega.

 destruct (property C H_susbset_C H_cardinal_C) as [e [He1 He2]].
 exists e.
 assert (H_dB_town:({d}∪B)⊆town).
  intros a Ha0; destruct ((proj1 (FM.add_iff B d a)) Ha0) as [Had|HaB].
   rewrite <- Had; apply diff_1 with B; assumption.
   apply HB1; assumption.
 assert (H_diff: town\C {d}∪B ).
  unfold C; split; intro H_mem.
   assert (H_a0:=diff_1 H_mem);
   assert (H_a1:=diff_2 H_mem);
   destruct (In_dec a ({d}∪B)) as [H_a2|H_a2]; trivial;
   apply False_ind; apply H_a1; exact (diff_3 H_a0 H_a2).
   destruct (In_dec a (town\({d}∪B))) as [H_a2|H_a2].
    apply False_ind; exact (diff_2 H_a2 H_mem).
    apply diff_3; trivial; apply H_dB_town; assumption.
 assert (H_e_dB:e∈({d}∪B)); [rewrite <- H_diff; assumption|].

 split.
  apply diff_1 with C; assumption...
  intros u [Hu Hu'].
  assert (H_town_part:town (C∪({d}∪B))).
   rewrite <- (diff_inter_all town ({d}∪B)); rewrite H_inter_town; apply equal_refl.
   rewrite H_town_part in Hu.
   destruct (union_1 Hu) as [HuC|HudB].
    apply He2; assumption.
    destruct ((proj1 (FM.add_iff B d u)) HudB) as [Hud|HuB].
     apply knows_extensional with d; trivial.
     apply knows_sym.
     destruct ((proj1 (FM.add_iff B d e)) H_e_dB) as [Hed|HeB].
      apply False_ind; apply Hu'; rewrite <- Hud; assumption.
      apply Hd2; assumption.
     destruct ((proj1 (FM.add_iff B d e)) H_e_dB) as [Hed|HeB].
      apply knows_sym; apply knows_extensional with d; trivial;
      apply knows_sym; apply Hd2; assumption.
      apply HB3; assumption || contradict Hu'; auto with *.
Qed.

End problem_knows_not_refl.

Extraction "amm11262" AMM11262.