(************************************************************************)
(* Copyright 2007 Milad Niqui                                           *)
(* This file is distributed under the terms of the                      *)
(* GNU Lesser General Public License Version 2.1                        *)
(* A copy of the license can be found at                                *)
(*                  <http://www.gnu.org/licenses/lgpl.txt>              *)
(************************************************************************)
Require OrderedTypeEx.
Require FSetList.
Require Extraction.
Module NatSet := FSetList.Make(OrderedTypeEx.Nat_as_OT).
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) (at level 50, left associativity).
Notation " X \ { x } " := (remove x X) (at level 40, left associativity).
Notation "∅" := empty.
Require FSetFacts FSetProperties.
Module GeneralProperties := FSetProperties.Properties NatSet.
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, n≡p ⇒ m ℛ n⇒ m ℛ p.
Variable property: ∀B, B ⊆ town ⇒ |B| = n ⇒
∃d, d∈(town\B) /\ (∀b, b∈B ⇒ d ℛ b).

(** 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'₁.