### Check out Sage Math! www.sagemath.org (I'll help you set it up)
### STOCHASTIC
### Initialize some stuff
var('t dt tf Tprint')
var('at m i')
X = [100,100,100,100,100] ## holds [species], ICs (n0,n1,n2,n3,n4)
k = [0.1,0.1,0.1,0.1,0.2,0.2,0.2,0.2,10.0] ## holds rate constants (4x k+,4x k-)
a = [0,0,0,0,0,0,0,0,0] ## holds calc'd rxn rates (once they ARE calculated)
r = [0,0,0,0,0,0,0,0,0] ## holds the random numbers (once they ARE created)
sol = [] ## holds the solution
t = 0 ## time, start
tf = 200 ## time, end
dt = 0.01 ## time, step (observational frequency)
m = len(a) ## the number of reactions under consideration
Tprint = t
### Loop 0: continues until target time ###
while (t<tf):
at = 0 ## 'overall reaction rate'; takes into account all reactions
## calculate the current reaction rates
## forward reactions:
a[0] = k[0]*X[0]
a[1] = k[1]*X[1]
a[2] = k[2]*X[2]
a[3] = k[3]*X[3]
## reverse reactions:
a[4] = k[4]*X[1]
a[5] = k[5]*X[2]
a[6] = k[6]*X[3]
a[7] = k[7]*X[4]
## irreversible activation:
a[8] = k[8]*X[4]
for j in range(0,m):
at = at + a[j] ## calculate the 'overall reaction rate'
r[j] = random() ## generate the needed random numbers
t = t+(1/at)*ln(1/r[0]) ## next rxn occurs in time increment 'tau'
while(t>=Tprint): ## until the next reaction occurs..
sol.append([Tprint,X[0],X[1],X[2],X[3],X[4]]) ## the concentrations stay the same
Tprint=Tprint+dt ## as time increments
i = 1 ## (which reaction is being investigated)
while (i <= m): ## and when a reaction DOES occur...
sum = 0
for l in range(0,i):
sum = sum + a[l] ## sum together the rates (for normalization)
if (sum > r[1]*at): ## randomly select a value (0, total rate)
if (i == 1): ## if value falls within rate #1, rxn #1 occurs
X[0] = X[0] - 1
X[1] = X[1] + 1
X[2] = X[2]
X[3] = X[3]
X[4] = X[4]
break
elif (i == 2): ## if value falls within rate #2, rxn #2 occurs
X[0] = X[0]
X[1] = X[1] - 1
X[2] = X[2] + 1
X[3] = X[3]
X[4] = X[4]
break
elif (i == 3): ## if value falls within rate #3, rxn #3 occurs
X[0] = X[0]
X[1] = X[1]
X[2] = X[2] - 1
X[3] = X[3] + 1
X[4] = X[4]
break
elif (i == 4): ## if value falls within rate #4, rxn #4 occurs
X[0] = X[0]
X[1] = X[1]
X[2] = X[2]
X[3] = X[3] - 1
X[4] = X[4] + 1
break
elif (i == 5): ## if value falls within rate #5, rxn #5 occurs
X[0] = X[0] + 1
X[1] = X[1] - 1
X[2] = X[2]
X[3] = X[3]
X[4] = X[4]
break
elif (i == 6): ## if value falls within rate #6, rxn #6 occurs
X[0] = X[0]
X[1] = X[1] + 1
X[2] = X[2] - 1
X[3] = X[3]
X[4] = X[4]
break
elif (i == 7): ## if value falls within rate #7, rxn #7 occurs
X[0] = X[0]
X[1] = X[1]
X[2] = X[2] + 1
X[3] = X[3] - 1
X[4] = X[4]
break
elif (i == 8): ## if value falls within rate #8, rxn #8 occurs
X[0] = X[0]
X[1] = X[1]
X[2] = X[2]
X[3] = X[3] + 1
X[4] = X[4] - 1
break
elif (i == 9): ## if value falls within rate #9, rxn #9 occurs
X[0] = X[0]
X[1] = X[1]
X[2] = X[2]
X[3] = X[3]
X[4] = X[4] - 1
break
else:
show("something went wrong...")
i = i + 1
#show(sol)
### Simple Plotting
sol0 = []
sol1 = []
sol2 = []
sol3 = []
sol4 = []
sol5 = []
for q in range(0,len(sol)):
sol0.append(sol[q][0])
sol1.append(sol[q][1])
sol2.append(sol[q][2])
sol3.append(sol[q][3])
sol4.append(sol[q][4])
sol5.append(sol[q][5])
a = list_plot([])
a += list_plot(zip(sol0,sol1), color='indianred')
a += list_plot(zip(sol0,sol2), color='lightsalmon')
a += list_plot(zip(sol0,sol3), color='khaki')
a += list_plot(zip(sol0,sol4), color='lightgreen')
a += list_plot(zip(sol0,sol5), color='lightblue')
#a.set_axes_range(0,100,0,200) ## (xmin,xmax,ymin,ymax)
#show(a)