Dilbert
Dilbert

Reputation: 101

using numpy fromfunction to fill a matrix with a custom function

This is related to another question I have except there I am looking for a vectorized/broadcasting solution.

Here I am hoping to try using np.fromfunction but am having issues.

The MWE is

# L1 and L2 will range from 0 to 3 typically, sometimes up to 5
# all of the following are dummy values but match correct `type`
L1, L2, x1, x2, fac = 2, 3, 2.0, 4.5, 2.3
saved_values = np.random.uniform(high=75.0, size=[max(L1,L2) + 1, max(L1,L2) + 1]) 
facts = np.random.uniform(high=65.0, size=[L1 + L2 + 1])
val = 0

for i in range(L1+1):
    sf = saved_values[L1][i] * x1 ** (L1 - i)
    for j in range(L2 + 1):
        m = i + j
        if m % 2 == 0:
            num = sf * facts[m] / (2 * fac) ** (m / 2)
            val += saved_values[L2][j] * x1 ** (L1 - j) * num

rather than use a double for loop, which is not vectorized and potentially slower (being vectorized is more important for me), I would like to use np.fromfunction to fill a matrix with the necessary values

I tried the following

matrix = np.fromfunction(lambda i, j:
                         saved_values[L1][i] * x1 ** (L1 - i) *
                         saved_values[L2][j] * x2 ** (L2 - j) *
                         facts[i+j] / (2 * fac) **( (i+j) / 2),
                         (L1+1,L2+1)
                         )

This generates the double for loop matrix, I then need to go over it and make anything that would fail (i+j) % 2 == 0 have a zero value, and then sum all elements in the matrix.

However

I get the following error

Traceback (most recent call last):                                                                                                                                                 
  File "main.py", line 54, in <module>                                                                                                                                             
    (L1+1,L2+1)                                                                                                                                                                    
  File "/usr/lib/python3/dist-packages/numpy/core/numeric.py", line 1808, in fromfunction                                                                                          
    return function(*args,**kwargs)                                                                                                                                                
  File "main.py", line 53, in <lambda>                                                                                                                                             
    facts[i+j] / (2 * fac) **( (i+j) / 2),                                                                                                                                         
IndexError: arrays used as indices must be of integer (or boolean) type

Upvotes: 0

Views: 885

Answers (1)

Valdi_Bo
Valdi_Bo

Reputation: 30991

As I suppose, you think that the function passed as the first parameter to np.fromfunction is called several times, for each combination of i and j.

Unfortunately, this is not the case. To see the actual way how it operates, make such experiment:

def myFun(i, j):
    print(f'myFun:\n{i.shape}\n{i}\n{j.shape}\n{j}')
    rv = i + j
    return rv

I deliberately put a trace printout, to show what I mean.

Then run it:

np.fromfunction(myFun, (2, 3))

The result is:

myFun:
(2, 3)
[[0. 0. 0.]
 [1. 1. 1.]]
(2, 3)
[[0. 1. 2.]
 [0. 1. 2.]]

array([[0., 1., 2.],
       [1., 2., 3.]])

The first part is the printout, occuring only once and the second - the actual result. Note that:

  • shapes of both i and j are (2,3),
  • both i and j are actually arrays, not integers,
  • the whole computation is performed by addition of both arrays.

So the conclusions are that:

  • the passed function operates in a vectorized way, on arrays of parameters, adding respective elements and returning the result,
  • your concept is probably impossible to implement.

Upvotes: 4

Related Questions