2
$\begingroup$

I have the following function that has been vectorized so that for every element in input array t, an array is output:

@np.vectorize
def Ham(t):
    d=np.array([[np.cos(t),np.sqrt(t)],[0,1]],dtype=np.complex128)
    return d

I am getting an error: TypeError: only length-1 arrays can be converted to Python scalars. I believe this error happens when there is conflicts with numpy and python, but I can't see where that would be. Also, if the dtype is not given, the error is ValueError: setting an array element with a sequence. I'm guessing you can't assign arrays inside arrays in python, but how else can I do this?

$\endgroup$

1 Answer 1

5
$\begingroup$

The problem is that np.cos(t) and np.sqrt(t) generate arrays with the length of t, whereas the second row ([0,1]) maintains the same size. To use np.vectorize with your function, you have to define the output type, and np.vectorize isn't really meant as a decorator except for the simplest cases. In this way however you can generate the function with the right type:

def Ham(t):
    d=np.array([[np.cos(t),np.sqrt(t)],[0,1]],dtype=np.complex128)
    return d

HamVec = np.vectorize(Ham, otypes=[np.ndarray])

Now you can use HamVec as a function:

>>> x=np.array([1,2,3])
>>> HamVec(x)
array([ array([[ 0.54030231+0.j,  1.00000000+0.j],
       [ 0.00000000+0.j,  1.00000000+0.j]]),
       array([[-0.41614684+0.j,  1.41421356+0.j],
       [ 0.00000000+0.j,  1.00000000+0.j]]),
       array([[-0.98999250+0.j,  1.73205081+0.j],
       [ 0.00000000+0.j,  1.00000000+0.j]])], dtype=object)

Notes:

  1. The np.vectorize is just a convenience function, it doesn't actually make code run any faster.
  2. This question might have been more suitable for StackOverflow.

Edit: as an answer to the follow up question: the resulting values of the matrix are of type numpy.complex128:

>>> y = HamVec(x)
>>> type(y[0][0][0])
<type 'numpy.complex128'>

And you can do for example:

>>> y*np.complex('3+2j')
array([ array([[ 1.62090692+1.08060461j,  3.00000000+2.j        ],
       [ 0.00000000+0.j        ,  3.00000000+2.j        ]]),
       array([[-1.24844051-0.83229367j,  4.24264069+2.82842712j],
       [ 0.00000000+0.j        ,  3.00000000+2.j        ]]),
       array([[-2.96997749-1.97998499j,  5.19615242+3.46410162j],
       [ 0.00000000+0.j        ,  3.00000000+2.j        ]])], dtype=object)
$\endgroup$
5
  • $\begingroup$ That worked, thanks! I just have another question though. Is there a way to change the output to be of type cfloat? I tried converting it inside the function, but it always returns an array of dtype=object $\endgroup$
    – Alex
    Commented Jan 11, 2016 at 17:14
  • $\begingroup$ Are you sure this matters? The values in the result matrix are in fact of type numpy.complex128. Also see this question. $\endgroup$
    – agold
    Commented Jan 11, 2016 at 17:35
  • $\begingroup$ Hmm I thought the dtype=object meant that the result matrix was of object type. Is there a reason why it says that it is of type object and not complex128? $\endgroup$
    – Alex
    Commented Jan 11, 2016 at 19:10
  • $\begingroup$ I have added an example to the answer. $\endgroup$
    – agold
    Commented Jan 11, 2016 at 19:17
  • $\begingroup$ Okay sorry if I keep asking questions here, but I am trying to take numpy.linalg.eig of the resulting matrix, but since there is dtype=object in the matrix, I get an error. Is there a simple way of removing dtype in the output array? $\endgroup$
    – Alex
    Commented Jan 12, 2016 at 1:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.