Использование ODE в другом ODE с аргументами делает код очень медленным

Я написал следующий код. Это ODE, в котором есть параметр в качестве другого ODE. Как мы видим, M(m0,z,b,c) используется в другом ODE, который сам является функцией ODE. код очень медленный, может ли кто-нибудь дать мне предложение, как его улучшить?

import numpy as np
from scipy.integrate import odeint

def model(m,z,c,b):
    dmdt = ((c**2-m)/(1+z))*(6-9*(m/c**2)+3*b*(m+(m**2)))
    return dmdt


def M(m0,z,c,b):
        m = odeint(model,m0,[0,z], args= (c, b))
        mm=m[-1,0]
        return mm

def model1(H ,z,m0,c,b):
    c = 0.6
    b=0.035
    dHdt = (H/(1+z))*(6-9*(M(m0,z,c,b)/c**2)+3*b*(M(m0,z,c,b)+(M(m0,z,c,b)**2)))
    return dHdt

def model2(H0,z,m0,c,b):
    H = odeint(model1,H0,[0,z], args=(m0,c,b))
    HH=H[-1,0]
    return HH

print(model2(70,1,0.75,0.69,0.035))

Это будет медленно - на каждом этапе решения большей модели вам придется решать меньшую. Сможете ли вы решить ее аналитически?

Grisha 02.05.2018 16:26

@Grisha Нет, в бесплатных параметрах больше 100000 номеров.

David 02.05.2018 16:33

Если у вас есть один вызов дорогостоящей функции, вы не повторяете его с одними и теми же параметрами несколько раз, вы вызываете его один раз, сохраняете результат в переменной и повторно используете его там, где это необходимо. Но это все же не лучший способ ускорить вычисления, см. Ответ.

Lutz Lehmann 02.05.2018 18:28

Кроме того, вы не должны изменять параметры в model1, параметры, переданные вызовом model2, становятся недействительными из-за жестко заданных значений.

Lutz Lehmann 02.05.2018 18:32
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
24
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете решить связанную систему как связанную систему.

def model(U,z,c,b):
    M, H = U
    dMdt = ((c**2-M)/(1+z))*(6-9*(M/c**2)+3*b*(M+M**2))
    dHdt =       (H /(1+z))*(6-9*(M/c**2)+3*b*(M+M**2))
    return [dMdt, dHdt]

def solution(H0,z,m0,c,b):
    U = odeint(model,[m0,H0],[0,z], args=(c,b))[-1]
    M, H = U
    return H

print(solution(70,1,0.75,0.69,0.035))

который быстро возвращает 0.107569653042, в то время как ваш код с модификациями

 def model1(H, z, m0, c, b):
     mm = M(m0,z,c,b)
     dHdt = (H/(1+z))*(6-9*(mm/c**2)+3*b*(mm+(mm)**2)))
     return dHdt

возвращает аналогичный 0.107569746892 несколько медленнее. Эти 6 цифр совпадения соответствуют допускам ошибок по умолчанию 1e-6.

Для получения результатов с большей точностью установите контрольные параметры для допусков ошибок atol, rtol.

Для дальнейшего сокращения операций сделайте

def model(U,z,c,b):
    M, H = U
    factor = (6-9*M/c**2+3*b*(M+M**2))/(1+z)
    return [(c**2-M)*factor, H*factor]

Если ваша задача действительно масштабная, используйте скомпилированный язык программирования для быстрого вычисления массовых чисел.

Спасибо. Я не мог уловить это предложение If your task is really massive, use a compiled programming language for fast mass number crunching.

David 02.05.2018 19:05

Python хорош для быстрого прототипирования, в темные века для этой роли использовался BASIC. Но интерпретируемые языки, даже с JIT-компиляцией в байтовый код, имеют большие накладные расходы на каждую вычислительную операцию. Эти накладные расходы сводятся практически к нулю, когда вычисления компилируются в машинный код. Вы даже можете использовать тот же решатель, если можете работать с интерфейсом FORTRAN пакета решателей lsoda,.... Или используйте решатели gsl в C, обширной библиотеке решателей julia, ...

Lutz Lehmann 02.05.2018 19:19

Ах, вы предлагаете использовать FORTRAN. Спасибо. Я делаю это для других расчетов.

David 02.05.2018 19:22

Нет, вы можете использовать эти библиотеки с любым другим языком, вам нужно знать только о соглашениях о вызовах, особенно. выделение памяти или используйте оболочку, если она доступна, например scipy.integrate.odeint, которая является оболочкой python для lsoda. С другой стороны, в качестве теста я просто применил свой код к образцу 100x100 пар (b,c), и это заняло 24,6 секунды, поэтому, если вы выполняете массовые вычисления не очень часто, вы можете остаться с python и подождать 5-10 минут, которые потребуются. на 100000 проб.

Lutz Lehmann 02.05.2018 19:42

Я могу понять, что вы говорите, но я не могу реализовать их своими собственными знаниями, я физик и просто использую то, что мне нужно, но из-за отсутствия надлежащих знаний я застрял в каком-то важном вопросе. Я не использую цикл for, я использую случайный выбор для каждого параметра и для 1000000 шагов. Я думаю, это огромно.

David 02.05.2018 21:03

Другие вопросы по теме