Why does Julia (DifferentialEquations.jl) JumpProblem stop jumping at later times? - julia

I am trying to implement a discrete stochastic simulation using tools from DifferentialEquations.jl. It works great for earlier time-points but does not do any jumps later on, inexplicably.
using DifferentialEquations
using Plots
#initial conditions
far1_ic = 0
cln_ic = 100
ste12_ic = 1000
far1cln_ic = 0
u0 = [far1_ic, cln_ic, ste12_ic, far1cln_ic]
#paramaters
#Far1
ks_F = 10 #1
kd_F = 0.01 #2
kd_F_C = 0.01 #3
kA_C = 200 #4
ks_F_S = 200 #5
#Cln
ks_C = 10 #6
kd_C = 0.1 #7
kA_F = 500 #8
ks_C_C = 100 #9
#Ste12
ks_S_alpha = 80 #10
ks_S = 1 #11
ks_S_S = 100 #12
kd_S = 0.01 #13
kA_S = 500 #14
kd_S_F = 0.005 #15
#Far1Cln
ks_FC = 100 #16
kd_FC = 0.05 #17
krev_FC = 600 #18
#misc
alpha = 17 #19
power_alpha = 1 #20
alpha_halfmax = 50 #21
p = [ks_F, kd_F, kd_F_C, kA_C, ks_F_S, ks_C, kd_C, kA_F, ks_C_C,
ks_S_alpha, ks_S, ks_S_S, kd_S, kA_S, kd_S_F, ks_FC, kd_FC,
krev_FC, alpha, power_alpha, alpha_halfmax];
s_far1(u,p,t) = (p[5] * ((u[3]^2)/(u[3]^2+p[14]^2)) + p[1]) * (p[19]^p[20]/(p[19]^p[20]+p[21]^p[20]))
d_far1(u,p,t) = p[2]*u[1] + p[3]*u[1]*u[2]
s_cln(u,p,t) = p[6] + p[9]*((u[2]^2)/(u[2]^2+p[4]^2))
d_cln(u,p,t) = p[7]*u[2]
s_ste12(u,p,t) = p[11]+(p[10]+p[12]*(u[3]^2/(u[3]^2+p[14]^2)))*(p[19]^p[20]/(p[19]^p[20]+p[21]^p[20]))
d_ste12(u,p,t) = p[13]*u[3] + p[15]*u[1]*u[3]
s_far1cln(u,p,t) = p[16]*u[1]*u[2]
d_far1cln(u,p,t) = p[17]*u[4]
r_far1cln(u,p,t) = p[18]*u[4]
function syn_f(integrator)
integrator.u[1] += 1
end
function deg_f(integrator)
integrator.u[1] -= 1
end
function syn_c(integrator)
integrator.u[2] += 1
end
function deg_c(integrator)
integrator.u[2] -= 1
end
function syn_s(integrator)
integrator.u[3] += 1
end
function deg_s(integrator)
integrator.u[3] -= 1
end
function syn_fc(integrator)
integrator.u[4] += 1
integrator.u[1] -= 1
integrator.u[2] -= 1
end
function deg_fc(integrator)
integrator.u[4] -= 1
end
function rev_fc(integrator)
integrator.u[4] -= 1
integrator.u[1] += 1
integrator.u[2] += 1
end
jump1 = ConstantRateJump(s_far1, syn_f)
jump2 = ConstantRateJump(d_far1, deg_f)
jump3 = ConstantRateJump(s_cln, syn_c)
jump4 = ConstantRateJump(d_cln, deg_c)
jump5 = ConstantRateJump(s_ste12, syn_s)
jump6 = ConstantRateJump(d_ste12, deg_s)
jump7 = ConstantRateJump(s_far1cln, syn_fc)
jump8 = ConstantRateJump(d_far1cln, deg_fc)
jump9 = ConstantRateJump(r_far1cln, rev_fc)
p[19] = 27 # reset parameter alpha
tspan = (0.0,600.0) #time span
prob = DiscreteProblem(u0,tspan,p) # variables must be discrete. Provide IC, span, paramaters.
jump_prob = JumpProblem(prob,DirectFW(),jump1,jump2,jump3,jump4,jump5,jump6,jump7,jump8,jump9,save_positions=(false,false))
sol = solve(jump_prob,SSAStepper(),saveat=1);
plot of simulation
I have tried saving all positions instead of only at every integer. I have tried using Direct instead of DirectFW. I have tried using default instead of SSAStepper. I checked the ODESolution object and it really does just repeat the same values at each timestep later on; it's not just the plot.
Really appreciate any advice!

