# How can you constraint parameters to be positive in SciML?

**URL:** <https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777>\
**Category:** New to Julia\
**Created:** [October 15, 2022, 1:03pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777 "2022-10-15T13:03:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ak47](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ak47](https://discourse.julialang.org/u/ak47)\
**Post date:** [October 15, 2022, 1:03pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777/1 "2022-10-15T13:03:46Z")

</div>

How do you constraint parameters results in this setup to be strictly positive?  
Here is my code:

```julia
using Flux, DiffEqFlux, DifferentialEquations, Plots
function f(du,u,p,t)
S,I,R = u
du[1] = -p[1]*u[1]*u[2]
du[2] = p[1]*u[1]*u[2] - p[2]*u[2]
du[3] = p[2]*u[2]
end

# initialise and have arange between 0 and 1.5 for time-t

tbegin=0.0
tend=15
tstep=1
trange = tbegin:tstep:tend
u0 =Float32[738.0,1.0,0.0]
tspan = (tbegin,tend)

t_f = collect(3:14)
I_data=Float32[25.0,75.0,227.0,296.0,258.0,236.0,192.0,126.0,71.0,28.0,11.0,7.0];

p = [0.002,0.3] # set initial values of parameters
prob = ODEProblem(f, u0, tspan, p)

sol=solve(prob,Tsit5(),reltol = 1e-12 , saveat=t_f,save_idxs = 2)
plot(sol)

function loss(p)
sol = solve(prob, Tsit5(),reltol = 1e-12 , saveat=t_f, save_idxs = 2)
loss = sum(abs2, I_data .- sol)
return loss, sol
end

callback = function (p, l, pred)
display(l)

# Tell sciml_train to not halt the optimization. If return true, then

# optimization stops.

return false
end

using Optimization
adtype = Optimization.AutoZygote()
optf = Optimization.OptimizationFunction((x, p) → loss(x), adtype)
optprob = Optimization.OptimizationProblem(optf, p)
result_ode = Optimization.solve(optprob,
ADAM(0.1),
callback = callback,
maxiters = 300)

```

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [October 15, 2022, 1:28pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777/2 "2022-10-15T13:28:19Z")

</div>

Guess the easiest way is to define the parameters on an unconstrained space and map them to the constrained space within `f`, i.e.,

```julia
constrain_positive(uparams) = exp.(uparams)

function f(du,u,up,t)
S,I,R = u
p = constrain_positive(up)
du[1] = -p[1]*u[1]*u[2]
du[2] = p[1]*u[1]*u[2] - p[2]*u[2]
du[3] = p[2]*u[2]
end

```

If you need more complicated transformations or their Jacobians, [Bijectors.jl](https://github.com/TuringLang/Bijectors.jl) has some predefined already.

---

<div class="post-metadata">

**Author:** ![ak47](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ak47](https://discourse.julialang.org/u/ak47)\
**Post date:** [October 15, 2022, 2:51pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777/3 "2022-10-15T14:51:53Z")

</div>

Thank you. Tired the easy way but get and error (UndefVarError: up not defined).

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [October 15, 2022, 2:59pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777/4 "2022-10-15T14:59:09Z")

</div>

Ok, unfortunately I could not run your code and did not test it. Where exactly do you get the error? (Note that I have changed the name of the parameter argument in the signature of `f(du,u,up,t)` to `up` as well)

---

<div class="post-metadata">

**Author:** ![ak47](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ak47](https://discourse.julialang.org/u/ak47)\
**Post date:** [October 15, 2022, 3:35pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777/5 "2022-10-15T15:35:43Z")

</div>

using Flux, DiffEqFlux, DifferentialEquations, Plots  
function f(du,u,p,t)  
S,I,R = u  
du[1] = -p[1]\*u[1]\*u[2]  
du[2] = p[1]\*u[1]\*u[2] - p[2]\*u[2]  
du[3] = p[2]\*u[2]  
end

# initialise and have arange between 0 and 1.5 for time-t

u0 =Float32[738.0,1.0,0.0]  
tspan = (1,15)

t\_f = collect(3:14)  
I\_data=Float32[25.0,75.0,227.0,296.0,258.0,236.0,192.0,126.0,71.0,28.0,11.0,7.0]; # 1 set of data used

p = [0.02,0.5] # set initial values of parameters to one  
prob = ODEProblem(f, u0, tspan, p)  
#The neural network consists of a single ODE solver type layer:  
sol=solve(prob,Tsit5(),reltol = 1e-12 ,p=p, saveat=t\_f)  
plot(sol)

function loss(p)  
sol = solve(prob, Tsit5(),reltol = 1e-12 ,p=p, saveat=t\_f)  
loss = sum(abs2, I\_data .- sol[2,:])  
return loss, sol  
end

callback = function (p, l, pred)  
display(l)

# Tell sciml\_train to not halt the optimization. If return true, then

# optimization stops.

return false  
end

using Optimization  
adtype = Optimization.AutoForwardDiff()  
optf = Optimization.OptimizationFunction((x, p) → loss(x), adtype)  
optprob = Optimization.OptimizationProblem(optf, p)  
result\_ode = Optimization.solve(optprob,  
ADAM(0.1),  
callback = callback,  
maxiters = 30)  
Sorry about the code. This is the running code similar to the code which brings negative parameters.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [October 15, 2022, 5:50pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777/6 "2022-10-15T17:50:00Z")

</div>

Your code is probably fine, but I have trouble installing all the required libraries to get it to run. Please try again to exchange your definition of `f` with the _complete_ snippet that I had posted. Sorry that I can not help in more detail at the moment.

---

<div class="post-metadata">

**Author:** ![ak47](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ak47](https://discourse.julialang.org/u/ak47)\
**Post date:** [October 15, 2022, 7:02pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777/7 "2022-10-15T19:02:26Z")

</div>

Thank you, but when it’s implemented, parameters are never estimated. You get back the initial parameters. Wonder whether there is strategy of limltling them by setting boundaries.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [October 15, 2022, 8:53pm UTC](https://discourse.julialang.org/t/how-can-you-constraint-parameters-to-be-positive-in-sciml/88777/8 "2022-10-15T20:53:21Z")

</div>

Instead of doing it like this, just use the `lb` in the `OptimizationProblem` definition to set a lower bound, i.e. `lb = [0.0,0.0]`. That should be much simpler, and the optimizer can choose how it wants to constrain to that box constraint.
