Library bar_induction

Require Import List.
Require Import Omega.

Record rule A :=
  { rule_set :> list A -> Prop
  ; rule_down : forall x a, rule_set (a::x) -> rule_set x
  ; rule_nil : rule_set nil
  }.

Definition choice_set A (X:list A -> Prop) :=
  forall l, X l -> exists a, X (a::l).

Record choices A :=
  { ch_set :> list A -> Prop
  ; ch_prf : choice_set A ch_set
  ; ch_nil : ch_set nil
  }.

Definition rule_following A (rule:rule A) (f:choices A) :=
  forall l, f l -> rule l.

Definition bar {A} (R:rule A) (B:list A -> Prop) :=
  forall f:choices A, rule_following A R f ->
    exists l, f l /\ B l.

Inductive securable {A} (R:rule A) (B:list A -> Prop) : list A -> Prop :=
| sec_incl : forall x, B x -> securable R B x
| sec_mono : forall x a, R (a::x) -> securable R B x -> securable R B (a::x)
| sec_hered : forall x,
     (forall a, R (a::x) -> securable R B (a::x)) ->
     securable R B x.

Class brouwer_thesis_on_games :=
  { bar_securable :
    forall A (R:rule A) (B:list A -> Prop), bar R B -> securable R B nil
  }.


Definition limited_principle_of_omniscience :=
  forall (R:nat -> Prop),
    (forall n, R n \/ ~R n) ->
    (forall n, R n) \/ (exists n, ~R n).

Definition limited_principle_of_omniscience' :=
  forall (R:nat -> Prop),
    (forall n, R n \/ ~R n) ->
    (exists n, R n) \/ ~(exists n, R n).

Lemma LPO_eq :
  limited_principle_of_omniscience <->
  limited_principle_of_omniscience'.

Lemma classic_brouwer_thesis (classic:forall P, P \/ ~P) : brouwer_thesis_on_games.

Section bar_induction.
  Hypothesis Bw:brouwer_thesis_on_games.

  Variable A:Type.
  Variable R:rule A.

  Variable U Y:list A -> Prop.

  Hypothesis inclUY : forall x, R x -> U x -> Y x.
  Hypothesis monoU : forall x a, R (a::x) -> U x -> U (a::x).
  Hypothesis heredY : forall x, R x -> (forall a, R (a::x) -> Y (a::x)) -> Y x.

  Lemma securable_induction : forall x, securable R U x -> forall x', R (x'++x) -> Y (x'++x).

  Lemma bar_induction : bar R U -> Y nil.

End bar_induction.

Definition bar_induction_statement :=
    forall (A : Type) (R : rule A) (U Y : list A -> Prop),
       (forall x : list A, R x -> U x -> Y x) ->
       (forall (x : list A) (a : A), R (a :: x) -> U x -> U (a :: x)) ->
       (forall x : list A, R x -> (forall a : A, R (a :: x) -> Y (a :: x)) -> Y x) ->
       bar R U -> Y nil.

Lemma bar_induction_brouwer : bar_induction_statement <-> brouwer_thesis_on_games.

Section omniscience.
  Hypothesis Bw:brouwer_thesis_on_games.

  Variable R:nat -> Prop.
  Hypothesis Rdec : forall n, R n \/ ~R n.

  Let R' x := forall n, n < x -> R n.

  Lemma R'down : forall n, R' (S n) -> R' n.

  Lemma R'0 : R' 0.

  Lemma R'dec : forall n, R' n \/ ~R' n.

  Program Definition T : rule nat :=
    Build_rule _ (fun l => R' (length l)) _ _ .

  Remark T_dec : forall l, T l \/ ~T l.

  Let B (l:list nat) := forall n, R' n.
  Let U (l:list nat) := (forall n, R' n) \/ (exists n, ~R' n).

  Lemma Unil : U nil.

  Theorem omniscience : (forall n, R n) \/ (exists n, ~R n).
End omniscience.

Theorem brouwer_games_LPO : brouwer_thesis_on_games -> limited_principle_of_omniscience.