Scrashdown
Scrashdown

Reputation: 557

Python Numpy error : setting an array element with a sequence

I'm quite new to Python and Numpy, so I apologize if I'm missing something obvious here.

I have a function that solves a system of 2 differential equations :

import numpy as np
import numpy.linalg as la

def solve_ode(x0, a0, beta, t):
    At = np.array([[0.23*t, (-10**5)*t], [0, -beta*t]], dtype=np.float32)

    # get eigenvalues and eigenvectors
    evals, V = la.eig(At)
    Vi = la.inv(V)

    # get e^At coeff
    eAt = V @ np.exp(evals) @ Vi

    xt = eAt*x0
    return xt

However, running it with this code :

import matplotlib.pyplot as plt

# initial values
x0 = 10**6
a0 = 2.5
beta = 0.05

t = np.linspace(0, 3600, 360)

plt.semilogy(t, solve_ode(x0, a0, beta, t))

... throws this error :

ValueError: setting an array element with a sequence.

At this line :

At = np.array([[0.23*t, (-10**5)*t], [0, -beta*t]], dtype=np.float32)

Note that t and beta are supposed to be floats. I think Python might not be able to infer this but I don't know how I could do this...

Thx in advance for your help.

Upvotes: 0

Views: 950

Answers (3)

hpaulj
hpaulj

Reputation: 231365

As others note the problem is the 0 in the inner list. It doesn't match the 360 length arrays generated by the other expressions. np.array can make an object dtype array from that (2x2), but can't make a float one.

At = np.array([[0.23*t, (-10**5)*t], [0*t, -beta*t]])

produces a (2,2,360) array. But I suspect the rest of that function is built around the assumption that At is (2,2) - a 2d square array with eig, inv etc.

What is the return xt supposed to be?

Does this work?

S = np.array([solve_ode(x0, a0, beta, i) for i in t])

giving a 1d array with the same number of values as in t?

I'm not suggesting this is the fastest way of solving the problem, but it's the simplest, especially if you are only generating 360 values.

Upvotes: 0

adrin
adrin

Reputation: 4886

When you give a list or a list of lists, or in this case, a list of list of listss, all of them should have the same length, so that numpy can automatically infer the dimensions (shape) of the resulting matrix.

In your example, it's all correctly put, except the part you put 0 as a column I guess. Not sure what to call it though, cause your expected output is a cube I suppose.

You can fix it by giving the correct number of zeros as bellow:

At = np.array([[0.23*t, (-10**5)*t], [np.zeros(len(t)), -beta*t]], dtype=np.float32)

But check the .shape of the resulting array, and make sure it's what you want.

Upvotes: 1

Ed Smith
Ed Smith

Reputation: 13206

You are supplying t as a numpy array of shape 360 from linspace and not simply a float. The resulting At numpy array you are trying to create is then ill formed as all columns must be the same length. In python there is an important difference between lists and numpy arrays. For example, you could do what you have here as a list of lists, e.g.

At = [[0.23*t, (-10**5)*t], [0, -beta*t]]

with dimensions [[360 x 360] x [1 x 360]].

Alternatively, if all elements of At are the length of t the array would work,

At = np.array([[0.23*t, (-10**5)*t], [t, -beta*t]], dtype=np.float32)

with shape [2, 2, 360].

Upvotes: 1

Related Questions