|
| 1 | +cd(@__DIR__) |
| 2 | +include("dual_number_arithmetic.jl") |
| 3 | + |
| 4 | +using CairoMakie |
| 5 | +function lotka_volterra(x,α) |
| 6 | + # right-hand-side of lotka-volterra system |
| 7 | + # inputs: |
| 8 | + # - x : current state x[1] = population of prey, |
| 9 | + # x[2] = populaiton of predator |
| 10 | + # - α : hunting efficiency of predator species |
| 11 | + # returns: |
| 12 | + # - dx/dt : rate of change of population sizes |
| 13 | + |
| 14 | + dx = [x[1] - x[1]*x[2]; |
| 15 | + -2*x[2] + α*x[1]*x[2]] |
| 16 | + return dx |
| 17 | +end |
| 18 | + |
| 19 | +# or when messing around with unicode symbols .... |
| 20 | +function lotka_volterra(x,α) |
| 21 | + # right-hand-side of lotka-volterra system |
| 22 | + # inputs: |
| 23 | + # - x : current state x[1] = population of prey, |
| 24 | + # x[2] = populaiton of predator |
| 25 | + # - α : hunting efficiency of predator species |
| 26 | + # returns: |
| 27 | + # - dx/dt : rate of change of population sizes |
| 28 | + |
| 29 | + 🐇, 🐺 = x |
| 30 | + d🐇 = 🐇 - α*🐇*🐺 |
| 31 | + d🐺 = -🐺 + α*🐇*🐺 |
| 32 | + return [d🐇, d🐺] |
| 33 | +end |
| 34 | + |
| 35 | +function simulate_lotka_volterra(x0,α,h,N) |
| 36 | + # simulator for lotka volterra system (explicit Euler) |
| 37 | + # inputs: |
| 38 | + # - x0 : initial condition |
| 39 | + # - α : hunting efficiency of predator |
| 40 | + # - h : step size |
| 41 | + # - N : number of steps |
| 42 | + # outputs: |
| 43 | + # - trajectory : Vector of population sizes, entry for each time point visisted |
| 44 | + # during integration |
| 45 | + # - time_points: Vector of time points visisted during integration |
| 46 | + trajectory = [x0] |
| 47 | + time_points = range(0, N*h, length=N+1) |
| 48 | + for i in 1:N |
| 49 | + x_current = trajectory[end] # current state |
| 50 | + x_hat = x_current + h*lotka_volterra(x_current,α) # explicit euler prediction |
| 51 | + push!(trajectory, x_hat) |
| 52 | + end |
| 53 | + return trajectory, time_points |
| 54 | +end |
| 55 | + |
| 56 | +# initial condition for the simulation |
| 57 | +x0 = [1.0, 0.25] |
| 58 | +# step size |
| 59 | +h = 0.01 |
| 60 | +# time horizon (0.0, N*h) |
| 61 | +N = 1500 |
| 62 | +# parameter range for the predator efficiency |
| 63 | +α_range = 1.2:0.01:2.8 |
| 64 | + |
| 65 | +# gradient prediction by automatic differentiation |
| 66 | +# |
| 67 | +# please complete the |
| 68 | +# to that end, recall that |
| 69 | +# x0_dual = [x0[1] + ∂x0[1]/∂α * ϵ, x0[2] + ∂x0[2]/∂α * ϵ] |
| 70 | +# α_dual = [α + ∂α/∂α * ϵ] |
| 71 | +# since we want to compute the sensitivity of the final state wrt. parameter α |
| 72 | +#α = DualNumber(1.5,?) |
| 73 | +#x0_dual = [DualNumber(?,?), DualNumber(?,?)] |
| 74 | +α = DualNumber(1.5, 1.0) |
| 75 | +x0_dual = [DualNumber(x0[1], 0.0), DualNumber(x0[2],0.0)] |
| 76 | + |
| 77 | + |
| 78 | +# propagate dual numbers through simulation: |
| 79 | +dual_trajectory, time_points = simulate_lotka_volterra(x0_dual, α, h, N) |
| 80 | + |
| 81 | +############## |
| 82 | +### No more modifications needed beyond this point |
| 83 | +############## |
| 84 | + |
| 85 | +# General Lotka-Volterra system oscilaltions |
| 86 | +trajectory, time_points = simulate_lotka_volterra(x0, 0.25, h, N) |
| 87 | + |
| 88 | +fig = Figure(fontsize=18); |
| 89 | +ax_prey = Axis(fig[1,1], ylabel = "prey population", xlabel = "time") |
| 90 | +ax_predator = Axis(fig[2,1], ylabel = "predator population", xlabel = "time") |
| 91 | +lines!(ax_prey, time_points, [x[1].val for x in dual_trajectory]) |
| 92 | +lines!(ax_predator, time_points, [x[2].val for x in dual_trajectory]) |
| 93 | +display(fig) |
| 94 | + |
| 95 | +# parameter dependence of the final state x(N*h) on α |
| 96 | +x_final = [] |
| 97 | +for α in α_range |
| 98 | + trajectory, time_points = simulate_lotka_volterra(x0, α, h, N) |
| 99 | + push!(x_final, trajectory[end]) |
| 100 | +end |
| 101 | + |
| 102 | +fig = Figure(fontsize=18); |
| 103 | +ax_prey = Axis(fig[1,1], ylabel = "prey population at $(N*h) months", xlabel = "α") |
| 104 | +ax_predator = Axis(fig[2,1], ylabel = "predator population at $(N*h) months", xlabel = "α") |
| 105 | +lines!(ax_prey, α_range, [x[1] for x in x_final]) |
| 106 | +lines!(ax_predator, α_range, [x[2] for x in x_final]) |
| 107 | +scatter!(ax_prey, [α.val], [dual_trajectory[end][1].val], color = :red) |
| 108 | +lines!(ax_prey, [α.val-0.2, α.val+0.2], |
| 109 | + [dual_trajectory[end][1].val - 0.2*dual_trajectory[end][1].grad, |
| 110 | + dual_trajectory[end][1].val + 0.2*dual_trajectory[end][1].grad], |
| 111 | + color = :red) |
| 112 | + |
| 113 | +scatter!(ax_predator, [α.val], [dual_trajectory[end][2].val], color = :red) |
| 114 | +lines!(ax_predator, [α.val-0.2, α.val+0.2], |
| 115 | + [dual_trajectory[end][2].val - 0.2*dual_trajectory[end][2].grad, |
| 116 | + dual_trajectory[end][2].val + 0.2*dual_trajectory[end][2].grad], |
| 117 | + color = :red) |
| 118 | +display(fig) |
| 119 | + |
| 120 | + |
0 commit comments