Zulip Chat Archive
Stream: new members
Topic: Rearranging and regrouping sums
Gareth Ma (Feb 06 2023 at 22:43):
Hi. I am trying to prove the following result: Screenshot-2023-02-06-at-22.38.37.png. In short and generalising, if an arithmetic function f satisfies f(p^k) = f(p), then summing f over all prime powers is the same as summing over primes and multiplying by floor(log_p(n)). On paper it sounds simple, and it really really should be, but I swear I can't figure out how to prove it in Lean. I have spent multiple hours on this one statement :tear: Can someone help?
Here is the statement:
import data.nat.basic
import data.real.basic
import number_theory.von_mangoldt
import tactic
open real finset
open_locale nat big_operators
example {n : ℕ} : ∑ (x : ℕ) in filter nat.prime (Icc 1 n), nat.log x n • real.log ↑x
= ∑ (a : ℕ) in filter is_prime_pow (Icc 1 n), real.log ↑(a.min_fac) :=
begin
sorry,
end
Eric Wieser (Feb 06 2023 at 22:45):
Can you rearrange to an equality of logs with the sum on the inside?
Gareth Ma (Feb 06 2023 at 22:45):
I had an idea to partition Icc into union of disjoint sets, as then I can write sum(x in S) = sum(x in S1) +sum(x in S2) + ... And in this case, if we write filter is_prime_pow (Icc 1 n) = union of {p ^ k}
, then it should work intuitively. But I cannot express this nor prove it in Lean.
Gareth Ma (Feb 06 2023 at 22:46):
What do you mean for that?
Gareth Ma (Feb 06 2023 at 22:46):
The summand on the left depends on p
Eric Wieser (Feb 06 2023 at 22:46):
Use the lemmas docs#real.log_prod, and docs#real.log_pow to move the real.log to the outside of both sides
Gareth Ma (Feb 06 2023 at 22:48):
image.png I will still have to prove this, what I think is similar in nature
Eric Wieser (Feb 06 2023 at 22:49):
Sure, but now all the real.log
s are gone so your problem is simpler
Eric Wieser (Feb 06 2023 at 22:51):
You should be able to rearrange into somehow
Ruben Van de Velde (Feb 06 2023 at 22:54):
Is this the kind of that sums over p's and k's?
Gareth Ma (Feb 06 2023 at 22:54):
Yes!
Gareth Ma (Feb 06 2023 at 22:55):
@Eric Wieser Right, let me try that, so I should write
as
And write the right hand side as you said, then they should be equal
Ruben Van de Velde (Feb 06 2023 at 22:58):
Once you have a product over the primes \le N on both sides, you can use... docs#finset.prod_congr
Eric Wieser (Feb 06 2023 at 23:08):
(deleted)
Gareth Ma (Feb 06 2023 at 23:08):
Thank you, I needed that :P I tried \( \)
, $ $
and finally ```maths
:D
Gareth Ma (Feb 06 2023 at 23:17):
I am not sure if I made it better or worse, but I have this:
∏ (a : ℕ) in Icc 1 n, ite (is_prime_pow a) ↑(a.min_fac) 1 = ∏ (x : ℕ) in filter nat.prime (Icc 1 n), ∏ (i : ℕ) in Icc 1 (nat.log x n), ↑x
And I can't manipulate the left hand side at all. Things like simp_rw [is_prime_pow_iff_min_fac_pow_factorization_eq _]
doesn't work.
Eric Wieser (Feb 06 2023 at 23:17):
I think you need
have :
(Icc 1 n).filter is_prime_pow =
((Icc 1 n).filter nat.prime).bUnion (λ p, (Icc 1 (nat.log p n)).image (λ k, p ^ k))
although I almost certainly made an off-by-one error
Gareth Ma (Feb 06 2023 at 23:19):
Oh, let me try that. It should be easy by ext
and rewriting using the mem_
lemmas right
Eric Wieser (Feb 06 2023 at 23:29):
Here's an overall outline:
import data.nat.basic
import data.real.basic
import number_theory.von_mangoldt
import tactic
open real finset
open_locale nat big_operators
example {n : ℕ} : ∑ (x : ℕ) in filter nat.prime (Icc 1 n), nat.log x n • real.log ↑x
= ∑ (a : ℕ) in filter is_prime_pow (Icc 1 n), real.log ↑(a.min_fac) :=
begin
simp_rw [nsmul_eq_mul, ←real.log_pow, ←nat.cast_pow],
rw [←real.log_prod _ _ (λ i hi, _), ←real.log_prod _ _ (λ i hi, _)],
{ congr' 1,
simp_rw [←nat.cast_prod, nat.cast_inj],
have :
(Icc 1 n).filter is_prime_pow =
((Icc 1 n).filter nat.prime).bUnion (λ p, (Icc 1 (nat.log p n)).image (λ k, p ^ k)),
{ sorry },
rw this,
rw prod_bUnion,
{ congr' 1 with x,
rw prod_image,
{ -- clean up under the sum
sorry },
{ -- prove the image is injective
sorry } },
{ intros i hi j hj hij,
simp_rw [mem_coe, mem_filter] at hi hj,
rw [function.on_fun, disjoint_left],
-- prove the families are disjoint
sorry } },
{ norm_cast,
exact (nat.min_fac_pos _).ne' },
{ norm_cast,
-- easy :)
sorry },
end
Gareth Ma (Feb 06 2023 at 23:33):
Thank you so much, I will try this! I didn't know about the bUnion
part and was writing your lemma as some finsupp.sum
, and of course it didn't work.
Eric Wieser (Feb 06 2023 at 23:43):
Right, your choices here are either docs#finset.bUnion, or if you want to prove the disjointness up front, docs#finset.disj_Union
Eric Wieser (Feb 06 2023 at 23:43):
(similarly you can prove the injectivity up front with docs#finset.map instead of docs#finset.image)
Gareth Ma (Feb 07 2023 at 00:45):
I got it!! Here it is: https://github.com/grhkm21/lean/commit/4e644cf032a5a1f4063f1607a6bbb05aba582960 Around 80 lines of code for what humans would consider trivial :P I feel like I will encounter this a lot while doing number theory or combinatorics.
Last updated: Dec 20 2023 at 11:08 UTC