2010-06-16 2 views
0

* отредактировал 6/17/10Python/Biomolecular Physics - попытка кодирования простого стохастического моделирования системы, демонстрирующей условное поведение!

Я пытаюсь понять, как улучшить мой код (сделайте его более питоническим). Кроме того, я заинтересован в написании более интуитивных «условностей», которые описывали бы сценарии, которые являются обычным явлением в биохимии. Условные критерии в приведенной ниже программе, которые я объяснил в ответе № 2, но меня не устраивает код - он работает отлично, но не является очевидным и нелегко реализовать для более сложных условных сценариев. Идеи приветствуются. Комментарии/критика приветствуются. Первый опыт публикации @ stackoverflow - прокомментируйте этикет, если необходимо.

код создает список значений, которые являются решением для следующего упражнения:

«В языке программирования по вашему выбору, реализация первой реакции Джиллеспи алгоритм для изучения временной ход реакции А --- > В, в котором переход от А к В может иметь место только в том случае, если присутствует другое соединение С, и где С динамически взаимно преобразуется с D, как смоделировано в Петри-сети ниже. Предположим, что существует 100 молекул A, 1 от C, и нет B или D, присутствующих в начале реакции. Установите kAB до 0,1 с-1 и оба kCD и kDC до 1,0 с-1. Имитируйте поведение системы за 100 секунд. "

def sim(): 
    # Set the rate constants for all transitions 
    kAB = 0.1 
    kCD = 1.0 
    kDC = 1.0 

    # Set up the initial state 
    A = 100 
    B = 0 
    C = 1 
    D = 0 

    # Set the start and end times 
    t = 0.0 
    tEnd = 100.0 

    print "Time\t", "Transition\t", "A\t", "B\t", "C\t", "D" 

    # Compute the first interval 
    transition, interval = transitionData(A, B, C, D, kAB, kCD, kDC) 
    # Loop until the end time is exceded or no transition can fire any more 
    while t <= tEnd and transition >= 0: 
     print t, '\t', transition, '\t', A, '\t', B, '\t', C, '\t', D 
     t += interval 
     if transition == 0: 
      A -= 1 
      B += 1 
     if transition == 1: 
      C -= 1 
      D += 1 
     if transition == 2: 
      C += 1 
      D -= 1 
     transition, interval = transitionData(A, B, C, D, kAB, kCD, kDC) 


def transitionData(A, B, C, D, kAB, kCD, kDC): 
    """ Returns nTransition, the number of the firing transition (0: A->B, 
    1: C->D, 2: D->C), and interval, the interval between the time of 
    the previous transition and that of the current one. """ 
    RAB = kAB * A * C 
    RCD = kCD * C 
    RDC = kDC * D 
    dt = [-1.0, -1.0, -1.0] 
    if RAB > 0.0: 
     dt[0] = -math.log(1.0 - random.random())/RAB 
    if RCD > 0.0: 
     dt[1] = -math.log(1.0 - random.random())/RCD 
    if RDC > 0.0: 
     dt[2] = -math.log(1.0 - random.random())/RDC 
    interval = 1e36 
    transition = -1 
    for n in range(len(dt)): 
     if dt[n] > 0.0 and dt[n] < interval: 
      interval = dt[n] 
      transition = n 
    return transition, interval  


if __name__ == '__main__': 
    sim() 
+4

Трудно разобрать ваш фактический вопрос из задыхающегося потока потока сознания. Не могли бы вы обобщить, каков ваш фактический вопрос на самом деле, чтобы мы могли на него ответить? –

+0

Кажется, что бит монте-карло это неверно. Если 'dt [2]' меньше 1e36, тогда переход всегда будет равен 2. Я признаю, что я не совсем понимаю такое моделирование, но эти части кажутся мне подозрительными. Похоже, что 'dt' следует использовать каким-то образом в качестве весов для случайного определения того, какой процесс будет проходить. Существует случайность, но похоже, что это происходит неправильно. –

+0

Спасибо, ребята. Мне еще предстоит посмотреть на Монте Карло, Джастин, но я прокомментирую, как только я доберусь до него. С. Лотт, ты прав, я плохо разбираюсь в этом. Я немного отредактирую свой пост. Ха-ха, я только что узнал, что означает «передача возвращаемых значений вызывающему» - это была та часть, в которой я был незнаком. Мне удалось уйти с некоторыми простыми симами, определив функции с массивами до сих пор * вздох *. Но да, суть моего поста - WTF? Я думаю, что я на правильном пути. Сегодня я расскажу об этом позже. – DocDubya

ответ

1

не уверен, что вы это видели.

http://stompy.sourceforge.net/html/userguide_doc.html

Я работаю на подобные вещи, и я случайно обнаружить это в последнее время.

+0

