# Should ForwardDiff.jl issue warnings at non-differentiable points?

**URL:** <https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228>\
**Category:** Optimization (Mathematical)\
**Tags:** question\
**Created:** [June 12, 2017, 3:33pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228 "2017-06-12T15:33:52Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [June 12, 2017, 3:33pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/1 "2017-06-12T15:33:52Z")

</div>

The derivative of `abs` is discontinuous at zero. Currently ForwardDiff chooses the +1.0 derivative. Should this choice be done without a warning?

In formal math, a new concept called the subgradient is defined to include both +1.0 and -1.0 and the whole [-1.0,1.0] interval. There is no inherent justification of choosing just the +1.0 point from the interval.  
Significant math follows from knowing and considering other values as representatives of the subgradient interval.

A possible set of warnings could be implemented with:

```julia
julia> using ForwardDiff

julia> @inline Base.:<(d::ForwardDiff.Dual{T,V,N} where T where V<:Real where N,x::AbstractFloat) = ( ForwardDiff.value(d)==x && warn("Subgradient is not a singleton. Forced to pick single value") ; ForwardDiff.value(d)<x )

julia> ForwardDiff.Dual(10.0,-1.0) < 10.0 # This can be both true and false
WARNING: Subgradient is not a singleton. Forced to pick single value
false

julia> @inline Base.abs(d::ForwardDiff.Dual) = ( ForwardDiff.value(d)==zero(typeof(d)) && warn("Subgradient is not a singleton. Forced to pick single value") ; signbit(ForwardDiff.value(d)) ? -d : d )

julia> abs(ForwardDiff.Dual(0.0,1.0))
WARNING: Subgradient is not a singleton. Forced to pick single value
Dual{Void}(0.0,1.0)

julia> @inline Base.:<(d::ForwardDiff.Dual{T,V,N} where T where V<:Real where N,x::W where W<:Integer) = ( ForwardDiff.value(d)==x && warn("Subgradient is not a singleton. Forced to pick single value") ; ForwardDiff.value(d)<x )

julia> ForwardDiff.Dual(0.0,-1.0)<0
WARNING: Subgradient is not a singleton. Forced to pick single value
false

julia> signbit(ForwardDiff.Dual(0.0,-1.0))
WARNING: Subgradient is not a singleton. Forced to pick single value
false

```

What are the forum’s views on this?

---

<div class="post-metadata">

**Author:** ![JaredCrean2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jaredcrean2/32/3574_2.png) [@JaredCrean2](https://discourse.julialang.org/u/JaredCrean2)\
**Post date:** [June 12, 2017, 6:26pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/2 "2017-06-12T18:26:43Z")

</div>

I suspect issuing warnings like this would kill the performance of the code. If benchmarking bears this out (be sure to check a case where the differentiated code vectorizes), I would be opposed to make this change.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 12, 2017, 7:00pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/3 "2017-06-12T19:00:54Z")

</div>

AFAIK this (= if you are trying to differentiate non-differentiable functions, be prepared to face the consequences) is well understood, but hard to deal with.

1. Ideally, one would not AD non-differentiable functions.
2. But sometimes this happens, and then one would hope for an almost zero-measure set of nondifferentiable points, so we can quietly ignore this (eg with MCMC).
3. Then the worst-case is some iterative procedure where your algorithm just loves hanging out at the nondifferentiable set.

Whether you want warnings depends on the use case. For 2, you would get the occasional one, for 3, your screen would be flooded with them, and indicate that you are using the wrong algorithm.

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [June 12, 2017, 7:29pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/4 "2017-06-12T19:29:06Z")

</div>

@Tamas_Papp, this is a good summary. But there are two points which made me put this out:

1. The deterministic symmetry breaking to one arbitrary and extreme derivative is bothersome - feels like missing out on the dimension of the possible results.
2. Julia is a good language to extend this AD facility to generate subgradients and calculate with them (like interval arithmetic). This route could potentially lead to multivariate subgradients i.e. cones and operations on them, which could make expressing optimization problems on polytopes nicely in native Julia (and have them run decently).

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [June 12, 2017, 7:39pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/5 "2017-06-12T19:39:12Z")

</div>

Ideally the user would be able to specify which direction to take the limit from or whether to have a warning. (Whether that’s practical here, I have no idea.)

Leaving this warning on by default seems like a recipe for a lot of pain and frustration for someone.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 12, 2017, 7:49pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/6 "2017-06-12T19:49:53Z")

