One way is to save some work from re-invoking the toeplitz () function by caching indexes into which values are placed. The following code is 30% faster than the source code. The rest of the performance is in rank calculation ... And I don't know if there is a faster rank calculation for greenhouse matrices with 0s and 1s.
(). ~ 4 , matrix_rank scipy.linalg.det() == 0 ( , )
import random
from scipy.linalg import toeplitz, det
import numpy as np,numpy.random
class si:
indx = None
l = None
def xtoeplitz(c,r):
vals = np.concatenate((r[-1:0:-1], c))
if si.indx is None or si.l != len(c):
a, b = np.ogrid[0:len(c), len(r) - 1:-1:-1]
si.indx = a + b
si.l = len(c)
return vals[si.indx]
def doit():
for n in xrange(1,25):
rankzero = 0
si.indx=None
for repeats in xrange(5000):
column = np.random.randint(0,2,n)
row = np.r_[column[0], np.random.randint(0,2,n-1)]
matrix = xtoeplitz(column, row)
if np.abs(det(matrix))<1e-4:
rankzero += 1
print n, (rankzero*1.0)/50000