Some months ago, I derived the following formula for the Merten's function $M(n)$ using the inclusion-exclusion principle:
$$M(n)=1-\pi\left(n\right)+\sum_{p_{i}\leq\frac{n}{p_i}}\left(\pi\left(\frac{n}{p_{i}}\right)-i\right)-\sum_{p_{i}<p_{j}\leq\frac{n}{p_ip_j}}\left(\pi\left(\frac{n}{p_{i}p_{j}}\right)-j\right)+\sum_{p_{i}<p_{j}<p_{k}\leq\frac{n}{p_ip_jp_k}}\left(\pi\left(\frac{n}{p_{i}p_{j}p_{k}}\right)-k\right)-\dots$$
I suspect that applying bounds for $\pi(n)$ could be useful to bound $M(n)$ in this formulation. For instance, maybe Dussart's bound $\frac {x}{\log (x)-1}<\pi(x)<\frac {x}{\log (x) -1.1}$ could be applicable. However, it still seems a very hard task, and I am not sure if it would be worthy to follow that path.
Question. Is the way proposed (or other similar) worthy to bound $M(n)$ in this formulation, or are there better methods to try?
Thanks!
EDIT
The formula can be divided into two great expressions as $$M(n)=\left(-\pi\left(n\right)+\sum_{p_{i}\leq\frac{n}{p_i}}\left(\pi\left(\frac{n}{p_{i}}\right)\right)-\sum_{p_{i}<p_{j}\leq\frac{n}{p_ip_j}}\left(\pi\left(\frac{n}{p_{i}p_{j}}\right)\right)+\sum_{p_{i}<p_{j}<p_{k}\leq\frac{n}{p_ip_jp_k}}\left(\pi\left(\frac{n}{p_{i}p_{j}p_{k}}\right)\right)-\dots\right)-\left(\sum_{p_{i}\leq\frac{n}{p_i}}i-\sum_{p_{i}<p_{j}\leq\frac{n}{p_ip_j}}j+\sum_{p_{i}<p_{j}<p_{k}\leq\frac{n}{p_ip_jp_k}}k-\dots\right)$$
Applying the Prime Number Theorem to the first of the two great expressions between brackets, yields the expression $$\left(-\frac{n}{\log\left(n\right)}+\sum_{p_{i}<\frac{n}{p_{i}}}\left(\frac{n}{p_{i}\left(\log\left(n\right)-\log\left(p_{i}\right)\right)}\right)-\sum_{p_{i}<p_{j}<\frac{n}{p_{i}p_{j}}}\left(\frac{n}{p_{i}p_{j}\left(\log\left(n\right)-\log\left(p_{i}\right)-\log\left(p_{j}\right)\right)}\right)+\sum_{p_{i}<p_{j}<p_{k}<\frac{n}{p_{i}p_{j}p_{k}}}\left(\frac{n}{p_{i}p_{j}p_{k}\left(\log\left(n\right)-\log\left(p_{i}\right)-\log\left(p_{j}\right)-\log\left(p_{k}\right)\right)}\right)-...\right) (1)$$ I have evaluated sepparately this last expression and the second great expression between brackets for the first thousands of values of $n$, and they oscillate as quasi-symmetric functions over the x-axis, as shown in the following graph:
I attach below the code used for getting the plot showed:
@author: juanmoreno
"""
import math
import matplotlib.pyplot as plt
def sieve_of_eratosthenes(n):
is_prime = [True] * (n + 1)
is_prime[0] = is_prime[1] = False
primes = []
for p in range(2, int(math.sqrt(n)) + 1):
if is_prime[p]:
for i in range(p * p, n + 1, p):
is_prime[i] = False
for i in range(2, n + 1):
if is_prime[i]:
primes.append(i)
return primes
def calculate_expression_1(n):
return (-n / math.log(n))
def calculate_expression_2(n, primes):
result = 0
result_2 = 0
for pi in primes:
if pi < n / pi:
result += (n / (pi * (math.log(n) - math.log(pi))))
result_2 -= primes.index(pi)
return result, result_2
def calculate_expression_3(n, primes):
result = 0
result_3 = 0
for i in range(len(primes)):
for j in range(i + 1, len(primes)):
pij = primes[i] * primes[j]
if primes[j] < n / pij:
result -= (n / (pij * (math.log(n) -
math.log(primes[i]) - math.log(primes[j]))))
result_3 += j
return result, result_3
def calculate_expression_4(n, primes):
result = 0
result_4 = 0
for i in range(len(primes)):
for j in range(i + 1, len(primes)):
pij = primes[i] * primes[j]
if pij < n / pij:
for k in range(j + 1, len(primes)):
pijk = pij * primes[k]
if primes[k] <= n / pijk:
result += (n / (pijk * (math.log(n) -
math.log(primes[i]) - math.log(primes[j]) - math.log(primes[k]))))
result_4 -= k
return result, result_4
def calculate_expression_5(n, primes):
result = 0
result_5 = 0
for i in range(len(primes)):
for j in range(i + 1, len(primes)):
pij = primes[i] * primes[j]
if pij < n / pij:
for k in range(j + 1, len(primes)):
pijk = pij * primes[k]
if pijk < n / pijk:
for l in range(k + 1, len(primes)):
pijkl = pijk * primes[l]
if primes[l] <= n / pijkl:
result -= (n / (pijkl * (math.log(n) - math.log(primes[i]) - math.log(primes[j]) - math.log(primes[k])-math.log(primes[l]))))
result_5 += l
return result, result_5
# Create lists to store results and square roots of n
results_1 = []
results_2 = []
sqrt_n = []
x_axis = []
for n in range(2, 10001):
primes = sieve_of_eratosthenes(n)
result1 = calculate_expression_1(n)
result2 = calculate_expression_2(n, primes)[0]
result3 = calculate_expression_3(n, primes)[0]
result4 = calculate_expression_4(n, primes)[0]
result5 = calculate_expression_5(n, primes)[0]
final_result_1 =1 + result1 + result2 + result3 + result4 + result5
result21 = calculate_expression_2(n, primes)[1]
result31 = calculate_expression_3(n, primes)[1]
result41 = calculate_expression_4(n, primes)[1]
result51 = calculate_expression_5(n, primes)[1]
final_result_2 = result21 + result31 + result41 + result51
results_1.append(final_result_1)
results_2.append(final_result_2)
sqrt_n.append(math.sqrt(n))
x_axis.append(0)
# Create a plot to compare results and sqrt(n)
plt.figure(figsize=(10, 6))
plt.plot(range(2, 10001), results_1, label='Expression (1)',
linewidth=2)
plt.plot(range(2, 10001), results_2, label='Expression (2)',
linewidth=2)
plt.plot(range(2, 10001), sqrt_n, label='square root of n',
linestyle='--', linewidth=2)
plt.plot(range(2, 10001), x_axis, label='x-axis', linestyle='--',
linewidth=2)
plt.xlabel('n')
plt.ylabel('Value')
plt.legend()
plt.title('Comparison of Final Result and x-axis')
plt.grid(True)
plt.show()