-6

When I try to run my code, I get this problem:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

I cannot understand what and where exactly I should change to fix the problem.

import numpy as np

n = int(input("Enter the value of n for the nxn matrix: "))

a=np.fromfunction(lambda i, j: n if i==j else (i+1) + (j+1) , (n,n), dtype=int)
print(a)
LordPol
  • 1
  • 2
  • In your own words, where the code says `lambda i, j: n if i==j else (i+1) + (j+1)`, what do you think will be the values of `i` and `j` each time the `lambda` gets used? How many times do you think it will be used? Why? Did you try to read the documentation, in order to understand how `np.fromfunction` works? – Karl Knechtel Apr 12 '23 at 11:33
  • Exactly what do you want to happen when the code runs? What should be the resulting value of `a`, for an example `n` value? More importantly: **is this a question** about how `np.fromfunction` works, or is it a question about how to get the result you want? – Karl Knechtel Apr 12 '23 at 11:34
  • The result should be a matrix in which the diagonal numbers are equal to the `n` integer that was input by the user, while other numbers in the matrix are equal to `(i+1) + (j+1)`. My concern is what I should change in the code to make it run. – LordPol Apr 12 '23 at 11:38
  • What's so important about using `fromfunction`? To use it, your function has to work with arrays, as shown in the answer. Instead you've written a function that works with scalar inputs. – hpaulj Apr 12 '23 at 15:03
  • Did you pay attention to the error traceback? You should have included that in your question. It clearly shows that `fromfunction` calls `np.indices` and passes that to your function. I added a duplicate that tries to describe that action in more detail. – hpaulj Apr 12 '23 at 16:14

1 Answers1

0

I think you're assuming that your function is being called n * n times, each time with a new pair of possible indices 0..n. Try printing the values to see what's going on:

>>> import numpy as np

>>> n = 3
>>> def f(i, j):
...     print(i)
...     print(j)
...     return n if i==j else (i+1) + (j+1)

>>> np.fromfunction(f, (n,n), dtype=int)
[[0 0 0]
 [1 1 1]
 [2 2 2]]
[[0 1 2]
 [0 1 2]
 [0 1 2]]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\Python\Python311\site-packages\numpy\core\numeric.py", line 1866, in fromfunction
    return function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<stdin>", line 4, in f
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Instead, the function is being called just once with a meshgrid of the possible indices!

In the ... if i == j else ... part, after i and j have been compared, you're left with a boolean array with both True and False values, so numpy is unsure what to do.


Instead, rely on np.where for this kind of if-else logic, and possibly use a little bit of broadcasting for efficiency:

>>> xs, ys = np.indices((n, n), sparse=True)
>>> np.where(np.eye(n), n, xs + ys + 2)
array([[5, 3, 4, 5, 6],
       [3, 5, 5, 6, 7],
       [4, 5, 5, 7, 8],
       [5, 6, 7, 5, 9],
       [6, 7, 8, 9, 5]])
Chrysophylaxs
  • 5,818
  • 3
  • 10
  • 21
  • Thank you for your help, but I am worried is it possible to create a matrix using exactly `np.fromfunction()` or not. – LordPol Apr 12 '23 at 11:27
  • @LordPol Sure, but you end up with essentially the same `np.where` construct inside your lambda, which `np.fromfunction` then calls: `np.fromfunction(lambda i, j: np.where(i == j, n, i + j + 2), (n, n), dtype=int)`. – Chrysophylaxs Apr 12 '23 at 19:12