Skip to content

Commit 8500a99

Browse files
committed
Add slope function for multidim case with tests and benchmarks
1 parent 3cd778a commit 8500a99

File tree

4 files changed

+177
-7
lines changed

4 files changed

+177
-7
lines changed

perf/slopes.jl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,53 @@ function benchmark_time()
6464
println(dfnew)
6565
dfnew
6666
end
67+
68+
struct SlopesMulti
69+
f::Function
70+
x::IntervalBox
71+
c::Vector
72+
sol::Matrix{Interval}
73+
end
74+
75+
function benchmark_multi()
76+
77+
rts = SlopesMulti[]
78+
f(x, y) = SVector(x^2 + y^2 - 1, y - 2x)
79+
f(X) = f(X...)
80+
X = (-6..6) × (-6..6)
81+
c = [0.0, 0.0]
82+
push!(rts, SlopesMulti(f, X, c, [-6..6 -6..6; -2.. -2 1..1]))
83+
84+
function g(x)
85+
(x1, x2, x3) = x
86+
SVector( x1^2 + x2^2 + x3^2 - 1,
87+
x1^2 + x3^2 - 0.25,
88+
x1^2 + x2^2 - 4x3
89+
)
90+
end
91+
92+
X = (-5..5)
93+
XX = IntervalBox(X, 3)
94+
cc = [0.0, 0.0, 0.0]
95+
push!(rts, SlopesMulti(g, XX, cc, [-5..5 -5..5 -5..5; -5..5 0..0 -5..5; -5..5 -5..5 -4.. -4]))
96+
97+
function h(x)
98+
(x1, x2, x3) = x
99+
SVector( x1 + x2^2 + x3^2 - 1,
100+
x1^2 + x3 - 0.25,
101+
x1^2 + x2 - 4x3
102+
)
103+
end
104+
105+
XXX = IntervalBox(1..5, 2..6, -3..7)
106+
ccc = [3.0, 4.0, 2.0]
107+
push!(rts, SlopesMulti(h, XXX, ccc, [1..1 6..10 -1..9; 4..8 0..0 1..1; 4..8 1..1 -4.. -4]))
108+
109+
for i in 1:length(rts)
110+
println("\nFunction $i")
111+
println("Slope Expansion: ")
112+
println(DataFrame(slope(rts[i].f, rts[i].x, rts[i].c)))
113+
println("\nJacobian: ")
114+
println(DataFrame(ForwardDiff.jacobian(rts[i].f, rts[i].x)))
115+
end
116+
end

perf/slopes_tabular.txt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,48 @@ Time
3535
│ 7 │ f7 │ 3.0198e-5 │ 7.2014e-5 │
3636
│ 8 │ f8 │ 7.43125e-6 │ 8.046e-6 │
3737
│ 9 │ f9 │ 7.118e-6 │ 7.8705e-6 │
38+
39+
40+
Multi-Dimensional Case:
41+
Function 1
42+
Slope Expansion:
43+
│ Row │ x1 │ x2 │
44+
├─────┼──────────┼─────────┤
45+
│ 1 │ [-6, 6] │ [-6, 6] │
46+
│ 2 │ [-2, -2] │ [1, 1] │
47+
48+
Jacobian:
49+
│ Row │ x1 │ x2 │
50+
├─────┼───────────┼───────────┤
51+
│ 1 │ [-12, 12] │ [-12, 12] │
52+
│ 2 │ [-2, -2] │ [1, 1] │
53+
54+
Function 2
55+
Slope Expansion:
56+
│ Row │ x1 │ x2 │ x3 │
57+
├─────┼─────────┼─────────┼──────────┤
58+
│ 1 │ [-5, 5] │ [-5, 5] │ [-5, 5] │
59+
│ 2 │ [-5, 5] │ [0, 0] │ [-5, 5] │
60+
│ 3 │ [-5, 5] │ [-5, 5] │ [-4, -4] │
61+
62+
Jacobian:
63+
│ Row │ x1 │ x2 │ x3 │
64+
├─────┼───────────┼───────────┼───────────┤
65+
│ 1 │ [-10, 10] │ [-10, 10] │ [-10, 10] │
66+
│ 2 │ [-10, 10] │ [0, 0] │ [-10, 10] │
67+
│ 3 │ [-10, 10] │ [-10, 10] │ [-4, -4] │
68+
69+
Function 3
70+
Slope Expansion:
71+
│ Row │ x1 │ x2 │ x3 │
72+
├─────┼────────┼─────────┼──────────┤
73+
│ 1 │ [1, 1] │ [6, 10] │ [-1, 9] │
74+
│ 2 │ [4, 8] │ [0, 0] │ [1, 1] │
75+
│ 3 │ [4, 8] │ [1, 1] │ [-4, -4] │
76+
77+
Jacobian:
78+
│ Row │ x1 │ x2 │ x3 │
79+
├─────┼─────────┼─────────┼──────────┤
80+
│ 1 │ [1, 1] │ [4, 12] │ [-6, 14] │
81+
│ 2 │ [2, 10] │ [0, 0] │ [1, 1] │
82+
│ 3 │ [2, 10] │ [1, 1] │ [-4, -4] │

