我一直在检查如何对外部和内部for
循环进行矢量化。这些都有一些计算,还有一个删除 - 这似乎使它更不直接。
如何最好地进行矢量化?
import numpy as np
flattenedArray = np.ndarray.tolist(someNumpyArray)
#flattenedArray is a python list of lists.
c = flattenedArray[:]
for a in range (len(flattenedArray)):
for b in range(a+1, len(flattenedArray)):
if a == b:
continue
i0 = flattenedArray[a][0]
j0 = flattenedArray[a][1]
z0 = flattenedArray[a][2]
i1 = flattenedArray[b][0]
i2 = flattenedArray[b][1]
z1 = flattenedArray[b][2]
if ((np.square(z0-z1)) <= (np.square(i0-i1) + (np.square(j0-j2)))):
if (np.square(i0-i1) + (np.square(j0-j1))) <= (np.square(z0+z1)):
c.remove(flattenedArray[b])
答案 0 :(得分:1)
import numpy as np
N = 4
data = np.random.random((N, 3))
# vectorised code
j, i = np.tril_indices(N, -1) # chose tril over triu to have contiguous columns
# useful later
sqsum = np.square(data[i,0]-data[j,0]) + np.square(data[i,1]-data[j,1])
cond = np.square(data[i, 2] + data[j, 2]) >= sqsum
cond &= np.square(data[i, 2] - data[j, 2]) <= sqsum
# because equal 'b's are grouped together we can use reduceat:
cond = np.r_[False, np.logical_or.reduceat(
cond, np.add.accumulate(np.arange(N-1)))]
left = data[~cond, :]
# original code (modified to make it run)
flattenedArray = np.ndarray.tolist(data)
#flattenedArray is a python list of lists.
c = flattenedArray[:]
for a in range (len(flattenedArray)):
for b in range(a+1, len(flattenedArray)):
if a == b:
continue
i0 = flattenedArray[a][0]
j0 = flattenedArray[a][1]
z0 = flattenedArray[a][2]
i1 = flattenedArray[b][0]
j1 = flattenedArray[b][1]
z1 = flattenedArray[b][2]
if ((np.square(z0-z1)) <= (np.square(i0-i1) + (np.square(j0-j1)))):
if (np.square(i0-i1) + (np.square(j0-j1))) <= (np.square(z0+z1)):
try:
c.remove(flattenedArray[b])
except:
pass
# check they are the same
print(np.alltrue(c == left))
答案 1 :(得分:0)
如果使用蒙版,对内部循环进行矢量化并不是一个大问题:
S <- 0.25 ### !!! Change this to "24" and see how another plot will appear !!! ###
Ur <- c(0.25, 24, 16)
if(S>=1){
plot(1, 1, type = "n", xlim = c(0,1.5), ylim = c(1/3, 100), log="y", bty="n", ann=F, axes=F, xaxs="i")
axis(side=1, at = seq(0,1.5,.25),labels = c("0",".25",".5",".75","1","1.25","1.5"))
axis(side=2, at = c(1/3, 1, 3, 10, 30, 100),labels = c("1/3", "1", "3", "10", "30", "100"),las=1)
}else{
plot(1, 1, type = "n", xlim = c(0,1.5), ylim = c(.01, 3), log="y", bty="n", ann=F ,axes=F, xaxs="i")
axis(side=1, at = seq(0,1.5,.25),labels = c("0",".25",".5",".75","1","1.25","1.5"))
axis(side=2, at = c(.01, 1/30, 1/10, 1/3, 1, 3),labels = c("1/100", "1/30", "1/10", "1/3", "1", "3"),las=1)
}
legend(0, (10^par("usr"))[4], bquote(paste("Selected Prior: ",bold('PN'[10])," = ", .(round(S,3)))), ## Legend
pch = 21,cex=2,pt.bg="green", col="red", pt.cex=2.8, bty="n")
如果你还想要对外循环进行矢量化,则必须通过广播来实现,但是会使用大量内存import numpy as np
# I'm using a random array
flattenedArray = np.random.randint(0, 100, (10, 3))
mask = np.zeros(flattenedArray.shape[0], bool)
for idx, row in enumerate(flattenedArray):
# Calculate the broadcasted elementwise addition/subtraction of this row
# with all following
added_squared = np.square(row[None, :] + flattenedArray[idx+1:])
subtracted_squared = np.square(row[None, :] - flattenedArray[idx+1:])
# Check the conditions
col1_col2_added = subtracted_squared[:, 0] + subtracted_squared[:, 1]
cond1 = subtracted_squared[:, 2] <= col1_col2_added
cond2 = col1_col2_added <= added_squared[:, 2]
# Update the mask
mask[idx+1:] |= cond1 & cond2
# Apply the mask
flattenedArray[mask]
而不是O(n**2)
。鉴于关键的内部循环已经被矢量化,因此通过矢量化外部循环将不会有很多加速。