Ссылка потрясающая. Благодаря! Начиная с публикации этого, я действительно перешел за рамки домашней работы, как это, в моделирование исследований. Вы искали метод «из коробки» для сравнения методов Direct/SSA/Tau! Ты качаешь человека. Ценить это. – DocDubya

+0

эй, хорошая ссылка. Как быстро? – Greg

0

Я не знаю алгоритм Гиллеспи, но я предполагаю, что вы проверили, что программа сходится к правильному равновесию. Поэтому я расцениваю вас вопросами, как

«Вот это рабочая программа физики, как я могу сделать его более вещим»

Это, вероятно, будет более вещим сделать что-то вроде следующего

R = [ kAB * A * C, kCD * C, kAB * A * C] 
dt = [(-math.log(1-random.random())/x,i) for i,x in enumerate(R) if x > 0] 
if dt: 
    interval,transition = min(dt) 
else: 
    transition = None 

Если вы хотите использовать python в физике, тогда я предлагаю вам изучить numpy. Потому что numpy быстрее для многих проблем. Итак, вот несколько непроверенных частей решения numpy. Добавьте следующие строки в заголовок запрограммированного

from numpy import log, array, isinf, zeros 
from numpy.random import rand 

Затем вы можете заменить внутри TransitionData что-то вроде следующего

R = array([ kAB * A * C, kCD * C, kAB * A * C]) 
dt = -log(1-rand(3))/R 
transition = dt.argmin() 
interval = dt[transition] 
if isinf(interval): 
    transition = None 

Я не знаю, будет ли это более вещим поднять StopIteration исключение вместо возврата None, но это деталь.

Вы также должны хранить свои концентрации в единой структуре данных. Если вы используете numpy, то я предлагаю вам использовать массив. Аналогично, yoy может использовать массив dABCD для хранения изменений в концентрации (возможно, вы можете найти лучшие имена переменных). Добавьте следующий код вне вашего цикла

ABCD = array([A,B,C,D]) 

dABCD = zeros(3,4) 
dABCD[0,0] = -1#A decreases when transition == 0 
dABCD[0,1] = 1 #B increases when transition == 0 
dABCD[1,2] = -1#C decreases when transition == 1 
dABCD[1,3] = 1 #D increases when transition == 1 
.....  etc 

Теперь вы можете заменить вам основной цикл что-то вроде следующего

while t <= tEnd: 
     print t, '\t', transition, '\t', ABCD 
     transition, interval = transitionData(ABCD, kAB, kCD, kDC) 
     if transition != None: 
      t += interval 
      ABCD += dABCD[transition,:] 
     else: 
      break; 
else: 
     print "Warning: Stopping due to timeout. The system did not equilibrate" 

Существует, вероятно, больше, чтобы сделать. В качестве примера dABCD, вероятно, должен быть редким массивом, но я надеюсь, что эти идеи могут стать началом.

+0

nielsle, ты мужчина. Я очень ценю вклад. Я сейчас переписываю w/numpy и matplotlib. Пожалуйста, зайдите завтра, так как я уверен, что у меня появятся вопросы - они должны быть краткими и ответственными, честь разведчика. Джастин Пил, мои мысли о монте-карло-бит были добавлены в качестве дополнительного ответа ниже (просьба прокомментировать, критика приветствуется!) Также третий «ответ» - это информация о том, что означают уравнения в контексте биофизики.Может быть, немного скучно для большинства из вас, ребята. – DocDubya

0

**** Редактировать **** Я изначально объяснил это неправильно !!!! Однако верно следующее: Justin, эта программа использует умные критерии для «веса» каждого события.Значениям RAB, RCD и RDC присваивается истинный/ложный параметр путем умножения kAB, kCD и kDC на C или D, что в этом случае может быть как одно, так и ноль. Нулевое значение D, и, таким образом RDC бы предотвратить DT [2] от вовлечения в

для п в диапазоне (LEN (DT)): , если дт [п]> 0,0 и дт [п] < интервал :

заявление. Кроме того, включено следующее:

if transition == 1: 
     C -= 1 
     D += 1 
    if transition == 2: 
     C += 1 
     D -= 1 

диктует, что, когда событие C-> D происходит (переход 1), следующее событие обязательно должно быть D-> С (переход 2), так как из трех значений в дт [ ], только dt [1] отлична от нуля и, таким образом, отвечает указанным выше критериям. Итак, как мы оцениваем вероятность перехода 0 или перехода 1? Это немного сложнее, но это присуще в следующих строках:

interval = 1e36 
transition = -1 
for n in range(len(dt)): 
    if dt[n] > 0.0 and dt[n] < interval:    
     interval = dt[n]    
     transition = n    
return transition, interval 

