Im trying to make a variant of the Gillespie algorithm, and to determine the reaction propensities Im trying to automatically generate the propensity vector using lambda expressions. However when creating SSA.P all goes wrong. The last loop in the block of code, PROPLOOP, returns two propensities, where the one generated using P_alternative is the correct one. The question is: how do I get the same values for SSA.P as for SSA.P_alternative?
import numpy as np
from numpy.random import uniform
class Markov:
def __init__(self,z0,t0,tf,rates,stoich):
self.S=stoich
self.z0=z0
self.rates=rates
self.P=self.propensities()
self.P_alternative=[
lambda z,rate:(0.5*rate[0]*z[0]*(z[0]-1)),
lambda z,rate:rate[1]*np.prod(z[0]),
lambda z,rate:rate[2]*np.prod(z[1]),
lambda z,rate:rate[3]*np.prod(z[1]),
lambda z,rate:rate[4]*np.prod(z[np.array([0,1])]),
lambda z,rate:rate[5]]
self.t0=t0
self.tf=tf
def propensities(self):
prop=[]
for i,reac in enumerate(self.S.T):
if all(z>=0 for z in reac):
prop.append(lambda z,rate:rate[i])
if any(z==-1 for z in reac):
j=np.where(reac==-1)[0]
prop.append(lambda z,rate:rate[i]*np.prod(z[j]))
if any(z==-2 for z in reac):
j=np.where(reac==-2)[0][0]
prop.append(lambda z,rate:(0.5*rate[i]*z[j]*(z[j]-1))[0])
return prop
stoich=np.array([
[-2, -1, 2, 0, -1, 0],
[ 1, 0, -1, -1, -1, 1],
[ 0, 0, 0, 1, 1, 0]])
rates=np.array([1.0,0.02,200.0,0.0004,0.9,0.9])
z0=np.array([540,730,0])
SSA=Markov(z0=z0,t0=0,tf=100,rates=rates,stoich=stoich)
#PROPLOOP; the values should be equal for both SSA.P and SSA.P_alternative, where SSA.P_alternative is the correct one
for i in xrange(len(SSA.P)):
print "Inexplicably wrong",SSA.P[i](z0,rates)
print "Correct answer",SSA.P_alternative[i](z0,rates), "\n"
output is:
Inexplicably wrong 130977.0
Correct answer 145530.0
Inexplicably wrong 354780.0
Correct answer 10.8
Inexplicably wrong 354780.0
Correct answer 146000.0
Inexplicably wrong 354780.0
Correct answer 0.292
Correct answer 354780.0
Correct answer 354780.0
Inexplicably wrong 0.9
Correct answer 0.9