首页 > 解决方案 > 在使用 scipy 集成期间,如何使用 print() 命令并使 numpy 数组的形状保持一致?

问题描述

我尝试检查辣味.integrate.ode 的工作原理。下面的代码是执行此操作的简单代码。

def func(t, z, p):
    x = z[0]
    y = z[1]
    print('x :', x)
    print('x.shape :', x.shape)
    print('y :', y)
    print('y.shape :', y.shape)
    return [x*0, y*0]

t_ini = 0
t_fin = 1
x_ini = np.array([[2, 2]])
y_ini = np.array([[2, 2]])

solver = ode(func)
solver.set_integrator('dopri5')
solver.set_initial_value([x_ini, y_ini], t_ini)
solver.set_f_params([0])
solver.integrate(t_fin)
x_fin, y_fin = solver.y
print('x_fin :', x_fin)
print('y_fin :', y_fin)

然而,

print('x :', x)
print('x.shape :', x.shape)
print('y :', y)
print('y.shape :', y.shape)
return [x*0, y*0]

没用。代码的结果是

x_fin : [[2. 2.]]
y_fin : [[2. 2.]]

.

有趣的是,当我改变x_iniy_ini进入

x_ini = np.array([[2]])
y_ini = np.array([[2]])

print()命令有效,代码的结果是重复

x : 2.0
x.shape : ()
y : 2.0
y.shape : ()

重复后的两行是

x_fin : [[2.]]
y_fin : [[2.]]

. 奇怪的是,即使我放置x_iniy_ini具有 (1, 1) 形状,两者都print(x.shape)显示print(y.shape)()。

所以问题是:

  1. 为什么print()没有工作,x_ini = y_ini = np.array([[2, 2]])我应该怎么做才能让他们工作?
  2. 为什么 numpy 数组的形状变成 () 而不是 (1, 1) xy
  3. 如何在使用 scipy. 如果两者的形状都是x_ini( y_ini2, 2) 并且我想在使用 scipy.

有大佬知道这些吗?

标签: pythonnumpyscipy

解决方案


使用初始值数组时出现警告:

In [9]: x_ini = np.array([[2, 2]])
   ...: y_ini = np.array([[2, 2]])
In [10]: solver.set_initial_value([x_ini, y_ini], 0)
Out[10]: <scipy.integrate._ode.ode at 0x7f1ab8953d60>
In [11]: solver.integrate(.1)
/usr/local/lib/python3.8/dist-packages/scipy/integrate/_ode.py:1181: UserWarning: dopri5: input is not consistent
  warnings.warn('{:s}: {:s}'.format(self.__class__.__name__,
Out[11]: 
array([[[2., 2.]],

       [[2., 2.]]])

输出与输入相同

In [12]: np.array([x_ini, y_ini])
Out[12]: 
array([[[2, 2]],

       [[2, 2]]])

x_ini = np.array([[2]])
y_ini = np.array([[2]])

初始值为 (2,1,1) 数组

In [18]: np.array([x_ini, y_ini])
Out[18]: 
array([[[2]],

       [[2]]])

确实可以运行,但是传递给您的函数的值是 0d 数组

x : 2.0
x.shape : ()
y : 2.0
y.shape : ()

===

让我们简化一下func

In [20]: def func(t, z, p):
    ...:     print(type(z), z.shape, z)
    ...:     return z*0
    ...: 
In [21]: solver = ode(func)
    ...: solver.set_integrator('dopri5')
Out[21]: <scipy.integrate._ode.ode at 0x7f1ab6debe50>
In [22]: solver.set_f_params([0])
Out[22]: <scipy.integrate._ode.ode at 0x7f1ab6debe50>
In [23]: solver.set_initial_value([1,2], 0)
Out[23]: <scipy.integrate._ode.ode at 0x7f1ab6debe50>
In [24]: solver.integrate(.1)
<class 'numpy.ndarray'> (2,) [1. 2.]
...

如果我将初始值更改为 (2,1,1),func得到相同的输入:

In [27]: solver.set_initial_value([[[1]],[[2]]], 0)
Out[27]: <scipy.integrate._ode.ode at 0x7f1ab6debe50>
In [28]: solver.integrate(.1)
<class 'numpy.ndarray'> (2,) [1. 2.]

将输入更改为 3 元素数组:

In [31]: solver.set_initial_value([1,2,3], 0)
Out[31]: <scipy.integrate._ode.ode at 0x7f1ab6debe50>
In [32]: solver.integrate(.1)
<class 'numpy.ndarray'> (3,) [1. 2. 3.]

从文档:

f : callable ``f(t, y, *f_args)``
    Right-hand side of the differential equation. t is a scalar,
    ``y.shape == (n,)``.
    ``f_args`` is set by calling ``set_f_params(*args)``.
    `f` should return a scalar, array or list (not a tuple).

f返回dy/dt。这y将是一个一维数组,它应该返回一个类似大小的数组。注意y.shape要求。

y传递给函数的ode是从初始值数组派生的。(2,1,1) 输入被展平为 (2,)。A (2,1,2) 产生警告。


推荐阅读