python – Premiums and SemiPrimes in Binary


I am re-learning the python. My current effort is an implementation around the main factorization. I am trying to reproduce something similar to the table found here (in binary):
https://math.stackexchange.com/questions/586010/relative-size-of-most-factors-of-semiprimes-close

The performance seems rather appalling. I've looked at profiling the code in cProfile but I do not see any obvious improvement.

I consider:
(a) Install PyPy to see if that improves performance and
(b) Take even more advantage of Numpy, even if, precisely, how is a bit vague for me. I am working on the following to see if this can help:
https://www.freecodecamp.org/news/if-you-have-slow-loops-in-python-you-can-fix-it-un-you-cant-3a39e03b6f35/

I've already refactored to eliminate the need for a list of half-premiums and that helped a bit, but I'm not sure if there are obvious inefficiencies that I do not see.

miller_rabin.py is not mine. I include it here for the sake of completeness. My effort is focused on the performance of prime_stats_bin.py. I recognize that the primality test will be an important part of the cost, I just do not understand why I can not even reach the 32-bit version in a reasonable amount of time. I'm using this version on a 5-year-old Windows 10 laptop (Core i5, 2.5GHz, 8GB RAM), under Python 3.7.3 (installed yesterday).

All comments would be appreciated.

With regard to the purpose of this effort, I would like to know if it is reasonable to expect an output for the prime numbers of up to 32 bits of this program in one day.

With 32 bits in the premium extension, the list of prime numbers generated is about 2xe ^ 8, which, considering my 32-bit Python installation, can not be maintained.

prime_stats_bin.py
import maths
randomly import
import hashlib
import numpy
from miller_rabin import *
from the import time process_time

time1 = process_time ()

iexp = 2 #init exponent
poe = 2 pieces of eight
mexp = 8 * poe #max exponent
cexp = 2 #curr exponent
prime numbers = [2] #list of prime numbers
account = [] #list of count (num prime numbers, number of semi-primes, number of semi-premiums close)

f = open ("prime_stats_bin.txt", "w", encoding = "utf-8")
f.write ("BinDigits  tPrimes  tSemiprimes  tClose semiprimes  n")
for x in the range (iexp, mexp + 1): #initialize lists for all exhibitors
count.append ([1,1,1]#since are loops that look only odd prime numbers, boot with 1 in all accounts
for x in the range (3, pow (2, mexp), 2):
if numpy.log2 (x)> = cexp: #output to file when we pass a power of 2
f.write (str (cexp) + ":  t" + str (count[cexp-2][0]) + "(" + str (round ((count)[cexp-2][0]* numpy.log (pow (2, cexp))) / pow (2, cexp), 4)) + ")  t" +
str (account[cexp-2][1]) + "(" + str (round ((count)[cexp-2][1]* numpy.log (pow (2, cexp))) / (pow (2, cexp) * numpy.log (numpy.log (pow (2, cexp)))), 4)) + ")  t" +
str (account[cexp-2][2]) + "(" + str (round ((count)[cexp-2][2]* numpy.log (pow (2, cexp))) / pow (2, cexp), 4)) + ";" + str (round ((100 * accounts[cexp-2][2]) / account[cexp-2][1], 4)) + ")  n")
if cexp% 8 == 0:
f.write (elapsed time:% f seconds &%% (process_time () - time1) + " n")
cexp + = 1
if is_prime (x):
premiums.append (x)
for z in the range (iexp, mexp + 1):
if x <= pow(2,z):
                counts[z-2][0] += 1 #increment count of primes less than z taken to the power of 2
        for y in primes:
            if y*x > pow (2, mexp): #No need to worry about semi-premiums lower than our upper limit
