(* ========================================================================= *)
(* Representation of primes == 1 (mod 4) as sum of 2 squares. *)
(* ========================================================================= *)
needs "Library/prime.ml";;
prioritize_num();;
(* ------------------------------------------------------------------------- *)
(* Definition of involution and various basic lemmas. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Involution with no fixpoints can only occur on finite set of even card *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* So an involution with exactly one fixpoint has odd card domain. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* And an involution on a set of odd finite card must have a fixpoint. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Consequently, if one involution has a unique fixpoint, other has one. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Formalization of Zagier's "one-sentence" proof over the natural numbers. *)
(* ------------------------------------------------------------------------- *)
let zag = new_definition
`zag(x,y,z) =
if x + z < y then (x + 2 * z,z,y - (x + z))
else if x < 2 * y then (2 * y - x, y, (x + z) - y)
else (x - 2 * y,(x + z) - y, y)`;;
let ZAG_INVOLUTION_GENERAL = prove
(`0 < x /\ 0 < y /\ 0 < z ==> (zag(zag(x,y,z)) = (x,y,z))`,
REWRITE_TAC[zag] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
REWRITE_TAC[zag] THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN
REWRITE_TAC[
PAIR_EQ] THEN
POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN ARITH_TAC);;
let ZAG_LEMMA = prove
(`(zag(x,y,z) = (x,y,z)) ==> (y = x)`,
REWRITE_TAC[zag;
INT_POW_2] THEN
REPEAT(COND_CASES_TAC THEN ASM_SIMP_TAC[
PAIR_EQ]) THEN
POP_ASSUM_LIST(MP_TAC o end_itlist CONJ) THEN ARITH_TAC);;
let ZSET_BOUND = prove
(`0 < y /\ 0 < z /\ (x
EXP 2 + 4 * y * z = p)
==> x <= p /\ y <= p /\ z <= p`,
REPEAT GEN_TAC THEN STRIP_TAC THEN
FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN CONJ_TAC THENL
[MESON_TAC[
EXP_2;
LE_SQUARE_REFL; ARITH_RULE `(a <= b ==> a <= b + c)`];
CONJ_TAC THEN MATCH_MP_TAC(ARITH_RULE `y <= z ==> y <= x + z`) THENL
[GEN_REWRITE_TAC (RAND_CONV o RAND_CONV) [
MULT_SYM]; ALL_TAC] THEN
REWRITE_TAC[ARITH_RULE `y <= 4 * a * y <=> 1 * y <= (4 * a) * y`] THEN
ASM_REWRITE_TAC[
LE_MULT_RCANCEL] THEN
ASM_SIMP_TAC[ARITH_RULE `0 < a ==> 1 <= 4 * a`]]);;
let SUM_OF_TWO_SQUARES = prove
(`!p k. prime(p) /\ (p = 4 * k + 1) ==> ?x y. p = x
EXP 2 + y
EXP 2`,
SIMP_TAC[] THEN REPEAT STRIP_TAC THEN
SUBGOAL_THEN `?t. t
IN zset(p) /\ (tag(t) = t)` MP_TAC THENL
[ALL_TAC;
REWRITE_TAC[
LEFT_IMP_EXISTS_THM;
FORALL_PAIR_THM; tag;
PAIR_EQ] THEN
REWRITE_TAC[zset;
IN_TRIPLE;
EXP_2] THEN
ASM_MESON_TAC[ARITH_RULE `4 * x * y = (2 * x) * (2 * y)`]] THEN
MATCH_MP_TAC
INVOLUTION_FIX_FIX THEN EXISTS_TAC `zag` THEN
ASM_SIMP_TAC[
ZAG_INVOLUTION;
TAG_INVOLUTION;
ZSET_FINITE] THEN
REWRITE_TAC[
EXISTS_UNIQUE_ALT] THEN EXISTS_TAC `1,1,k:num` THEN
REWRITE_TAC[
FORALL_PAIR_THM] THEN
MAP_EVERY X_GEN_TAC [`x:num`; `y:num`; `z:num`] THEN EQ_TAC THENL
[ALL_TAC;
DISCH_THEN(SUBST1_TAC o SYM) THEN
REWRITE_TAC[zset; zag;
IN_TRIPLE; ARITH] THEN
REWRITE_TAC[
MULT_CLAUSES; ARITH_RULE `~(1 + k < 1)`;
PAIR_EQ] THEN
ARITH_TAC] THEN
REWRITE_TAC[zset;
IN_TRIPLE] THEN STRIP_TAC THEN
FIRST_ASSUM(SUBST_ALL_TAC o MATCH_MP
ZAG_LEMMA) THEN
UNDISCH_TAC `x
EXP 2 + 4 * x * z = 4 * k + 1` THEN
REWRITE_TAC[
EXP_2; ARITH_RULE `x * x + 4 * x * z = x * (4 * z + x)`] THEN
DISCH_THEN(ASSUME_TAC o SYM) THEN UNDISCH_TAC `prime p` THEN
ASM_REWRITE_TAC[] THEN REWRITE_TAC[prime] THEN
DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (MP_TAC o SPEC `x:num`)) THEN
SIMP_TAC[
DIVIDES_RMUL;
DIVIDES_REFL] THEN
DISCH_THEN(DISJ_CASES_THEN2 SUBST_ALL_TAC MP_TAC) THENL
[UNDISCH_TAC `4 * k + 1 = 1 * (4 * z + 1)` THEN
REWRITE_TAC[
MULT_CLAUSES;
PAIR_EQ] THEN ARITH_TAC;
ONCE_REWRITE_TAC[ARITH_RULE `(a = a * b) = (a * b = a * 1)`] THEN
ASM_SIMP_TAC[
EQ_MULT_LCANCEL] THEN STRIP_TAC THENL
[UNDISCH_TAC `4 * k + 1 = x * (4 * z + x)` THEN
ASM_REWRITE_TAC[
MULT_CLAUSES;
ADD_EQ_0;
ARITH_EQ];
UNDISCH_TAC `4 * z + x = 1` THEN REWRITE_TAC[
PAIR_EQ] THEN
ASM_CASES_TAC `z = 0` THENL
[ALL_TAC; UNDISCH_TAC `~(z = 0)` THEN ARITH_TAC] THEN
UNDISCH_TAC `4 * k + 1 = x * (4 * z + x)` THEN
ASM_REWRITE_TAC[
MULT_CLAUSES;
ADD_CLAUSES] THEN
ASM_CASES_TAC `x = 1` THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[
MULT_CLAUSES] THEN ARITH_TAC]]);;