This was a bug that has been fixed. Run ]up and your code will work.

Related

Direved and integral problème [SCILAB]

I'm working on a project that calculates the derivative of the speed and the integral of the acceleration.
my problem is that I have a lot of acceleration points and speed over time and I can not find the right program for that.
example:
acceleration from 0 km / h to 40 km / h in 5 seconds
from 5 to 10 seconds, the speed is constant 40km/h;
from 10 to 17 seconds there is a deceleration from 40 km / h to 20 km / h
So dv/dt = (v2-v1)/(t2-t1) but I don't know how to declare multiple variables for v1 v2 t1 t2
function a=acc(v1,v2,t1,t2)
a= (v2-v1)/(t2-t1)
endfunction
v1=
v2=
t1=
t2=
disp(acc(v1,v2,t1,t2),'acc = ')
and the same for the integral of (dv/dt)*dt
please help me guys
V(1:5) = linspace(0,40,5);
V(6:10) = 40;
V(11:17) = linspace(40,20,7);
Acc = diff(V);
First we populate a array V with your values for the speed.
Then we create an array Acc with the acceleration a each seconds with diffsince there's only 1s between two values of V.
Another solution based on what you wrote
function a=acc_2(v1,v2,t1,t2)
a= (v2-v1)./(t2-t1) // since v,t are vectors, we need './' and not '/' !
endfunction
V(1:5) = linspace(0,40,5);
V(6:10) = 40;
V(11:17) = linspace(40,20,7);
v1 = V(1:$-1);
v2 = V(2:$);
t1 = 1:length(V)-1;
t2 = 2:length(V);
Acc_2 = acc_2(v1,v2,t1,t2)
And if you want to have h(x) = int_t0^x dv/dt dt then use cumsum
H = cumsum(Acc)
i put this code
V(1:5) = linspace(0,40,5);
V(6:10) = 40;
V(11:17) = linspace(40,20,7);
function a = acc(V)
a=diff(V)
endfunction
function aa = acc_2(v1,v2,t1,t2)
aa = (v2-v1)/(t2-t1)
endfunction
v1 = V(1:$-1);
v2 = V(2:$);
t1 = 1:length(V)-1;
t2 = 2:length(V);
Acc_2 = acc_2(v1,v2,t1,t2)
but he gives me the result of a single variable of Acc_2 ?

Julia ldlfact and sparse conversion

I'm trying to solve a linear system in Julia with ldlfact. Why am I getting different results in the following cases?
Setup:
srand(10)
n = 7
pre = sprand(n,n,0.5)
H = pre + pre' + speye(n,n)
p_true = rand(n)
g = H*-p_true
fac = ldltfact(H; shift=0.0)
perm = fac[:p]
p1 = zeros(n)
p2 = zeros(n)
Case 1:
LDs = sparse(fac[:LD])
q1 = LDs\-g[perm]
p1[perm] = fac[:U]\q1
H*p - H*p_true
Case 2:
q2 = fac[:LD]\-g[perm]
p2[perm] = fac[:U]\q2
H*p2 - H*p_true
The solution p1 is wrong in the first case.
Couldn't post this nicely as a comment, so wanted to add for posterity. Solving Case 1 in the following way worked for this example (thanks to #DanGetz's post)
L = copy(LDs)
for i=1:size(L,1)
L[i,i] = 1.0
end
D = sparse(1:size(L,1),1:size(L,1),diag(LDs))
q1 = (L*D)\-g[perm]
p1[perm] = L'\q1
H*p1 - H*p_true

Time complexity of doubly recursive function

