Как использовать команду print () и сделать форму массива numpy согласованной во время интеграции с использованием scipy?

#python #numpy #scipy

#python #numpy #scipy

Вопрос:

Я попытался изучить, как работает spicy.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_ini и y_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_ini и y_ini , имеющий (1, 1) форму, оба print(x.shape) и print(y.shape) показали () .

Итак, вопросы:

  1. Почему print() это не сработало x_ini = y_ini = np.array([[2, 2]]) и что я должен сделать, чтобы заставить их работать?
  2. Почему форма массивов numpy, которые являются x и y стали () вместо (1, 1) .
  3. Как сделать форму массивов numpy, которые являются x и y, равными (1, 1) во время интеграции с использованием scipy. Что мне делать, если форма обоих x_ini и y_ini равна (2, 2), и я хочу сделать форму согласованной во время интеграции с использованием scipy.

Есть ли какие-нибудь ребята, которые знают об этом?

Ответ №1:

Я получаю предупреждение при использовании вашего массива начальных значений:

 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.]
...
 

Если я изменю начальное значение на a (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) выдает предупреждение.