Home > Software engineering >  Is it possible to vectorize the following function?
Is it possible to vectorize the following function?

Time:12-20

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.
  • Related