-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrect root of function involving max
#146
Comments
It has to do with the fact that the function is not differentiable, which is an implicit requirement for Newton (the default) and Krawczyk methods. I don't know what We should probably document that, with a big warning sign. |
|
For a function like
As far as I can tell, we don't currently have a mechanism to conclude that e.g.
|
Here I showed how to define a general piecewise function. Copying (with a slight improvement) here for simplicity: "Evaluate interval function with piecewise region--function pairs"
function piecewise(pieces::Vector{<:Pair}, X)
return reduce(∪, f(X ∩ region) for (region, f) in pieces)
end
piecewise(pieces) = X -> piecewise(pieces, X)
X = 2..5
f2 = piecewise([0..3 => x->x+1,
3..6 => x->x,
6..∞ => x->x+2])
f(x) = sum(f2 ∘ abs, x) EDIT: We should probably just export this function from |
If we introduce a |
Hmm, making this efficient could require |
Something like this, Note that ideally we would somehow generate and store only once the derivative; currently it is re-constructed each time: using IntervalArithmetic
struct PiecewiseFunction{P}
pieces::P
end
"Evaluate f over the region X if X is non-empty"
function evaluate(f, X)
isempty(X) && return X
return f(X)
end
function (f::PiecewiseFunction)(X::Interval)
return reduce(∪, evaluate(f, X ∩ region) for (region, f) in f.pieces)
end
pieces = (0..3 => x->x+1,
3..6 => x->x,
6..∞ => x->x+2)
f = PiecewiseFunction(pieces)
X = 2..5
f(X)
using ForwardDiff
import ForwardDiff: derivative
ForwardDiff.derivative(f) = x -> ForwardDiff.derivative(f, x)
ForwardDiff.derivative(f::PiecewiseFunction) =
PiecewiseFunction( Tuple(region => ForwardDiff.derivative(g) for (region, g) in f.pieces))
ForwardDiff.derivative(f::PiecewiseFunction, x::Interval) = ForwardDiff.derivative(f)(x)
myabs = PiecewiseFunction( (
(-Inf..0) => x -> -x,
(0..Inf) => x -> x ) )
ForwardDiff.derivative(myabs, -1..1)
ForwardDiff.derivative(myabs, 2..3)
myabs( (-1..1) ∩ (2..3))
myabsderiv = ForwardDiff.derivative(myabs)
myabsderiv(-1..1) # -1..1
myabsderiv(2..3) # 1..1
myabsderiv(-3.. -2) # -1.. -1 |
Now errors, but doesn't give wrong results. Support for piecewise function in IntervalArithmetic is a separate issue. |
This seems like an incorrect result. The function (equivalent to
abs(x)+1
) does not have any roots.Providing a derivative explicitly:
roots(x -> max(x,-x)+1, sign, -2..2)
or changing the contractor:roots(x -> max(x,-x)+1, -2..2, Bisection)
makes the problem go away.Maybe related to #98 ?
The text was updated successfully, but these errors were encountered: