(* ========================================================================= *)
(* Analysis of solutions to Pell equation *)
(* ========================================================================= *)
needs "Library/analysis.ml";;
needs "Library/transc.ml";;
needs "Library/prime.ml";;
prioritize_real();;
let PELL_INDUCTION = prove
(`P 0 /\ P 1 /\ (!n. P n /\ P (n + 1) ==> P(n + 2)) ==> !n. P n`,
STRIP_TAC THEN
SUBGOAL_THEN `!n. P n /\ P(n + 1)` (fun th -> REWRITE_TAC[th]) THEN
INDUCT_TAC THEN ASM_REWRITE_TAC[
ADD_CLAUSES] THEN
ASM_SIMP_TAC[
ADD1; ARITH_RULE `SUC(n + 1) = n + 2`]);;
(* ------------------------------------------------------------------------- *)
(* Useful number-theoretic basics *)
(* ------------------------------------------------------------------------- *)
let ROOT_NONPOWER = prove
(`!p q d n. ~(q = 0) /\ (p
EXP n = d * q
EXP n) ==> ?a. d = a
EXP n`,
REPEAT GEN_TAC THEN
ASM_CASES_TAC `n = 0` THEN ASM_SIMP_TAC[
EXP;
MULT_CLAUSES] THEN
STRIP_TAC THEN
MP_TAC(SPECL [`n:num`; `q:num`; `p:num`] DIVIDES_EXP2_REV) THEN
ASM_REWRITE_TAC[divides;
LEFT_IMP_EXISTS_THM] THEN
DISCH_THEN(MP_TAC o SPEC `d:num`) THEN
REWRITE_TAC[EQT_INTRO(SPEC_ALL
MULT_SYM)] THEN
ONCE_REWRITE_TAC[
MULT_SYM] THEN
DISCH_THEN(X_CHOOSE_THEN `a:num` SUBST_ALL_TAC) THEN
EXISTS_TAC `a:num` THEN
UNDISCH_TAC `(a * q)
EXP n = d * q
EXP n` THEN
ASM_SIMP_TAC[
MULT_EXP;
EQ_MULT_RCANCEL;
EXP_EQ_0]);;
let INTEGER_SUB_LEMMA = prove
(`!x y. ?n. (&x - &y) pow 2 = &n pow 2`,
REPEAT STRIP_TAC THEN
DISJ_CASES_THEN MP_TAC (SPECL [`&x`; `&y`]
REAL_LE_TOTAL) THEN
REWRITE_TAC[REAL_OF_NUM_LE] THEN DISCH_TAC THENL
[EXISTS_TAC `y - x:num`; EXISTS_TAC `x - y:num`] THEN
ASM_SIMP_TAC[GSYM
REAL_OF_NUM_SUB] THEN
REWRITE_TAC[REAL_POW_2] THEN REAL_ARITH_TAC);;
let SQRT_LINEAR_EQ = prove
(`!a u v x y.
2 <= a
==> ((&u + &v * sqrt(&a pow 2 - &1) = &x + &y * sqrt(&a pow 2 - &1)) <=>
(u = x) /\ (v = y))`,
REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[] THEN
REWRITE_TAC[REAL_ARITH `(a + b = c + d) <=> (a - c = d - b)`] THEN
REWRITE_TAC[GSYM
REAL_SUB_RDISTRIB] THEN
DISCH_THEN(MP_TAC o C AP_THM `2` o AP_TERM `(pow)`) THEN
REWRITE_TAC[
REAL_POW_MUL] THEN
ASM_SIMP_TAC[
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `2 <= a ==> 1 <= a`] THEN
X_CHOOSE_TAC `p:num` (SPECL [`u:num`; `x:num`]
INTEGER_SUB_LEMMA) THEN
X_CHOOSE_TAC `q:num` (SPECL [`y:num`; `v:num`]
INTEGER_SUB_LEMMA) THEN
ASM_REWRITE_TAC[] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` SUBST1_TAC THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `2 <= a ==> 1 <= a`]; ALL_TAC] THEN
REWRITE_TAC[
REAL_OF_NUM_POW; REAL_OF_NUM_MUL; REAL_OF_NUM_EQ] THEN
DISCH_TAC THEN
MP_TAC(SPECL [`p:num`; `q:num`; `a
EXP 2 - 1`; `2`]
ROOT_NONPOWER) THEN
ASM_REWRITE_TAC[EQT_INTRO(SPEC_ALL
MULT_SYM)] THEN
MATCH_MP_TAC(TAUT `~b /\ (a ==> c) ==> ((~a ==> b) ==> c)`) THEN
CONJ_TAC THENL
[DISCH_THEN(X_CHOOSE_THEN `b:num` MP_TAC) THEN
DISCH_THEN(MP_TAC o MATCH_MP
(ARITH_RULE `(a - 1 = b) ==> 1 < a ==> (a - b = 1)`)) THEN
SUBST1_TAC(SYM(SPEC `a:num` (CONJUNCT1
EXP))) THEN
ASM_REWRITE_TAC[
LT_EXP;
ARITH_LE;
ARITH_LT] THEN
REWRITE_TAC[
EXP] THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(a - b = 1) ==> (a = b + 1)`)) THEN
REWRITE_TAC[GSYM REAL_OF_NUM_EQ; GSYM REAL_OF_NUM_ADD; GSYM
REAL_OF_NUM_POW] THEN
REWRITE_TAC[REAL_POW_2] THEN
DISCH_THEN(MP_TAC o MATCH_MP
(REAL_ARITH `(a * a = b * b + &1) ==> ((a + b) * (a - b) = &1)`)) THEN
DISCH_THEN(MP_TAC o C AP_THM `2` o AP_TERM `(pow)`) THEN
REWRITE_TAC[
REAL_POW_MUL] THEN
X_CHOOSE_TAC `c:num` (SPECL [`a:num`; `b:num`]
INTEGER_SUB_LEMMA) THEN
ASM_REWRITE_TAC[] THEN
REWRITE_TAC[GSYM
REAL_POW_MUL] THEN
REWRITE_TAC[
REAL_OF_NUM_POW; REAL_OF_NUM_MUL; REAL_OF_NUM_ADD] THEN
REWRITE_TAC[REAL_OF_NUM_EQ;
EXP_ONE;
EXP_EQ_1;
MULT_EQ_1;
ARITH_EQ] THEN
UNDISCH_TAC `2 <= a` THEN ARITH_TAC;
DISCH_THEN SUBST_ALL_TAC THEN
UNDISCH_TAC `p
EXP 2 = 0
EXP 2 * (a
EXP 2 - 1)` THEN
REWRITE_TAC[ARITH;
MULT_CLAUSES;
EXP_EQ_0] THEN
DISCH_THEN SUBST_ALL_TAC THEN
UNDISCH_TAC `(&u - &x) pow 2 = &0 pow 2` THEN
UNDISCH_TAC `(&y - &v) pow 2 = &0 pow 2` THEN
CONV_TAC REAL_RAT_REDUCE_CONV THEN
REWRITE_TAC[
REAL_POW_EQ_0;
ARITH_EQ;
REAL_SUB_0] THEN
SIMP_TAC[REAL_OF_NUM_EQ]]);;
(* ------------------------------------------------------------------------- *)
(* Recurrence defining the solutions. *)
(* ------------------------------------------------------------------------- *)
let X_DEF =
let th = prove
(`!a. ?X. !n. X n = if n = 0 then 1
else if n = 1 then a
else 2 * a * X(n-1) - X(n-2)`,
GEN_TAC THEN MATCH_MP_TAC(MATCH_MP
WF_REC WF_num) THEN
REPEAT STRIP_TAC THEN
REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
BINOP_TAC THEN
ASM_SIMP_TAC[ARITH_RULE `n - m < n <=> ~(m = 0) /\ ~(n = 0)`;
ARITH_EQ]) in
new_specification ["X"] (REWRITE_RULE[
SKOLEM_THM] th);;
let X_CLAUSES = prove
(`(!a. X a 0 = 1) /\
(!a. X a 1 = a) /\
(!a n. X a (n + 2) = 2 * a * X a (n + 1) - X a (n))`,
REPEAT STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [X_DEF] THEN
REWRITE_TAC[
ARITH_EQ;
ADD_EQ_0; ARITH_RULE `~(n + 2 = 1)`] THEN
REWRITE_TAC[ARITH_RULE `((n + 2) - 2 = n) /\ ((n + 2) - 1 = n + 1)`]);;
let Y_DEF =
let th = prove
(`!a. ?Y. !n. Y n = if n = 0 then 0
else if n = 1 then 1
else 2 * a * Y(n-1) - Y(n-2)`,
GEN_TAC THEN MATCH_MP_TAC(MATCH_MP
WF_REC WF_num) THEN
REPEAT STRIP_TAC THEN
REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
BINOP_TAC THEN
ASM_SIMP_TAC[ARITH_RULE `n - m < n <=> ~(m = 0) /\ ~(n = 0)`;
ARITH_EQ]) in
new_specification ["Y"] (REWRITE_RULE[
SKOLEM_THM] th);;
let Y_CLAUSES = prove
(`(!a. Y a 0 = 0) /\
(!a. Y a 1 = 1) /\
(!a n. Y a (n + 2) = 2 * a * Y a (n + 1) - Y a (n))`,
REPEAT STRIP_TAC THEN GEN_REWRITE_TAC LAND_CONV [Y_DEF] THEN
REWRITE_TAC[
ARITH_EQ;
ADD_EQ_0; ARITH_RULE `~(n + 2 = 1)`] THEN
REWRITE_TAC[ARITH_RULE `((n + 2) - 2 = n) /\ ((n + 2) - 1 = n + 1)`]);;
(* ------------------------------------------------------------------------- *)
(* An obvious but tiresome lemma: the Xs and Ys increase. *)
(* ------------------------------------------------------------------------- *)
let X_INCREASES = prove
(`!a n. ~(a = 0) ==> X a n <= X a (n + 1)`,
GEN_TAC THEN REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
MATCH_MP_TAC
num_WF THEN REPEAT STRIP_TAC THEN
ASM_CASES_TAC `n = 0` THEN
ASM_REWRITE_TAC[
X_CLAUSES;
ADD_CLAUSES;
ARITH_RULE `1 <= a <=> ~(a = 0)`] THEN
GEN_REWRITE_TAC RAND_CONV [X_DEF] THEN
ASM_REWRITE_TAC[
ADD_EQ_0;
ARITH_EQ;
ARITH_RULE `(n + 1 = 1) <=> (n = 0)`] THEN
REWRITE_TAC[
ADD_SUB] THEN
MATCH_MP_TAC(ARITH_RULE `a + b <= c ==> a <= c - b:num`) THEN
MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `2 * X a n` THEN CONJ_TAC THENL
[ALL_TAC;
REWRITE_TAC[
LE_MULT_LCANCEL;
ARITH_EQ] THEN
UNDISCH_TAC `~(a = 0)` THEN SPEC_TAC(`a:num`,`a:num`) THEN
INDUCT_TAC THEN REWRITE_TAC[
ADD_CLAUSES;
MULT_CLAUSES] THEN
REWRITE_TAC[ARITH_RULE `a <= b + a:num`]] THEN
MATCH_MP_TAC(ARITH_RULE `b <= a ==> a + b <= 2 * a`) THEN
SUBGOAL_THEN `n = (n - 1) + 1` SUBST1_TAC THENL
[UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[ARITH_RULE `((n + 1) + 1) - 2 = n`] THEN
FIRST_ASSUM MATCH_MP_TAC THEN
UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC);;
let Y_INCREASES = prove
(`!a n. ~(a = 0) ==> Y a n <= Y a (n + 1)`,
GEN_TAC THEN REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
MATCH_MP_TAC
num_WF THEN REPEAT STRIP_TAC THEN
ASM_CASES_TAC `n = 0` THEN
ASM_REWRITE_TAC[
Y_CLAUSES;
ADD_CLAUSES;
LE_0] THEN
GEN_REWRITE_TAC RAND_CONV [Y_DEF] THEN
ASM_REWRITE_TAC[
ADD_EQ_0;
ARITH_EQ;
ARITH_RULE `(n + 1 = 1) <=> (n = 0)`] THEN
REWRITE_TAC[
ADD_SUB] THEN
MATCH_MP_TAC(ARITH_RULE `a + b <= c ==> a <= c - b:num`) THEN
MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `2 * Y a n` THEN CONJ_TAC THENL
[ALL_TAC;
REWRITE_TAC[
LE_MULT_LCANCEL;
ARITH_EQ] THEN
UNDISCH_TAC `~(a = 0)` THEN SPEC_TAC(`a:num`,`a:num`) THEN
INDUCT_TAC THEN REWRITE_TAC[
ADD_CLAUSES;
MULT_CLAUSES] THEN
REWRITE_TAC[ARITH_RULE `a <= b + a:num`]] THEN
MATCH_MP_TAC(ARITH_RULE `b <= a ==> a + b <= 2 * a`) THEN
SUBGOAL_THEN `n = (n - 1) + 1` SUBST1_TAC THENL
[UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[ARITH_RULE `((n + 1) + 1) - 2 = n`] THEN
FIRST_ASSUM MATCH_MP_TAC THEN
UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* Show that the expression is a power of the basis. *)
(* ------------------------------------------------------------------------- *)
let XY_POWER_POS = prove
(`!a n. ~(a = 0) ==> (&(X a n) + &(Y a n) * sqrt(&a pow 2 - &1) =
(&a + sqrt(&a pow 2 - &1)) pow n)`,
GEN_TAC THEN REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
MATCH_MP_TAC
num_WF THEN GEN_TAC THEN DISCH_TAC THEN
ONCE_REWRITE_TAC[X_DEF; Y_DEF] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[
ARITH_EQ] THEN
REWRITE_TAC[
REAL_MUL_LZERO;
REAL_ADD_RID;
real_pow] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[
REAL_POW_1; REAL_MUL_LID] THEN
REWRITE_TAC[REAL_OF_NUM_ADD] THEN
SUBGOAL_THEN
`(&(2 * a * X a (n - 1) - X a (n - 2)) =
&(2 * a * X a (n - 1)) - &(X a (n - 2))) /\
(&(2 * a * Y a (n - 1) - Y a (n - 2)) =
&(2 * a * Y a (n - 1)) - &(Y a (n - 2)))`
(CONJUNCTS_THEN SUBST1_TAC)
THENL
[CONJ_TAC THEN MATCH_MP_TAC(GSYM
REAL_OF_NUM_SUB) THEN
MATCH_MP_TAC(ARITH_RULE
`x <= y /\ y <= 2 * a * y ==> x <= 2 * a * y`) THEN
ASM_SIMP_TAC[ARITH_RULE
`~(n = 0) /\ ~(n = 1) ==> (n - 1 = (n - 2) + 1)`] THEN
ASM_SIMP_TAC[
X_INCREASES;
Y_INCREASES] THEN
REWRITE_TAC[
MULT_ASSOC] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `n = 1 * n`] THEN
REWRITE_TAC[
LE_MULT_RCANCEL] THEN DISJ1_TAC THEN
UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[REAL_ARITH
`(x1 - x2) + (y1 - y2) * a = (x1 + y1 * a) - (x2 + y2 * a)`] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN
REWRITE_TAC[GSYM REAL_MUL_ASSOC; GSYM REAL_ADD_LDISTRIB] THEN
ASM_SIMP_TAC[ARITH_RULE
`~(n = 0) /\ ~(n = 1) ==> n - 2 < n /\ n - 1 < n`] THEN
ASM_SIMP_TAC[ARITH_RULE
`~(n = 0) /\ ~(n = 1) ==> (n - 1 = 1 + (n - 2))`] THEN
REWRITE_TAC[
REAL_POW_ADD; REAL_MUL_ASSOC;
REAL_POW_1] THEN
REWRITE_TAC[REAL_ARITH `a * b - b = (a - &1) * b`] THEN
SUBGOAL_THEN `n = 2 + (n - 2)`
(fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th])
THENL
[MAP_EVERY UNDISCH_TAC [`~(n = 0)`; `~(n = 1)`] THEN ARITH_TAC;
ALL_TAC] THEN
REWRITE_TAC[
REAL_POW_ADD] THEN AP_THM_TAC THEN AP_TERM_TAC THEN
REWRITE_TAC[REAL_POW_2; REAL_ADD_LDISTRIB;
REAL_ADD_RDISTRIB] THEN
REWRITE_TAC[GSYM REAL_POW_2] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `1 <= a <=> ~(a = 0)`] THEN
REWRITE_TAC[REAL_POW_2] THEN REAL_ARITH_TAC);;
let XY_POWER_NEG = prove
(`!a n. ~(a = 0) ==> (&(X a n) - &(Y a n) * sqrt(&a pow 2 - &1) =
(&a - sqrt(&a pow 2 - &1)) pow n)`,
GEN_TAC THEN REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
MATCH_MP_TAC
num_WF THEN GEN_TAC THEN DISCH_TAC THEN
ONCE_REWRITE_TAC[X_DEF; Y_DEF] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[
ARITH_EQ] THEN
REWRITE_TAC[
REAL_MUL_LZERO;
REAL_SUB_RZERO;
real_pow] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[
REAL_POW_1; REAL_MUL_LID] THEN
REWRITE_TAC[REAL_OF_NUM_ADD] THEN
SUBGOAL_THEN
`(&(2 * a * X a (n - 1) - X a (n - 2)) =
&(2 * a * X a (n - 1)) - &(X a (n - 2))) /\
(&(2 * a * Y a (n - 1) - Y a (n - 2)) =
&(2 * a * Y a (n - 1)) - &(Y a (n - 2)))`
(CONJUNCTS_THEN SUBST1_TAC)
THENL
[CONJ_TAC THEN MATCH_MP_TAC(GSYM
REAL_OF_NUM_SUB) THEN
MATCH_MP_TAC(ARITH_RULE
`x <= y /\ y <= 2 * a * y ==> x <= 2 * a * y`) THEN
ASM_SIMP_TAC[ARITH_RULE
`~(n = 0) /\ ~(n = 1) ==> (n - 1 = (n - 2) + 1)`] THEN
ASM_SIMP_TAC[
X_INCREASES;
Y_INCREASES] THEN
REWRITE_TAC[
MULT_ASSOC] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `n = 1 * n`] THEN
REWRITE_TAC[
LE_MULT_RCANCEL] THEN DISJ1_TAC THEN
UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[REAL_ARITH
`(x1 - x2) - (y1 - y2) * a = (x1 - y1 * a) - (x2 - y2 * a)`] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN
REWRITE_TAC[GSYM REAL_MUL_ASSOC; GSYM
REAL_SUB_LDISTRIB] THEN
ASM_SIMP_TAC[ARITH_RULE
`~(n = 0) /\ ~(n = 1) ==> n - 2 < n /\ n - 1 < n`] THEN
ASM_SIMP_TAC[ARITH_RULE
`~(n = 0) /\ ~(n = 1) ==> (n - 1 = 1 + (n - 2))`] THEN
REWRITE_TAC[
REAL_POW_ADD; REAL_MUL_ASSOC;
REAL_POW_1] THEN
REWRITE_TAC[REAL_ARITH `a * b - b = (a - &1) * b`] THEN
SUBGOAL_THEN `n = 2 + (n - 2)`
(fun th -> GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [th])
THENL
[MAP_EVERY UNDISCH_TAC [`~(n = 0)`; `~(n = 1)`] THEN ARITH_TAC;
ALL_TAC] THEN
REWRITE_TAC[
REAL_POW_ADD] THEN AP_THM_TAC THEN AP_TERM_TAC THEN
REWRITE_TAC[REAL_POW_2;
REAL_SUB_LDISTRIB;
REAL_SUB_RDISTRIB] THEN
REWRITE_TAC[GSYM REAL_POW_2] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `1 <= a <=> ~(a = 0)`] THEN
REWRITE_TAC[REAL_POW_2] THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* Hence all members of recurrence relations are Pell solutions. *)
(* ------------------------------------------------------------------------- *)
let XY_ARE_SOLUTIONS = prove
(`!a n. ~(a = 0)
==> ((X a n)
EXP 2 = (a
EXP 2 - 1) * (Y a n)
EXP 2 + 1)`,
REPEAT STRIP_TAC THEN
FIRST_ASSUM(MP_TAC o SPEC `n:num` o MATCH_MP
XY_POWER_NEG) THEN
FIRST_ASSUM(MP_TAC o SPEC `n:num` o MATCH_MP
XY_POWER_POS) THEN
REWRITE_TAC[IMP_IMP] THEN
DISCH_THEN(fun th ->
MP_TAC(MK_COMB(AP_TERM `( * )` (CONJUNCT1 th),CONJUNCT2 th))) THEN
REWRITE_TAC[GSYM
REAL_POW_MUL] THEN
REWRITE_TAC[REAL_ARITH `(x + y) * (x - y) = x * x - y * y`] THEN
ONCE_REWRITE_TAC[AC
REAL_MUL_AC
`(a * b) * (c * d) = (a * c) * (b * d)`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `1 <= a <=> ~(a = 0)`] THEN
REWRITE_TAC[REAL_ARITH `a - (a - &1) = &1`;
REAL_POW_ONE] THEN
REWRITE_TAC[
REAL_EQ_SUB_RADD] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` SUBST1_TAC THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `1 <= a <=> ~(a = 0)`];
REWRITE_TAC[REAL_OF_NUM_ADD; REAL_OF_NUM_MUL; REAL_OF_NUM_EQ;
REAL_OF_NUM_POW] THEN
REWRITE_TAC[
MULT_AC;
ADD_AC]]);;
(* ------------------------------------------------------------------------- *)
(* And they are all solutions. *)
(* ------------------------------------------------------------------------- *)
let SOLUTIONS_INDUCTION = prove
(`!a x y.
~(a = 0) /\ ~(a = 1) /\ ~(y = 0) /\
(x
EXP 2 = (a
EXP 2 - 1) * y
EXP 2 + 1)
==> ?x' y'. x' < x /\ y' < y /\
(x'
EXP 2 = (a
EXP 2 - 1) * y'
EXP 2 + 1) /\
(&x + &y * sqrt(&a pow 2 - &1) =
(&x' + &y' * sqrt(&a pow 2 - &1)) *
(&a + sqrt(&a pow 2 - &1)))`,
REPEAT STRIP_TAC THEN
EXISTS_TAC `a * x - (a
EXP 2 - 1) * y` THEN
EXISTS_TAC `a * y - x:num` THEN
SUBGOAL_THEN `x <= a * y:num` ASSUME_TAC THENL
[ONCE_REWRITE_TAC[GSYM(SPECL [`x:num`; `y:num`; `1`]
EXP_MONO_LE_SUC)] THEN
ASM_REWRITE_TAC[
ARITH_SUC] THEN
REWRITE_TAC[GSYM
ADD1;
LE_SUC_LT] THEN
REWRITE_TAC[
MULT_EXP;
LT_MULT_RCANCEL] THEN
REWRITE_TAC[ARITH_RULE `a - 1 < a <=> ~(a = 0)`] THEN
ASM_REWRITE_TAC[
EXP_EQ_0]; ALL_TAC] THEN
SUBGOAL_THEN `(a
EXP 2 - 1) * y <= a * x:num` ASSUME_TAC THENL
[SUBGOAL_THEN `(a
EXP 2 - 1) * y
EXP 2 < a * x * y` MP_TAC THENL
[ALL_TAC;
ASM_SIMP_TAC[
MULT_ASSOC;
EXP_2;
LT_MULT_RCANCEL;
LT_IMP_LE]] THEN
REWRITE_TAC[GSYM
LE_SUC_LT;
ADD1] THEN
FIRST_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [SYM th]) THEN
GEN_REWRITE_TAC RAND_CONV [
MULT_SYM] THEN
REWRITE_TAC[
EXP_2; GSYM
MULT_ASSOC;
LE_MULT_LCANCEL] THEN
DISJ2_TAC THEN ONCE_REWRITE_TAC[
MULT_SYM] THEN ASM_REWRITE_TAC[];
ALL_TAC] THEN
MATCH_MP_TAC(TAUT `d /\ (d ==> a /\ b /\ c)
==> a /\ b /\ c /\ d`) THEN
CONJ_TAC THENL
[MATCH_MP_TAC
REAL_EQ_RCANCEL_IMP THEN
EXISTS_TAC `&a - sqrt(&a pow 2 - &1)` THEN CONJ_TAC THENL
[REWRITE_TAC[
REAL_SUB_0] THEN
DISCH_THEN(MP_TAC o C AP_THM `2` o AP_TERM `(pow)`) THEN
ASM_SIMP_TAC[
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REAL_ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN
REWRITE_TAC[REAL_ARITH `(a + b) * (a - b) = a * a - b * b`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1;
REAL_OF_NUM_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REWRITE_TAC[REAL_ARITH `a - (a - b) = b`;
REAL_MUL_RID] THEN
ASM_SIMP_TAC[GSYM
REAL_OF_NUM_SUB] THEN
REWRITE_TAC[REAL_ARITH
`(x + y * s) * (a - s) = (a * x - (s * s) * y) + (a * y - x) * s`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1;
REAL_OF_NUM_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN
AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
AP_THM_TAC THEN AP_TERM_TAC THEN
REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
DISCH_THEN(fun th -> ASSUME_TAC th THEN MP_TAC th) THEN
SUBGOAL_THEN
`(&x - &y * sqrt(&a pow 2 - &1)) =
(&(a * x - (a
EXP 2 - 1) * y) - &(a * y - x) * sqrt (&a pow 2 - &1)) *
(&a - sqrt(&a pow 2 - &1))`
MP_TAC THENL
[MATCH_MP_TAC
REAL_EQ_RCANCEL_IMP THEN
EXISTS_TAC `&a + sqrt(&a pow 2 - &1)` THEN CONJ_TAC THENL
[MATCH_MP_TAC(REAL_ARITH `~(a = --b) ==> ~(a + b = &0)`) THEN
DISCH_THEN(MP_TAC o C AP_THM `2` o AP_TERM `(pow)`) THEN
REWRITE_TAC[
REAL_POW_NEG; ARITH] THEN
ASM_SIMP_TAC[
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REAL_ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN
REWRITE_TAC[REAL_ARITH `(a - b) * (a + b) = a * a - b * b`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1;
REAL_OF_NUM_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REWRITE_TAC[REAL_ARITH `a - (a - b) = b`;
REAL_MUL_RID] THEN
ASM_SIMP_TAC[GSYM
REAL_OF_NUM_SUB] THEN
REWRITE_TAC[REAL_ARITH
`(x - y * s) * (a + s) = (a * x - (s * s) * y) - (a * y - x) * s`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1;
REAL_OF_NUM_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN
AP_THM_TAC THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
AP_THM_TAC THEN AP_TERM_TAC THEN
REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
DISCH_THEN(fun th1 -> DISCH_THEN (fun th2 ->
MP_TAC(MK_COMB(AP_TERM `( * )` th1,th2)))) THEN
ONCE_REWRITE_TAC[AC
REAL_MUL_AC
`(a * b) * (c * d) = (c * a) * (d * b)`] THEN
REWRITE_TAC[REAL_ARITH `(a + b) * (a - b) = a * a - b * b`] THEN
REWRITE_TAC[REAL_ARITH `(a - b) * (a + b) = a * a - b * b`] THEN
ONCE_REWRITE_TAC[AC
REAL_MUL_AC
`(a * b) * (c * b) = (c * a) * (b * b)`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1;
REAL_OF_NUM_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REWRITE_TAC[REAL_ARITH `a - (a - b) = b`;
REAL_MUL_RID] THEN
ASM_REWRITE_TAC[
REAL_OF_NUM_POW] THEN
REWRITE_TAC[GSYM
REAL_OF_NUM_POW; GSYM REAL_OF_NUM_ADD;
GSYM REAL_OF_NUM_MUL] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` (SUBST1_TAC o SYM) THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
`((a * b + &1) - b * a = x - y) ==> (x = y + &1)`)) THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` SUBST1_TAC THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
ASM_SIMP_TAC[
REAL_OF_NUM_SUB; REAL_OF_NUM_ADD; REAL_OF_NUM_EQ;
REAL_OF_NUM_POW; REAL_OF_NUM_MUL] THEN
ABBREV_TAC `u = a * x - (a
EXP 2 - 1) * y` THEN
ABBREV_TAC `v = a * y - x:num` THEN
DISCH_THEN(ASSUME_TAC o ONCE_REWRITE_RULE[
MULT_SYM]) THEN
REWRITE_TAC[
MULT_AC] THEN
MATCH_MP_TAC(TAUT `(a <=> b) /\ (~a /\ ~b ==> F) ==> a /\ b`) THEN
CONJ_TAC THENL
[GEN_REWRITE_TAC LAND_CONV [GSYM(SPEC `1`
EXP_MONO_LT_SUC)] THEN
ASM_REWRITE_TAC[
ARITH_SUC] THEN
REWRITE_TAC[
LT_ADD_RCANCEL;
LT_MULT_LCANCEL] THEN
REWRITE_TAC[num_CONV `2`;
EXP_MONO_LT_SUC] THEN
MATCH_MP_TAC(TAUT `a ==> (a /\ b <=> b)`) THEN
REWRITE_TAC[
SUB_EQ_0;
ARITH_SUC;
NOT_LE] THEN
SUBST1_TAC(SYM(SPEC `a:num` (CONJUNCT1
EXP))) THEN
REWRITE_TAC[
LT_EXP] THEN REWRITE_TAC[ARITH] THEN
MATCH_MP_TAC(ARITH_RULE `~(a = 0) /\ ~(a = 1) ==> 2 <= a`) THEN
ASM_REWRITE_TAC[]; ALL_TAC] THEN
REWRITE_TAC[
NOT_LT] THEN STRIP_TAC THEN
UNDISCH_TAC
`&x + &y * sqrt (&a pow 2 - &1) =
(&u + &v * sqrt (&a pow 2 - &1)) * (&a + sqrt (&a pow 2 - &1))` THEN
REWRITE_TAC[] THEN
MATCH_MP_TAC(REAL_ARITH `a < b ==> ~(a = b)`) THEN
MATCH_MP_TAC
REAL_LET_TRANS THEN
EXISTS_TAC `(&u + &v * sqrt (&a pow 2 - &1)) * &1` THEN CONJ_TAC THENL
[REWRITE_TAC[
REAL_MUL_RID] THEN MATCH_MP_TAC
REAL_LE_ADD2 THEN
ASM_REWRITE_TAC[REAL_OF_NUM_LE] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
ASM_SIMP_TAC[REAL_OF_NUM_LE;
SQRT_POS_LE;
REAL_POW_LE_1;
REAL_SUB_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`];
ALL_TAC] THEN
MATCH_MP_TAC
REAL_LT_LMUL THEN CONJ_TAC THENL
[MATCH_MP_TAC
REAL_LTE_ADD THEN CONJ_TAC THENL
[REWRITE_TAC[
REAL_OF_NUM_LT;
LT_NZ] THEN DISCH_THEN SUBST_ALL_TAC THEN
UNDISCH_TAC `0
EXP 2 = (a
EXP 2 - 1) * v
EXP 2 + 1` THEN
DISCH_THEN(MP_TAC o SYM) THEN CONV_TAC NUM_REDUCE_CONV THEN
REWRITE_TAC[
ADD_EQ_0;
ARITH_EQ]; ALL_TAC] THEN
MATCH_MP_TAC
REAL_LE_MUL THEN REWRITE_TAC[
REAL_POS] THEN
ASM_SIMP_TAC[REAL_OF_NUM_LE;
SQRT_POS_LE;
REAL_POW_LE_1;
REAL_SUB_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`];
ALL_TAC] THEN
MATCH_MP_TAC(REAL_ARITH `&1 < x /\ &0 <= y ==> &1 < x + y`) THEN
ASM_SIMP_TAC[REAL_OF_NUM_LE;
SQRT_POS_LE;
REAL_POW_LE_1;
REAL_SUB_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REWRITE_TAC[
REAL_OF_NUM_LT] THEN
MATCH_MP_TAC(ARITH_RULE `~(a = 0) /\ ~(a = 1) ==> 1 < a`) THEN
ASM_REWRITE_TAC[]);;
let SOLUTIONS_ARE_XY = prove
(`!a x y.
~(a = 0) /\
(x
EXP 2 = (a
EXP 2 - 1) * y
EXP 2 + 1)
==> ?n. (x = X a n) /\ (y = Y a n)`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `a = 1` THENL
[ASM_REWRITE_TAC[ARITH;
MULT_CLAUSES;
ADD_CLAUSES;
EXP_2] THEN
SIMP_TAC[
MULT_EQ_1;
X_DEGENERATE;
Y_DEGENERATE; GSYM
EXISTS_REFL];
ALL_TAC] THEN
STRIP_TAC THEN
SUBGOAL_THEN `?n. &x + &y * sqrt(&a pow 2 - &1) =
(&a + sqrt(&a pow 2 - &1)) pow n`
MP_TAC THENL
[UNDISCH_TAC `x
EXP 2 = (a
EXP 2 - 1) * y
EXP 2 + 1` THEN
SPEC_TAC(`x:num`,`x:num`) THEN SPEC_TAC(`y:num`,`y:num`) THEN
MATCH_MP_TAC
num_WF THEN X_GEN_TAC `y0:num` THEN DISCH_TAC THEN
X_GEN_TAC `x0:num` THEN
ASM_CASES_TAC `y0 = 0` THENL
[ASM_REWRITE_TAC[
EXP_2;
MULT_CLAUSES;
ADD_CLAUSES;
MULT_EQ_1] THEN
DISCH_THEN SUBST1_TAC THEN EXISTS_TAC `0` THEN
REWRITE_TAC[
REAL_MUL_LZERO;
REAL_ADD_RID;
real_pow]; ALL_TAC] THEN
DISCH_TAC THEN
MP_TAC(SPECL [`a:num`; `x0:num`; `y0:num`]
SOLUTIONS_INDUCTION) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `x1:num` (X_CHOOSE_THEN `y1:num`
STRIP_ASSUME_TAC)) THEN
FIRST_X_ASSUM(MP_TAC o SPEC `y1:num`) THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN(MP_TAC o SPEC `x1:num`) THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `n:num` SUBST1_TAC) THEN
EXISTS_TAC `SUC n` THEN REWRITE_TAC[
real_pow;
REAL_MUL_AC]; ALL_TAC] THEN
ASM_SIMP_TAC[GSYM
XY_POWER_POS] THEN MATCH_MP_TAC
MONO_EXISTS THEN
X_GEN_TAC `n:num` THEN
ASM_SIMP_TAC[
SQRT_LINEAR_EQ;
ARITH_RULE `~(a = 0) /\ ~(a = 1) ==> 2 <= a`]);;
(* ------------------------------------------------------------------------- *)
(* Addition formulas. *)
(* ------------------------------------------------------------------------- *)
let ADDITION_FORMULA_POS = prove
(`!a m n.
~(a = 0)
==> ((X a (m + n) = X a m * X a n + (a
EXP 2 - 1) * Y a m * Y a n) /\
(Y a (m + n) = X a m * Y a n + X a n * Y a m))`,
REPEAT GEN_TAC THEN DISCH_TAC THEN ASM_CASES_TAC `a = 1` THENL
[ASM_REWRITE_TAC[
X_DEGENERATE;
Y_DEGENERATE] THEN
REWRITE_TAC[ARITH;
MULT_CLAUSES] THEN REWRITE_TAC[
ADD_AC]; ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `m + n:num`]
XY_POWER_POS) THEN
MP_TAC(SPECL [`a:num`; `m:num`]
XY_POWER_POS) THEN
MP_TAC(SPECL [`a:num`; `n:num`]
XY_POWER_POS) THEN
ASM_REWRITE_TAC[] THEN
REWRITE_TAC[
REAL_POW_ADD] THEN
DISCH_THEN(SUBST1_TAC o SYM) THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
REWRITE_TAC[REAL_ARITH
`(a + b * s) * (c + d * s) = (a * c + (s * s) * b * d) +
(a * d + b * c) * s`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1;
REAL_OF_NUM_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` SUBST1_TAC THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
REWRITE_TAC[REAL_OF_NUM_MUL; REAL_OF_NUM_ADD] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` (SUBST1_TAC o SYM) THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
ASM_SIMP_TAC[
SQRT_LINEAR_EQ;
ARITH_RULE `~(a = 0) /\ ~(a = 1) ==> 2 <= a`] THEN
REWRITE_TAC[
MULT_AC]);;
let ADDITION_FORMULA_NEG = prove
(`!a m n.
~(a = 0) /\ m <= n
==> ((X a (n - m) = X a m * X a n - (a
EXP 2 - 1) * Y a m * Y a n) /\
(Y a (n - m) = X a m * Y a n - X a n * Y a m))`,
REPEAT GEN_TAC THEN STRIP_TAC THEN ASM_CASES_TAC `a = 1` THENL
[ASM_REWRITE_TAC[
X_DEGENERATE;
Y_DEGENERATE] THEN
REWRITE_TAC[ARITH;
MULT_CLAUSES]; ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `n - m:num`]
XY_POWER_POS) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(MP_TAC o AP_TERM
`( * ) (((&a - sqrt (&a pow 2 - &1)) *
(&a + sqrt (&a pow 2 - &1))) pow m)`) THEN
GEN_REWRITE_TAC (LAND_CONV o LAND_CONV o ONCE_DEPTH_CONV)
[REAL_ARITH `(x - y) * (x + y) = x * x - y * y`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
REWRITE_TAC[REAL_ARITH `x - (x - &1) = &1`] THEN
REWRITE_TAC[
REAL_POW_MUL;
REAL_POW_ONE; REAL_MUL_LID] THEN
REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN
REWRITE_TAC[GSYM
REAL_POW_ADD] THEN
ASM_SIMP_TAC[ARITH_RULE `m <= n ==> (m + (n - m) = n:num)`] THEN
MP_TAC(SPECL [`a:num`; `m:num`]
XY_POWER_NEG) THEN
MP_TAC(SPECL [`a:num`; `n:num`]
XY_POWER_POS) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(SUBST1_TAC o SYM) THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
REWRITE_TAC[REAL_ARITH
`(a - b * s) * (c + d * s) = (a * c - (s * s) * b * d) +
(a * d - b * c) * s`] THEN
ASM_SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_SUB_LE;
REAL_POW_LE_1;
REAL_OF_NUM_LE; ARITH_RULE `~(a = 0) ==> 1 <= a`] THEN
ONCE_REWRITE_TAC[REAL_ARITH
`(a + b * s = (x1 - x2) + (y1 - y2) * s) =
((a + x2) + (b + y2) * s = x1 + y1 * s)`] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` SUBST1_TAC THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
REWRITE_TAC[REAL_OF_NUM_MUL; REAL_OF_NUM_ADD] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` (SUBST1_TAC o SYM) THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
ASM_SIMP_TAC[
SQRT_LINEAR_EQ;
ARITH_RULE `~(a = 0) /\ ~(a = 1) ==> 2 <= a`] THEN
DISCH_THEN(CONJUNCTS_THEN(SUBST1_TAC o SYM)) THEN
REWRITE_TAC[
MULT_AC] THEN REWRITE_TAC[
ADD_SUB]);;
(* ------------------------------------------------------------------------- *)
(* Some stronger monotonicity theorems for Y. *)
(* ------------------------------------------------------------------------- *)
let Y_INJ = prove
(`!a m n. ~(a = 0) ==> ((Y a m = Y a n) <=> (m = n))`,
REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[] THEN
MP_TAC(SPEC `a:num`
Y_INCREASES_LT) THEN ASM_REWRITE_TAC[] THEN
MESON_TAC[
LT_CASES;
LT_REFL]);;
(* ------------------------------------------------------------------------- *)
(* One for X (to get the same as Y, need a /= 1). *)
(* ------------------------------------------------------------------------- *)
let X_INCREASES_LT = prove
(`!a m n. ~(a = 0) /\ ~(a = 1) /\ m < n ==> X a m < X a n`,
REPEAT GEN_TAC THEN
GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM
LE_SUC_LT] THEN
STRIP_TAC THEN
MATCH_MP_TAC
LTE_TRANS THEN EXISTS_TAC `X a (SUC m)` THEN
ASM_SIMP_TAC[
X_INCREASES_LE] THEN
SPEC_TAC(`m:num`,`p:num`) THEN
INDUCT_TAC THEN ASM_SIMP_TAC[ARITH;
X_CLAUSES; ARITH_RULE
`~(a = 0) /\ ~(a = 1) ==> 1 < a`] THEN
REWRITE_TAC[ARITH_RULE `SUC(SUC p) = p + 2`] THEN
REWRITE_TAC[
X_CLAUSES;
ADD1] THEN
MATCH_MP_TAC(ARITH_RULE `a <= b /\ c < b ==> a < 2 * b - c`) THEN
CONJ_TAC THENL
[ALL_TAC;
MATCH_MP_TAC
LTE_TRANS THEN EXISTS_TAC `X a (SUC p)` THEN
ASM_REWRITE_TAC[]] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = 1 * a`] THEN
REWRITE_TAC[
LE_MULT_RCANCEL;
ADD1] THEN DISJ1_TAC THEN
MAP_EVERY UNDISCH_TAC [`~(a = 0)`; `~(a = 1)`] THEN ARITH_TAC);;
let X_INJ = prove
(`!a m n. ~(a = 0) /\ ~(a = 1) ==> ((X a m = X a n) <=> (m = n))`,
REPEAT STRIP_TAC THEN EQ_TAC THEN SIMP_TAC[] THEN
MP_TAC(SPEC `a:num`
X_INCREASES_LT) THEN ASM_REWRITE_TAC[] THEN
MESON_TAC[
LT_CASES;
LT_REFL]);;
(* ------------------------------------------------------------------------- *)
(* Coprimality of "X a n" and "Y a n". *)
(* ------------------------------------------------------------------------- *)
let XY_COPRIME = prove
(`!a n. ~(a = 0) ==> coprime(X a n,Y a n)`,
REPEAT GEN_TAC THEN
DISCH_THEN(MP_TAC o SPEC `n:num` o MATCH_MP
XY_ARE_SOLUTIONS) THEN
ONCE_REWRITE_TAC[TAUT `a ==> b <=> ~b ==> ~a`] THEN
REWRITE_TAC[coprime;
NOT_FORALL_THM;
LEFT_IMP_EXISTS_THM] THEN
X_GEN_TAC `d:num` THEN REWRITE_TAC[NOT_IMP] THEN
REWRITE_TAC[divides] THEN STRIP_TAC THEN ASM_REWRITE_TAC[
EXP_2] THEN
REWRITE_TAC[GSYM
MULT_ASSOC] THEN
GEN_REWRITE_TAC (funpow 2 RAND_CONV o LAND_CONV)
[AC
MULT_AC `a * d * x * d * x = d * d * a * x * x:num`] THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(a = b + 1) ==> (a - b = 1)`)) THEN
ASM_REWRITE_TAC[GSYM
LEFT_SUB_DISTRIB;
MULT_EQ_1]);;
(* ------------------------------------------------------------------------- *)
(* Divisibility properties. *)
(* ------------------------------------------------------------------------- *)
let Y_DIVIDES = prove
(`!a m n. ~(a = 0) ==> ((Y a m) divides (Y a n) <=> m divides n)`,
REPEAT STRIP_TAC THEN EQ_TAC THENL
[ALL_TAC;
GEN_REWRITE_TAC LAND_CONV [divides] THEN
ASM_SIMP_TAC[
LEFT_IMP_EXISTS_THM;
Y_DIVIDES_LEMMA]] THEN
ONCE_REWRITE_TAC[TAUT `a ==> b <=> ~b ==> ~a`] THEN
ASM_CASES_TAC `n = 0` THEN ASM_REWRITE_TAC[
DIVIDES_0] THEN
ASM_CASES_TAC `m = 0` THENL
[ASM_REWRITE_TAC[
Y_CLAUSES;
DIVIDES_ZERO] THEN
MATCH_MP_TAC(ARITH_RULE
`!n. (n = 1) /\ n <= m ==> ~(m = 0)`) THEN
EXISTS_TAC `Y a 1` THEN CONJ_TAC THENL
[REWRITE_TAC[
Y_CLAUSES]; ALL_TAC] THEN
ASM_SIMP_TAC[
Y_INCREASES_LE; ARITH_RULE `1 <= n <=> ~(n = 0)`];
ALL_TAC] THEN
MP_TAC(SPECL [`n:num`; `m:num`]
DIVISION) THEN
ASM_REWRITE_TAC[] THEN
ABBREV_TAC `q = n DIV m` THEN ABBREV_TAC `r = n MOD m` THEN
STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
ASM_CASES_TAC `r = 0` THEN
ASM_SIMP_TAC[
ADD_CLAUSES;
DIVIDES_LMUL;
DIVIDES_REFL] THEN
DISCH_TAC THEN
ASM_SIMP_TAC[
ADDITION_FORMULA_POS] THEN
SUBGOAL_THEN `~((Y a m) divides (X a (q * m) * Y a r))` MP_TAC THENL
[ALL_TAC;
REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN DISCH_TAC THEN
MATCH_MP_TAC
DIVIDES_ADD_REVL THEN
EXISTS_TAC `X a r * Y a (q * m)` THEN
ASM_REWRITE_TAC[] THEN
GEN_REWRITE_TAC (funpow 3 RAND_CONV) [
MULT_SYM] THEN
ASM_SIMP_TAC[
DIVIDES_LMUL;
Y_DIVIDES_LEMMA]] THEN
DISCH_THEN(MP_TAC o MATCH_MP
(REWRITE_RULE[
IMP_CONJ]
COPRIME_DIVPROD)) THEN
REWRITE_TAC[NOT_IMP] THEN CONJ_TAC THENL
[MP_TAC(SPECL [`a:num`; `q * m:num`]
XY_COPRIME) THEN ASM_REWRITE_TAC[] THEN
ONCE_REWRITE_TAC[TAUT `a ==> b <=> ~b ==> ~a`] THEN
REWRITE_TAC[coprime;
NOT_FORALL_THM; NOT_IMP] THEN
MATCH_MP_TAC
MONO_EXISTS THEN X_GEN_TAC `d:num` THEN
STRIP_TAC THEN ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[
MULT_SYM] THEN
ASM_MESON_TAC[
DIVIDES_TRANS;
Y_DIVIDES_LEMMA]; ALL_TAC] THEN
DISCH_THEN(MP_TAC o MATCH_MP
DIVIDES_LE) THEN
ASM_SIMP_TAC[DE_MORGAN_THM;
NOT_LE;
Y_INCREASES_LT] THEN
ONCE_REWRITE_TAC[GSYM(CONJUNCT1
Y_CLAUSES)] THEN ASM_SIMP_TAC[
Y_INJ]);;
(* ------------------------------------------------------------------------- *)
(* This lemma would be trivial from binomial theorem. *)
(* ------------------------------------------------------------------------- *)
let BINOMIAL_TRIVIALITY = prove
(`!x y d n. ?p q.
(&x + &y * sqrt(&d)) pow (n + 2) =
&x pow (n + 2) +
&(n + 2) * &x pow (n + 1) * &y * sqrt(&d) +
&(((n + 1) * (n + 2)) DIV 2) * &x pow n * &y pow 2 * &d +
&p * &y pow 3 + &q * &y pow 3 * sqrt(&d)`,
GEN_TAC THEN GEN_TAC THEN GEN_TAC THEN INDUCT_TAC THENL
[REPEAT(EXISTS_TAC `0`) THEN CONV_TAC NUM_REDUCE_CONV THEN
REWRITE_TAC[
REAL_POW_1;
real_pow;
REAL_MUL_LZERO;
REAL_ADD_RID] THEN
REWRITE_TAC[REAL_MUL_LID] THEN REWRITE_TAC[REAL_POW_2] THEN
REWRITE_TAC[REAL_ARITH
`(x + y) * (x + y) = x * x + &2 * x * y + y * y`] THEN
AP_TERM_TAC THEN AP_TERM_TAC THEN
ONCE_REWRITE_TAC[AC
REAL_MUL_AC `(a * b) * (a * b) = (a * a) * b * b`] THEN
SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_POS]; ALL_TAC] THEN
GEN_REWRITE_TAC (funpow 2 BINDER_CONV o LAND_CONV o TOP_DEPTH_CONV)
[
ADD_CLAUSES;
real_pow] THEN
FIRST_ASSUM(X_CHOOSE_THEN `p:num` (X_CHOOSE_THEN `q:num` SUBST1_TAC)) THEN
REWRITE_TAC[REAL_ARITH
`(x + y) * (xn + xn1 + xn2 + p + q) =
(x * xn) + (x * xn1 + y * xn) + (x * xn2 + y * xn1) +
(y * xn2 + p * x + q * y) + (p * y + q * x)`] THEN
ONCE_REWRITE_TAC[REAL_ARITH
`x * n2 * xn1 * y * d + (y * d) * xn2 = (n2 * x * xn1 + xn2) * y * d`] THEN
REWRITE_TAC[GSYM(CONJUNCT2
real_pow)] THEN
REWRITE_TAC[ARITH_RULE `SUC(n + m) = n + SUC m`] THEN
REWRITE_TAC[ARITH_RULE `SUC n + m = n + SUC m`] THEN
CONV_TAC NUM_REDUCE_CONV THEN
REWRITE_TAC[REAL_ARITH `&n * x + x = (&n + &1) * x`] THEN
REWRITE_TAC[REAL_OF_NUM_ADD; ARITH_RULE `(n + 2) + 1 = n + 3`] THEN
REWRITE_TAC[GSYM REAL_ADD_ASSOC; GSYM REAL_MUL_ASSOC;
REAL_EQ_LADD] THEN
ONCE_REWRITE_TAC[REAL_ARITH
`x * n12 * xn * y2 * d + y * s * n2 * xn1 * y * s + a =
(n12 * (x * xn) * y2 * d + n2 * xn1 * (y * y) * (s * s)) + a`] THEN
REWRITE_TAC[GSYM REAL_POW_2; GSYM(CONJUNCT2
real_pow)] THEN
SIMP_TAC[
SQRT_POW_2;
REAL_POS] THEN
REWRITE_TAC[
ADD1; REAL_MUL_ASSOC; GSYM
REAL_ADD_RDISTRIB] THEN
SUBGOAL_THEN `&(((n + 1) * (n + 2)) DIV 2) + &(n + 2) =
&(((n + 2) * (n + 3)) DIV 2)`
SUBST1_TAC THENL
[REWRITE_TAC[REAL_OF_NUM_ADD; REAL_OF_NUM_EQ] THEN
CONV_TAC SYM_CONV THEN MATCH_MP_TAC
DIV_UNIQ THEN
EXISTS_TAC `0` THEN REWRITE_TAC[ARITH;
ADD_CLAUSES] THEN
REWRITE_TAC[ARITH_RULE `(n + 2) * (n + 3) = n * n + 5 * n + 6`] THEN
REWRITE_TAC[ARITH_RULE
`(x + 5 * n + 6 = (y + n + 2) * 2) <=> (x + 3 * n + 2 = 2 * y)`] THEN
REWRITE_TAC[ARITH_RULE `n * n + 3 * n + 2 = (n + 1) * (n + 2)`] THEN
SUBGOAL_THEN `
EVEN((n + 1) * (n + 2))` MP_TAC THENL
[REWRITE_TAC[
EVEN_MULT;
EVEN_ADD;
ARITH_EVEN] THEN
CONV_TAC(EQT_INTRO o TAUT); ALL_TAC] THEN
SIMP_TAC[
EVEN_EXISTS;
LEFT_IMP_EXISTS_THM] THEN
SIMP_TAC[DIV_MULT;
ARITH_EQ]; ALL_TAC] THEN
REWRITE_TAC[
REAL_EQ_LADD] THEN REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN
ONCE_REWRITE_TAC[REAL_ARITH `q * y3 * s * y * s = q * y * y3 * s * s`] THEN
SIMP_TAC[GSYM REAL_POW_2;
SQRT_POW_2;
REAL_POS] THEN
ONCE_REWRITE_TAC[REAL_ARITH
`y * s * nn * xn * y2 * d = nn * d * xn * (y * y2) * s`] THEN
REWRITE_TAC[GSYM(CONJUNCT2
real_pow)] THEN
EXISTS_TAC `p * x + q * y * d:num` THEN REWRITE_TAC[
ARITH_SUC] THEN
EXISTS_TAC `((n + 1) * (n + 2)) DIV 2 * d * x
EXP n +
p * y + q * x` THEN
REWRITE_TAC[GSYM REAL_OF_NUM_MUL; GSYM REAL_OF_NUM_ADD;
GSYM
REAL_OF_NUM_POW] THEN
REWRITE_TAC[REAL_ADD_LDISTRIB;
REAL_ADD_RDISTRIB] THEN
REWRITE_TAC[
REAL_MUL_AC] THEN REWRITE_TAC[
REAL_ADD_AC]);;
(* ------------------------------------------------------------------------- *)
(* A lower bound theorem. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Now a key congruence. *)
(* ------------------------------------------------------------------------- *)
let XY_Y3_CONGRUENCE = prove
(`!a n k. ~(a = 0)
==> ?q. Y a (n * k) =
k * (X a n)
EXP (k - 1) * Y a n + q * (Y a n)
EXP 3`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `k = 0` THENL
[EXISTS_TAC `0` THEN
ASM_REWRITE_TAC[
Y_CLAUSES;
MULT_CLAUSES;
ADD_CLAUSES;
SUB_0]; ALL_TAC] THEN
ASM_CASES_TAC `a = 1` THENL
[ASM_REWRITE_TAC[
X_DEGENERATE;
Y_DEGENERATE;
EXP_ONE] THEN
EXISTS_TAC `0` THEN REWRITE_TAC[
ADD_CLAUSES;
MULT_CLAUSES] THEN
REWRITE_TAC[
MULT_AC]; ALL_TAC] THEN
ASM_CASES_TAC `k = 1` THENL
[ASM_REWRITE_TAC[
MULT_CLAUSES;
SUB_REFL;
EXP] THEN
EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES]; ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `n * k:num`]
XY_POWER_POS) THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[GSYM
REAL_POW_POW] THEN
MP_TAC(SPECL [`a:num`; `n:num`]
XY_POWER_POS) THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[GSYM
REAL_POW_POW] THEN DISCH_THEN(SUBST1_TAC o SYM) THEN
SUBGOAL_THEN `2 <= k` MP_TAC THENL
[MAP_EVERY UNDISCH_TAC [`~(k = 0)`; `~(k = 1)`] THEN ARITH_TAC;
ALL_TAC] THEN
GEN_REWRITE_TAC LAND_CONV [
LE_EXISTS] THEN
DISCH_THEN(X_CHOOSE_THEN `d:num`
(SUBST1_TAC o ONCE_REWRITE_RULE[
ADD_SYM])) THEN
MP_TAC(SPECL [`X a n`; `Y a n`; `a
EXP 2 - 1`; `d:num`]
BINOMIAL_TRIVIALITY) THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` (SUBST1_TAC o SYM) THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
DISCH_THEN(X_CHOOSE_THEN `p:num` (X_CHOOSE_THEN `q:num` SUBST1_TAC)) THEN
ONCE_REWRITE_TAC[REAL_ARITH
`x1 + y1 + x2 + x3 + y2 = (x1 + x2 + x3) + (y1 + y2)`] THEN
REWRITE_TAC[REAL_MUL_ASSOC; GSYM
REAL_ADD_RDISTRIB] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` SUBST1_TAC THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
REWRITE_TAC[
REAL_OF_NUM_POW; REAL_OF_NUM_MUL; REAL_OF_NUM_ADD] THEN
SUBGOAL_THEN `&a pow 2 - &1 = &(a
EXP 2 - 1)` (SUBST1_TAC o SYM) THENL
[REWRITE_TAC[
REAL_OF_NUM_POW] THEN MATCH_MP_TAC
REAL_OF_NUM_SUB THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM
REAL_OF_NUM_POW] THEN
ASM_SIMP_TAC[
REAL_POW_LE_1; REAL_OF_NUM_LE;
ARITH_RULE `~(a = 0) ==> 1 <= a`]; ALL_TAC] THEN
ASM_SIMP_TAC[
SQRT_LINEAR_EQ;
ARITH_RULE `~(p = 0) /\ ~(p = 1) ==> 2 <= p`] THEN
DISCH_THEN(K ALL_TAC) THEN
REWRITE_TAC[ARITH_RULE `(d + 2) - 1 = d + 1`] THEN
EXISTS_TAC `q:num` THEN REWRITE_TAC[GSYM
MULT_ASSOC]);;
(* ------------------------------------------------------------------------- *)
(* The other key divisibility result. *)
(* ------------------------------------------------------------------------- *)
let Y2_DIVIDES = prove
(`!a m n. ~(a = 0)
==> (((Y a m)
EXP 2) divides (Y a n) <=> (m * Y a m) divides n)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `m = 0` THENL
[ASM_REWRITE_TAC[
Y_CLAUSES;
MULT_CLAUSES;
DIVIDES_ZERO;
EXP_2] THEN
GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [GSYM(CONJUNCT1
Y_CLAUSES)] THEN
ASM_SIMP_TAC[
Y_INJ]; ALL_TAC] THEN
SUBGOAL_THEN `~(Y a m = 0)` ASSUME_TAC THENL
[GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [GSYM(CONJUNCT1
Y_CLAUSES)] THEN
ASM_SIMP_TAC[
Y_INJ]; ALL_TAC] THEN
MATCH_MP_TAC(TAUT
`!c. (a ==> c) /\ (b ==> c) /\ (c ==> (a <=> b)) ==> (a <=> b)`) THEN
EXISTS_TAC `m divides n` THEN REPEAT CONJ_TAC THENL
[DISCH_TAC THEN
SUBGOAL_THEN `(Y a m) divides (Y a n)` MP_TAC THENL
[ALL_TAC; ASM_SIMP_TAC[
Y_DIVIDES]] THEN
UNDISCH_TAC `((Y a m)
EXP 2) divides (Y a n)` THEN
REWRITE_TAC[divides;
EXP_2; GSYM
MULT_ASSOC] THEN MESON_TAC[];
REWRITE_TAC[divides; GSYM
MULT_ASSOC] THEN MESON_TAC[];
ALL_TAC] THEN
GEN_REWRITE_TAC LAND_CONV [divides] THEN
DISCH_THEN(X_CHOOSE_THEN `k:num` SUBST1_TAC) THEN
MP_TAC(SPECL [`a:num`; `m:num`; `k:num`]
XY_Y3_CONGRUENCE) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `q:num` SUBST1_TAC) THEN
MATCH_MP_TAC
EQ_TRANS THEN
EXISTS_TAC `((Y a m)
EXP 2) divides (k * (X a m)
EXP (k - 1) * Y a m)` THEN
CONJ_TAC THENL
[REWRITE_TAC[num_CONV `3`;
EXP] THEN
MESON_TAC[
DIVIDES_ADD;
DIVIDES_ADD_REVL;
DIVIDES_LMUL;
DIVIDES_REFL];
ALL_TAC] THEN
REWRITE_TAC[
MULT_ASSOC] THEN
GEN_REWRITE_TAC (LAND_CONV o RAND_CONV) [
MULT_SYM] THEN
REWRITE_TAC[
EXP_2; GSYM
MULT_ASSOC] THEN
ASM_SIMP_TAC[
DIVIDES_LMUL2_EQ] THEN
EQ_TAC THEN SIMP_TAC[
DIVIDES_RMUL] THEN
DISCH_TAC THEN MATCH_MP_TAC
COPRIME_DIVPROD THEN
EXISTS_TAC `X a m
EXP (k - 1)` THEN
ONCE_REWRITE_TAC[
MULT_SYM] THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC
COPRIME_EXP THEN
ONCE_REWRITE_TAC[
COPRIME_SYM] THEN ASM_SIMP_TAC[
XY_COPRIME]);;
(* ------------------------------------------------------------------------- *)
(* Some more congruences. *)
(* ------------------------------------------------------------------------- *)
let Y_N_MOD2 = prove
(`!a n. ~(a = 0) ==> ?q. Y a n = 2 * q + n`,
GEN_TAC THEN REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
MATCH_MP_TAC
PELL_INDUCTION THEN REWRITE_TAC[
Y_CLAUSES] THEN
REPEAT CONJ_TAC THENL
[EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
ALL_TAC] THEN
REWRITE_TAC[
RIGHT_AND_EXISTS_THM;
LEFT_AND_EXISTS_THM;
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`n:num`; `q1:num`; `q2:num`] THEN STRIP_TAC THEN
FIRST_ASSUM(MP_TAC o SPEC `n:num` o MATCH_MP
Y_INCREASES) THEN
ASM_REWRITE_TAC[] THEN
REWRITE_TAC[ARITH_RULE `2 * q1 + n <= 2 * q2 + n + 1 <=> q1 <= q2`] THEN
DISCH_TAC THEN
EXISTS_TAC `(2 * a * q2 - q1) + (a - 1) * (n + 1)` THEN
MATCH_MP_TAC(ARITH_RULE
`v <= u /\ y <= x /\ (2 * (x + z) + w + v = 2 * y + u)
==> (u - v = 2 * ((x - y) + z) + w)`) THEN
REPEAT CONJ_TAC THENL
[REWRITE_TAC[
LEFT_ADD_DISTRIB] THEN
MATCH_MP_TAC(ARITH_RULE
`x <= u /\ y <= v ==> 2 * x + y <= 2 * u + v + w`) THEN
REWRITE_TAC[
MULT_ASSOC] THEN CONJ_TAC THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `n = 1 * n`] THENL
[MATCH_MP_TAC
LE_MULT2 THEN ASM_REWRITE_TAC[];
REWRITE_TAC[
LE_MULT_RCANCEL] THEN DISJ1_TAC] THEN
UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC;
REWRITE_TAC[
MULT_ASSOC] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `n = 1 * n`] THEN
MATCH_MP_TAC
LE_MULT2 THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC;
UNDISCH_TAC `~(a = 0)` THEN SPEC_TAC(`a:num`,`a:num`) THEN
INDUCT_TAC THEN REWRITE_TAC[
NOT_SUC] THEN
REWRITE_TAC[ARITH_RULE `SUC a - 1 = a`] THEN
REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THEN
ARITH_TAC]);;
let Y_N_MODA1 = prove
(`!a n. ~(a = 0) ==> ?q. Y a n = q * (a - 1) + n`,
GEN_TAC THEN REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
ASM_CASES_TAC `a = 1` THENL
[ASM_REWRITE_TAC[
SUB_REFL;
Y_DEGENERATE;
MULT_CLAUSES;
ADD_CLAUSES];
ALL_TAC] THEN
MATCH_MP_TAC
PELL_INDUCTION THEN REWRITE_TAC[
Y_CLAUSES] THEN
REPEAT CONJ_TAC THENL
[EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
ALL_TAC] THEN
REWRITE_TAC[
RIGHT_AND_EXISTS_THM;
LEFT_AND_EXISTS_THM;
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`n:num`; `q1:num`; `q2:num`] THEN
STRIP_TAC THEN
FIRST_ASSUM(MP_TAC o SPEC `n:num` o MATCH_MP
Y_INCREASES) THEN
ASM_REWRITE_TAC[] THEN
REWRITE_TAC[ARITH_RULE `q1 + n <= q2 + n + 1 <=> q1 <= q2 + 1`] THEN
ASM_CASES_TAC `q2 = 0` THENL
[ASM_REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THEN
REWRITE_TAC[ARITH_RULE `a <= 1 <=> (a = 0) \/ (a = 1)`] THEN
ASM_REWRITE_TAC[
MULT_EQ_0;
MULT_EQ_1] THEN
ASM_REWRITE_TAC[ARITH_RULE `(a - 1 = 0) <=> (a = 0) \/ (a = 1)`] THEN
SIMP_TAC[ARITH_RULE `(a - 1 = 1) <=> (a = 2)`] THEN
STRIP_TAC THEN ASM_REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THENL
[EXISTS_TAC `2 * (n + 1)` THEN
UNDISCH_TAC `~(a = 0)` THEN SPEC_TAC(`a:num`,`b:num`) THEN
INDUCT_TAC THEN REWRITE_TAC[
NOT_SUC] THEN
REWRITE_TAC[ARITH_RULE `SUC n - 1 = n`] THEN
REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THEN
MATCH_MP_TAC(ARITH_RULE `(a + c = b) ==> (b - a = c:num)`) THEN
ARITH_TAC;
REWRITE_TAC[
MULT_ASSOC; ARITH] THEN
REWRITE_TAC[ARITH_RULE `4 * (n + 1) - (1 + n) = 3 * (n + 1)`] THEN
EXISTS_TAC `2 * n + 1` THEN ARITH_TAC];
ALL_TAC] THEN
DISCH_THEN(fun th ->
EXISTS_TAC `2 * (n + 1) + 2 * a * q2 - q1` THEN MP_TAC th) THEN
UNDISCH_TAC `~(a = 1)` THEN
UNDISCH_TAC `~(a = 0)` THEN SPEC_TAC(`a:num`,`b:num`) THEN
INDUCT_TAC THEN REWRITE_TAC[
NOT_SUC] THEN
REWRITE_TAC[ARITH_RULE `(SUC n = 1) <=> (n = 0)`] THEN DISCH_TAC THEN
REWRITE_TAC[ARITH_RULE `SUC n - 1 = n`] THEN DISCH_TAC THEN
REWRITE_TAC[
RIGHT_ADD_DISTRIB;
RIGHT_SUB_DISTRIB] THEN
MATCH_MP_TAC(ARITH_RULE
`v <= u /\ y <= x /\ (u + y = z + x + w + v)
==> (u - v = (z + (x - y)) + w:num)`) THEN
REPEAT CONJ_TAC THENL
[GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = 1 * a`] THEN
REWRITE_TAC[
MULT_ASSOC] THEN MATCH_MP_TAC
LE_MULT2 THEN
ASM_REWRITE_TAC[ARITH_RULE `q1 + n <= q2 + n + 1 <=> q1 <= q2 + 1`] THEN
REWRITE_TAC[
MULT_CLAUSES] THEN ARITH_TAC;
MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `q2 * b + 1` THEN
ASM_REWRITE_TAC[] THEN
REWRITE_TAC[ARITH_RULE `a + 1 <= b <=> a < b`] THEN
ASM_SIMP_TAC[
LT_MULT_RCANCEL] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = 1 * a`] THEN
REWRITE_TAC[
MULT_ASSOC] THEN
ASM_SIMP_TAC[
LT_MULT_RCANCEL] THEN
REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THEN ARITH_TAC;
REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THEN ARITH_TAC]);;
let X_CONGRUENT = prove
(`!a b c n. ~(a = 0) ==> ?q. X (a + b * c) n = X a n + q * c`,
GEN_TAC THEN GEN_TAC THEN GEN_TAC THEN
REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
ASM_CASES_TAC `b * c = 0` THENL
[GEN_TAC THEN EXISTS_TAC `0` THEN
ASM_REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES]; ALL_TAC] THEN
UNDISCH_TAC `~(b * c = 0)` THEN
REWRITE_TAC[
MULT_EQ_0; DE_MORGAN_THM] THEN STRIP_TAC THEN
MATCH_MP_TAC
PELL_INDUCTION THEN REWRITE_TAC[
X_CLAUSES] THEN
REPEAT CONJ_TAC THENL
[EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
EXISTS_TAC `b:num` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
ALL_TAC] THEN
REWRITE_TAC[
RIGHT_AND_EXISTS_THM;
LEFT_AND_EXISTS_THM;
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`n:num`; `q1:num`; `q2:num`] THEN
STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[ARITH_RULE
`2 * (x + y) * (u + v) = 2 * x * u + 2 * u * y + 2 * (x + y) * v`] THEN
EXISTS_TAC `(2 * X a (n + 1) * b + 2 * (a + b * c) * q2) - q1` THEN
MATCH_MP_TAC(ARITH_RULE
`a <= x /\ b <= y + z:num /\ ((x - a) + ((y + z) - b) = u)
==> ((x + y + z) - (a + b) = u)`) THEN
REWRITE_TAC[
RIGHT_SUB_DISTRIB;
RIGHT_ADD_DISTRIB; GSYM
MULT_ASSOC] THEN
CONJ_TAC THENL
[MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `1 * X a (n + 1)` THEN CONJ_TAC THENL
[ASM_SIMP_TAC[
MULT_CLAUSES;
X_INCREASES]; ALL_TAC] THEN
REWRITE_TAC[
MULT_ASSOC;
LE_MULT_RCANCEL] THEN DISJ1_TAC THEN
UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC; ALL_TAC] THEN
MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `X (a + b * c) n` THEN CONJ_TAC THENL
[ASM_REWRITE_TAC[ONCE_REWRITE_RULE[
ADD_SYM]
LE_ADD]; ALL_TAC] THEN
MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `X (a + b * c) (n + 1)` THEN
CONJ_TAC THENL [ASM_SIMP_TAC[
X_INCREASES;
ADD_EQ_0]; ALL_TAC] THEN
ASM_REWRITE_TAC[] THEN MATCH_MP_TAC
LE_ADD2 THEN CONJ_TAC THENL
[GEN_REWRITE_TAC RAND_CONV [
MULT_SYM] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = a * 1`] THEN
REWRITE_TAC[GSYM
MULT_ASSOC;
LE_MULT_LCANCEL] THEN
ASM_REWRITE_TAC[ARITH_RULE `1 <= x <=> ~(x = 0)`;
MULT_EQ_0;
ARITH_EQ];
MATCH_MP_TAC(ARITH_RULE `a <= y ==> a <= 2 * (x + y)`) THEN
ONCE_REWRITE_TAC[AC
MULT_AC `a * b * c * d = (a * b) * (c * d:num)`] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = 1 * a`] THEN
REWRITE_TAC[
LE_MULT_RCANCEL] THEN
ASM_REWRITE_TAC[ARITH_RULE `1 <= x <=> ~(x = 0)`;
MULT_EQ_0;
ARITH_EQ]]);;
let Y_CONGRUENT = prove
(`!a b c n. ~(a = 0) ==> ?q. Y (a + b * c) n = Y a n + q * c`,
GEN_TAC THEN GEN_TAC THEN GEN_TAC THEN
REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN DISCH_TAC THEN
ASM_CASES_TAC `b * c = 0` THENL
[GEN_TAC THEN EXISTS_TAC `0` THEN
ASM_REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES]; ALL_TAC] THEN
UNDISCH_TAC `~(b * c = 0)` THEN
REWRITE_TAC[
MULT_EQ_0; DE_MORGAN_THM] THEN STRIP_TAC THEN
MATCH_MP_TAC
PELL_INDUCTION THEN REWRITE_TAC[
Y_CLAUSES] THEN
REPEAT CONJ_TAC THENL
[EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
ALL_TAC] THEN
REWRITE_TAC[
RIGHT_AND_EXISTS_THM;
LEFT_AND_EXISTS_THM;
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`n:num`; `q1:num`; `q2:num`] THEN
STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[ARITH_RULE
`2 * (x + y) * (u + v) = 2 * x * u + 2 * u * y + 2 * (x + y) * v`] THEN
EXISTS_TAC `(2 * Y a (n + 1) * b + 2 * (a + b * c) * q2) - q1` THEN
MATCH_MP_TAC(ARITH_RULE
`a <= x /\ b <= y + z:num /\ ((x - a) + ((y + z) - b) = u)
==> ((x + y + z) - (a + b) = u)`) THEN
REWRITE_TAC[
RIGHT_SUB_DISTRIB;
RIGHT_ADD_DISTRIB; GSYM
MULT_ASSOC] THEN
CONJ_TAC THENL
[MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `1 * Y a (n + 1)` THEN CONJ_TAC THENL
[ASM_SIMP_TAC[
MULT_CLAUSES;
Y_INCREASES]; ALL_TAC] THEN
REWRITE_TAC[
MULT_ASSOC;
LE_MULT_RCANCEL] THEN DISJ1_TAC THEN
UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC; ALL_TAC] THEN
MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `Y (a + b * c) n` THEN CONJ_TAC THENL
[ASM_REWRITE_TAC[ONCE_REWRITE_RULE[
ADD_SYM]
LE_ADD]; ALL_TAC] THEN
MATCH_MP_TAC
LE_TRANS THEN EXISTS_TAC `Y (a + b * c) (n + 1)` THEN
CONJ_TAC THENL [ASM_SIMP_TAC[
Y_INCREASES;
ADD_EQ_0]; ALL_TAC] THEN
ASM_REWRITE_TAC[] THEN MATCH_MP_TAC
LE_ADD2 THEN CONJ_TAC THENL
[GEN_REWRITE_TAC RAND_CONV [
MULT_SYM] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = a * 1`] THEN
REWRITE_TAC[GSYM
MULT_ASSOC;
LE_MULT_LCANCEL] THEN
ASM_REWRITE_TAC[ARITH_RULE `1 <= x <=> ~(x = 0)`;
MULT_EQ_0;
ARITH_EQ];
MATCH_MP_TAC(ARITH_RULE `a <= y ==> a <= 2 * (x + y)`) THEN
ONCE_REWRITE_TAC[AC
MULT_AC `a * b * c * d = (a * b) * (c * d:num)`] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = 1 * a`] THEN
REWRITE_TAC[
LE_MULT_RCANCEL] THEN
ASM_REWRITE_TAC[ARITH_RULE `1 <= x <=> ~(x = 0)`;
MULT_EQ_0;
ARITH_EQ]]);;
(* ------------------------------------------------------------------------- *)
(* A more important congruence. *)
(* ------------------------------------------------------------------------- *)
let X_CONGRUENT_2NJ_POS = prove
(`!a n j. ~(a = 0) ==> ?q. X a (2 * n + j) + X a j = q * X a n`,
REPEAT STRIP_TAC THEN
MP_TAC(SPECL [`a:num`; `n:num`; `n + j:num`]
ADDITION_FORMULA_POS) THEN
ASM_REWRITE_TAC[ARITH_RULE `n + n + j = 2 * n + j`] THEN
DISCH_THEN(SUBST1_TAC o CONJUNCT1) THEN
MP_TAC(SPECL [`a:num`; `n:num`; `j:num`]
ADDITION_FORMULA_POS) THEN
ASM_REWRITE_TAC[] THEN DISCH_THEN(SUBST1_TAC o CONJUNCT2) THEN
ONCE_REWRITE_TAC[ARITH_RULE
`(xn * a + d * yn * (xn * yj + xj * yn)) + xj =
xn * (a + d * yn * yj) + xj * (d * yn * yn + 1)`] THEN
ASM_SIMP_TAC[GSYM
XY_ARE_SOLUTIONS; GSYM
EXP_2] THEN
REWRITE_TAC[
EXP_2; ARITH_RULE
`xn * a + xj * xn * xn = (a + xj * xn) * xn:num`] THEN
MESON_TAC[]);;
let X_CONGRUENT_4NJ_POS = prove
(`!a n j. ~(a = 0) ==> ?q. X a (4 * n + j) = q * X a n + X a j`,
REPEAT STRIP_TAC THEN
MP_TAC(SPECL [`a:num`; `n:num`; `2 * n + j`]
X_CONGRUENT_2NJ_POS) THEN
ASM_REWRITE_TAC[ARITH_RULE `2 * n + 2 * n + j = 4 * n + j`] THEN
DISCH_THEN(X_CHOOSE_THEN `q1:num` MP_TAC) THEN
DISCH_THEN(MP_TAC o C AP_THM `X a j` o AP_TERM `(+):num->num->num`) THEN
REWRITE_TAC[GSYM
ADD_ASSOC] THEN
MP_TAC(SPECL [`a:num`; `n:num`; `j:num`]
X_CONGRUENT_2NJ_POS) THEN
ASM_REWRITE_TAC[] THEN DISCH_THEN(X_CHOOSE_THEN `q2:num` MP_TAC) THEN
DISCH_THEN SUBST1_TAC THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(y + q2 = q1 + x) ==> x <= y ==> (y = (q1 - q2) + x:num)`)) THEN
ASM_SIMP_TAC[
X_INCREASES_LE; ARITH_RULE `j <= 4 * n + j`] THEN
DISCH_THEN(K ALL_TAC) THEN REWRITE_TAC[GSYM
RIGHT_SUB_DISTRIB] THEN
MESON_TAC[]);;
let X_CONGRUENT_4MNJ_POS = prove
(`!a m n j. ~(a = 0) ==> ?q. X a (4 * m * n + j) = q * X a n + X a j`,
GEN_TAC THEN REWRITE_TAC[
RIGHT_FORALL_IMP_THM] THEN
DISCH_TAC THEN INDUCT_TAC THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THENL
[REPEAT GEN_TAC THEN EXISTS_TAC `0` THEN
REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES]; ALL_TAC] THEN
UNDISCH_TAC `!n j. ?q. X a (4 * m * n + j) = q * X a n + X a j` THEN
REPEAT(MATCH_MP_TAC
MONO_FORALL THEN GEN_TAC) THEN
DISCH_THEN(X_CHOOSE_THEN `q1:num` ASSUME_TAC) THEN
MP_TAC(SPECL [`a:num`; `n:num`; `4 * m * n + j`]
X_CONGRUENT_4NJ_POS) THEN
ASM_REWRITE_TAC[ARITH_RULE
`4 * (m * n + n) + j = 4 * n + 4 * m * n + j`] THEN
DISCH_THEN(X_CHOOSE_THEN `q2:num` SUBST1_TAC) THEN
EXISTS_TAC `q2 + q1:num` THEN ARITH_TAC);;
let X_CONGRUENT_2NJ_NEG_LEMMA = prove
(`!a n j. ~(a = 0) /\ j <= n ==> ?q. X a (2 * n - j) + X a j = q * X a n`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `j = n:num` THENL
[EXISTS_TAC `2` THEN ASM_REWRITE_TAC[
MULT_2;
ADD_SUB]; ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `n:num`; `n - j:num`]
ADDITION_FORMULA_POS) THEN
ASM_SIMP_TAC[ARITH_RULE `j <= n ==> (n + n - j = 2 * n - j)`] THEN
STRIP_TAC THEN
MP_TAC(SPECL [`a:num`; `j:num`; `n:num`]
ADDITION_FORMULA_NEG) THEN
ASM_REWRITE_TAC[] THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
EXISTS_TAC `(X a j * X a n - (a
EXP 2 - 1) * Y a j * Y a n) +
(X a j * X a n - (a
EXP 2 - 1) * Y a j * Y a n)` THEN
REWRITE_TAC[ARITH_RULE
`((xn * a + b) + c = (a + d) * xn) <=> (b + c = xn * d:num)`] THEN
REWRITE_TAC[
LEFT_SUB_DISTRIB] THEN
MATCH_MP_TAC(ARITH_RULE
`b <= a /\ e <= d /\ (e + a + c = d + b)
==> ((a - b) + c = d - e:num)`) THEN
REPEAT CONJ_TAC THENL
[REWRITE_TAC[
LE_MULT_LCANCEL] THEN REPEAT DISJ2_TAC THEN
FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (ARITH_RULE
`(c = a - b) ==> 1 <= c ==> b <= a`)) THEN
SUBST1_TAC(SYM(SPEC `a:num` (el 1 (CONJUNCTS
Y_CLAUSES)))) THEN
MATCH_MP_TAC
Y_INCREASES_LE THEN
ASM_SIMP_TAC[ARITH_RULE `j <= n ==> (1 <= n - j <=> ~(j = n))`];
REWRITE_TAC[
LE_MULT_LCANCEL] THEN DISJ2_TAC THEN
FIRST_ASSUM(MATCH_MP_TAC o MATCH_MP (ARITH_RULE
`(c = a - b) ==> 1 <= c ==> b <= a`)) THEN
SUBST1_TAC(SYM(SPEC `a:num` (CONJUNCT1
X_CLAUSES))) THEN
MATCH_MP_TAC
X_INCREASES_LE THEN ASM_REWRITE_TAC[
LE_0];
REWRITE_TAC[ARITH_RULE
`xn * a * yj * yn + a * yn * xj * yn + xj =
xj * (a * yn * yn + 1) + a * yn * xn * yj`] THEN
ASM_SIMP_TAC[GSYM
XY_ARE_SOLUTIONS; GSYM
EXP_2] THEN
REWRITE_TAC[
EXP_2;
MULT_AC]]);;
let X_CONGRUENT_2NJ_NEG = prove
(`!a n j. ~(a = 0) /\ j <= 2 * n ==> ?q. X a (2 * n - j) + X a j = q * X a n`,
REPEAT STRIP_TAC THEN
ASM_CASES_TAC `j <= n:num` THEN ASM_SIMP_TAC[
X_CONGRUENT_2NJ_NEG_LEMMA] THEN
MP_TAC(SPECL [`a:num`; `n:num`; `2 * n - j`]
X_CONGRUENT_2NJ_NEG_LEMMA) THEN
ASM_SIMP_TAC[ARITH_RULE `~(j <= n) ==> 2 * n - j <= n`] THEN
ASM_SIMP_TAC[ARITH_RULE `y <= x ==> (x - (x - y) = y:num)`] THEN
SIMP_TAC[
ADD_AC]);;
(* ------------------------------------------------------------------------- *)
(* The cute GCD fact given by Smorynski. *)
(* ------------------------------------------------------------------------- *)
let XY_GCD_LEMMA = prove
(`!a m n. ~(a = 0) /\ m < n
==> (gcd(Y a m,Y a n) = Y a (gcd(m,n)))`,
GEN_TAC THEN ASM_CASES_TAC `a = 0` THEN ASM_REWRITE_TAC[] THEN
ASM_CASES_TAC `a = 1` THEN ASM_REWRITE_TAC[
Y_DEGENERATE] THEN
MATCH_MP_TAC
num_WF THEN X_GEN_TAC `m:num` THEN DISCH_TAC THEN
X_GEN_TAC `n:num` THEN DISCH_TAC THEN
MP_TAC(SPECL [`n:num`; `m:num`]
DIVISION) THEN
ASM_CASES_TAC `m = 0` THEN ASM_REWRITE_TAC[
Y_CLAUSES;
GCD_0] THEN
ABBREV_TAC `q = n DIV m` THEN ABBREV_TAC `r = n MOD m` THEN
DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN
FIRST_X_ASSUM(MP_TAC o SPEC `r:num`) THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN(MP_TAC o SPEC `m:num`) THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC EQ_IMP THEN BINOP_TAC THENL
[EXPAND_TAC "n" THEN ASM_SIMP_TAC[
ADDITION_FORMULA_POS] THEN
GEN_REWRITE_TAC LAND_CONV [
GCD_SYM] THEN MATCH_MP_TAC
GCD_EQ THEN
X_GEN_TAC `d:num` THEN CONV_TAC SYM_CONV THEN MATCH_MP_TAC(TAUT
`(a ==> (b <=> c)) ==> (a /\ b <=> a /\ c)`) THEN
DISCH_TAC THEN MATCH_MP_TAC
EQ_TRANS THEN
EXISTS_TAC `d divides (X a (q * m) * Y a r)` THEN CONJ_TAC THENL
[SUBGOAL_THEN `d divides (Y a (q * m))` MP_TAC THENL
[ASM_MESON_TAC[
Y_DIVIDES;
DIVIDES_TRANS;
DIVIDES_LMUL;
DIVIDES_REFL];
ALL_TAC] THEN
MESON_TAC[
DIVIDES_ADD;
DIVIDES_LMUL;
DIVIDES_RMUL;
DIVIDES_REFL;
DIVIDES_ADD_REVL];
ALL_TAC] THEN
EQ_TAC THEN SIMP_TAC[
DIVIDES_LMUL] THEN
SUBGOAL_THEN `coprime(d,X a (q * m))`
(fun th -> MESON_TAC[
COPRIME_DIVPROD; th]) THEN
SUBGOAL_THEN `d divides (Y a (q * m))` MP_TAC THENL
[ASM_MESON_TAC[
Y_DIVIDES;
DIVIDES_TRANS;
DIVIDES_LMUL;
DIVIDES_REFL];
ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `q * m:num`]
XY_COPRIME) THEN ASM_REWRITE_TAC[] THEN
DISCH_TAC THEN DISCH_TAC THEN REWRITE_TAC[coprime] THEN
X_GEN_TAC `e:num` THEN STRIP_TAC THEN
UNDISCH_TAC `coprime (X a (q * m),Y a (q * m))` THEN
REWRITE_TAC[coprime] THEN DISCH_THEN(MP_TAC o SPEC `e:num`) THEN
DISCH_THEN MATCH_MP_TAC THEN ASM_MESON_TAC[
DIVIDES_TRANS];
AP_TERM_TAC THEN EXPAND_TAC "n" THEN
GEN_REWRITE_TAC I [GSYM
DIVIDES_ANTISYM] THEN
POP_ASSUM_LIST(K ALL_TAC) THEN NUMBER_TAC]);;
let XY_GCD = prove
(`!a m n. ~(a = 0) ==> (gcd(Y a m,Y a n) = Y a (gcd(m,n)))`,
(* ------------------------------------------------------------------------- *)
(* The "step-down" lemma. *)
(* ------------------------------------------------------------------------- *)
let STEP_DOWN_LEMMA = prove
(`!a i j n q.
~(a = 0) /\ ~(a = 1) /\
i <= j /\ j <= 2 * n /\
(X a j = q * X a n + X a i)
==> (i = j) \/ ((a = 2) /\ (n = 1) /\ (i = 0) /\ (j = 2))`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `j <= n:num` THENL
[ASM_CASES_TAC `i = j:num` THEN ASM_REWRITE_TAC[] THEN
SUBGOAL_THEN `i < n:num` ASSUME_TAC THENL
[ASM_MESON_TAC[
LTE_TRANS;
LT_LE]; ALL_TAC] THEN
UNDISCH_TAC `X a j = q * X a n + X a i` THEN
ASM_CASES_TAC `q = 0` THEN
ASM_SIMP_TAC[
ADD_CLAUSES;
MULT_CLAUSES;
X_INJ] THEN
DISCH_TAC THEN
MP_TAC(SPECL [`a:num`; `j:num`; `n:num`]
X_INCREASES_LE) THEN
ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC(TAUT `~a ==> a ==> b`) THEN
MATCH_MP_TAC(ARITH_RULE `1 <= b /\ 1 * x <= qx ==> ~(qx + b <= x)`) THEN
SIMP_TAC[
LE_MULT_RCANCEL] THEN
ASM_SIMP_TAC[ARITH_RULE `~(x = 0) ==> 1 <= x`] THEN
ONCE_REWRITE_TAC[GSYM(CONJUNCT1
X_CLAUSES)] THEN
ASM_SIMP_TAC[
X_INCREASES_LE;
LE_0]; ALL_TAC] THEN
ASM_CASES_TAC `n = 0` THENL
[UNDISCH_TAC `i <= j:num` THEN UNDISCH_TAC `j <= 2 * n` THEN
ASM_SIMP_TAC[
LE;
MULT_CLAUSES]; ALL_TAC] THEN
ASM_CASES_TAC `i <= n:num` THENL
[MP_TAC(SPECL [`a:num`; `n:num`; `j:num`]
X_CONGRUENT_2NJ_NEG) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `q1:num` MP_TAC) THEN
UNDISCH_TAC `X a j = q * X a n + X a i` THEN
ASM_CASES_TAC `q = 0` THEN
ASM_SIMP_TAC[
ADD_CLAUSES;
MULT_CLAUSES;
X_INJ] THEN DISCH_TAC THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(a + b + c = d:num) ==> (a + c = d - b)`)) THEN
REWRITE_TAC[GSYM
RIGHT_SUB_DISTRIB] THEN
ASM_CASES_TAC `i = n:num` THENL
[ASM_REWRITE_TAC[] THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(x + n = q * n) ==> (x = q * n - 1 * n)`)) THEN
MATCH_MP_TAC(TAUT `~a ==> a ==> b`) THEN
REWRITE_TAC[GSYM
RIGHT_SUB_DISTRIB] THEN
ASM_CASES_TAC `q1 - q - 1 = 0` THENL
[ASM_REWRITE_TAC[
MULT_CLAUSES; ARITH_RULE `~(n = 0) <=> 1 <= n`] THEN
ONCE_REWRITE_TAC[GSYM(CONJUNCT1
X_CLAUSES)] THEN
ASM_SIMP_TAC[
X_INCREASES_LE;
LE_0]; ALL_TAC] THEN
MATCH_MP_TAC(ARITH_RULE
`j < n /\ 1 * n <= a * n ==> ~(j = a * n)`) THEN
ASM_SIMP_TAC[
LE_MULT_RCANCEL; ARITH_RULE `~(x = 0) ==> 1 <= x`] THEN
MATCH_MP_TAC
X_INCREASES_LT THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `~(j <= n:num)` THEN
UNDISCH_TAC `~(n = 0)` THEN ARITH_TAC; ALL_TAC] THEN
ASM_CASES_TAC `q1 - q = 0` THENL
[ASM_REWRITE_TAC[
MULT_CLAUSES;
ADD_EQ_0] THEN
MATCH_MP_TAC(TAUT `~c ==> a /\ c ==> b`) THEN
REWRITE_TAC[ARITH_RULE `~(n = 0) <=> 1 <= n`] THEN
ONCE_REWRITE_TAC[GSYM(CONJUNCT1
X_CLAUSES)] THEN
ASM_SIMP_TAC[
X_INCREASES_LE;
LE_0]; ALL_TAC] THEN
MATCH_MP_TAC(TAUT `(~b ==> a ==> c) ==> a ==> b \/ c`) THEN
DISCH_TAC THEN DISCH_TAC THEN
ASM_CASES_TAC `n = 1` THENL
[UNDISCH_TAC `j <= 2 * n` THEN ASM_REWRITE_TAC[
MULT_CLAUSES] THEN
UNDISCH_TAC `~(j <= n:num)` THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[IMP_IMP] THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`~(j <= 1) /\ j <= 2 ==> (j = 2)`)) THEN
DISCH_THEN SUBST_ALL_TAC THEN REWRITE_TAC[] THEN
UNDISCH_THEN `n = 1` SUBST_ALL_TAC THEN
SUBGOAL_THEN `i = 0` SUBST_ALL_TAC THENL
[MAP_EVERY UNDISCH_TAC [`i <= 1`; `~(i = 1)`] THEN ARITH_TAC;
ALL_TAC] THEN
UNDISCH_TAC `X a (2 * 1 - 2) + X a 0 = (q1 - q) * X a 1` THEN
REWRITE_TAC[ARITH;
X_CLAUSES] THEN DISCH_THEN(ASSUME_TAC o SYM) THEN
MATCH_MP_TAC(ARITH_RULE
`~(a = 0) /\ ~(a = 1) /\ a <= 2 ==> (a = 2)`) THEN
ASM_REWRITE_TAC[] THEN
UNDISCH_THEN `(q1 - q) * a = 2` (SUBST1_TAC o SYM) THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = 1 * a`] THEN
REWRITE_TAC[
LE_MULT_RCANCEL] THEN
ASM_SIMP_TAC[ARITH_RULE `~(q = 0) ==> 1 <= q`]; ALL_TAC] THEN
UNDISCH_TAC `X a (2 * n - j) + X a i = (q1 - q) * X a n` THEN
MATCH_MP_TAC(TAUT `~b ==> b ==> a`) THEN
MATCH_MP_TAC(ARITH_RULE
`s < x /\ x <= q * x ==> ~(s = q * x:num)`) THEN
CONJ_TAC THENL
[ALL_TAC;
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `a = 1 * a`] THEN
REWRITE_TAC[
LE_MULT_RCANCEL] THEN
ASM_SIMP_TAC[ARITH_RULE `~(q = 0) ==> 1 <= q`]] THEN
MATCH_MP_TAC
LET_TRANS THEN
EXISTS_TAC `2 * X a (n - 1)` THEN CONJ_TAC THENL
[MATCH_MP_TAC(ARITH_RULE `a <= c /\ b <= c ==> a + b <= 2 * c`) THEN
CONJ_TAC THEN MATCH_MP_TAC
X_INCREASES_LE THEN ASM_REWRITE_TAC[] THENL
[UNDISCH_TAC `~(n = 0)` THEN UNDISCH_TAC `~(j <= n:num)` THEN ARITH_TAC;
UNDISCH_TAC `~(i = n:num)` THEN UNDISCH_TAC `i <= n:num` THEN
ARITH_TAC];
ALL_TAC] THEN
SUBGOAL_THEN `n - 1 = (n - 2) + 1` SUBST1_TAC THENL
[UNDISCH_TAC `~(n = 0)` THEN UNDISCH_TAC `~(n = 1)` THEN ARITH_TAC;
ALL_TAC] THEN
SUBGOAL_THEN `n = (n - 2) + 2`
(fun th -> GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [th])
THENL
[UNDISCH_TAC `~(n = 0)` THEN UNDISCH_TAC `~(n = 1)` THEN ARITH_TAC;
ALL_TAC] THEN
REWRITE_TAC[
X_CLAUSES] THEN
MATCH_MP_TAC(ARITH_RULE `z < x /\ 3 * x <= y ==> 2 * x < y - z`) THEN
ASM_SIMP_TAC[
X_INCREASES_LT; ARITH_RULE `n < n + 1`] THEN
REWRITE_TAC[
MULT_ASSOC;
LE_MULT_RCANCEL] THEN DISJ1_TAC THEN
UNDISCH_TAC `~(a = 1)` THEN UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC;
ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `n:num`; `j:num`]
X_CONGRUENT_2NJ_NEG) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `q1:num` MP_TAC) THEN
MP_TAC(SPECL [`a:num`; `n:num`; `i:num`]
X_CONGRUENT_2NJ_NEG) THEN
ANTS_TAC THENL
[ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[
LE_TRANS]; ALL_TAC] THEN
DISCH_THEN(X_CHOOSE_THEN `q2:num` MP_TAC) THEN
ASM_REWRITE_TAC[] THEN
REWRITE_TAC[IMP_IMP] THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(a = b) /\ (c = d) ==> (a + d = b + c:num)`)) THEN
REWRITE_TAC[ARITH_RULE
`((x + i) + q1 = q2 + y + q3 + i) <=> (x + q1 = y + q2 + q3:num)`] THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(x + q1 = y + q2) ==> y <= x ==> (x = y + (q2 - q1:num))`)) THEN
ANTS_TAC THENL
[MATCH_MP_TAC
X_INCREASES_LE THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `i <= j:num` THEN ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[GSYM
RIGHT_ADD_DISTRIB; GSYM
RIGHT_SUB_DISTRIB] THEN
ASM_CASES_TAC `(q2 + q) - q1 = 0` THENL
[ASM_SIMP_TAC[
ADD_CLAUSES;
MULT_CLAUSES;
X_INJ] THEN
MATCH_MP_TAC(TAUT `(a ==> b) ==> (a ==> b \/ c)`) THEN
UNDISCH_TAC `j <= 2 * n` THEN UNDISCH_TAC `i <= j:num` THEN ARITH_TAC;
ALL_TAC] THEN
MATCH_MP_TAC(TAUT `~a ==> a ==> b`) THEN
MATCH_MP_TAC(ARITH_RULE
`1 * xi <= qxn /\ 1 <= xj ==> ~(xi = xj + qxn)`) THEN
CONJ_TAC THENL
[MATCH_MP_TAC
LE_MULT2 THEN
ASM_REWRITE_TAC[ARITH_RULE `1 <= a <=> ~(a = 0)`] THEN
MATCH_MP_TAC
X_INCREASES_LE THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `~(i <= n:num)` THEN ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[GSYM(CONJUNCT1
X_CLAUSES)] THEN
MATCH_MP_TAC
X_INCREASES_LE THEN ASM_REWRITE_TAC[
LE_0]);;
let STEP_DOWN_LEMMA_4_ASYM = prove
(`!a i j n q.
~(a = 0) /\ ~(a = 1) /\
0 < i /\ i <= n /\ j < 4 * n /\
(X a i + q * X a n = X a j)
==> (j = i) \/ (j = 4 * n - i)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `j <= 2 * n` THENL
[MP_TAC(SPECL [`a:num`; `i:num`; `j:num`; `n:num`; `q:num`]
STEP_DOWN_LEMMA) THEN
ANTS_TAC THENL
[ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `X a i + q * X a n = X a j` THEN
SIMP_TAC[
ADD_AC;
MULT_AC] THEN DISCH_THEN(ASSUME_TAC o SYM) THEN
SUBGOAL_THEN `X a i <= X a j` MP_TAC THENL
[ASM_REWRITE_TAC[ONCE_REWRITE_RULE[
ADD_SYM]
LE_ADD]; ALL_TAC] THEN
ONCE_REWRITE_TAC[TAUT `a ==> b <=> ~b ==> ~a`] THEN
ASM_SIMP_TAC[
X_INCREASES_LT;
NOT_LE]; ALL_TAC] THEN
ASM_SIMP_TAC[ARITH_RULE `0 < i ==> ~(i = 0)`]; ALL_TAC] THEN
DISJ_CASES_TAC(SPECL [`i:num`; `4 * n - j`]
LE_CASES) THEN
(MP_TAC(SPECL [`a:num`; `n:num`; `2 * n - (4 * n - j)`]
X_CONGRUENT_2NJ_POS) THEN
MP_TAC(SPECL [`a:num`; `n:num`; `4 * n - j`]
X_CONGRUENT_2NJ_NEG) THEN
ASM_SIMP_TAC[ARITH_RULE `~(j <= 2 * n) ==> 4 * n - j <= 2 * n`] THEN
ASM_SIMP_TAC[ARITH_RULE
`j < 4 * n /\ ~(j <= 2 * n)
==> (2 * n + 2 * n - (4 * n - j) = j)`] THEN
DISCH_THEN(X_CHOOSE_THEN `q1:num` ASSUME_TAC) THEN
DISCH_THEN(X_CHOOSE_THEN `q2:num` MP_TAC) THEN
SUBST1_TAC(SYM(ASSUME `X a i + q * X a n = X a j`)) THEN
UNDISCH_TAC
`X a (2 * n - (4 * n - j)) + X a (4 * n - j) = q1 * X a n` THEN
REWRITE_TAC[IMP_IMP] THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(a + b = c) /\ (d + a = e) ==> (b + e = c + d:num)`)))
THENL
[DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(x + q1 = q2 + y + q3)
==> y <= x ==> (x = ((q2 + q3) - q1) + y:num)`));
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(x + q1 = q2 + y + q3)
==> x <= y ==> (y = (q1 - (q2 + q3)) + x:num)`))] THEN
REWRITE_TAC[GSYM
RIGHT_SUB_DISTRIB; GSYM
RIGHT_ADD_DISTRIB] THEN
ASM_SIMP_TAC[
X_INCREASES_LE] THEN DISCH_TAC THENL
[MP_TAC(SPECL [`a:num`; `i:num`; `4 * n - j`; `n:num`; `(q1 + q) - q2:num`]
STEP_DOWN_LEMMA) THEN
ANTS_TAC THENL
[ASM_REWRITE_TAC[] THEN UNDISCH_TAC `~(j <= 2 * n)` THEN ARITH_TAC;
ALL_TAC] THEN
ASM_SIMP_TAC[ARITH_RULE `0 < i ==> ~(i = 0)`] THEN
DISCH_TAC THEN DISJ2_TAC THEN UNDISCH_TAC `j < 4 * n` THEN ARITH_TAC;
MP_TAC(SPECL [`a:num`; `4 * n - j`; `i:num`; `n:num`; `q2:num - (q1 + q)`]
STEP_DOWN_LEMMA) THEN
ANTS_TAC THENL
[ASM_REWRITE_TAC[] THEN UNDISCH_TAC `i <= n:num` THEN ARITH_TAC;
ALL_TAC] THEN
ASM_REWRITE_TAC[
SUB_EQ_0; GSYM
NOT_LT] THEN
DISCH_THEN(SUBST1_TAC o SYM) THEN
DISJ2_TAC THEN UNDISCH_TAC `j < 4 * n` THEN ARITH_TAC]);;
let STEP_DOWN_LEMMA_4 = prove
(`!a i j n q1 q2.
~(a = 0) /\ ~(a = 1) /\
0 < i /\ i <= n /\ j < 4 * n /\
(X a i + q1 * X a n = X a j + q2 * X a n)
==> (j = i) \/ (j = 4 * n - i)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `j < i:num` THENL
[UNDISCH_TAC `X a i + q1 * X a n = X a j + q2 * X a n` THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(x + q1 = y + q2) ==> y < x ==> (x = y + (q2 - q1:num))`)) THEN
ASM_SIMP_TAC[
X_INCREASES_LT; GSYM
RIGHT_SUB_DISTRIB] THEN
ASM_CASES_TAC `q2 - q1 = 0` THENL
[ASM_SIMP_TAC[
MULT_CLAUSES;
ADD_CLAUSES;
X_INJ]; ALL_TAC] THEN
MATCH_MP_TAC(TAUT `~a ==> a ==> b`) THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(i = j + q * n) ==> 1 <= j /\ 1 * n <= q * n ==> ~(i <= n)`)) THEN
ASM_SIMP_TAC[
X_INCREASES_LE] THEN
ASM_SIMP_TAC[
LE_MULT_RCANCEL;
ARITH_RULE `~(q2 - q1 = 0) ==> 1 <= q2 - q1`] THEN
ONCE_REWRITE_TAC[GSYM(CONJUNCT1
X_CLAUSES)] THEN
ASM_SIMP_TAC[
X_INCREASES_LE;
LE_0]; ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `i:num`; `j:num`; `n:num`; `q1 - q2:num`]
STEP_DOWN_LEMMA_4_ASYM) THEN
DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[
RIGHT_SUB_DISTRIB] THEN
MATCH_MP_TAC(ARITH_RULE
`(i + q1 = j + q2) /\ ~(j < i) ==> (i + q1 - q2 = j:num)`) THEN
RULE_ASSUM_TAC(REWRITE_RULE[
NOT_LT]) THEN
ASM_SIMP_TAC[
NOT_LT;
X_INCREASES_LE]);;
let STEP_DOWN_LEMMA_STRONG_ASYM = prove
(`!a i j n c.
~(a = 0) /\ ~(a = 1) /\
0 < i /\ i <= n /\
(X a i + c * X a n = X a j)
==> (?q. j = i + 4 * n * q) \/
(?q. j + i = 4 * n * q)`,
REPEAT STRIP_TAC THEN
MP_TAC(SPECL [`j:num`; `4 * n`]
DIVISION) THEN
ABBREV_TAC `q = j DIV (4 * n)` THEN ABBREV_TAC `k = j MOD (4 * n)` THEN
ANTS_TAC THENL
[UNDISCH_TAC `0 < i` THEN UNDISCH_TAC `i <= n:num` THEN ARITH_TAC;
ALL_TAC] THEN
DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN
MP_TAC(SPECL [`a:num`; `q:num`; `n:num`; `k:num`]
X_CONGRUENT_4MNJ_POS) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `q1:num` MP_TAC) THEN
SUBST1_TAC(ARITH_RULE `4 * q * n + k = q * 4 * n + k`) THEN
ASM_REWRITE_TAC[] THEN DISCH_THEN SUBST_ALL_TAC THEN
ASM_CASES_TAC `k < i:num` THENL
[UNDISCH_TAC `X a i + c * X a n = q1 * X a n + X a k` THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(a + q1 = q2 + b) ==> b < a ==> (a = (q2 - q1) + b:num)`)) THEN
ASM_SIMP_TAC[
X_INCREASES_LT] THEN REWRITE_TAC[GSYM
RIGHT_SUB_DISTRIB] THEN
ASM_CASES_TAC `q1 - c = 0` THENL
[ASM_SIMP_TAC[
MULT_CLAUSES;
ADD_CLAUSES;
X_INJ] THEN
DISCH_TAC THEN DISJ1_TAC THEN EXISTS_TAC `q:num` THEN
FIRST_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [SYM th]) THEN
REWRITE_TAC[
ADD_AC;
MULT_AC];
MATCH_MP_TAC(TAUT `~a ==> a ==> b`) THEN
MATCH_MP_TAC(ARITH_RULE
`a <= b /\ 1 <= c ==> ~(a = b + c)`) THEN
CONJ_TAC THENL
[GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `n = 1 * n`] THEN
MATCH_MP_TAC
LE_MULT2 THEN
ASM_REWRITE_TAC[ARITH_RULE `1 <= n <=> ~(n = 0)`] THEN
ASM_SIMP_TAC[
X_INCREASES_LE;
LT_IMP_LE];
SUBST1_TAC(SYM(SPEC `a:num` (CONJUNCT1
X_CLAUSES))) THEN
ASM_SIMP_TAC[
X_INCREASES_LE;
LE_0]]];
MP_TAC(SPECL [`a:num`; `i:num`; `k:num`; `n:num`; `c - q1:num`]
STEP_DOWN_LEMMA_4_ASYM) THEN
ANTS_TAC THENL
[ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `X a i + c * X a n = q1 * X a n + X a k` THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(a + q1 = q2 + b) ==> ~(b < a) ==> (a + (q1 - q2)= b:num)`)) THEN
REWRITE_TAC[GSYM
RIGHT_SUB_DISTRIB] THEN
DISCH_THEN MATCH_MP_TAC THEN REWRITE_TAC[
NOT_LT] THEN
MATCH_MP_TAC
X_INCREASES_LE THEN ASM_REWRITE_TAC[GSYM
NOT_LT];
ALL_TAC] THEN
DISCH_THEN DISJ_CASES_TAC THENL
[DISJ1_TAC THEN EXISTS_TAC `q:num` THEN
UNDISCH_THEN `q * 4 * n + k = j` (SUBST1_TAC o SYM) THEN
ASM_REWRITE_TAC[
MULT_AC;
ADD_AC];
DISJ2_TAC THEN EXISTS_TAC `q + 1` THEN
UNDISCH_THEN `q * 4 * n + k = j` (SUBST1_TAC o SYM) THEN
REWRITE_TAC[GSYM
ADD_ASSOC;
LEFT_ADD_DISTRIB;
MULT_CLAUSES] THEN
ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC(ARITH_RULE
`(a' = a) /\ i <= b ==> (a + (b - i) + i = a' + b:num)`) THEN
REWRITE_TAC[
MULT_AC] THEN
UNDISCH_TAC `i <= n:num` THEN ARITH_TAC]]);;
let STEP_DOWN_LEMMA_STRONG = prove
(`!a i j n c1 c2.
~(a = 0) /\ ~(a = 1) /\ 0 < i /\ i <= n /\
(X a i + c1 * X a n = X a j + c2 * X a n)
==> (?q. j = i + 4 * n * q) \/
(?q. j + i = 4 * n * q)`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `j < i:num` THENL
[UNDISCH_TAC `X a i + c1 * X a n = X a j + c2 * X a n` THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(x + q1 = y + q2) ==> y < x ==> (x = y + (q2 - q1:num))`)) THEN
ASM_SIMP_TAC[
X_INCREASES_LT; GSYM
RIGHT_SUB_DISTRIB] THEN
ASM_CASES_TAC `c2 - c1 = 0` THENL
[ASM_SIMP_TAC[
MULT_CLAUSES;
ADD_CLAUSES;
X_INJ] THEN
DISCH_THEN(K ALL_TAC) THEN DISJ1_TAC THEN
EXISTS_TAC `0` THEN REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES];
ALL_TAC] THEN
MATCH_MP_TAC(TAUT `~a ==> a ==> b`) THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(i = j + q * n) ==> 1 <= j /\ 1 * n <= q * n ==> ~(i <= n)`)) THEN
ASM_SIMP_TAC[
X_INCREASES_LE] THEN
ASM_SIMP_TAC[
LE_MULT_RCANCEL;
ARITH_RULE `~(q2 - q1 = 0) ==> 1 <= q2 - q1`] THEN
ONCE_REWRITE_TAC[GSYM(CONJUNCT1
X_CLAUSES)] THEN
ASM_SIMP_TAC[
X_INCREASES_LE;
LE_0]; ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `i:num`; `j:num`; `n:num`; `c1 - c2:num`]
STEP_DOWN_LEMMA_STRONG_ASYM) THEN
DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[
RIGHT_SUB_DISTRIB] THEN
MATCH_MP_TAC(ARITH_RULE
`(i + q1 = j + q2) /\ ~(j < i) ==> (i + q1 - q2 = j:num)`) THEN
RULE_ASSUM_TAC(REWRITE_RULE[
NOT_LT]) THEN
ASM_SIMP_TAC[
NOT_LT;
X_INCREASES_LE]);;
(* ------------------------------------------------------------------------- *)
(* Diophantine nature of the Y sequence. *)
(* ------------------------------------------------------------------------- *)
let Y_DIOPH = prove
(`~(a = 0) /\ ~(a = 1) /\ ~(y = 0)
==> ((y = Y a k) <=>
?x u v r b p q s t c d.
0 < r /\
(x
EXP 2 = (a
EXP 2 - 1) * y
EXP 2 + 1) /\
(u
EXP 2 = (a
EXP 2 - 1) * v
EXP 2 + 1) /\
(s
EXP 2 = (b
EXP 2 - 1) * t
EXP 2 + 1) /\
(v = r * y
EXP 2) /\
(b = 1 + 4 * p * y) /\
(b = a + q * u) /\
(s = x + c * u) /\
(t = k + 4 * d * y) /\
k <= y)`,
REPEAT STRIP_TAC THEN EQ_TAC THENL
[ALL_TAC;
DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN
MP_TAC(SPECL [`a:num`; `x:num`; `y:num`]
SOLUTIONS_ARE_XY) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `i:num` (STRIP_ASSUME_TAC o GSYM)) THEN
MP_TAC(SPECL [`a:num`; `u:num`; `v:num`]
SOLUTIONS_ARE_XY) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `n:num` (STRIP_ASSUME_TAC o GSYM)) THEN
SUBGOAL_THEN `~(b = 0)` ASSUME_TAC THENL
[SUBST1_TAC(SYM(ASSUME `1 + 4 * p * y = b`)) THEN
REWRITE_TAC[
ADD_EQ_0;
ARITH_EQ]; ALL_TAC] THEN
MP_TAC(SPECL [`b:num`; `s:num`; `t:num`]
SOLUTIONS_ARE_XY) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `j:num` (STRIP_ASSUME_TAC o GSYM)) THEN
SUBGOAL_THEN `y <= v:num` ASSUME_TAC THENL
[SUBST1_TAC(SYM(ASSUME `r * y
EXP 2 = v`)) THEN REWRITE_TAC[
EXP_2] THEN
GEN_REWRITE_TAC LAND_CONV [ARITH_RULE `y = 1 * y`] THEN
REWRITE_TAC[
MULT_ASSOC;
LE_MULT_RCANCEL] THEN DISJ1_TAC THEN
ASM_REWRITE_TAC[ARITH_RULE `1 <= a <=> ~(a = 0)`;
MULT_EQ_0] THEN
ASM_SIMP_TAC[ARITH_RULE `0 < r ==> ~(r = 0)`]; ALL_TAC] THEN
SUBGOAL_THEN `i <= n:num` ASSUME_TAC THENL
[UNDISCH_TAC `y <= v:num` THEN
SUBST1_TAC(SYM(ASSUME `Y a i = y`)) THEN
SUBST1_TAC(SYM(ASSUME `Y a n = v`)) THEN
ONCE_REWRITE_TAC[TAUT `a ==> b <=> ~b ==> ~a`] THEN
ASM_SIMP_TAC[
NOT_LE;
Y_INCREASES_LT]; ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `q:num`; `u:num`; `j:num`]
X_CONGRUENT) THEN
REWRITE_TAC[ASSUME `~(a = 0)`; ASSUME `a + q * u = b:num`] THEN
DISCH_THEN(X_CHOOSE_THEN `q1:num` MP_TAC) THEN
SUBST1_TAC(ASSUME `X b j = s`) THEN
SUBST1_TAC(SYM(ASSUME `x + c * u = s:num`)) THEN
SUBST1_TAC(SYM(ASSUME `X a i = x`)) THEN
SUBST1_TAC(SYM(ASSUME `X a n = u`)) THEN DISCH_TAC THEN
SUBGOAL_THEN `~(i = 0)` ASSUME_TAC THENL
[UNDISCH_TAC `~(y = 0)` THEN
REWRITE_TAC[TAUT `~a ==> ~b <=> b ==> a`] THEN
EXPAND_TAC "y" THEN SIMP_TAC[
Y_CLAUSES; ASSUME `~(a = 0)`];
ALL_TAC] THEN
SUBGOAL_THEN `(?q. j = i + 4 * n * q) \/ (?q. j + i = 4 * n * q)`
ASSUME_TAC THENL
[MATCH_MP_TAC
STEP_DOWN_LEMMA_STRONG THEN
MAP_EVERY EXISTS_TAC [`a:num`; `c:num`; `q1:num`] THEN
ASM_SIMP_TAC[ARITH_RULE `~(i = 0) ==> 0 < i`]; ALL_TAC] THEN
MP_TAC(SPECL [`a:num`; `i:num`; `n:num`]
Y2_DIVIDES) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(MP_TAC o fst o EQ_IMP_RULE) THEN
REWRITE_TAC[divides;
LEFT_IMP_EXISTS_THM] THEN
DISCH_THEN(MP_TAC o SPEC `r:num`) THEN
SUBST1_TAC(SYM(ASSUME `r * y
EXP 2 = v`)) THEN
REWRITE_TAC[EQT_INTRO(SPEC_ALL
MULT_SYM)] THEN
DISCH_THEN(X_CHOOSE_THEN `d1:num` (ASSUME_TAC o SYM)) THEN
UNDISCH_TAC `(?q. j = i + 4 * n * q) \/ (?q. j + i = 4 * n * q:num)` THEN
UNDISCH_THEN `(i * y) * d1 = n:num` (SUBST1_TAC o SYM) THEN DISCH_TAC THEN
SUBGOAL_THEN `(?q. j = i + q * 4 * Y a i) \/
(?q. j + i = q * 4 * Y a i)`
MP_TAC THENL
[FIRST_ASSUM(UNDISCH_TAC o check is_disj o concl) THEN
REWRITE_TAC[
OR_EXISTS_THM] THEN
DISCH_THEN(X_CHOOSE_THEN `d2:num`
(fun th -> EXISTS_TAC `i * d1 * d2:num` THEN MP_TAC th)) THEN
SUBST1_TAC(ASSUME `Y a i = y`) THEN REWRITE_TAC[
MULT_AC];
FIRST_X_ASSUM(K ALL_TAC o check (is_disj o concl)) THEN
DISCH_TAC] THEN
MP_TAC(SPECL [`b:num`; `j:num`]
Y_N_MODA1) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `d3:num` MP_TAC) THEN
SUBST1_TAC(SYM(ASSUME `1 + 4 * p * y = b`)) THEN REWRITE_TAC[
ADD_SUB2] THEN
SUBST1_TAC(SYM(ASSUME `k + 4 * d * y = t`)) THEN DISCH_TAC THEN
SUBST1_TAC(SYM(ASSUME `Y a i = y`)) THEN AP_TERM_TAC THEN
SUBGOAL_THEN `(?q1 q2. k + q1 * 4 * Y a i = i + q2 * 4 * Y a i) \/
(?q. i + k = q * 4 * Y a i)`
MP_TAC THENL
[UNDISCH_TAC `(?q. j = i + q * 4 * Y a i) \/
(?q. j + i = q * 4 * Y a i)` THEN
MATCH_MP_TAC(TAUT
`(a1 ==> b1) /\ (a2 ==> b2) ==> a1 \/ a2 ==> b1 \/ b2`) THEN
CONJ_TAC THEN DISCH_TAC THEN
UNDISCH_TAC `k + 4 * d * y = d3 * 4 * p * y + j` THENL
[FIRST_X_ASSUM(X_CHOOSE_THEN `d4:num` SUBST1_TAC) THEN
DISCH_THEN(fun th ->
EXISTS_TAC `d:num` THEN
EXISTS_TAC `d3 * p + d4:num` THEN MP_TAC th) THEN
SUBST1_TAC(SYM(ASSUME `Y a i = y`)) THEN
REWRITE_TAC[
RIGHT_ADD_DISTRIB] THEN
REWRITE_TAC[
MULT_AC] THEN REWRITE_TAC[
ADD_AC];
DISCH_THEN(MP_TAC o C AP_THM `i:num` o
AP_TERM `(+):num->num->num`) THEN
REWRITE_TAC[GSYM
ADD_ASSOC] THEN
FIRST_X_ASSUM(X_CHOOSE_THEN `d4:num` SUBST1_TAC) THEN
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(k + q1 + i = q2) ==> (i + k = q2 - q1:num)`)) THEN
DISCH_THEN SUBST1_TAC THEN
SUBST1_TAC(SYM(ASSUME `Y a i = y`)) THEN
REWRITE_TAC[GSYM
RIGHT_ADD_DISTRIB;
MULT_ASSOC;
GSYM
RIGHT_SUB_DISTRIB] THEN
REWRITE_TAC[GSYM
MULT_ASSOC] THEN
REWRITE_TAC[ARITH_RULE
`(d3 * 4 * p + d4 * 4) - 4 * x =
((d3 * p + d4) - x) * 4`] THEN REWRITE_TAC[GSYM
MULT_ASSOC] THEN
EXISTS_TAC `(d3 * p + d4) - d:num` THEN REFL_TAC];
ALL_TAC] THEN
SUBGOAL_THEN `k <= Y a i` ASSUME_TAC THENL
[ASM_REWRITE_TAC[]; ALL_TAC] THEN
SUBGOAL_THEN `i <= Y a i` ASSUME_TAC THENL
[MP_TAC(SPECL [`a:num`; `i:num`]
Y_N_MODA1) THEN
ASM_SIMP_TAC[
LEFT_IMP_EXISTS_THM] THEN
REWRITE_TAC[ONCE_REWRITE_RULE[
ADD_SYM]
LE_ADD]; ALL_TAC] THEN
DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL
[DISCH_THEN(X_CHOOSE_THEN `q4:num` (X_CHOOSE_THEN `q5:num` MP_TAC)) THEN
REPEAT_TCL DISJ_CASES_THEN ASSUME_TAC
(SPECL [`q4:num`; `q5:num`]
LT_CASES)
THENL
[DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(k + q4 = i + q5) ==> q4 < q5:num ==> (k = i + (q5 - q4))`)) THEN
REWRITE_TAC[
MULT_ASSOC;
LT_MULT_RCANCEL; GSYM
RIGHT_SUB_DISTRIB] THEN
ASM_REWRITE_TAC[
MULT_EQ_0;
ARITH_EQ] THEN
UNDISCH_TAC `k <= y:num` THEN
MATCH_MP_TAC(TAUT `(a ==> ~b) ==> b ==> a ==> c`) THEN
DISCH_THEN SUBST1_TAC THEN
MATCH_MP_TAC(ARITH_RULE `1 * y < k * y ==> ~(i + k * y <= y)`) THEN
ASM_REWRITE_TAC[
LT_MULT_RCANCEL] THEN
UNDISCH_TAC `q4 < q5:num` THEN ARITH_TAC;
DISCH_THEN(MP_TAC o MATCH_MP (ARITH_RULE
`(k + q4 = i + q5) ==> q5 < q4:num ==> (i = k + (q4 - q5))`)) THEN
REWRITE_TAC[
MULT_ASSOC;
LT_MULT_RCANCEL; GSYM
RIGHT_SUB_DISTRIB] THEN
ASM_REWRITE_TAC[
MULT_EQ_0;
ARITH_EQ] THEN
UNDISCH_TAC `i <= Y a i` THEN
MATCH_MP_TAC(TAUT `(a ==> ~b) ==> b ==> a ==> c`) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN SUBST1_TAC THEN
MATCH_MP_TAC(ARITH_RULE `1 * y < k * y ==> ~(i + k * y <= y)`) THEN
ASM_REWRITE_TAC[
LT_MULT_RCANCEL] THEN
UNDISCH_TAC `q5 < q4:num` THEN ARITH_TAC;
ASM_SIMP_TAC[
EQ_ADD_RCANCEL]];
DISCH_THEN(X_CHOOSE_THEN `q6:num` MP_TAC) THEN
ASM_CASES_TAC `q6 = 0` THEN ASM_REWRITE_TAC[
MULT_CLAUSES;
ADD_EQ_0] THEN
UNDISCH_TAC `k <= Y a i` THEN UNDISCH_TAC `i <= Y a i` THEN
SUBST1_TAC(ASSUME `Y a i = y`) THEN
MATCH_MP_TAC(ARITH_RULE
`2 * y < ay ==> i <= y ==> k <= y ==> (i + k = ay) ==> (i = k)`) THEN
REWRITE_TAC[
MULT_ASSOC;
LT_MULT_RCANCEL] THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `~(q6 = 0)` THEN ARITH_TAC]] THEN
DISCH_THEN(ASSUME_TAC o SYM) THEN ABBREV_TAC `x = X a k` THEN
SUBGOAL_THEN `x
EXP 2 = (a
EXP 2 - 1) * y
EXP 2 + 1` (ASSUME_TAC o SYM) THENL
[MAP_EVERY EXPAND_TAC ["x";
"y"] THEN
SIMP_TAC[XY_ARE_SOLUTIONS; ASSUME `~(a = 0)`]; ALL_TAC] THEN
EXISTS_TAC `x:num` THEN ASM_REWRITE_TAC[] THEN
ABBREV_TAC `m = 2 * k * Y a k` THEN
ABBREV_TAC `u = X a m` THEN ABBREV_TAC `v = Y a m` THEN
SUBGOAL_THEN `u EXP 2 = (a EXP 2 - 1) * v EXP 2 + 1` (ASSUME_TAC o SYM) THENL
[MAP_EVERY EXPAND_TAC ["u"; "v"] THEN
SIMP_TAC[XY_ARE_SOLUTIONS; ASSUME `~(a = 0)`]; ALL_TAC] THEN
EXISTS_TAC `u:num` THEN EXISTS_TAC `v:num` THEN ASM_REWRITE_TAC[] THEN
SUBGOAL_THEN `(y EXP 2) divides v` MP_TAC THENL
[SUBST1_TAC(SYM(ASSUME `Y a m = v`)) THEN
SUBST1_TAC(SYM(ASSUME `Y a k = y`)) THEN
SIMP_TAC[Y2_DIVIDES; ASSUME `~(a = 0)`] THEN
SUBST1_TAC(SYM(ASSUME `2 * k * Y a k = m`)) THEN
REWRITE_TAC[divides] THEN EXISTS_TAC `2` THEN
REWRITE_TAC[MULT_AC]; ALL_TAC] THEN
REWRITE_TAC[divides] THEN
DISCH_THEN(X_CHOOSE_THEN `r:num` (ASSUME_TAC o SYM)) THEN
EXISTS_TAC `r:num` THEN ASM_REWRITE_TAC[] THEN
ASM_CASES_TAC `r = 0` THENL
[UNDISCH_TAC `y EXP 2 * r = v` THEN ASM_REWRITE_TAC[MULT_CLAUSES] THEN
DISCH_THEN(ASSUME_TAC o SYM) THEN REWRITE_TAC[LT_REFL] THEN
UNDISCH_TAC `Y a m = v` THEN ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
SUBGOAL_THEN `m = 0` ASSUME_TAC THENL
[UNDISCH_TAC `Y a m = 0` THEN
ONCE_REWRITE_TAC[GSYM(CONJUNCT1 Y_CLAUSES)] THEN
SIMP_TAC[Y_INJ; ASSUME `~(a = 0)`] THEN
REWRITE_TAC[Y_CLAUSES]; ALL_TAC] THEN
SUBGOAL_THEN `k = 0` ASSUME_TAC THENL
[UNDISCH_TAC `2 * k * Y a k = m` THEN
REWRITE_TAC[ASSUME `m = 0`; MULT_EQ_0; ARITH_EQ] THEN
ONCE_REWRITE_TAC[GSYM(CONJUNCT1 Y_CLAUSES)] THEN
SIMP_TAC[Y_INJ; ASSUME `~(a = 0)`] THEN
REWRITE_TAC[Y_CLAUSES; EQ_SYM]; ALL_TAC] THEN
UNDISCH_TAC `Y a k = y` THEN ASM_REWRITE_TAC[Y_CLAUSES];
ALL_TAC] THEN
ASM_SIMP_TAC[ARITH_RULE `~(r = 0) ==> 0 < r`] THEN
SUBGOAL_THEN `ODD(u)` ASSUME_TAC THENL
[UNDISCH_TAC `(a EXP 2 - 1) * v EXP 2 + 1 = u EXP 2` THEN
DISCH_THEN(MP_TAC o AP_TERM `EVEN`) THEN
REWRITE_TAC[EXP_2; EVEN_ADD; EVEN_MULT; ARITH_EVEN] THEN
SUBGOAL_THEN `EVEN v` (fun th -> REWRITE_TAC[GSYM NOT_EVEN; th]) THEN
SUBST1_TAC(SYM(ASSUME `Y a m = v`)) THEN
MP_TAC(SPECL [`a:num`; `m:num`] Y_N_MOD2) THEN
SIMP_TAC[ASSUME `~(a = 0)`; LEFT_IMP_EXISTS_THM] THEN
SUBST1_TAC(SYM(ASSUME `2 * k * Y a k = m`)) THEN
REWRITE_TAC[EVEN_ADD; EVEN_MULT; ARITH_EVEN]; ALL_TAC] THEN
SUBGOAL_THEN `?b0 q6 q7. (b0 = 1 + q6 * 4 * y) /\ (b0 = a + q7 * u)`
MP_TAC THENL
[MATCH_MP_TAC CHINESE_REMAINDER THEN
UNDISCH_TAC `ODD u` THEN
ASM_CASES_TAC `u = 0` THEN ASM_REWRITE_TAC[ARITH_ODD] THEN
DISCH_TAC THEN ASM_REWRITE_TAC[MULT_EQ_0; ARITH_EQ] THEN
ONCE_REWRITE_TAC[COPRIME_SYM] THEN MATCH_MP_TAC COPRIME_MUL THEN
CONJ_TAC THENL
[SUBST1_TAC(SYM(NUM_REDUCE_CONV `2 * 2`)) THEN
MATCH_MP_TAC COPRIME_MUL THEN REWRITE_TAC[] THEN
MP_TAC(SPECL [`u:num`; `2`] PRIME_COPRIME) THEN REWRITE_TAC[PRIME_2] THEN
MATCH_MP_TAC(TAUT `~b /\ (a ==> d) /\ (c ==> d)
==> a \/ b \/ c ==> d`) THEN
REPEAT CONJ_TAC THENL
[UNDISCH_TAC `ODD u` THEN
ONCE_REWRITE_TAC[TAUT `a ==> b <=> ~b ==> ~a`] THEN
SIMP_TAC[divides; LEFT_IMP_EXISTS_THM; ODD_MULT; ARITH_ODD];
ONCE_REWRITE_TAC[COPRIME_SYM] THEN SIMP_TAC[COPRIME_1];
REWRITE_TAC[COPRIME_SYM]];
MP_TAC(SPECL [`a:num`; `m:num`] XY_COPRIME) THEN ASM_REWRITE_TAC[] THEN
SUBST1_TAC(SYM(ASSUME `y EXP 2 * r = v`)) THEN
REWRITE_TAC[coprime; EXP_2] THEN
MESON_TAC[DIVIDES_RMUL; DIVIDES_LMUL]]; ALL_TAC] THEN
DISCH_THEN(X_CHOOSE_THEN `b:num` (X_CHOOSE_THEN `p:num`
(X_CHOOSE_THEN `q:num` (STRIP_ASSUME_TAC o GSYM)))) THEN
MAP_EVERY EXISTS_TAC [`b:num`; `p:num`; `q:num`] THEN
ONCE_REWRITE_TAC[ARITH_RULE `1 + 4 * p * y = 1 + p * 4 * y`] THEN
ASM_REWRITE_TAC[] THEN
ABBREV_TAC `s = X b k` THEN ABBREV_TAC `t = Y b k` THEN
EXISTS_TAC `s:num` THEN EXISTS_TAC `t:num` THEN
SUBST1_TAC(ARITH_RULE `r * y EXP 2 = y EXP 2 * r`) THEN
ASM_REWRITE_TAC[] THEN
SUBST1_TAC(SYM(ASSUME `X b k = s`)) THEN
SUBST1_TAC(SYM(ASSUME `Y b k = t`)) THEN
SUBGOAL_THEN `~(b = 0)` ASSUME_TAC THENL
[UNDISCH_THEN `1 + p * 4 * y = b` (SUBST1_TAC o SYM) THEN
ONCE_REWRITE_TAC[TAUT `~b ==> a ==> b ==> ~a`] THEN
REWRITE_TAC[ADD_EQ_0; ARITH_EQ]; ALL_TAC] THEN
SIMP_TAC[XY_ARE_SOLUTIONS; ASSUME `~(b = 0)`] THEN
MP_TAC(SPECL [`a:num`; `q:num`; `u:num`; `k:num`] X_CONGRUENT) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `c:num` (ASSUME_TAC o SYM)) THEN
EXISTS_TAC `c:num` THEN ASM_REWRITE_TAC[] THEN
MP_TAC(SPECL [`b:num`; `k:num`] Y_N_MODA1) THEN
SUBST1_TAC(SYM(ASSUME `1 + p * 4 * y = b`)) THEN
REWRITE_TAC[ADD_EQ_0; ADD_SUB2; ARITH_EQ] THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN(X_CHOOSE_THEN `q8:num` SUBST1_TAC) THEN
EXISTS_TAC `q8 * p:num` THEN REWRITE_TAC[MULT_AC; ADD_AC] THEN
MP_TAC(SPECL [`a:num`; `k:num`] Y_N_MODA1) THEN
ASM_SIMP_TAC[LEFT_IMP_EXISTS_THM] THEN
REWRITE_TAC[ONCE_REWRITE_RULE[ADD_SYM] LE_ADD]);;
(* ------------------------------------------------------------------------- *)
(* A ratio approaches a^n for large enough k. *)
(* ------------------------------------------------------------------------- *)
let XY_EXP_LEMMA = prove
(`!a k n.
~(a = 0) /\
2 * n * a
EXP n < k
==> abs(&(Y (a * k) (n + 1)) / &(Y k (n + 1)) - &a pow n) < &1 / &2`,
let Y_EQ_0 = prove
(`!a n. ~(a = 0) ==> ((Y a n = 0) <=> (n = 0))`,
REPEAT STRIP_TAC THEN
SUBST1_TAC(SYM(SPEC `a:num` (CONJUNCT1
Y_CLAUSES))) THEN
ASM_SIMP_TAC[
Y_INJ] THEN REWRITE_TAC[
Y_CLAUSES]);;
let XY_EXP = prove
(`~(a = 0)
==> ((a
EXP n = p) <=>
?k x y z. (Y (a * k) (n + 1) = x) /\
(Y k (n + 1) = y) /\
(Y a (n + 1) = z) /\
2 * n * z < k /\
4 * x
EXP 2 + 4 * (y * p)
EXP 2 < 8 * x * y * p + y
EXP 2)`,
let lemma1 = prove
(`(?x y z. (a = x) /\ (b = y) /\ (c = z) /\ P x y z) <=> P a b c`,
MESON_TAC[])
and lemma2 =
CONV_RULE(RAND_CONV(ONCE_DEPTH_CONV SYM_CONV))
(SPEC_ALL ABS_LT_REPRESENTATION) in
REPEAT STRIP_TAC THEN REWRITE_TAC[lemma1] THEN
GEN_REWRITE_TAC (RAND_CONV o BINDER_CONV o LAND_CONV)
[ARITH_RULE `n < k <=> n < k /\ ~(k = 0)`] THEN
ONCE_REWRITE_TAC[TAUT `a /\ b <=> ~(a ==> ~b)`] THEN
ASM_SIMP_TAC[lemma2; Y_EQ_0; ADD_EQ_0; ARITH_EQ] THEN
REWRITE_TAC[NOT_IMP] THEN
REWRITE_TAC[ARITH_RULE `n < k /\ ~(k = 0) <=> n < k`] THEN
EQ_TAC THENL
[DISCH_THEN(SUBST1_TAC o SYM) THEN
EXISTS_TAC `2 * n * Y a (n + 1) + 1` THEN
REWRITE_TAC[ARITH_RULE `c < c + 1`; GSYM REAL_OF_NUM_POW] THEN
MATCH_MP_TAC XY_EXP_LEMMA THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC(ARITH_RULE `a <= b ==> 2 * a < 2 * b + 1`) THEN
REWRITE_TAC[LE_MULT_LCANCEL] THEN DISJ2_TAC THEN
MATCH_MP_TAC LE_TRANS THEN EXISTS_TAC `(2 * a - 1) EXP n` THEN
REWRITE_TAC[Y_LOWERBOUND] THEN
SPEC_TAC(`n:num`,`n:num`) THEN INDUCT_TAC THEN
REWRITE_TAC[CONJUNCT1 EXP; LE_REFL; EXP_MONO_LE_SUC] THEN
UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC; ALL_TAC] THEN
DISCH_THEN(X_CHOOSE_THEN `k:num` (CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
MP_TAC(SPECL [`a:num`; `k:num`; `n:num`] XY_EXP_LEMMA) THEN
ANTS_TAC THENL
[ASM_REWRITE_TAC[] THEN
FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (ARITH_RULE
`2 * a < k ==> b <= a ==> 2 * b < k`)) THEN
REWRITE_TAC[LE_MULT_LCANCEL] THEN DISJ2_TAC THEN
MATCH_MP_TAC LE_TRANS THEN EXISTS_TAC `(2 * a - 1) EXP n` THEN
REWRITE_TAC[Y_LOWERBOUND] THEN
SPEC_TAC(`n:num`,`n:num`) THEN INDUCT_TAC THEN
REWRITE_TAC[CONJUNCT1 EXP; LE_REFL; EXP_MONO_LE_SUC] THEN
UNDISCH_TAC `~(a = 0)` THEN ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[IMP_IMP] THEN
DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
`abs(x - a) < e1 /\ abs(x - b) < e2 ==> abs(a - b) < e1 + e2`)) THEN
CONV_TAC REAL_RAT_REDUCE_CONV THEN
DISCH_THEN(MP_TAC o MATCH_MP (REAL_ARITH
`abs(a - b) < &1
==> a + &1 <= b \/ (a = b) \/ b + &1 <= a ==> (a = b)`)) THEN
REWRITE_TAC[REAL_OF_NUM_POW; REAL_OF_NUM_ADD;
REAL_OF_NUM_EQ; REAL_OF_NUM_LE] THEN
DISCH_THEN MATCH_MP_TAC THEN ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* Lemmas. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Combining theorems for conjunction and disjunction. *)
(* ------------------------------------------------------------------------- *)
let DIOPH_CONJ = prove
(`(x1 = x2) /\ (y1 = y2) <=>
(x1 * x1 + x2 * x2 + y1 * y1 + y2 * y2 = 2 * x1 * x2 + 2 * y1 * y2)`,
REWRITE_TAC[GSYM REAL_OF_NUM_EQ;
GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_MUL] THEN
ONCE_REWRITE_TAC[GSYM
REAL_SUB_0] THEN
REWRITE_TAC[GSYM
REAL_SUM_OF_SQUARES] THEN
REWRITE_TAC[REAL_POW_2] THEN REAL_ARITH_TAC);;
let DIOPH_DISJ = prove
(`(x1 = x2) \/ (y1 = y2) <=>
(x1 * y1 + x2 * y2 = x1 * y2 + x2 * y1)`,
REWRITE_TAC[GSYM REAL_OF_NUM_EQ;
GSYM REAL_OF_NUM_ADD; GSYM REAL_OF_NUM_MUL] THEN
ONCE_REWRITE_TAC[GSYM
REAL_SUB_0] THEN
REWRITE_TAC[GSYM
REAL_ENTIRE] THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* Inequalities. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Exponentiation (from the Pell stuff). *)
(* ------------------------------------------------------------------------- *)
let Y_0 = prove
(`!k. Y 0 k = if k = 1 then 1 else 0`,
INDUCT_TAC THEN REWRITE_TAC[
Y_CLAUSES;
ARITH_EQ] THEN
SPEC_TAC(`k:num`,`k:num`) THEN
INDUCT_TAC THEN REWRITE_TAC[
Y_CLAUSES; ARITH] THEN
REWRITE_TAC[ARITH_RULE `SUC(SUC n) = n + 2`;
Y_CLAUSES; ARITH] THEN
REWRITE_TAC[
MULT_CLAUSES;
SUB_0; ARITH_RULE `~(k + 2 = 1)`]);;
let Y_0_TRIV = prove
(`!k. (Y 0 k = 0) <=> ~(k = 1)`,
GEN_TAC THEN REWRITE_TAC[
Y_0] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[
ARITH_EQ]);;
let DIOPH_Y = prove
(`(Y a k = y) <=>
(a = 0) /\ (k = 1) /\ (y = 1) \/
(a = 0) /\ ~(k = 1) /\ (y = 0) \/
(k = 0) /\ (y = 0) \/
(a = 1) /\ (y = k) \/
~(a = 0) /\ ~(k = 0) /\ ~(a = 1) /\ ~(y = 0) /\
?x u v r b p q s t c d.
0 < r /\
(x
EXP 2 = (a
EXP 2 - 1) * y
EXP 2 + 1) /\
(u
EXP 2 = (a
EXP 2 - 1) * v
EXP 2 + 1) /\
(s
EXP 2 = (b
EXP 2 - 1) * t
EXP 2 + 1) /\
(v = r * y
EXP 2) /\
(b = 1 + 4 * p * y) /\
(b = a + q * u) /\
(s = x + c * u) /\
(t = k + 4 * d * y) /\
k <= y`,
ASM_CASES_TAC `a = 0` THENL
[ASM_CASES_TAC `y = 0` THENL
[ASM_REWRITE_TAC[
Y_0_TRIV;
ARITH_EQ] THEN ARITH_TAC; ALL_TAC] THEN
ASM_CASES_TAC `k = 0` THEN ASM_REWRITE_TAC[
Y_CLAUSES;
ARITH_EQ] THEN
ASM_REWRITE_TAC[
ARITH_EQ] THEN CONV_TAC NUM_REDUCE_CONV THEN
REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THEN
REWRITE_TAC[
EXP_2;
MULT_EQ_1] THEN
REWRITE_TAC[
Y_0] THEN COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[
EQ_SYM_EQ]; ALL_TAC] THEN
ASM_REWRITE_TAC[
ARITH_EQ] THEN
ASM_CASES_TAC `k = 0` THEN ASM_REWRITE_TAC[
Y_CLAUSES] THENL
[REWRITE_TAC[
EQ_SYM_EQ] THEN CONV_TAC(EQT_INTRO o TAUT); ALL_TAC] THEN
ASM_CASES_TAC `a = 1` THEN ASM_REWRITE_TAC[
Y_DEGENERATE] THENL
[REWRITE_TAC[
EQ_SYM_EQ]; ALL_TAC] THEN
ASM_CASES_TAC `y = 0` THEN ASM_SIMP_TAC[
Y_EQ_0] THEN
GEN_REWRITE_TAC LAND_CONV [
EQ_SYM_EQ] THEN ASM_SIMP_TAC[
Y_DIOPH]);;
let DIOPH_EXP_LEMMA = prove
(`(m
EXP n = p) <=>
(m = 0) /\ (n = 0) /\ (p = 1) \/
(m = 0) /\ ~(n = 0) /\ (p = 0) \/
~(m = 0) /\
?k x y z. (Y (m * k) (n + 1) = x) /\
(Y k (n + 1) = y) /\
(Y m (n + 1) = z) /\
2 * n * z < k /\
4 * x
EXP 2 + 4 * (y * p)
EXP 2 < 8 * x * y * p + y
EXP 2`,
let DIOPH_EXP =
let th1 = REWRITE_RULE[DIOPH_Y] DIOPH_EXP_LEMMA in
let th2 = REWRITE_RULE[EXP_2] th1 in
let th3 = REWRITE_RULE[DIOPH_NE; DIOPH_LT; DIOPH_LE] th2 in
let th4 = REWRITE_RULE[ADD_CLAUSES; ARITH_EQ; ADD_EQ_0;
ARITH_RULE `(n + 1 = 1) = (n = 0)`; ADD_ASSOC;
EQ_ADD_RCANCEL] th3 in
let th5 = REWRITE_RULE[GSYM ADD_ASSOC] th4 in
REWRITE_RULE
[OR_EXISTS_THM; LEFT_OR_EXISTS_THM; RIGHT_OR_EXISTS_THM;
LEFT_AND_EXISTS_THM; RIGHT_AND_EXISTS_THM] th5;;
(****** This takes about an hour to compute, and longer to print out!
let DIOPH_EXP_ONE_EQUATION =
REWRITE_RULE[DIOPH_CONJ; DIOPH_DISJ] DIOPH_EXP;;
*******)