N /\ ~(k = 0) /\ ~(m = 0) /\
(!x:A. {y | r x y}
m) /\
(!x y. r x y ==> r y x) /\
(!x y. ~(x = y) ==> ?!z. r x z /\ r z y)
==> {x | path r (k + 2) x /\ x(k + 2) = x(0)}
REPEAT STRIP_TAC THEN
REWRITE_TAC[SET_RULE
`{x | path r (k + 2) x /\ x(k + 2) = x(0)} =
{x | path r (k + 2) x /\ x k = x 0 /\ x(k + 2) = x(0)}
UNION
{x | path r (k + 2) x /\ ~(x k = x 0) /\ x(k + 2) = x(0)}`] THEN
MATCH_MP_TAC
HAS_SIZE_UNION THEN GEN_REWRITE_TAC I [
CONJ_ASSOC] THEN
CONJ_TAC THENL [ALL_TAC; SET_TAC[]] THEN CONJ_TAC THENL
[SUBGOAL_THEN
`{x:num->A | path r (k + 2) x /\ x k = x 0 /\ x (k + 2) = x 0} =
IMAGE (\(x,a) i. if i = k + 1 then a
else if i = k + 2 then x(0)
else x(i))
{x,a | x
IN {x | path r k x /\ x(k) = x(0)} /\
a
IN {u | r (x k) u}}`
SUBST1_TAC THENL
[ALL_TAC;
MATCH_MP_TAC
HAS_SIZE_IMAGE_INJ THEN CONJ_TAC THENL
[REWRITE_TAC[
FORALL_PAIR_THM;
IN_ELIM_PAIR_THM] THEN
REWRITE_TAC[
IN_ELIM_THM;
FUN_EQ_THM;
PAIR_EQ] THEN
MAP_EVERY X_GEN_TAC [`y:num->A`; `a:A`; `z:num->A`; `b:A`] THEN
DISCH_THEN(fun th -> CONJ_TAC THEN MP_TAC th THENL
[ALL_TAC; MESON_TAC[]]) THEN
REPEAT(DISCH_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC)) THEN
DISCH_THEN(fun th -> X_GEN_TAC `i:num` THEN MP_TAC th) THEN
DISCH_THEN(fun th -> MP_TAC th THEN MP_TAC(SPEC `0` th)) THEN
REWRITE_TAC[ARITH_RULE `~(0 = k + 1) /\ ~(0 = k + 2)`] THEN
DISCH_TAC THEN ASM_CASES_TAC `k:num < i` THENL
[ASM_MESON_TAC[path]; ALL_TAC] THEN
DISCH_THEN(MP_TAC o SPEC `i:num`) THEN
ASM_MESON_TAC[ARITH_RULE `k < k + 1 /\ k < k + 2`];
ALL_TAC] THEN
ONCE_REWRITE_TAC[
MULT_SYM] THEN
MATCH_MP_TAC
HAS_SIZE_PRODUCT_DEPENDENT THEN
ASM_REWRITE_TAC[] THEN REWRITE_TAC[
HAS_SIZE] THEN
MATCH_MP_TAC
FINITE_SUBSET THEN
EXISTS_TAC `{x:num->A | path r k x}` THEN CONJ_TAC THENL
[ALL_TAC; SET_TAC[]] THEN
ASM_MESON_TAC[
HAS_SIZE;
FINITE_PATHS]] THEN
REWRITE_TAC[
EXTENSION;
IN_IMAGE] THEN
REWRITE_TAC[
EXISTS_PAIR_THM;
IN_ELIM_PAIR_THM] THEN
REWRITE_TAC[
FUN_EQ_THM;
IN_ELIM_THM] THEN
X_GEN_TAC `x:num->A` THEN EQ_TAC THENL
[STRIP_TAC THEN
EXISTS_TAC `\i. if i <= k then x(i):A else @x. T` THEN
EXISTS_TAC `(x:num->A) (k + 1)` THEN
REWRITE_TAC[
IN_ELIM_THM;
LE_REFL;
LE_0] THEN
ASM_REWRITE_TAC[
CONJ_ASSOC] THEN CONJ_TAC THENL
[ALL_TAC; ASM_MESON_TAC[path; ARITH_RULE `k < k + 2`]] THEN
CONJ_TAC THENL
[ALL_TAC;
UNDISCH_TAC `path r (k + 2) (x:num->A)` THEN
SIMP_TAC[path;
LT_IMP_LE; ARITH_RULE `i < k ==> i + 1 <= k`] THEN
SIMP_TAC[GSYM
NOT_LT] THEN
MESON_TAC[ARITH_RULE `i < k ==> i < k + 2`]] THEN
X_GEN_TAC `i:num` THEN
ASM_CASES_TAC `i = k + 1` THEN ASM_REWRITE_TAC[] THEN
ASM_CASES_TAC `i = k + 2` THEN ASM_REWRITE_TAC[] THEN
FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [path]) THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN(MP_TAC o SPEC `i:num` o CONJUNCT2) THEN
ASM_REWRITE_TAC[ARITH_RULE
`k + 2 < i <=> ~(i <= k) /\ ~(i = k + 1) /\ ~(i = k + 2)`];
ALL_TAC] THEN
REWRITE_TAC[
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`z:num->A`; `b:A`] THEN
DISCH_THEN(CONJUNCTS_THEN2 MP_TAC STRIP_ASSUME_TAC) THEN
DISCH_THEN(fun th -> MP_TAC th THEN MP_TAC(SPEC `0` th)) THEN
REWRITE_TAC[
COND_ID; ARITH_RULE `~(0 = k + 1)`] THEN DISCH_TAC THEN
REWRITE_TAC[
CONJ_ASSOC] THEN DISCH_THEN(LABEL_TAC "*") THEN CONJ_TAC THENL
[ALL_TAC; REMOVE_THEN "*" (MP_TAC o SPEC `k + 2`) THEN
ASM_REWRITE_TAC[ARITH_RULE `~(k + 2 = k + 1)`]] THEN
CONJ_TAC THENL
[ALL_TAC; REMOVE_THEN "*" (MP_TAC o SPEC `k:num`) THEN
ASM_REWRITE_TAC[ARITH_RULE `~(k = k + 2) /\ ~(k = k + 1)`]] THEN
UNDISCH_TAC `path r k (z:num->A)` THEN ASM_REWRITE_TAC[path] THEN
SIMP_TAC[ARITH_RULE
`k + 2 < i ==> k < i /\ ~(i = k + 1) /\ ~(i = k + 2)`] THEN
STRIP_TAC THEN X_GEN_TAC `i:num` THEN DISCH_TAC THEN
ASM_SIMP_TAC[ARITH_RULE `i < k + 2 ==> ~(i = k + 2)`] THEN
REWRITE_TAC[ARITH_RULE `i + 1 = k + 2 <=> i = k + 1`] THEN
ASM_CASES_TAC `i = k + 1` THEN ASM_REWRITE_TAC[] THENL
[ASM_MESON_TAC[ARITH_RULE `~(x + 1 = x)`]; ALL_TAC] THEN
REWRITE_TAC[
EQ_ADD_RCANCEL] THEN COND_CASES_TAC THEN ASM_SIMP_TAC[] THENL
[ASM_MESON_TAC[]; ALL_TAC] THEN
ASM_MESON_TAC[ARITH_RULE `i < k + 2 /\ ~(i = k) /\ ~(i = k + 1)
==> i < k`];
ALL_TAC] THEN
SUBGOAL_THEN
`{x:num->A | path r (k + 2) x /\ ~(x k = x 0) /\ x (k + 2) = x 0} =
IMAGE (\x i. if i = k + 1 then @z. r (x k) z /\ r z (x 0)
else if i = k + 2 then x(0)
else x(i))
{x | path r k x /\ ~(x(k) = x(0))}`
SUBST1_TAC THENL
[ALL_TAC;
MATCH_MP_TAC
HAS_SIZE_IMAGE_INJ THEN CONJ_TAC THENL
[ALL_TAC;
REWRITE_TAC[
HAS_SIZE] THEN
MATCH_MP_TAC
FINITE_SUBSET THEN
EXISTS_TAC `{x:num->A | path r k x}` THEN CONJ_TAC THENL
[ALL_TAC; SET_TAC[]] THEN
ASM_MESON_TAC[
HAS_SIZE;
FINITE_PATHS]] THEN
MAP_EVERY X_GEN_TAC [`x:num->A`; `y:num->A`] THEN
REWRITE_TAC[
IN_ELIM_THM] THEN STRIP_TAC THEN
REWRITE_TAC[
FUN_EQ_THM] THEN X_GEN_TAC `i:num` THEN
ASM_CASES_TAC `k:num < i` THENL
[ASM_MESON_TAC[path]; ALL_TAC] THEN
FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [
FUN_EQ_THM]) THEN
DISCH_THEN(MP_TAC o SPEC `i:num`) THEN
ASM_MESON_TAC[ARITH_RULE `k < k + 1 /\ k < k + 2`]] THEN
REWRITE_TAC[
EXTENSION;
IN_IMAGE;
IN_ELIM_THM] THEN
X_GEN_TAC `x:num->A` THEN REWRITE_TAC[
IN_ELIM_THM] THEN EQ_TAC THENL
[STRIP_TAC THEN
EXISTS_TAC `\i. if i <= k then x(i):A else @x. T` THEN
ASM_REWRITE_TAC[
LE_REFL;
LE_0] THEN CONJ_TAC THENL
[ALL_TAC;
UNDISCH_TAC `path r (k + 2) (x:num->A)` THEN
SIMP_TAC[path;
LT_IMP_LE; ARITH_RULE `i < k ==> i + 1 <= k`] THEN
SIMP_TAC[GSYM
NOT_LT] THEN
MESON_TAC[ARITH_RULE `i < k ==> i < k + 2`]] THEN
REWRITE_TAC[
FUN_EQ_THM] THEN X_GEN_TAC `i:num` THEN
ASM_CASES_TAC `i = k + 1` THEN ASM_REWRITE_TAC[] THENL
[CONV_TAC SYM_CONV THEN MATCH_MP_TAC
SELECT_UNIQUE THEN
UNDISCH_TAC `path r (k + 2) (x:num->A)` THEN REWRITE_TAC[path] THEN
DISCH_THEN(MP_TAC o CONJUNCT1) THEN
DISCH_THEN(fun th -> MP_TAC(SPEC `k:num` th) THEN
MP_TAC(SPEC `k + 1` th)) THEN
REWRITE_TAC[ARITH_RULE `k < k + 2 /\ k + 1 < k + 2`] THEN
REWRITE_TAC[GSYM
ADD_ASSOC; ARITH] THEN ASM_MESON_TAC[];
ALL_TAC] THEN
ASM_CASES_TAC `i = k + 2` THEN ASM_REWRITE_TAC[] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `path r (k + 2) (x:num->A)` THEN REWRITE_TAC[path] THEN
DISCH_THEN(MP_TAC o CONJUNCT2) THEN
ASM_MESON_TAC[ARITH_RULE `~(i <= k) /\ ~(i = k + 1) /\ ~(i = k + 2)
==> k + 2 < i`];
ALL_TAC] THEN
DISCH_THEN(X_CHOOSE_THEN `y:num->A` STRIP_ASSUME_TAC) THEN
ASM_REWRITE_TAC[ARITH_RULE
`~(k + 2 = k + 1) /\ ~(0 = k + 1) /\ ~(0 = k + 2) /\ ~(k = k + 1) /\
~(k = k + 2)`] THEN
REWRITE_TAC[path] THEN CONJ_TAC THEN X_GEN_TAC `i:num` THEN DISCH_TAC THENL
[REWRITE_TAC[ARITH_RULE `i + 1 = k + 2 <=> i = k + 1`] THEN
ASM_CASES_TAC `i = k + 1` THEN ASM_REWRITE_TAC[] THENL
[REWRITE_TAC[ARITH_RULE `(k + 1) + 1 = k + 1 <=> F`] THEN ASM_MESON_TAC[];
ALL_TAC] THEN
ASM_SIMP_TAC[ARITH_RULE `i < k + 2 ==> ~(i = k + 2)`] THEN
REWRITE_TAC[
EQ_ADD_RCANCEL] THEN COND_CASES_TAC THEN ASM_SIMP_TAC[] THENL
[ASM_MESON_TAC[]; ALL_TAC] THEN
UNDISCH_TAC `path r k (y:num->A)` THEN REWRITE_TAC[path] THEN
DISCH_THEN(MATCH_MP_TAC o CONJUNCT1) THEN
MAP_EVERY UNDISCH_TAC [`~(i:num = k)`; `~(i = k + 1)`; `i < k + 2`] THEN
ARITH_TAC;
ALL_TAC] THEN
ASM_SIMP_TAC[ARITH_RULE `k + 2 < i ==> ~(i = k + 1) /\ ~(i = k + 2)`] THEN
ASM_MESON_TAC[path; ARITH_RULE `k + 2 < i ==> k < i`]);;