The best I can do is to prove your lemma with the axioms of excluded middle (XM) and König’s lemma (KL) in the following forms:
Require Import List Arith Lia.
Import ListNotations.
Inductive rel_seq {X} (R : X -> X -> Prop) : list X -> Prop :=
| seq_zero : rel_seq R []
| seq_one x : rel_seq R [x]
| seq_more l x y : R x y -> rel_seq R (l++[x]) -> rel_seq R (l++[x;y]).
Definition finite {X} (P : X -> Prop) := exists l, forall x, P x <-> In x l.
Axiom Konigs_lemma :
forall X (R : X -> X -> Prop) (HR : forall x, finite (R x)) (x : X),
(forall n, exists l, rel_seq R (x::l) /\ n <= length l)
-> (exists f, f 0 = x /\ forall n, R (f n) (f (S n))).
Axiom xm : forall A : Prop, A \/ ~ A.
(** a good amount of interesting proofs *)
Check functional_list_choice.
Print Assumptions functional_list_choice.
(** outputs
functional_list_choice
: forall (A : Type) (R : A -> A -> Prop) (f_list : nat -> list A),
(forall k : nat, f_list k <> []) ->
(forall (k : nat) (v2 : A),
In v2 (f_list (S k)) -> exists v1 : A, In v1 (f_list k) /\ R v1 v2) ->
exists f : nat -> A,
In (f 0) (f_list 0) /\ (forall k : nat, R (f k) (f (S k)))
Axioms: xm, Konigs_lemma
*)
König’s lemma (KL) states that if a relation R
is finitely branching and, starting from x
, has R
-sequences of unbounded size, then there is a nat
-indexed R
-sequence starting from x
.
Assuming X
can be totally sorted you only need XM and unique choice to prove KL, otherwise dependent choice is also required to establish KL.
[EDIT] I needed to edit that post because I am new user, limited to 3 replies, but here is a complete proof assuming XM and KL:
Require Import List Arith Lia.
Import ListNotations.
Fact list_snoc2_eq X l (x y : X) : l++[x;y] = (l++[x])++[y].
Proof. now rewrite <- app_assoc. Qed.
Inductive rel_seq {X} (R : X -> X -> Prop) : list X -> Prop :=
| seq_zero : rel_seq R []
| seq_one x : rel_seq R [x]
| seq_more l x y : R x y -> rel_seq R (l++[x]) -> rel_seq R (l++[x;y]).
Local Fact rel_seq_inv_rec X R l :
@rel_seq X R l
-> forall m x y, l = m++[x;y] -> R x y /\ rel_seq R (m++[x]).
Proof.
destruct 1.
+ now intros [].
+ now intros [ | ? [] ].
+ intros m u v.
rewrite !list_snoc2_eq.
intros ([]%app_inj_tail & ?)%app_inj_tail; now subst m u v.
Qed.
Fact rel_seq_inv X R l x y :
@rel_seq X R (l++[x;y]) <-> R x y /\ rel_seq R (l++[x]).
Proof.
split.
+ intros H; now apply rel_seq_inv_rec with (1 := H).
+ intros []; now constructor 3.
Qed.
Inductive choice_seq {X} (P : nat -> X -> Prop) : list X -> Prop :=
| choice_seq_nil : choice_seq P []
| choice_seq_cons x l : P (length l) x -> choice_seq P l -> choice_seq P (l++[x]).
Local Fact choice_seq_inv_rec X P l :
@choice_seq X P l
-> forall m x, l = m++[x] -> P (length m) x /\ choice_seq P m.
Proof.
destruct 1.
+ now intros [].
+ intros m y (<- & <-)%app_inj_tail; auto.
Qed.
Fact choice_seq_inv X P l x :
@choice_seq X P (l++[x]) <-> P (length l) x /\ choice_seq P l.
Proof.
split.
+ intros H; now apply choice_seq_inv_rec with (1 := H).
+ intros []; now constructor.
Qed.
Section list_prod.
Variables (X Y Z : Type) (f : X -> Y -> Z).
Definition list_prod l m := flat_map (fun x => map (f x) m) l.
Fact list_prod_spec l m c : In c (list_prod l m) <-> exists x y, c = f x y /\ In x l /\ In y m.
Proof.
unfold list_prod.
rewrite in_flat_map; split.
+ intros (? & ? & (? & [])%in_map_iff); eauto.
+ intros (x & ? & -> & []).
exists x; split; auto.
apply in_map_iff; eauto.
Qed.
End list_prod.
Arguments list_prod {_ _ _}.
Definition finite {X} (P : X -> Prop) := exists l, forall x, P x <-> In x l.
Axiom XM : forall A : Prop, A \/ ~ A.
(** Notice that this critically depends on xm, or at least P being (weakly) decidable *)
Fact finite_anti__XM X P Q : (forall x : X, P x -> Q x) -> finite Q -> finite P.
Proof.
intros HPQ (l & Hl).
cut (forall x, P x -> In x l).
2: intros ? ?; now apply Hl, HPQ.
clear Q HPQ Hl.
induction l as [ | x l IHl ] in P |- *; intros HP.
+ exists []; split; simpl.
* now intros H%HP.
* easy.
+ destruct (XM (P x)) as [ Hx | Hx ].
* destruct (IHl (fun y => P y /\ In y l)) as (m & Hm).
- tauto.
- exists (x::m).
intros; simpl; rewrite <- Hm; split.
++ intros H; destruct (HP _ H) as [ <- | ]; auto.
++ intros [ <- | [] ]; auto.
* apply IHl.
intros y Hy.
destruct (HP _ Hy) as [ -> | ]; now auto.
Qed.
Axiom Konigs_lemma :
forall X (R : X -> X -> Prop) (HR : forall x, finite (R x)) (x : X),
(forall n, exists l, rel_seq R (x::l) /\ n <= length l)
-> (exists f, f 0 = x /\ forall n, R (f n) (f (S n))).
Section functional_list_choice.
Variables (A : Type) (R: A -> A -> Prop) (f_list : nat -> list A)
(f0 : forall k, f_list k <> [])
(f1 : forall k v2, In v2 (f_list (S k)) -> exists v1, In v1 (f_list k) /\ R v1 v2).
Let P n x := In x (f_list n).
Local Fact unbounded n x : P n x -> exists l, rel_seq R (l++[x]) /\ choice_seq P (l++[x]) /\ length l = n.
Proof.
induction n as [ | n IHn ] in x |- *.
+ exists []; repeat split; auto.
* constructor 2.
* constructor; simpl; auto; constructor.
+ intros G0.
destruct f1 with (1 := G0) as (y & (l & H1 & H2 & H3)%IHn & H4).
exists (l++[y]); repeat split; auto.
* rewrite <- app_assoc; simpl.
now constructor.
* constructor; auto.
rewrite length_app, H3; simpl.
replace (n+1) with (S n); auto; lia.
* rewrite length_app; simpl; lia.
Qed.
Let T (x y : option (nat * A)) :=
match x, y with
| None, Some (i,y) => i = 0 /\ In y (f_list 0)
| Some (i,x), Some (j,y) => j = S i /\ In x (f_list i) /\ In y (f_list j) /\ R x y
| _, _ => False
end.
Local Fact T_fin x : finite (T x).
Proof.
destruct x as [ (i,x) | ]; simpl.
+ cut (finite (fun y => match y with | Some (n,y) => n = S i /\ In y (f_list n) | None => False end)).
* apply finite_anti__XM; intros [ [] | ]; simpl; tauto.
* exists (list_prod (fun n a => Some (n,a)) [S i] (f_list (S i))).
intros [ (j,y) | ]; rewrite list_prod_spec; split.
- intros (-> & ?); exists (S i), y; simpl; auto.
- intros (? & ? & [=] & [ <- | [] ] & ?); subst; auto.
- tauto.
- now intros (? & ? & ? & _).
+ exists (list_prod (fun n a => Some (n,a)) [0] (f_list 0)).
intros [ (j,y) | ]; rewrite list_prod_spec; split; simpl.
- intros (-> & ?); exists 0, y; auto.
- intros (? & ? & [=] & [ <- | [] ] & ?); subst; auto.
- tauto.
- now intros (? & ? & ? & _).
Qed.
Fixpoint iseq (l : list A) n :=
match l with
| [] => []
| a::l => Some (n,a) :: iseq l (S n)
end.
Fact iseq_length l n : length (iseq l n) = length l.
Proof. induction l in n |- *; simpl; auto. Qed.
Fact iseq_app l m n : iseq (l++m) n = iseq l n ++ iseq m (length l + n).
Proof.
induction l as [ | x l IHl ] in n |- *; simpl; f_equal; auto.
rewrite IHl; do 2 f_equal; lia.
Qed.
Fact iseq_S l x : iseq (l++[x]) 0 = iseq l 0 ++ [Some (length l,x)].
Proof. rewrite iseq_app; simpl; do 4 f_equal; lia. Qed.
Fact rel_seq_R__T l : rel_seq R l -> choice_seq P l -> rel_seq T (None::iseq l 0).
Proof.
induction 1 as [ | | l x y H1 H2 IH2 ].
+ simpl; constructor.
+ simpl; intros E.
constructor 3 with (l := []).
* red; split; auto.
apply choice_seq_inv with (l := []) in E as (E & _).
exact E.
* simpl; constructor.
+ rewrite list_snoc2_eq.
intros (H3 & H4)%choice_seq_inv.
rewrite !iseq_S, <- list_snoc2_eq.
constructor 3 with (l := _::_).
* repeat split; auto.
- rewrite length_app; simpl; lia.
- apply choice_seq_inv in H4.
apply H4.
* simpl; rewrite <- iseq_S; auto.
Qed.
Local Lemma from_Konig : exists f, f 0 = None /\ forall n, T (f n) (f (S n)).
Proof.
apply Konigs_lemma.
+ apply T_fin.
+ intros n.
specialize (f0 n).
case_eq (f_list n); [ easy | ].
intros x m Hm.
destruct (unbounded n x) as (l & H1 & H2 & H3).
1: red; rewrite Hm; simpl; auto.
exists (iseq (l++[x]) 0); split.
* apply rel_seq_R__T; auto.
* rewrite iseq_length, length_app, H3; lia.
Qed.
Lemma functional_list_choice : exists f, In (f 0) (f_list 0) /\ forall k, R (f k) (f (S k)).
Proof.
destruct from_Konig as (f & H1 & H2).
assert (forall n, { x | f (S n) = Some (n,x)}) as G.
1:{ intros n; induction n as [ | n (x & Hx) ].
+ generalize (H2 0).
rewrite H1.
destruct (f 1) as [ (i,x) | ]; simpl; try easy.
intros (-> & _); eauto.
+ generalize (H2 (S n)).
rewrite Hx.
destruct (f (S (S n))) as [ (i,y) | ]; simpl; try easy.
intros (-> & _); eauto. }
exists (fun n => proj1_sig (G n)); split.
+ destruct (G 0) as (x & Hx); simpl.
generalize (H2 1).
rewrite Hx.
destruct (G 1) as (y & ->).
simpl; tauto.
+ intros n.
generalize (H2 (S n)).
destruct (G n) as (x & ->).
destruct (G (S n)) as (y & ->); simpl; tauto.
Qed.
End functional_list_choice.
Check functional_list_choice.
Print Assumptions functional_list_choice.