I have the following function that I would like to vectorize in order to speed it up. the function takes one column vector of arbitrary length and must output a single number. The function is:
xs = np.array([0.3, 5.01, 13.5, -1.01, 66.0, -101.6, 41.44, 11.0, 36.2, 9.0])
def func(xs):
fitness = xs[0]
for i in xs:
if np.abs(i) > fitness:
fitness = np.abs(i - 30)
return fitness
CodePudding user response:
Let's rewrite the function to better visualize the action:
In [221]: xs = np.array([0.3, 5.01, 13.5, -1.01, 66.0, -101.6, 41.44, 11.0, 36.2, 9.0])
...: def func(xs):
...: x1 = np.abs(xs); x2 =np.abs(xs-30)
...: print(x1); print(x2)
...: fitness = x1[0]
...: for i,j in zip(x1,x2):
...: if i > fitness:
...: fitness = j
...: print(fitness)
...: return fitness
...:
In [222]: xs
Out[222]:
array([ 0.3 , 5.01, 13.5 , -1.01, 66. , -101.6 , 41.44,
11. , 36.2 , 9. ])
In [223]: func(xs)
[ 0.3 5.01 13.5 1.01 66. 101.6 41.44 11. 36.2 9. ]
[ 29.7 24.99 16.5 31.01 36. 131.6 11.44 19. 6.2 21. ]
0.3
24.990000000000002
24.990000000000002
24.990000000000002
36.0
131.6
131.6
131.6
131.6
131.6
Out[223]: 131.6
In [224]: x1 = np.abs(xs); x2 =np.abs(xs-30)
So the successive values of fitness
look a lot like the accumulated maximum of x2
:
In [225]: np.maximum.accumulate(x2)
Out[225]:
array([ 29.7 , 29.7 , 29.7 , 31.01, 36. , 131.6 , 131.6 , 131.6 ,
131.6 , 131.6 ])
Or skipping the first value of x2
:
In [226]: np.maximum.accumulate(x2[1:])
Out[226]:
array([ 24.99, 24.99, 31.01, 36. , 131.6 , 131.6 , 131.6 , 131.6 ,
131.6 ])
That's not a perfect substitute, but may give you/us some ideas of how to make it better.
CodePudding user response:
You can try,
index = np.argmax(np.abs(xs)-np.hstack([xs[0],xs][:-1]))
#basically does `abs(x[i]) - x[i-1]`
np.abs(xs[index]-30*np.bool_(index))
#30*np.bool_(index) is to make sure to return the first element as-is if its the largest element.