(* ========================================================================= *)
(* Multiplicative functions into N or R (could add Z, C etc.) *)
(* ========================================================================= *)
needs "Library/prime.ml";;
needs "Library/pocklington.ml";;
(* ------------------------------------------------------------------------- *)
(* Definition of multiplicativity of functions into N. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* We can really ignore the value at zero. *)
(* ------------------------------------------------------------------------- *)
let MULTIPLICATIVE = prove
(`multiplicative f <=>
f(1) = 1 /\
!m n. ~(m = 0) /\ ~(n = 0) /\ coprime(m,n) ==> f(m * n) = f(m) * f(n)`,
let MULTIPLICATIVE_IGNOREZERO = prove
(`!f g. (!n. ~(n = 0) ==> g(n) = f(n)) /\ multiplicative f
==> multiplicative g`,
REPEAT GEN_TAC THEN SIMP_TAC[
MULTIPLICATIVE;
ARITH_EQ] THEN
REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
REPEAT(MATCH_MP_TAC
MONO_FORALL THEN GEN_TAC) THEN
DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN
ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[
MULT_EQ_0]);;
(* ------------------------------------------------------------------------- *)
(* A key "building block" theorem. *)
(* ------------------------------------------------------------------------- *)
let MULTIPLICATIVE_CONVOLUTION = prove
(`!f g. multiplicative f /\ multiplicative g
==> multiplicative (\n. nsum {d | d divides n}
(\d. f(d) * g(n DIV d)))`,
REPEAT GEN_TAC THEN
GEN_REWRITE_TAC (LAND_CONV o BINOP_CONV) [multiplicative] THEN
REWRITE_TAC[
MULTIPLICATIVE; GSYM
NSUM_LMUL] THEN STRIP_TAC THEN
ASM_REWRITE_TAC[
DIVIDES_ONE; DIV_1;
SING_GSPEC;
NSUM_SING;
MULT_CLAUSES] THEN
MAP_EVERY X_GEN_TAC [`m:num`; `n:num`] THEN STRIP_TAC THEN
GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [
MULT_SYM] THEN
ASM_SIMP_TAC[GSYM
NSUM_LMUL;
NSUM_NSUM_PRODUCT;
FINITE_DIVISORS] THEN
CONV_TAC SYM_CONV THEN MATCH_MP_TAC
NSUM_EQ_GENERAL THEN
EXISTS_TAC `\(a:num,b). a * b` THEN REWRITE_TAC[EXISTS_UNIQUE_DEF] THEN
REWRITE_TAC[
FORALL_PAIR_THM;
EXISTS_PAIR_THM;
IN_ELIM_PAIR_THM] THEN
CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN REWRITE_TAC[
IN_ELIM_THM] THEN
REWRITE_TAC[
PAIR_EQ] THEN CONJ_TAC THENL
[GEN_TAC THEN DISCH_THEN(ASSUME_TAC o MATCH_MP DIVISION_DECOMP) THEN
CONJ_TAC THENL [ASM_MESON_TAC[
MULT_SYM]; ALL_TAC] THEN
MAP_EVERY X_GEN_TAC [`a1:num`; `b1:num`; `a2:num`; `b2:num`] THEN
STRIP_TAC THEN FIRST_X_ASSUM(SUBST_ALL_TAC o SYM) THEN
REWRITE_TAC[GSYM
DIVIDES_ANTISYM] THEN REPEAT CONJ_TAC THEN
MATCH_MP_TAC
COPRIME_DIVPROD THENL
(map EXISTS_TAC [`b2:num`; `b1:num`; `a2:num`; `a1:num`]) THEN
ASM_MESON_TAC[
COPRIME_DIVISORS;
DIVIDES_REFL;
DIVIDES_RMUL;
COPRIME_SYM;
MULT_SYM];
MAP_EVERY X_GEN_TAC [`d:num`; `e:num`] THEN STRIP_TAC THEN
CONJ_TAC THENL [ASM_MESON_TAC[
DIVIDES_MUL2;
MULT_SYM]; ALL_TAC] THEN
MP_TAC(REWRITE_RULE[divides] (ASSUME `(d:num) divides n`)) THEN
DISCH_THEN(X_CHOOSE_THEN `d':num` SUBST_ALL_TAC) THEN
MP_TAC(REWRITE_RULE[divides] (ASSUME `(e:num) divides m`)) THEN
DISCH_THEN(X_CHOOSE_THEN `e':num` SUBST_ALL_TAC) THEN
RULE_ASSUM_TAC(REWRITE_RULE[
MULT_EQ_0; DE_MORGAN_THM]) THEN
ONCE_REWRITE_TAC[AC
MULT_AC
`(e * e') * d * d':num = (d * e) * (d' * e')`] THEN
ASM_SIMP_TAC[DIV_MULT;
MULT_EQ_0] THEN
FIRST_ASSUM(ASSUME_TAC o MATCH_MP (NUMBER_RULE
`coprime(a * b,c * d) ==> coprime(c,a) /\ coprime(d,b)`)) THEN
ASM_SIMP_TAC[] THEN ARITH_TAC]);;
(* ------------------------------------------------------------------------- *)
(* Some particular multiplicative functions. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Uniqueness of multiplicative functions if equal on prime powers. *)
(* ------------------------------------------------------------------------- *)
let MULTIPLICATIVE_UNIQUE = prove
(`!f g. multiplicative f /\ multiplicative g /\
(!p k. prime p ==> f(p
EXP k) = g(p
EXP k))
==> !n. ~(n = 0) ==> f n = g n`,
REPEAT GEN_TAC THEN STRIP_TAC THEN MATCH_MP_TAC
num_WF THEN
X_GEN_TAC `n:num` THEN REPEAT STRIP_TAC THEN
FIRST_X_ASSUM(DISJ_CASES_THEN2 ASSUME_TAC MP_TAC o MATCH_MP (ARITH_RULE
`~(n = 0) ==> n = 1 \/ 1 < n`))
THENL [ASM_MESON_TAC[multiplicative]; ALL_TAC] THEN
SPEC_TAC(`n:num`,`n:num`) THEN MATCH_MP_TAC
INDUCT_COPRIME_STRONG THEN
ASM_MESON_TAC[multiplicative]);;
(* ------------------------------------------------------------------------- *)
(* Derive the divisor-sum identity for phi from this. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Now the real analog. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* The Mobius function (into the reals). *)
(* ------------------------------------------------------------------------- *)
prioritize_real();;
let MOBIUS_PRIME = prove
(`!p. prime p ==> mobius(p) = -- &1`,
REPEAT STRIP_TAC THEN REWRITE_TAC[mobius] THEN COND_CASES_TAC THENL
[FIRST_X_ASSUM(X_CHOOSE_THEN `q:num`
(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
DISCH_THEN(fun th -> MP_TAC th THEN ASSUME_TAC
(MATCH_MP(NUMBER_RULE `q
EXP 2 divides p ==> q divides p`) th)) THEN
SUBGOAL_THEN `q:num = p` SUBST_ALL_TAC THENL
[ASM_MESON_TAC[
DIVIDES_PRIME_PRIME]; ALL_TAC] THEN
DISCH_THEN(MP_TAC o MATCH_MP
DIVIDES_LE) THEN
REWRITE_TAC[ARITH_RULE `p
EXP 2 <= p <=> p * p <= 1 * p`] THEN
REWRITE_TAC[
LE_MULT_RCANCEL] THEN
FIRST_ASSUM(MP_TAC o MATCH_MP
PRIME_GE_2) THEN ARITH_TAC;
SUBGOAL_THEN `{q | prime q /\ q divides p} = {p}` SUBST1_TAC THENL
[ASM SET_TAC[
DIVIDES_PRIME_PRIME]; ALL_TAC] THEN
SIMP_TAC[
CARD_CLAUSES;
FINITE_RULES;
NOT_IN_EMPTY; ARITH;
REAL_POW_1]]);;
let MOBIUS_PRIMEPOW = prove
(`!p k. prime p ==> mobius(p
EXP k) = if k = 0 then &1
else if k = 1 then -- &1
else &0`,
REPEAT STRIP_TAC THEN
ASM_CASES_TAC `k = 0` THEN ASM_REWRITE_TAC[
EXP;
MOBIUS_1] THEN
ASM_CASES_TAC `k = 1` THEN ASM_SIMP_TAC[
EXP_1;
MOBIUS_PRIME] THEN
REWRITE_TAC[mobius] THEN
SUBGOAL_THEN `?q. prime q /\ q
EXP 2 divides p
EXP k`
(fun th -> REWRITE_TAC[th]) THEN
EXISTS_TAC `p:num` THEN ASM_SIMP_TAC[
DIVIDES_PRIME_EXP_LE] THEN
ASM_ARITH_TAC);;
let MOBIUS_INVERSION = prove
(`!f g. (!n. 1 <= n ==> g(n) = sum {d | d divides n} f)
==> !n. 1 <= n
==> f(n) = sum {d | d divides n} (\d. mobius(d) * g(n DIV d))`,