Python Polya'的反例;s猜想

Python Polya'的反例;s猜想,python,mathematical-optimization,discrete-mathematics,Python,Mathematical Optimization,Discrete Mathematics,是一个数学猜想,假设第一个(-1)^(ω(n))的和,其中ω(n)是n的重数素数因子的个数,始终为负或零 一个反例是50年前发现的906316571。我想知道他们怎么能找到它,因为这需要大量的时间,我试图优化我的python算法,但它仍然需要大量的时间,你能帮我优化它吗 这是我的代码(我用备忘录) >>类备忘录: 定义初始化(self,f): self.f=f self.memo={} 定义调用(self,*args): 如果self.memo中没有参数: self.memo[args]=sel

是一个数学猜想,假设第一个(-1)^(ω(n))的和,其中ω(n)是n的重数素数因子的个数,始终为负或零

一个反例是50年前发现的906316571。我想知道他们怎么能找到它,因为这需要大量的时间,我试图优化我的python算法,但它仍然需要大量的时间,你能帮我优化它吗

这是我的代码(我用备忘录)

>>类备忘录:
定义初始化(self,f):
self.f=f
self.memo={}
定义调用(self,*args):
如果self.memo中没有参数:
self.memo[args]=self.f(*args)
返回self.memo[args]
>>>def筛(m):
n=m+1;
s=[];
对于范围(2,n)内的i:
s、 附加(i);
k=0;
而k>>s=筛(100000);
>>>defω(n):
k=0;
如果n==1:
返回0;
其他:
而k>omega=记忆(omega)
>>>def polya(n):
h=ω(n);
如果n==1:
返回0;
其他:
如果ω(n)%2==0:
返回polya(n-1)+1;
其他:
返回polya(n-1)-1;
>>>波利亚=记忆化(波利亚);

>>>虽然波利亚(k)如切普纳(chepner)所说,1958年的原始证据并不是用蛮力完成的。它也没有透露打破这一规则的最小数字,它是在1980年才发现的。我根本没有研究过这个案子,但1980年的证据可能是用电脑做的。这更多的是可用RAM的数量问题,而不是处理速度的问题

然而,对于现代计算机来说,用蛮力解决这个问题应该不会太难。Python并不是这里的最佳选择,但仍然可以在合理的时间内找到数字

import numpy as np
import time

max_number = 1000000000

# array for results
arr = np.zeros(max_number, dtype='int8')

# starting time
t0 = time.time()

# some tracking for the time spent
time_spent = []

# go through all possible numbers up to the larges possible factor
for p in range(2, int(np.sqrt(max_number))):
    # if the number of factors for the number > 0, it is not a prime, jump to the next
    if arr[p] > 0:
        continue
    # if we have a prime, we will have to go through all its powers < max_number
    n = p
    while n < max_number:
         # increment the counter at n, 2n, 3n, ...
        arr[n::n] += 1
        # take the next power
        n = n * p
    # track the time spent

print "Time spent calculating the table of number of factors: {0} s".format(time.time()-t0)

# now we have the big primes left, but their powers are not needed any more
# they need to be taken into account up to max_number / 2
j = 0
for p in range(p + 1, (max_number + 1) / 2):
    if arr[p] > 0:
        continue
    arr[p::p] += 1
    if j % 10000 == 0:
        print "{0} at {1} s".format(p, time.time()-t0)
    j += 1

print "Primes up to {0} done at {1} s".format(p, time.time()-t0)
# now we have only big primes with no multiples left, they will be all 1
arr[arr == 0] = 1

print "Factor table done at {0} s".format(time.time() - t0)

# calculate the odd/even balance, note that 0 is not included and 1 has 0 factors
cumulative = np.cumsum(1 - 2 * (arr[1:] & 1), dtype='int32')
print "Total time {0} s".format(time.time()-t0)
将numpy导入为np
导入时间
最大数量=100000000
#结果数组
arr=np.zero(最大值,dtype='int8')
#开始时间
t0=时间。时间()
#对花费的时间进行一些跟踪
花费的时间=[]
#检查所有可能的数字,直到最大可能的系数
对于范围(2,int(np.sqrt(max_数))中的p:
#如果数字的因子数>0,则它不是素数,请跳到下一个
如果arr[p]>0:
持续
#如果我们有一个素数,我们将必须通过它的所有幂0:
持续
arr[p::p]+=1
如果j%10000==0:
在{1}s.处打印“{0}”。格式(p,time.time()-t0)
j+=1
打印“在{1}完成的{0}之前的素数”。格式(p,time.time()-t0)
#现在我们只有大素数,没有倍数了,它们都是1
arr[arr==0]=1
打印“系数表在{0}完成”。格式(time.time()-t0)
#计算奇偶平衡,注意不包括0,1有0个因子
累计=np.cumsum(1-2*(arr[1::&1),dtype='int32')
打印“总时间{0}s”。格式(time.time()-t0)
这不是最快或最优化的函数,其背后的数学原理应该非常明显。在我的机器(i7)中,运行在一个内核上,计算素数因子的完整表大约需要2800秒,最大值为1 x 10^9。(但请注意,在没有64位python和至少8GB RAM的情况下不要尝试此操作。累积和表消耗4GB。)

为了证明上述函数至少运行得相当好,下面是一个有趣区域的图:


由于第一个数字存在一些问题,上面代码给出的结果略有偏差。要获得正式的Liouville lambda总结,请使用
累积[n-1]+2
。对于问题中提到的数字(906 316 571),结果是
累积[906316570]+2
等于829,这是该地区的最大值。

50年前,他们不太可能尝试暴力计算方法。他们可能使用了更先进的分析技术来缩小搜索空间。也许你应该阅读中列出的一些参考资料,了解他们是如何做到这一点的。
import numpy as np
import time

max_number = 1000000000

# array for results
arr = np.zeros(max_number, dtype='int8')

# starting time
t0 = time.time()

# some tracking for the time spent
time_spent = []

# go through all possible numbers up to the larges possible factor
for p in range(2, int(np.sqrt(max_number))):
    # if the number of factors for the number > 0, it is not a prime, jump to the next
    if arr[p] > 0:
        continue
    # if we have a prime, we will have to go through all its powers < max_number
    n = p
    while n < max_number:
         # increment the counter at n, 2n, 3n, ...
        arr[n::n] += 1
        # take the next power
        n = n * p
    # track the time spent

print "Time spent calculating the table of number of factors: {0} s".format(time.time()-t0)

# now we have the big primes left, but their powers are not needed any more
# they need to be taken into account up to max_number / 2
j = 0
for p in range(p + 1, (max_number + 1) / 2):
    if arr[p] > 0:
        continue
    arr[p::p] += 1
    if j % 10000 == 0:
        print "{0} at {1} s".format(p, time.time()-t0)
    j += 1

print "Primes up to {0} done at {1} s".format(p, time.time()-t0)
# now we have only big primes with no multiples left, they will be all 1
arr[arr == 0] = 1

print "Factor table done at {0} s".format(time.time() - t0)

# calculate the odd/even balance, note that 0 is not included and 1 has 0 factors
cumulative = np.cumsum(1 - 2 * (arr[1:] & 1), dtype='int32')
print "Total time {0} s".format(time.time()-t0)