src/slopes.jl

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# Reference : Dietmar Ratz - An Optimized Interval Slope Arithmetic and its Application
2-
using IntervalArithmetic, ForwardDiff
2+
using IntervalArithmetic, ForwardDiff, StaticArrays
33
import Base: +, -, *, /, ^, sqrt, exp, log, sin, cos, tan, asin, acos, atan
44
import IntervalArithmetic: mid, interval
55

6-
function slope(f::Function, x::Interval, c::Number)
6+
"""
7+
Expands the slope of `f` over `x` at the point `c` (default `c = mid(x)`)
8+
"""
9+
function slope(f::Function, x::Interval, c::Number = mid(x))
710
try
811
f(slope_var(x, c)).s
912
catch y
@@ -13,6 +16,25 @@ function slope(f::Function, x::Interval, c::Number)
1316
end
1417
end
1518

19+
function slope(f::Function, x::Union{IntervalBox, SVector}, c::AbstractVector = mid.(x)) # multidim
20+
try
21+
T = typeof(x[1].lo)
22+
n = length(x)
23+
s = Vector{Slope{T}}[]
24+
for i in 1:n
25+
arr = fill(Slope(zero(T)), n)
26+
arr[i] = slope_var(x[i], c[i])
27+
push!(s, arr)
28+
end
29+
return slope.(hcat(([(f(s[i])) for i=1:n])...))
30+
catch y
31+
if isa(y, MethodError)
32+
ForwardDiff.jacobian(f, x)
33+
end
34+
end
35+
36+
end
37+
1638
struct Slope{T}
1739
x::Interval{T}
1840
c::Interval{T}
@@ -76,12 +98,19 @@ end
7698

7799
+(v::Slope, u) = u + v
78100

79-
-(v::Slope, u) = u - v
80-
-(u::Slope) = u * -1.0
81-
82101
*(v::Slope, u) = u * v
83102

84-
/(v::Slope, u) = u / v
103+
function -(u::Slope, v)
104+
Slope(u.x - v, u.c - v, u.s)
105+
end
106+
107+
function -(u::Slope)
108+
Slope(-u.x, -u.c, -u.s)
109+
end
110+
111+
function /(u::Slope, v)
112+
Slope(u.x / v, u.c / v, u.s / v)
113+
end
85114

86115
function sqr(u::Slope)
87116
Slope(u.x ^ 2, u.c ^ 2, (u.x + u.c) * u.s)

test/slopes.jl

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using IntervalArithmetic, IntervalRootFinding
2-
using ForwardDiff
2+
using ForwardDiff, StaticArrays
33
using Base.Test
44

55
struct Slopes{T}
@@ -45,3 +45,49 @@ end
4545
@test slope(rts[i].f, rts[i].x, rts[i].c) rts[i].sol
4646
end
4747
end
48+
49+
struct SlopesMulti
50+
f::Function
51+
x::IntervalBox
52+
c::Vector
53+
sol::Matrix{Interval}
54+
end
55+
56+
@testset "Multidim slope expansion" begin
57+
58+
rts = SlopesMulti[]
59+
f(x, y) = SVector(x^2 + y^2 - 1, y - 2x)
60+
f(X) = f(X...)
61+
X = (-6..6) × (-6..6)
62+
c = [0.0, 0.0]
63+
push!(rts, SlopesMulti(f, X, c, [-6..6 -6..6; -2.. -2 1..1]))
64+
65+
function g(x)
66+
(x1, x2, x3) = x
67+
SVector( x1^2 + x2^2 + x3^2 - 1,
68+
x1^2 + x3^2 - 0.25,
69+
x1^2 + x2^2 - 4x3
70+
)
71+
end
72+
73+
X = (-5..5)
74+
XX = IntervalBox(X, 3)
75+
cc = [0.0, 0.0, 0.0]
76+
push!(rts, SlopesMulti(g, XX, cc, [-5..5 -5..5 -5..5; -5..5 0..0 -5..5; -5..5 -5..5 -4.. -4]))
77+
function h(x)
78+
(x1, x2, x3) = x
79+
SVector( x1 + x2^2 + x3^2 - 1,
80+
x1^2 + x3 - 0.25,
81+
x1^2 + x2 - 4x3
82+
)
83+
end
84+
85+
XXX = IntervalBox(1..5, 2..6, -3..7)
86+
ccc = [3.0, 4.0, 2.0]
87+
push!(rts, SlopesMulti(h, XXX, ccc, [1..1 6..10 -1..9; 4..8 0..0 1..1; 4..8 1..1 -4.. -4]))
88+
89+
for i in 1:length(rts)
90+
@test slope(rts[i].f, rts[i].x, rts[i].c) == rts[i].sol
91+
end
92+
93+
end

0 commit comments

Comments
 (0)