You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用NumPy与SciPy求解动态系统时数组转标量报错求助

解决动态系统求解中的only size-1 arrays can be converted to Python scalars错误

嘿,我来帮你搞定这个问题!你遇到的报错其实是两个关键问题叠加导致的,咱们一步步拆解并修正:

错误根源分析

  1. 微分方程函数的参数顺序搞反了
    scipy.integrate.odeint要求你的微分方程函数必须遵循func(y, t, *args)的顺序——第一个参数是状态向量y,第二个是时间t。但你定义的g(t,y,B)把顺序反过来了,这会导致odeint调用时把y数组传给t参数,把t标量传给y参数,后续的np.dot(y,B)实际是在计算标量和矩阵的点乘,得到一个5×5的数组,再传给math.exp就触发了报错。

  2. 用了错误的指数函数
    Python标准库的math.exp只能处理单个标量数值,完全无法处理numpy数组。而咱们这里的计算结果是数组类型,必须用numpy提供的np.exp来处理数组输入。

修正后的代码方案

根据你可能的动态系统需求,提供两种常见的修正方案:

方案1:每个状态分量的导数对应exp(y·B)的分量

如果你的方程是每个dy_i/dt = exp( (y·B)_i )(即状态向量和矩阵点乘后,每个分量取指数作为对应状态的导数),代码如下:

import numpy as np
from scipy.integrate import odeint
import pylab

y0 = np.array([1, 3, 2, 3, 5])
b = np.array([[1], [3], [4], [2], [5]])
B = np.dot(b, b.T)  # 生成5×5的对称矩阵

# 修正参数顺序:先y,再t,最后是额外参数B
def g(y, t, B):
    # 用np.exp处理数组,替代只能处理标量的math.exp
    return np.exp(np.dot(y, B))

t = np.linspace(0, 1, 100)
# 将B作为额外参数传入odeint
y = odeint(g, y0, t, args=(B,))

# 可视化求解结果
pylab.plot(t, y)
pylab.legend(['y₁', 'y₂', 'y₃', 'y₄', 'y₅'])
pylab.xlabel('时间t')
pylab.ylabel('状态y(t)')
pylab.show()

方案2:每个状态分量的导数为二次型的指数

如果你想计算的是二次型y^T B y(一个标量)的指数,并用这个值作为所有状态分量的导数(即dy_i/dt = exp(y^T B y)),代码如下:

import numpy as np
from scipy.integrate import odeint
import pylab

y0 = np.array([1, 3, 2, 3, 5])
b = np.array([[1], [3], [4], [2], [5]])
B = np.dot(b, b.T)

def g(y, t, B):
    # 计算二次型:y^T * B * y,得到一个标量
    quadratic_term = np.dot(y, np.dot(B, y))
    # 返回和y同维度的数组,每个元素都是指数结果
    return np.full_like(y, np.exp(quadratic_term))

t = np.linspace(0, 1, 100)
y = odeint(g, y0, t, args=(B,))

# 绘图展示结果
pylab.plot(t, y)
pylab.legend(['y₁', 'y₂', 'y₃', 'y₄', 'y₅'])
pylab.xlabel('时间t')
pylab.ylabel('状态y(t)')
pylab.show()

内容的提问来源于stack exchange,提问作者Luke

火山引擎 最新活动