hi Ahmed -
Both Pumas.Constrained and Pumas.truncated have a somewhat similar signature (dist, lower, upper) where dist is. distribution and lower and upper are bounds that we want to apply. However, one fundamental difference is that Pumas.Constrained supports multivariate distributions for dists whereas Pumas.truncated only supports univariate distributions for dists. Look at the example below
## multivariate distribution
julia> mvnd = MvNormal(Diagonal([0.04, 0.04, 0.04]))
ZeroMeanDiagNormal(
dim: 3
μ: 3-element Zeros{Float64}
Ī£: [0.04 0.0 0.0; 0.0 0.04 0.0; 0.0 0.0 0.04]
)
## univariate
julia> unvd = Normal(0,1)
Normal{Float64}(μ=0.0, Ļ=1.0)
## truncated works on univariate
julia> Pumas.truncated(unvd, 0.5, 0.5)
Truncated(Normal{Float64}(μ=0.0, Ļ=1.0); lower=0.5, upper=0.5)
## truncated does not work on multivariate
julia> Pumas.truncated(mvnd, 0.5, 0.5)
ERROR: MethodError: no method matching truncated(::ZeroMeanDiagNormal{Tuple{Base.OneTo{Int64}}}, ::Float64, ::Float64)
Closest candidates are:
  truncated(::UnivariateDistribution, ::T, ::T) where T<:Real at ~/actions-runner/_work/PumasSystemImages/PumasSystemImages/julia_depot/packages/Pumas/89e4W/src/deps_compat/distributions.jl:9
  truncated(::UnivariateDistribution, ::Real, ::Real) at ~/actions-runner/_work/PumasSystemImages/PumasSystemImages/julia_depot/packages/Pumas/89e4W/src/deps_compat/distributions.jl:5
Stacktrace:
  [1] top-level scope
    @ REPL[41]:1
  [2] eval_user_input(ast::Any, backend::REPL.REPLBackend)
    @ REPL /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
  [3] repl_backend_loop(backend::REPL.REPLBackend)
    @ REPL /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
  [4] start_repl_backend(backend::REPL.REPLBackend, consumer::Any)
    @ REPL /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
  [5] run_repl(repl::REPL.AbstractREPL, consumer::Any; backend_on_current_task::Bool)
    @ REPL /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
  [6] run_repl(repl::REPL.AbstractREPL, consumer::Any)
    @ REPL /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
  [7] (::Base.var"#936#938"{Bool, Bool, Bool})(REPL::Module)
    @ Base /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
  [8] run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_file::Bool, color_set::Bool)
    @ Base /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
  [9] exec_options(opts::Base.JLOptions)
    @ Base /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
 [10] _start()
    @ Base /Applications/Pumas-2.3.0.app/Contents/Resources/julia/Contents/Resources/julia/lib/julia/sys.pumas.dylib:-1
## Constrained works on univariate
julia> Pumas.Constrained(unvd,lower =  -0.5, upper =  0.5)
Constrained{Normal{Float64}, RealDomain{Float64, Float64, Float64}}(Normal{Float64}(μ=0.0, Ļ=1.0), RealDomain{Float64, Float64, Float64}(-0.5, 0.5, 0.0))
## Constrained works on multivariate
julia> Pumas.Constrained(mvnd,lower =  -0.5, upper =  0.5)
Constrained{ZeroMeanDiagNormal{Tuple{Base.OneTo{Int64}}}, VectorDomain{Vector{Float64}, Vector{Float64}, Vector{Float64}}}(ZeroMeanDiagNormal(
dim: 3
μ: 3-element Zeros{Float64}
Ī£: [0.04 0.0 0.0; 0.0 0.04 0.0; 0.0 0.0 0.04]
)
, VectorDomain{Vector{Float64}, Vector{Float64}, Vector{Float64}}([-0.5, -0.5, -0.5], [0.5, 0.5, 0.5], [0.0, 0.0, 0.0]))
In general, itās recommended to use Pumas.Constrained in the @param block and Pumas.truncated  in the @random and @derived blocks (cc @mohamed82008  can you confirm this statement)