You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从scipy.odeint中返回非微分类型的额外值?

解决scipy.odeint中额外值存储过量的问题

问题根源

odeint采用自适应步长算法,为保证求解精度,会在内部多次调用你的model函数(调用次数远多于你指定的t数组长度),直接在model里追加值自然会导致列表长度远超预期。

实用解决方案

方案1:仅在指定输出时间点存储额外值

通过判断当前调用model时的t是否属于你定义的输出时间点(注意浮点数比较要加容差),只在这些时刻存储值:

import numpy as np
from scipy.integrate import odeint

def model(y, t, target_times, tol=1e-8):
    dydt = -2 * y
    x = np.random.rand(1,1)
    # 检查当前时间是否在目标输出时间点中(规避浮点数误差)
    if np.any(np.abs(t - target_times) < tol):
        addtional_value.append(x)
    return dydt

y0 = 5
addtional_value = []
t = np.arange(0, 5, 1)

# 把目标时间点传给model函数
y = odeint(model, y0, t, args=(t,))

print(len(y))          # 输出5
print(len(addtional_value))  # 输出5

方案2:将额外值打包进状态变量

把不需要微分的额外值作为状态的一部分,设置它们的导数为0,求解后再分离出需要的部分:

import numpy as np
from scipy.integrate import odeint

def model(y, t):
    # y[0]是原状态变量,y[1]是额外值
    dydt = np.zeros_like(y)
    dydt[0] = -2 * y[0]
    dydt[1] = 0  # 额外值的导数设为0,保持状态稳定
    y[1] = np.random.rand()  # 更新当前额外值
    return dydt

y0 = np.array([5, 0])  # 初始状态:原变量+额外值初始占位
t = np.arange(0, 5, 1)

y_full = odeint(model, y0, t)
y = y_full[:, 0]  # 提取原ODE的解
addtional_value = y_full[:, 1]  # 提取额外值

print(len(y))  # 输出5
print(len(addtional_value))  # 输出5

方案3:改用solve_ivp(推荐,更灵活)

如果可以切换到scipy.integrate.solve_ivp,它支持自定义输出回调,能精准控制何时存储额外值:

import numpy as np
from scipy.integrate import solve_ivp

addtional_value = []

def model(t, y):
    dydt = -2 * y
    return dydt

def store_extra(t, y):
    x = np.random.rand(1,1)
    addtional_value.append(x)
    return 0  # 回调返回值不影响求解逻辑

y0 = [5]
t_span = [0, 4]
t_eval = np.arange(0, 5, 1)

# 用t_eval指定输出点,回调函数在每个t_eval点触发
sol = solve_ivp(model, t_span, y0, t_eval=t_eval, events=store_extra)

print(len(sol.y[0]))  # 输出5
print(len(addtional_value))  # 输出5

方案说明

  • 方案1适合只需要在指定输出时间点获取额外值的场景,注意容差设置要合理,避免漏判或误判。
  • 方案2不需要额外传参,但会增加状态变量维度,适合额外值数量不多的情况。
  • 方案3的solve_ivp是scipy官方推荐的新一代求解器,功能更丰富,回调机制更可靠。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:22:13