Ответ 1
Кажется, что новая функция не имеет параметра args
. В качестве обходного пути вы можете создать обертку, например
def wrapper(t, y):
orig_func(t,y,hardcoded_args)
и передать это.
Для решения простых ODE с помощью SciPy я использовал функцию odeint с формой:
scipy.integrate.odeint(func, y0, t, args=(), Dfun=None, col_deriv=0, full_output=0, ml=None, mu=None, rtol=None, atol=None, tcrit=None, h0=0.0, hmax=0.0, hmin=0.0, ixpr=0, mxstep=0, mxhnil=0, mxordn=12, mxords=5, printmessg=0)[source]
где простая интегрируемая функция может включать дополнительные аргументы в форме:
def dy_dt(t, y, arg1, arg2):
# processing code here
В SciPy 1.0 кажется, что функции ode и odeint были заменены более новым методом solve_ivp.
scipy.integrate.solve_ivp(fun, t_span, y0, method='RK45', t_eval=None, dense_output=False, events=None, vectorized=False, **options)
Однако, похоже, что здесь нет ни параметра args, ни каких-либо указаний в документации на реализацию передачи аргументов.
Поэтому мне интересно, возможна ли передача аргументов с помощью нового API, или эта функция еще не добавлена? (Мне показалось бы упущением, если бы эти функции были намеренно удалены?)
Ссылка: https://docs.scipy.org/doc/scipy/reference/integrate.html
Кажется, что новая функция не имеет параметра args
. В качестве обходного пути вы можете создать обертку, например
def wrapper(t, y):
orig_func(t,y,hardcoded_args)
и передать это.
Относительно недавно появился похожий вопрос о scipy github. Их решение заключается в использовании lambda
:
solve_ivp(fun=lambda t, y: fun(t, y, *args), ...)
И они утверждают, что накладных расходов уже достаточно, чтобы это не имело значения.
Недавно в solve_ivp была добавлена опция 'args', смотрите здесь: https://github.com/scipy/scipy/issues/8352#issuecomment-535689344
В добавление к ответу Клеба приведен пример использования метода lambda t,y: fun(t,y,args)
. Мы установили дескриптор функции, который возвращает rhs однородного ODE второго порядка с двумя параметрами. Затем мы передаем его нашему решателю вместе с несколькими вариантами.
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
def rhs_2nd_order_ode(t, y, a, b):
"""
2nd order ODE function handle for use with scipy.integrate.solve_ivp
Solves u'' + au'+ bu = 0 after reducing order with y[0]=u and y[1]=u'.
:param t: dependent variable
:param y: independent variables
:param a: a
:param b: b
:return: Returns the rhs of y[0]' = y[1] and y[1]' = -a*y[1] - b*y[0]
"""
return [y[1], -a*y[1] - b*y[0]]
if __name__ == "__main__":
t_span = (0, 10)
t_eval = np.linspace(t_span[0], t_span[1], 100)
y0 = [0, 1]
a = 1
b = 2
sol = integrate.solve_ivp(lambda t,y: rhs_2nd_order_ode(t,y,a,b), t_span, y0,
method='RK45', t_eval=t_eval)
fig, ax = plt.subplots(1, 1)
ax.plot(sol.t, sol.y[0])
ax.set(xlabel='t',ylabel='y')
Для полноты, я думаю, что вы также можете сделать это, но я не уверен, почему вы будете беспокоиться о двух других опциях, опубликованных здесь, которые выглядят идеально.
from functools import partial
fun = partial(dy_dt, arg1=arg1, arg2=arg2)
scipy.integrate.solve_ivp(fun, t_span, y0, method='RK45', t_eval=None, dense_output=False, events=None, vectorized=False, **options)