So this is the code:
int test ( int n)
{
if (n ≤2) return 1;
else return test(n-2) * test(n-2);
}
I'm not confident in how to reason about this recursive function. I tried mapping the N value to the recursion depth like so:
N = 2 -> 0 recursions
N = 4 -> 2
N = 8 -> 14
But to be honest I'm not sure this gets me anywhere (and just thinking about test(16) hurts my head.
Let's start by writing out a recurrence relation for the total number of calls made:
T(0) = T(1) = T(2) 1, since there's one total call (the initial call).
T(n+2) = 2T(n) + 1, since there's one call for the initial call, plus two recursive calls to problems of size n.
Let's start by looking at the case where n is even. Then
T(0) = 1
T(2) = 1
T(4) = 2T(2) + 1 = 3
T(6) = 2T(4) + 1 = 7
T(8) = 2T(6) + 1 = 15
T(9) = 2T(8) + 1 = 31
Except for the 0 case, it looks like these values take on the pattern 1, 3, 7, 15, 31, etc. Notice that each of these is one less than a power of two: 1 = 2 - 1, 3 = 4 - 1, 7 = 8 - 1, etc. We can guess that what we're looking at has something to do with powers of two.
Going back to our sequence, we might make a guess that
T(2) = 1 = 21 - 1
T(4) = 3 = 22 - 1
T(6) = 7 = 23 - 1
...
T(2n) = 2n - 1
So if n is even, we have T(n) = 2n/2 - 1 = (√2)n - 1. You can formalize this using a proof by induction.
For the odd case, we basically get the same thing:
T(1) = 1
T(3) = 2T(1) + 1 = 3
T(5) = 2T(3) + 1 = 7
T(7) = 2T(5) + 1 = 15
T(9) = 2T(7) + 1 = 31
...
T(2n+1) = 2n - 1
So if n is even, then T(n) = 2(n-1)/2 - 1. Again, you can prove this by induction to formalize things if you'd like.

Difference in local & let scoping rule?

In the following example:
Fs = cell(2)
i = 1
for i = 1:2
local i # same as local i = i
Fs[i] = () -> i
end
println(Fs[1]()) # 1
println(Fs[2]()) # 2
println(i) # 1
Is it true that local i is the same as local i = i?
Why cannot I do the same for while loop as such?
Fs = cell(2)
i = 1
while i <= 2 #LoadError: UndefVarError: i not define
local i = i
Fs[i] = ()->i
i += 1
end
But have to use let:
Fs = cell(2)
i = 1
while i <= 2
let i = i
Fs[i] = ()->i
end
i += 1
end
println(Fs[1]()) # 1
println(Fs[2]()) # 2
When you introduce new variable, and try to get it's value before assignment, Julia throws an UndefVarError error, in the first example:
Fs = cell(2)
i = 1
for i = 1:2
local i # same as local i = i
Fs[i] = () -> i
end
println(Fs[1]()) # 1
println(Fs[2]()) # 2
println(i) # 1
For block introduces a new local i, adn for command itself assign it so the code successfully dose it's duty. But in the second example:
Fs = cell(2)
i = 1
while i <= 2 #LoadError: UndefVarError: i not define
local i = i
Fs[i] = ()->i
i += 1
end
A new i was introduced in while block, but before assignment you try to get it's value, and this produces an error.
In 3d one let command declare a new local block and a new i variable for it's block.
julia> function test3()
Fs = cell(2)
i = 1
while i <= 2
let i = 100
println(i)
end
i += 1
end
println(i)
end
test3 (generic function with 1 method)
julia> test3()
100
100
3# while block use the function's scope

Strange BASIC math formula

I like converting old BASIC games - I ran across one that had this odd formula. Currently I am writing in Pascal, but I can write it in any language. After rummaging through the code, I could not find if this var in use, but still would like to know what kind of math shortcut BASIC was using back in the day.
d1 = 1-(( 0.23 + random / 10 ) * (-(d <= 50 )))
d1 is a dummy var, d = depth of sub
I broke it down into steps and found that part (-(d <= 50)) causes my compile to fail.
Can someone shed some light on to it?
-(d <= 50) should, AFAIK (boolean -> int conversion), return -1 if d <= 50 and 0 if d > 50. To sum up, if d > 50, the right part of multiplication will be equal to 0, so d1 will be equal to 1. You should write it using else or ternary construct (C-like pseudocode below):
d1 = (d > 50) ? 1 : 1.23 + random / 10;
Step by step explanation:
d1 = 1-(( 0.23 + random / 10 ) * (-(d <= 50 )))
then
if ( d <= 50 )
d1 = 1-(( 0.23 + random / 10 ) * (-TRUE)))
else
d1 = 1-(( 0.23 + random / 10 ) * (-FALSE)))
then
if ( d <= 50 )
d1 = 1-(( 0.23 + random / 10 ) * (-1)))
else
d1 = 1-(( 0.23 + random / 10 ) * (-0)))
then
if ( d <= 50 )
d1 = 1 - (( 0.23 + random / 10 ) * -1))
else
d1 = 1 - (( 0.23 + random / 10 ) * 0))
then
if ( d <= 50 )
d1 = 1 - (-( 0.23 + random / 10 ))
else
d1 = 1 - (0)
then
if ( d <= 50 )
d1 = 1 + ( 0.23 + random / 10 );
else
d1 = 1;
then, finally
d1 = (d > 50) ? 1 : 1.23 + random / 10;

Resources