«для п в диапазоне (LEN (DT)):» возвращает все значения списка Dt []. Следующая строка определяет критерии, которые должны быть выполнены, а именно: каждое значение должно быть больше 0 и меньше интервала. Для перехода 0 интервал равен 1e36 (который, как предполагается, является представителем бесконечности). В результате этого интервала устанавливается переход 0, поэтому для второго значения в dt [], переход 1, критерии утверждают, что он должен быть меньше, чем dt для перехода 0, чтобы произойти ... или другими словами что, должно быть, произошло быстрее, чем вообще произошло, что согласуется с химической логикой. Моя самая большая проблема заключается в том, что накопленные значения t, предусмотренные линией «t + = interval», могут быть не совсем справедливыми ... потому что, поскольку стрельба t1 не зависит от стрельбы t0, стрельба t0 и, скажем, 1 сек, не должна исключить t1 из использования того же .1 сек для запуска ... но я работаю над исправлением для этого ... предложения приветствуются! Это подробная распечатка из сценария, в то числе обжига перехода 1 и 2:

Время перехода ABCD

dt0= 0.0350693547214 
dt1= 2.26710773787 
interval= 1e+36 
dt= 0.0350693547214 
transition= 0 

0,0 0 100 0 1 0

dt0= 0.000339596342313 
dt1= 0.21083283004 
interval= 1e+36 
dt= 0.000339596342313 
transition= 0 

0,0350693547214-99 1 1 0

dt0= 0.0510125874767 
dt1= 1.26127048627 
interval= 1e+36 
dt= 0.0510125874767 
transition= 0 

0,0354089510637 0 98 2 1 0

dt0= 0.0809691957218 
dt1= 0.593246425076 
interval= 1e+36 
dt= 0.0809691957218 
transition= 0 

0,0864215385404 0 97 3 1 0

dt0= 0.00205040633531 
dt1= 1.70623338677 
interval= 1e+36 
dt= 0.00205040633531 
transition= 0 

0,167390734262 0 96 4 1 0

dt0= 0.106140534256 
dt1= 0.0915160378053 
interval= 1e+36 
dt= 0.106140534256 
transition= 0 
interval= 0.106140534256 
dt= 0.0915160378053 
transition= 1 

0,169441140598 1 95 5 1 0

dt2= 0.0482892532952 
interval= 1e+36 
dt= 0.0482892532952 
transition= 2 

0,260957178403 2 95 5 0 1

dt0= 0.112545351421 
dt1= 1.84936696832 
interval= 1e+36 
dt= 0.112545351421 
transition= 0 

0,309246431698 0 95 5 1 0

Джастин, я не уверен, что вы имеете в виду DT [2] составляет менее 1e36, что делает его 'пребывание' на переходе 2? Этого не происходит из-за

if transition == 2: 
      C += 1 
      D -= 1 

заявление.Кто-нибудь знает о более прямом способе достижения этого

Ха-ха, пусть начнется пылающий, вы, ребята, потрясающие, хотя я очень ценю обратную связь! Stackoverflow является soooooo законным.

1

Информация о математике за простой стохастического моделирования химических rxns:

Как правило, такие процессы, как это моделируется в виде дискретных событий с каждым событием происходит с вероятностью «Р» дается конкретная константа скорости «к» и ряд возможных событий «n» в интервале времени «dt»: P = 1-e ** (- k dt n). Здесь мы пренебрегаем фактическим временем каждого события (~ 0) и фокусируемся вместо этого на промежутке времени, в которое происходит событие. Любой, кто знаком с N, выбирает проблемы K/испытания bernouli, оценят наличие 1/e, например. при N = K и N-> оо вероятность несоблюдения конкретного элемента из N приближается к 1/e. Следовательно, в стохастической химической реакции (первый порядок) вероятность того, что молекула не будет подвергаться реакции (не выбрана), представляет собой некоторую степень 1/е ..., что мощность зависит от временного интервала и константы скорости, а также от количество молекул и константа скорости, о которой идет речь. Напротив, 1- (1/e)^xyz дает вероятность того, что какая-либо конкретная молекула будет реагировать (быть выбрана).

С точки зрения моделирования было бы логично разделить наш общий временной интервал на все меньшие интервалы и использовать генератор случайных чисел для прогнозирования того, произошло ли событие за данный промежуток времени - например, если бы мы разделили dt на один, даже на 10 меньших интервалов, число от 0 до 0,1 означало бы событие, а число между .1 и 1.0 означало бы, что это не так. Тем не менее существует неопределенность относительно того, когда именно произошло событие, поэтому мы должны сократить интервалы между этими интервалами - это быстро становится проигранной битвой, поскольку неопределенность сохраняется с этим методом.

Решение этой проблемы состоит в том, чтобы взять естественный журнал ('ln' здесь, log() по умолчанию в py) обеих сторон приведенного выше уравнения и решение для dt, которое дает dt = (-ln (1 -P))/(К * п). Затем вероятность P генерируется случайным образом, давая окончательное dt для каждого события.

Смежные вопросы