присвоение атрибута методу - PullRequest
1 голос
/ 09 апреля 2019

У меня есть класс для динамической системы, с методами для функции ODE, а также функцией события для завершения интеграции.Я хочу решить это с scipy.integrate.solve_ivp.Согласно документам , это делается путем присвоения атрибута вашей функции события, как myEvent.terminal = True.Однако, поскольку у меня есть все мои функции в объекте, это методы, а не сами объекты, поэтому я не могу назначать атрибуты.Есть предложения?

М (не) МЫ:

import numpy as np
from scipy.integrate import solve_ivp

class MySystem:

    def __init__(self):
        self.param_ = 1

    def dynamics(self,t,x):
        return (x-self.param)**3-x

    def event(self, t, x):
        return x

model = MySystem()
event1 = model.event
event1.terminal = True # this does not work
sol = solve_ivp(model.dynamics, [0, 100], [0, 10], events=event1)

Ответы [ 3 ]

3 голосов
/ 09 апреля 2019

Предположим, вы сделали два экземпляра MySystem:

model1 = MySystem()
model2 = MySystem()

Если бы model1.event.terminal = True было разрешено, то это также повлияло бы model2.event.terminal. Python запрещает устанавливать атрибуты методов предотвратить это удивительное действие на расстоянии. Подробнее о том, почему это запрещено, объясняется здесь .

За PEP-0232 (мой акцент):

Невозможно установить атрибуты в связанных или несвязанных методах , за исключением случаев, когда это делается явно в базовый объект функции

Можно установить атрибуты метода, используя event1.__dict__['terminal'] = True но учтите, что это влияет на все экземпляры MySystem, а не только на один экземпляр model.

Так как это влияет на MySystem.event на уровне класса, лучше установить event.terminal в определении класса, или с помощью MySystem.event.terminal = True сразу после определения класса. (Обратите внимание, что MySystem.event является базовым объектом функции упоминается в приведенной выше цитате PEP.)

import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

class MySystem:

    def __init__(self):
        self.param = 1

    def dynamics(self,t,x):
        return (x-self.param)**3-x

    def event(self, t, x):
        return x
    event.terminal = True
# MySystem.event.terminal = True       # also works


model = MySystem()
event1 = model.event
# event1.__dict__['terminal'] = True   # works, but perhaps confusing because it affects all instances

sol = solve_ivp(model.dynamics, t_span=(0, 1.5), y0=[1], events=event1)
print(sol)
plt.plot(sol['t'], sol['y'][0])
plt.scatter(sol['t_events'][0], [0], c='red')
plt.show()

enter image description here

0 голосов
/ 09 апреля 2019

Удалите self из event и добавьте @staticmethod сверху, это позволяет назначить terminal для события1.

    @staticmethod
    def event(t, x):
        return x
0 голосов
/ 09 апреля 2019

Не совсем понятно, чего вы хотите достичь. Но чтобы дать вам несколько идей:

1.Вы можете попытаться создать оболочку для события функции или заставить функцию получить объект, который может принимать входные данные, как вам нравится.

  1. вы можете передать требуемый ввод объекту модели и внутренне установить его для события или создать функцию, которая передает его событию, когда он был установлен для объекта модели.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...