Skip to content

Commit e5fdd29

Browse files
committed
Add slope function for multidim case with tests and benchmarks
1 parent dac2c72 commit e5fdd29

File tree

4 files changed

+173
-6
lines changed

4 files changed

+173
-6
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: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
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

66
function slope(f::Function, x::Interval, c::Number)
77
f(slope_var(x, c)).s
88
end
99

10+
function slope(f::Function, x::Union{IntervalBox, SVector}, c::AbstractVector = mid.(x)) # multidim
11+
try
12+
T = typeof(x[1].lo)
13+
n = length(x)
14+
s = Vector{Slope{T}}[]
15+
for i in 1:n
16+
arr = fill(Slope(zero(T)), n)
17+
arr[i] = slope_var(x[i], c[i])
18+
push!(s, arr)
19+
end
20+
return slope.(hcat(([(f(s[i])) for i=1:n])...))
21+
catch y
22+
if isa(y, MethodError)
23+
ForwardDiff.jacobian(f, x)
24+
end
25+
end
26+
27+
end
28+
1029
struct Slope{T}
1130
x::Interval{T} # Interval on which slope is evaluated
1231
c::Interval{T} # Point about which slope is evaluated (Interval to get bounded rounding errors)
@@ -70,12 +89,19 @@ end
7089

7190
+(v::Slope, u) = u + v
7291

73-
-(v::Slope, u) = u - v
74-
-(u::Slope) = u * -1.0
75-
7692
*(v::Slope, u) = u * v
7793

78-
/(v::Slope, u) = u / v
94+
function -(u::Slope, v)
95+
Slope(u.x - v, u.c - v, u.s)
96+
end
97+
98+
function -(u::Slope)
99+
Slope(-u.x, -u.c, -u.s)
100+
end
101+
102+
function /(u::Slope, v)
103+
Slope(u.x / v, u.c / v, u.s / v)
104+
end
79105

80106
function sqr(u::Slope)
81107
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}
@@ -28,3 +28,49 @@ end
2828
end
2929
end
3030
end
31+
32+
struct SlopesMulti
33+
f::Function
34+
x::IntervalBox
35+
c::Vector
36+
sol::Matrix{Interval}
37+
end
38+
39+
@testset "Multidim slope expansion" begin
40+
41+
rts = SlopesMulti[]
42+
f(x, y) = SVector(x^2 + y^2 - 1, y - 2x)
43+
f(X) = f(X...)
44+
X = (-6..6) × (-6..6)
45+
c = [0.0, 0.0]
46+
push!(rts, SlopesMulti(f, X, c, [-6..6 -6..6; -2.. -2 1..1]))
47+
48+
function g(x)
49+
(x1, x2, x3) = x
50+
SVector( x1^2 + x2^2 + x3^2 - 1,
51+
x1^2 + x3^2 - 0.25,
52+
x1^2 + x2^2 - 4x3
53+
)
54+
end
55+
56+
X = (-5..5)
57+
XX = IntervalBox(X, 3)
58+
cc = [0.0, 0.0, 0.0]
59+
push!(rts, SlopesMulti(g, XX, cc, [-5..5 -5..5 -5..5; -5..5 0..0 -5..5; -5..5 -5..5 -4.. -4]))
60+
function h(x)
61+
(x1, x2, x3) = x
62+
SVector( x1 + x2^2 + x3^2 - 1,
63+
x1^2 + x3 - 0.25,
64+
x1^2 + x2 - 4x3
65+
)
66+
end
67+
68+
XXX = IntervalBox(1..5, 2..6, -3..7)
69+
ccc = [3.0, 4.0, 2.0]
70+
push!(rts, SlopesMulti(h, XXX, ccc, [1..1 6..10 -1..9; 4..8 0..0 1..1; 4..8 1..1 -4.. -4]))
71+
72+
for i in 1:length(rts)
73+
@test slope(rts[i].f, rts[i].x, rts[i].c) == rts[i].sol
74+
end
75+
76+
end

0 commit comments

Comments
 (0)