</div>

> [@Dan](#):
>
> extend this AD facility to generate subgradients

Possibly, but the solutions I can imagine would be very heavyweight and/or sacrifice type stability. If you have a good solution, make a PR or a proof of concept.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [June 12, 2017, 8:27pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/7 "2017-06-12T20:27:22Z")

</div>

If you have floating point accuracy, how do you know that you are at 0.0 or, say, 1e-32? I think it is correct to treat those points as null-sets and move on.

Also a user who ADs a non-differentiable function should just be aware of what they are doing and deal with the consequences.

---

<div class="post-metadata">

**Author:** ![jrevels](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jrevels/32/10393_2.png) [@jrevels](https://discourse.julialang.org/u/jrevels)\
**Post date:** [June 12, 2017, 9:43pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/8 "2017-06-12T21:43:58Z")

</div>

Relevant issues:

> <https://github.com/JuliaMath/Calculus.jl/pull/70>

> <https://github.com/JuliaDiff/DualNumbers.jl/issues/14>
>
> Perhaps we should have
> abs(Dual(-0.0,1.0)) == Dual(0.0,-1.0)?
> 
> \`\`\` julia
> 
> julia\>… abs(Dual(0.0,1.0))
> 0.0 + 1.0du
> 
> julia\> abs(Dual(-0.0,1.0))
> \-0.0 + 1.0du
> 
> julia\> abs(Dual(-eps(),1.0))
> 2.220446049250313e-16 - 1.0du
> \`\`\`

There’s probably some other relevant discussions floating about the various JuliaDiff repos. Deciding what to do at (or near) nondifferentiable points can be tricky for the reasons everybody has listed.

> [@Dan](#):
>
> Julia is a good language to extend this AD facility to generate subgradients and calculate with them (like interval arithmetic). This route could potentially lead to multivariate subgradients i.e. cones and operations on them, which could make expressing optimization problems on polytopes nicely in native Julia (and have them run decently).

This is actually something I and @dpsanders have discussed before. He’s made some pretty cool [ValidatedNumerics](https://github.com/JuliaIntervals/ValidatedNumerics.jl) demos by combining AD and interval arithmetic.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [June 12, 2017, 9:51pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/9 "2017-06-12T21:51:30Z")

</div>

What is a good reference for subgradients?

---

<div class="post-metadata">

**Author:** ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)\
**Post date:** [June 12, 2017, 9:55pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/10 "2017-06-12T21:55:04Z")

</div>

Any convex analysis book, e.g., Rockafellar’s.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [June 12, 2017, 11:34pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/11 "2017-06-12T23:34:43Z")

</div>

Thanks. Who would like to implement them?

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [June 12, 2017, 11:40pm UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/12 "2017-06-12T23:40:27Z")

</div>

What about a freely-available reference?

---

<div class="post-metadata">

**Author:** ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)\
**Post date:** [June 13, 2017, 2:15am UTC](https://discourse.julialang.org/t/should-forwarddiff-jl-issue-warnings-at-non-differentiable-points/4228/13 "2017-06-13T02:15:18Z")

</div>

There’s [https://see.stanford.edu/materials/lsocoee364b/01-subgradients\_notes.pdf](https://see.stanford.edu/materials/lsocoee364b/01-subgradients_notes.pdf). Strangely enough, they don’t talk much about subgradients in their book.
