Как читать систему дифференциальных уравнений из текстового файла для решения системы с помощью scipy.odeint?

У меня есть большая (> 2000 уравнений) система ODE, которую я хочу решить с odeint python scipy.

У меня есть три проблемы, которые я хочу решить (может быть, мне придется задать 3 разных вопроса?). Для простоты я объясню их здесь с игрушечной моделью, но, пожалуйста, имейте в виду, что моя система большая. Предположим, что у меня есть следующая система ODE:

dS/dt = -beta*S dI/dt = beta*S - gamma*I dR/dt = gamma*I 

с бета = c p I

где c, p и gamma – параметры, которые я хочу передать в odeint.

odeint ожидает такой файл:

 def myODEs(y, t, params): c,p, gamma = params beta = c*p S = y[0] I = y[1] R = y[2] dydt = [-beta*S*I, beta*S*I - gamma*I, - gamma*I] return dydt 

который затем можно передать в odeint следующим образом:

 myoutput = odeint(myODEs, [1000, 1, 0], np.linspace(0, 100, 50), args = ([c,p,gamma], )) 

Я сгенерировал текстовый файл в Mathematica, скажем, myOdes.txt, где каждая строка файла соответствует RHS моей системы ODE, поэтому она выглядит так

 #myODEs.txt -beta*S*I beta*S*I - gamma*I - gamma*I 

Мой текстовый файл похож на то, что ожидает odeint, но я пока не совсем там. У меня есть три основные проблемы:

  1. Как передать мой текстовый файл, чтобы odeint понимал, что это RHS моей системы?
  2. Как я могу определить свои переменные разумным способом, то есть систематически? Поскольку есть 2000 экземпляров, я не могу их вручную определить. В идеале я бы определил их в отдельном файле и прочитал это.
  3. Как передать параметры (их тоже много) в качестве текстового файла?

Я прочитал этот вопрос , близкий к моим проблемам 1 и 2, и попытался его скопировать (я прямо поставил значения для параметров, чтобы мне не пришлось беспокоиться о моей точке 3 выше):

  systemOfEquations = [] with open("myODEs.txt", "r") as fp : for line in fp : systemOfEquations.append(line) def dX_dt(X, t): vals = dict(S=X[0], I=X[1], R=X[2], t=t) return [eq for eq in systemOfEquations] out = odeint(dX_dt, [1000,1,0], np.linspace(0, 1, 5)) 

но я получил ошибку:

  odepack.error: Result from function call is not a proper array of floats. ValueError: could not convert string to float: -((12*0.01/1000)*I*S), 

Изменить: я изменил свой код на:

  systemOfEquations = [] with open("SIREquationsMathematica2.txt", "r") as fp : for line in fp : pattern = regex.compile(r'.+?\s+=\s+(.+?)$') expressionString = regex.search(pattern, line) systemOfEquations.append( sympy.sympify( expressionString) ) def dX_dt(X, t): vals = dict(S=X[0], I=X[1], R=X[2], t=t) return [eq for eq in systemOfEquations] out = odeint(dX_dt, [1000,1,0], np.linspace(0, 100, 50), ) 

и это работает (я не совсем понимаю, что делают первые две строки цикла for). Тем не менее, я хотел бы сделать процесс определения переменных более автоматическим, и я до сих пор не знаю, как использовать это решение и передать параметры в текстовом файле. Вдоль тех же строк, как я могу определить параметры (которые будут зависеть от переменных) внутри функции dX_dt?

Заранее спасибо!

  • Sympy: Решение матриц в конечном поле
  • Python - SymPy - Принудительный Sympy для поддержания порядка
  • проблема с отображением sympy rendered svg в python
  • Хотите сделать мульти-вариационный минимум с помощью sympy
  • Предотвратите замену Sympy уравнения
  • Как форматировать контурные линии от Matplotlib
  • Как решить пару нелинейных уравнений с использованием Python?
  • SymPy / SciPy: решение системы обыкновенных дифференциальных уравнений с различными переменными
  • One Solution collect form web for “Как читать систему дифференциальных уравнений из текстового файла для решения системы с помощью scipy.odeint?”

    Это не полный ответ, а скорее некоторые замечания / вопросы, но они слишком длинны для комментариев.

    dX_dt вызывается много раз по odeint с 1d массивом y и tuple t . Вы предоставляете t через параметр args . y генерируется odeint и изменяется с каждым шагом. dX_dt должен быть оптимизирован, чтобы он dX_dt быстро.

    Обычно выражение system [eq for eq in systemOfEquations] может быть упрощено для systemOfEquations . [eq for eq...] не делает ничего значимого. Но это может быть что-то о systemOfEquations которое это требует.

    Я предлагаю вам распечатать systemOfEquations (для этого небольшого 3-строчного), как для вашей выгоды, так и для нас. Вы используете sympy для перевода строк из файла в уравнения. Нам нужно посмотреть, что он производит.

    Обратите внимание, что myODEs – это функция, а не файл. Он может быть импортирован из модуля, который, конечно же, является файлом.

    Точка to vals = dict(S=X[0], I=X[1], R=X[2], t=t) – это создать словарь, с sympy могут работать выражения sympy . Более прямая (и, я думаю, быстрее) функция dX_dt будет выглядеть так:

     def myODEs(y, t, params): c,p, gamma = params beta = c*p dydt = [-beta*y[0]*y[1], beta*y[0]*y[1] - gamma*y[1], - gamma*y[1]] return dydt 

    Я подозреваю, что dX_dt который запускает генерируемые выражением sympy, будет намного медленнее, чем «жестко закодированный».

    Я собираюсь добавить тег sympy , потому что, как написано, это ключ к переводу вашего текстового файла в функцию, odeint может использовать odeint .

    Я бы склонялся к изменению вариации уравнения в параметрах t , а скорее в списке симплексных выражений.

    Это заменяет:

      dydt = [-beta*y[0]*y[1], beta*y[0]*y[1] - gamma*y[1], - gamma*y[1]] 

    с чем-то вроде

      arg12=np.array([-beta, beta, 0]) arg1 = np.array([0, -gamma, -gamma]) arg0 = np.array([0,0,0]) dydt = arg12*y[0]*y[1] + arg1*y[1] + arg0*y[0] 

    Как только это будет правильно, определения argxx могут перемещаться за пределы dX_dt и передаваться через args . Теперь dX_dt – это простой и быстрый расчет.

    Весь этот sympy подход может работать нормально, но я боюсь, что на практике это будет медленным. Но у кого-то с более sympy опытом могут быть другие идеи.

    Python - лучший язык программирования в мире.