Существует очень хороший ответ о том, как передать дополнительные аргументы производному оценщику в функции solve_ivp
SciPy, используя выражение lambda
.Этот подход является официальным способом работы с производными в зависимости от дополнительных аргументов, как указано в трекере ошибок github SciPy .
Этот подход, кажется, работает очень хорошо при запуске внутри скрипта Python, однако один разпри запуске внутри ядра Python среды Jupyter возникает непредсказуемое поведение, для которого я не могу определить причину.
Следующий пример основан на официальном примере .
from scipy.integrate import solve_ivp
import numpy as np
def exponential_decay(t, y, alpha, beta): return -alpha*y + beta
for alpha in np.linspace(0.5, 0.7, 5) :
beta = 1.
sol = solve_ivp(lambda t, y: exponential_decay(t, y, alpha, beta), [0, 10], [2, 4, 8])
Как только он помещается в блокнот Jupyter, локальная переменная области видимости внутри цикла for alpha
вызывает NameError
.После повторного запуска без цикла все работает хорошо.Я перезапускаю ядро перед каждым запуском всех ячеек, чтобы убедиться, что в среде нет определенных глобальных переменных.Эта ошибка сохраняется и для ядер Python 2 и Python 3.
Подробности можно найти в этой общедоступной сущности , которую я подготовил.Трассировка стека, как требуется из комментариев, выглядит следующим образом:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<timed exec> in <module>
~/.pyenv/versions/3.6.7/envs/jupyter3/lib/python3.6/site-packages/scipy/integrate/_ivp/ivp.py in solve_ivp(fun, t_span, y0, method, t_eval, dense_output, events, vectorized, **options)
454 method = METHODS[method]
455
--> 456 solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
457
458 if t_eval is None:
~/.pyenv/versions/3.6.7/envs/jupyter3/lib/python3.6/site-packages/scipy/integrate/_ivp/rk.py in __init__(self, fun, t0, y0, t_bound, max_step, rtol, atol, vectorized, first_step, **extraneous)
98 self.max_step = validate_max_step(max_step)
99 self.rtol, self.atol = validate_tol(rtol, atol, self.n)
--> 100 self.f = self.fun(self.t, self.y)
101 if first_step is None:
102 self.h_abs = select_initial_step(
~/.pyenv/versions/3.6.7/envs/jupyter3/lib/python3.6/site-packages/scipy/integrate/_ivp/base.py in fun(t, y)
137 def fun(t, y):
138 self.nfev += 1
--> 139 return self.fun_single(t, y)
140
141 self.fun = fun
~/.pyenv/versions/3.6.7/envs/jupyter3/lib/python3.6/site-packages/scipy/integrate/_ivp/base.py in fun_wrapped(t, y)
19
20 def fun_wrapped(t, y):
---> 21 return np.asarray(fun(t, y), dtype=dtype)
22
23 return fun_wrapped, y0
<timed exec> in <lambda>(t, y)
NameError: name 'alpha' is not defined
Я не очень разбираюсь в Jupyter и у меня нет идей, поэтому я хотел бы попросить вас несколько советов, здесьУ меня есть несколько основных вопросов
- Что еще можно проверить?Я проверил ошибки имен внутри цикла с использованием подхода
try ... catch NameError : ...
, и все было четко определено, как и ожидалось, однажды возникла проблема внутри лямбда-функции. - Каковы оптимальные методы работы с ноутбуками Jupyter, чтобы избежать проблемс предварительно вычисленными значениями переменных и их областью действия?Мне нравится писать простые сценарии, так как они позволяют мне не беспокоиться о таких вещах, однако возможность комментировать фрагменты кода с помощью LaTeX - это огромное преимущество, которое дает Jupyter, который я тоже очень ценю.
- Я пыталсянемного исследовать эту проблему, и, возможно, это не проблема объема, а скорее проблема указателя / ссылки (основанная на этом ответе), однако, если это так, почему проблема возникаеттолько в блокноте Jupyter, а не в простом скрипте Python?
Любая помощь, советы, примеры будут оценены.Спасибо!