# ModelingToolkit variable with Distributions.cdf()

**URL:** <https://discourse.julialang.org/t/modelingtoolkit-variable-with-distributions-cdf/51434>\
**Category:** Modelling & Simulations\
**Tags:** question, distributions, modelingtoolkit\
**Created:** [December 8, 2020, 1:58am UTC](https://discourse.julialang.org/t/modelingtoolkit-variable-with-distributions-cdf/51434 "2020-12-08T01:58:46Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jmmm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmmm/32/20055_2.png) [@jmmm](https://discourse.julialang.org/u/jmmm)\
**Post date:** [December 8, 2020, 1:58am UTC](https://discourse.julialang.org/t/modelingtoolkit-variable-with-distributions-cdf/51434/1 "2020-12-08T01:58:46Z")

</div>

Hi,

I am new to Julia and trying out the ModelingToolking package. I have a basic understanding of the type system and the dynamic dispatch, but couldn’t figure out why this didn’t work.

This works perfectly - almost magic to me:

```julia
>>> using ModelingToolkit
>>> using Distributions
>>> @variables t
>>> d = Normal()
>>> pdf(d, t)
(exp((-abs2((t - 0.0) / 1.0)) / 2) * invsqrt2π) / 1.0

```

Then this didn’t work.

```julia
>>> cdf(d, t)
MethodError: no method matching AbstractFloat(::Num)
Closest candidates are:
  AbstractFloat(::Real, !Matched::RoundingMode) where T<:AbstractFloat at rounding.jl:200
  AbstractFloat(::T) where T<:Number at boot.jl:716
  AbstractFloat(!Matched::Bool) at float.jl:258

```

If I check the Distributions package documentation, both functions have the same function signature:

```julia
cdf(d::UnivariateDistribution, x::Real)
pdf(d::UnivariateDistribution, x::Real)

```

Also, from the ModelingToolkit tutorial,

> Note that by default, `@variables` returns `Sym` or `Term` objects wrapped in `Num` in order to make them behave like subtypes of `Real` .

So, I’m wondering why it worked for pdf but not for cdf.

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [December 8, 2020, 3:01am UTC](https://discourse.julialang.org/t/modelingtoolkit-variable-with-distributions-cdf/51434/2 "2020-12-08T03:01:11Z")

</div>

Symbolic values get passed through normal Julia code fine, but in this case `erfc` is implemented in C and Julia attempts to convert the symbolic value `t` to a floating point number to pass to the C routine. This can’t work, so you get the traceback. The solution is to tell `ModelingToolkit` that `erfc` is a fundamental operation and that it shouldn’nt bother trying to look inside it.

```julia
julia> using SpecialFunctions
julia> @register SpecialFunctions.erfc(x)
julia> cdf(d, t)
erfc((-((t - 0.0) / 1.0)) * invsqrt2) / 2

```

In the case of `pdf`, `exp` had already been registered with `ModelingToolkit`, so it already knew not to look inside.

---

<div class="post-metadata">

**Author:** ![Yifan\_Liu](https://avatars.discourse-cdn.com/v4/letter/y/4da419/32.png) [@Yifan\_Liu](https://discourse.julialang.org/u/Yifan_Liu)\
**Post date:** [December 8, 2020, 3:04am UTC](https://discourse.julialang.org/t/modelingtoolkit-variable-with-distributions-cdf/51434/3 "2020-12-08T03:04:32Z")

</div>

I kinda remember that Matlab can symbolically differentiate its normcdf function. Does that mean Matlab’s normcdf is not derived from erfc?

I encountered this same issue two years but still haven’t figured out how to do it in Julia…

---

<div class="post-metadata">

**Author:** ![jmmm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmmm/32/20055_2.png) [@jmmm](https://discourse.julialang.org/u/jmmm)\
**Post date:** [December 8, 2020, 3:24am UTC](https://discourse.julialang.org/t/modelingtoolkit-variable-with-distributions-cdf/51434/4 "2020-12-08T03:24:18Z")

</div>

Thanks, @contradict. It’s great to know that this works!

```julia
@register SpecialFunctions.erfc(x)
@variables t
@derivatives G'~t 
Φ = cdf(d, t)
expand_derivatives(G(Φ))
# 0.3989422804014327 * exp(-0.5000000000000001 * (t ^ 2))

```

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [December 8, 2020, 3:36am UTC](https://discourse.julialang.org/t/modelingtoolkit-variable-with-distributions-cdf/51434/5 "2020-12-08T03:36:20Z")

</div>

Oh, yikes, I’m surprised that worked! For a function like `erfc` that is implemented in a C library, you also need to [register a derivative](https://mtk.sciml.ai/stable/IR/#Adding-Derivatives-1) if you want to differentiate it. It looks like a derivative was [registered](https://github.com/JuliaDiff/DiffRules.jl/blob/master/src/rules.jl#L106) for `erfc`, but the function itself was not registered, and I’m not sure where it should have been.

I don’t know how Matlab handles this, but `ModelingToolkit` defines the derivatives of some base set of functions and then works to express derivatives of your expression in terms of that base set.
