We need to speed up the calls toeplitzand det:
- works in
2**klot size - create index first
toeplitz - NumPy 1.8,
det - ufunc, det .
:
import itertools
import numpy as np
from scipy.linalg import toeplitz, det
:
%%time
n = 12
todo = itertools.islice(itertools.product([0,1], repeat = 2*n-1), 0, 2**16)
r1 = []
for longtuple in todo:
A = toeplitz(longtuple[0:n], longtuple[n-1:2*n-1])
r1.append(det(A))
:
%%time
batch = 2**10
todo = itertools.islice(itertools.product([0,1], repeat = 2*n-1), 0, 2**16)
idx = toeplitz(range(n), range(n-1, 2*n-1))
r2 = []
while True:
rows = list(itertools.islice(todo, 0, batch))
if not rows:
break
rows_arr = np.array(rows)
A = rows_arr[:, idx]
r2.extend(np.linalg.det(A).tolist())
:
original: Wall time: 4.65 s
optimized: Wall time: 646 ms
:
np.allclose(r1, r2)
unpackbits():
%%time
r3 = []
todo = np.arange(0, 2**16).astype(np.uint32).byteswap().view(np.uint8).reshape(-1, 4)
for i in range(todo.shape[0]//batch):
B = np.unpackbits(todo[i*batch:(i+1)*batch], axis=-1)
rows_arr = B[:, -23:]
A = rows_arr[:, idx]
r3.extend(np.linalg.det(A).tolist())
:
Wall time: 494 ms
singcount n = 10:
%%time
count = 0
batch = 2**10
n = 10
n2 = 10*2-1
idx = toeplitz(range(n), range(n-1, 2*n-1))
todo = np.arange(0, 2**n2).astype(np.uint32).byteswap().view(np.uint8).reshape(-1, 4)
for i in range(todo.shape[0]//batch):
B = np.unpackbits(todo[i*batch:(i+1)*batch], axis=-1)
rows_arr = B[:, -n2:]
A = rows_arr[:, idx]
det = np.linalg.det(A)
count += np.sum(np.isclose(det, 0))
print count
43892, 2,15 .