Pause
for w in the range (iexp, mexp + 1):
if y * x <= pow (2, w):
account[w-2][1]    + = 1 number of semi-premiums lower than w taken at the power of 2
if x <= pow (y, 2):
account[w-2][2]    + = 1 # closing number (p * q = N, where p <q and q <= p ^ 2) semi-prime less than w taken at the power of 2
f.write (str (mexp) + ":  t" + str (count[mexp-2][0]) + "(" + str (round ((count)[mexp-2][0]* numpy.log (pow (2, mexp))) / pow (2, mexp), 4)) + ")  t" +
str (account[mexp-2][1]) + "(" + str (round ((count)[mexp-2][1]* numpy.log (pow (2, mexp-1))) / (pow (2, mexp) * numpy.log (numpy.log (pow (2, mexp)))), 4)) + ")  t "+
str (account[mexp-2][2]) + "(" + str (round ((count)[mexp-2][2]* numpy.log (pow (2, mexp-1))) / pow (2, mexp), 4)) + ";" + str (round ((100 * accounts[mexp-2][2]) / account[mexp-2][1], 4)) + ")  n")
f.write (elapsed time:% f seconds &%% (process_time () - time1) + " n")
f.close
miller_rabin.py
def _try_composite (a, d, n, s):
if pow (a, d, n) == 1:
returns False
for i in the interval (s):
if pow (a, 2 ** i * d, n) == n-1:
returns False
return True # n is definitely composite

def is_prime (n, _precision_for_huge_n = 16):
if n in _known_primes:
returns True
if necessary ((n% p) == 0 for p in _known_primes) or n in (0, 1):
returns False
d, s = n - 1, 0
as long as not d% 2:
d, s = d >> 1, s + 1
# Returns exactly as per http://primes.utm.edu/prove/prove2_3.html
if n <1373653:
returns no (_try_composite (a, d, n, s) for an in (2, 3))
if n <25326001:
returns no (_try_composite (a, d, n, s) for an in (2, 3, 5))
if n <118670087467:
if n == 3215031751:
returns False
returns no (_try_composite (a, d, n, s) for an in (2, 3, 5, 7))
if n <2152302898747:
returns no (_try_composite (a, d, n, s) for an in (2, 3, 5, 7, 11))
if n <3474749660383:
returns no (_try_composite (a, d, n, s) for an in (2, 3, 5, 7, 11, 13))
if n <341550071728321:
returns no (_try_composite (a, d, n, s) for an in (2, 3, 5, 7, 11, 13, 17))
# other
returns no (_try_composite (a, d, n, s)
for one in _known_primes[:_precision_for_huge_n])

_known_primes = [2, 3]
_known_primes + = [x for x in range(5, 1000, 2) if is_prime(x)]
output and timing
BinDigits Semiprimes Premiums Close semiPrimes
2: 2 (0.6931) 1 (1.061) 1 (0.3466; 100.0)
3: 4 (1.0397) 2 (0.7101) 2 (0.5199; 100.0)
4: 6 (1,0397) 6 (1,0196) 4 (0.6931; 66.6667)
5: 11 (1.1913) (0.8714)? (0.6498; 60.0)
6: 18 (1,1697) 22 (1,0031) 9 (0.5848; 40.9091)
7:31 (1,171) 42 (1,008) 17 (0.6444; 40.4762)
8: 54 (1,1697) 82 (1,0369)? (0.6065; 34.1463)
elapsed time: 0.140625 seconds
9: 97 (1,1819) 157 (1,0449) 47 (0.5727; 29.9363)
10: 172 (1,163) 304 (1.0629) 89 (0.6024; 29.2763)
11: 309 (1,1504) 589 (1.0795) 171 (0.6366; 29.0323)
12: 564 (1,1453) 1124 (1.0775) 311 (0.6315; 27.669)
13: 1028 (1,1308) 2186 (1.0937) 584 (0.6424; 26.7155)
14: 1900 (1.1253) 4192 (1.0926) 1086 (0.6432; 25.9065)
15: 3512 (1,113) 8110 (1,099) 2093 (0.6641; 25.8076)
16: 6542 (1.1071) 15658 (1.1013) 4023 (0.6808; 25.6929)
elapsed time: 27.906250 seconds
17: 12251 (1,1014) 30253 (1,1026) 7617 (0.6848; 25.1777)
18: 23000 (1.0947) 58546 (1.1041) 14597 (0.6947; 24.9325)
19: 43390 (1.0899) 113307 (1.1041) 27817 (0.6987; 24.5501)
20: 82025 (1.0844) 219759 (1,105) 53301 (0.7047; 24.2543)
21: 155611 (1.0801) 426180 (1.1046) 101532 (0.7047; 23.8237);
22: 295947 (1,076) 827702 (1,1045) 195376 (0.7103; 23.6046)
24: 1077871 (1.0688) 3129211 (1.1036) 721504 (0.7154; 23.0571);
elapsed time: 292.140625 seconds