prioritize_num();;
let FORSTER_PUZZLE = prove
(`(!n. f(n + 1) > f(f(n))) ==> !n. f(n) = n`,
REWRITE_TAC[
GT; GSYM
ADD1] THEN STRIP_TAC THEN
SUBGOAL_THEN `!n m. f(m) < n ==> m <= f m` ASSUME_TAC THENL
[INDUCT_TAC THEN REWRITE_TAC[
LT] THEN
INDUCT_TAC THEN ASM_MESON_TAC[
LE_0;
LE_SUC_LT;
LET_TRANS]; ALL_TAC] THEN
SUBGOAL_THEN `!n. n <= f n` ASSUME_TAC THENL
[ASM_MESON_TAC[
LT]; ALL_TAC] THEN
SUBGOAL_THEN `!n. f(n) < f(SUC n)` ASSUME_TAC THENL
[ASM_MESON_TAC[
LET_TRANS]; ALL_TAC] THEN
SUBGOAL_THEN `!m n. m < n ==> f(m) < f(n)` ASSUME_TAC THENL
[GEN_TAC THEN INDUCT_TAC THEN ASM_MESON_TAC[
LT;
LT_TRANS]; ALL_TAC] THEN
SUBGOAL_THEN `!m n. (f m < f n) <=> m < n` ASSUME_TAC THENL
[ASM_MESON_TAC[
LT_CASES;
LT_ANTISYM;
LT_REFL]; ALL_TAC] THEN
ASM_MESON_TAC[
LE_ANTISYM;
LT_SUC_LE]);;
(* ------------------------------------------------------------------------- *)
(* Alternative; shorter but less transparent and taking longer to run. *)
(* ------------------------------------------------------------------------- *)
let FORSTER_PUZZLE = prove
(`(!n. f(n + 1) > f(f(n))) ==> !n. f(n) = n`,
REWRITE_TAC[
GT; GSYM
ADD1] THEN STRIP_TAC THEN
SUBGOAL_THEN `!n m. f(m) < n ==> m <= f m` ASSUME_TAC THENL
[INDUCT_TAC THEN REWRITE_TAC[
LT] THEN
INDUCT_TAC THEN ASM_MESON_TAC[
LE_0;
LE_SUC_LT;
LET_TRANS]; ALL_TAC] THEN
SUBGOAL_THEN `!n. n <= f n` ASSUME_TAC THENL
[ASM_MESON_TAC[
LT]; ALL_TAC] THEN
SUBGOAL_THEN `!n. f(n) < f(SUC n)` ASSUME_TAC THENL
[ASM_MESON_TAC[
LET_TRANS]; ALL_TAC] THEN
SUBGOAL_THEN `!m n. m < n ==> f(m) < f(n)` ASSUME_TAC THENL
[GEN_TAC THEN INDUCT_TAC THEN ASM_MESON_TAC[
LT;
LT_TRANS]; ALL_TAC] THEN
ASM_MESON_TAC[
LE_ANTISYM;
LT_CASES;
LT_ANTISYM;
LT_REFL;
LT_SUC_LE]);;
(* ------------------------------------------------------------------------- *)
(* Robin Milner's proof. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* A variant of Robin's proof avoiding explicit use of addition. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* The shortest? *)
(* ------------------------------------------------------------------------- *)