The solution meshgrid / where / indexing is already very fast. I did it about 65% faster. This is not too much, but I still explain it: step by step:
, 2D 3 x M. meshgrid - ( , 3D- >= 1.7, vstack + reshape . :
>>> np.vstack(np.meshgrid(*[np.arange(0, 2)]*3)).reshape(3,-1)
array([[0, 0, 1, 1, 0, 0, 1, 1],
[0, 0, 0, 0, 1, 1, 1, 1],
[0, 1, 0, 1, 0, 1, 0, 1]])
3D-. 1x1x1 ( 1 1 ).
vectors ( 3D-, ). bool , mod2:
mod2bool = np.sum(vectors, axis=0) % 2 == 0
np.sum(vectors, axis=0) 1 x M, . , mod2bool 1 x M bool . bool:
vectorsubset = vectors[:,mod2bool]
(:) , numpy. , numpy:
lengths = np.sqrt(np.sum(vectorsubset**2, axis=0))
- scipy.stats.ss bottleneck.ss , .
, :
with np.errstate(divide='ignore'):
p = (r/lengths)**n
, Inf . . numpy errstate , .
( inf) :
return np.sum(p[np.isfinite(p)])
. , , ss nansum. , np.where((x*x+y*y+z*z)!=0), Inf s , , isfinite.
import sys
import numpy as np
import bottleneck as bn
N = 100
n = 12
r = np.sqrt(2)
x,y,z = np.meshgrid(*[np.arange(-N, N+1)]*3)
gridvectors = np.vstack((x,y,z)).reshape(3, -1)
def measure_time(func):
import time
def modified_func(*args, **kwargs):
t0 = time.time()
result = func(*args, **kwargs)
duration = time.time() - t0
print("%s duration: %.3f s" % (func.__name__, duration))
return result
return modified_func
@measure_time
def method_columnvecs(vectors):
mod2bool = np.sum(vectors, axis=0) % 2 == 0
vectorsubset = vectors[:,mod2bool]
lengths = np.sqrt(np.sum(vectorsubset**2, axis=0))
with np.errstate(divide='ignore'):
p = (r/lengths)**n
return np.sum(p[np.isfinite(p)])
@measure_time
def method_columnvecs_opt(vectors):
mod2bool = bn.nansum(vectors, axis=0) % 2 == 0
lengths = np.sqrt(bn.ss(vectors[:,mod2bool]))
with np.errstate(divide='ignore'):
p = (r/lengths)**n
return bn.nansum(p[np.isfinite(p)])
@measure_time
def method_original(x,y,z):
ind = np.where((x+y+z)%2==0)
x = x[ind]
y = y[ind]
z = z[ind]
ind = np.where((x*x+y*y+z*z)!=0)
x = x[ind]
y = y[ind]
z = z[ind]
p=np.sqrt(x*x+y*y+z*z)/r
return np.sum((1/p)**n)
@measure_time
def method_original_finitesum(x,y,z):
ind = np.where((x+y+z)%2==0)
x = x[ind]
y = y[ind]
z = z[ind]
lengths = np.sqrt(x*x+y*y+z*z)
with np.errstate(divide='ignore'):
p = (r/lengths)**n
return np.sum(p[np.isfinite(p)])
print method_columnvecs(gridvectors)
print method_columnvecs_opt(gridvectors)
print method_original(x,y,z)
print method_original_finitesum(x,y,z)
:
$ python test.py
method_columnvecs duration: 1.295 s
12.1318801965
method_columnvecs_opt duration: 1.162 s
12.1318801965
method_original duration: 1.936 s
12.1318801965
method_original_finitesum duration: 1.714 s
12.1318801965
. isfinite . , , , : -)
: , N = 3 12. . 12,1317530867 N = 3. ?