Skip to content

Commit 3cd778a

Browse files
committed
Use concrete types and add BigFloat tests
1 parent 7b67107 commit 3cd778a

File tree

4 files changed

+83
-42
lines changed

4 files changed

+83
-42
lines changed

perf/slopes.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ function benchmark_results()
99
push!(f, x->(exp(x^2)))
1010
push!(f, x->(x^4 - 12x^3 + 47x^2 - 60x - 20exp(-x)))
1111
push!(f, x->(x^6 - 15x^4 + 27x^2 + 250))
12+
push!(f, x->(atan(cos(tan(x)))))
13+
push!(f, x->(asin(cos(acos(sin(x))))))
1214

1315
s = interval(0.75, 1.75)
1416
df = DataFrame()
@@ -40,12 +42,16 @@ function benchmark_time()
4042
push!(f, x->(exp(x^2)))
4143
push!(f, x->(x^4 - 12x^3 + 47x^2 - 60x - 20exp(-x)))
4244
push!(f, x->(x^6 - 15x^4 + 27x^2 + 250))
45+
push!(f, x->(atan(cos(tan(x)))))
46+
push!(f, x->(asin(cos(acos(sin(x))))))
47+
48+
s = interval(0.75, 1.75)
4349
df = DataFrame()
4450
df[:Method] = ["Automatic Differentiation", "Slope Expansion"]
4551
for n in 1:length(f)
4652

47-
t1 = @belapsed ForwardDiff.derivative($f[$n], 0.75..1.75)
48-
t2 = @belapsed slope($f[$n], 0.75..1.75, 1.25)
53+
t1 = @belapsed ForwardDiff.derivative($f[$n], $s)
54+
t2 = @belapsed slope($f[$n], $s, mid($s))
4955
df[Symbol("f" * "$n")] = [t1, t2]
5056
end
5157
a = []

perf/slopes_tabular.txt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ Results
99
│ 5 │ f5 │ [2.63258, 74.8333] │ [6.03135, 33.2205] │
1010
│ 6 │ f6 │ [-94.5871, 115.135] │ [-38.9908, 65.5595] │
1111
│ 7 │ f7 │ [-279.639, 167.667] │ [-146.852, 67.0665] │
12+
│ 8 │ f8 │ [-∞, ∞] │ [1, 2] │
13+
│ 9 │ f9 │ [-∞, ∞] │ [1.3667, ∞] │
1214

1315
Time
14-
16+
<Using abstract types>
1517
│ Row │ Function │ Automatic Differentiation │ Slope Expansion │
1618
├─────┼──────────┼───────────────────────────┼─────────────────┤
1719
│ 1 │ f1 │ 8.847e-6 │ 2.4192e-5 │
@@ -21,3 +23,15 @@ Time
2123
│ 5 │ f5 │ 8.29233e-6 │ 2.2186e-5 │
2224
│ 6 │ f6 │ 3.0895e-5 │ 7.9524e-5 │
2325
│ 7 │ f7 │ 3.0847e-5 │ 7.6188e-5 │
26+
<After using concrete types>
27+
│ Row │ Function │ Automatic Differentiation │ Slope Expansion │
28+
├─────┼──────────┼───────────────────────────┼─────────────────┤
29+
│ 1 │ f1 │ 8.34067e-6 │ 2.1679e-5 │
30+
│ 2 │ f2 │ 2.9766e-5 │ 7.194e-5 │
31+
│ 3 │ f3 │ 6.0278e-6 │ 7.827e-6 │
32+
│ 4 │ f4 │ 1.7114e-5 │ 3.5235e-5 │
33+
│ 5 │ f5 │ 8.36567e-6 │ 2.0747e-5 │
34+
│ 6 │ f6 │ 3.0061e-5 │ 7.273e-5 │
35+
│ 7 │ f7 │ 3.0198e-5 │ 7.2014e-5 │
36+
│ 8 │ f8 │ 7.43125e-6 │ 8.046e-6 │
37+
│ 9 │ f9 │ 7.118e-6 │ 7.8705e-6 │

src/slopes.jl

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ using IntervalArithmetic, ForwardDiff
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::Real)
6+
function slope(f::Function, x::Interval, c::Number)
77
try
88
f(slope_var(x, c)).s
99
catch y
@@ -17,16 +17,17 @@ struct Slope{T}
1717
x::Interval{T}
1818
c::Interval{T}
1919
s::Interval{T}
20-
Slope{T}(a, b, c) where T = new(a, b, c)
21-
Slope{T}(c) where T = Slope{T}(c, c, 0)
2220
end
2321

24-
function slope_var(v::Real)
25-
Slope{Float64}(v, v, 1)
22+
Slope(c) = Slope(c, c, 0)
23+
Slope(a, b, c) = Slope(promote(convert(Interval, a), b, c)...)
24+
25+
function slope_var(v::Number)
26+
Slope(v, v, 1)
2627
end
2728

28-
function slope_var(v::Interval, c::Real)
29-
Slope{Float64}(v, c, 1)
29+
function slope_var(v::Interval, c::Number)
30+
Slope(v, c, 1)
3031
end
3132

3233
function interval(u::Slope)
@@ -42,53 +43,53 @@ function slope(u::Slope)
4243
end
4344

4445
function +(u::Slope, v::Slope)
45-
Slope{Float64}(u.x + v.x, u.c + v.c, u.s + v.s)
46+
Slope(u.x + v.x, u.c + v.c, u.s + v.s)
4647
end
4748

4849
function -(u::Slope, v::Slope)
49-
Slope{Float64}(u.x - v.x, u.c - v.c, u.s - v.s)
50+
Slope(u.x - v.x, u.c - v.c, u.s - v.s)
5051
end
5152

5253
function *(u::Slope, v::Slope)
53-
Slope{Float64}(u.x * v.x, u.c * v.c, u.s * v.c + u.x * v.s)
54+
Slope(u.x * v.x, u.c * v.c, u.s * v.c + u.x * v.s)
5455
end
5556

5657
function /(u::Slope, v::Slope)
57-
Slope{Float64}(u.x / v.x, u.c / v.c, (u.s - (u.c / v.c) * v.s) / v.x)
58+
Slope(u.x / v.x, u.c / v.c, (u.s - (u.c / v.c) * v.s) / v.x)
5859
end
5960

60-
function +(u::Union{Interval, Real}, v::Slope)
61-
Slope{Float64}(u + v.x, u + v.c, v.s)
61+
function +(u, v::Slope)
62+
Slope(u + v.x, u + v.c, v.s)
6263
end
6364

64-
function -(u::Union{Interval, Real}, v::Slope)
65-
Slope{Float64}(u - v.x, u - v.c, -v.s)
65+
function -(u, v::Slope)
66+
Slope(u - v.x, u - v.c, -v.s)
6667
end
6768

68-
function *(u::Union{Interval, Real}, v::Slope)
69-
Slope{Float64}(u * v.x, u * v.c, u * v.s)
69+
function *(u, v::Slope)
70+
Slope(u * v.x, u * v.c, u * v.s)
7071
end
7172

72-
function /(u::Union{Interval, Real}, v::Slope)
73-
Slope{Float64}(u / v.x, u / v.c, -(u / v.c) * (v.s / v.x))
73+
function /(u, v::Slope)
74+
Slope(u / v.x, u / v.c, -(u / v.c) * (v.s / v.x))
7475
end
7576

76-
+(v::Slope, u::Union{Interval, Real}) = u + v
77+
+(v::Slope, u) = u + v
7778

78-
-(v::Slope, u::Union{Interval, Real}) = u - v
79-
-(u::Slope) = u * -1
79+
-(v::Slope, u) = u - v
80+
-(u::Slope) = u * -1.0
8081

81-
*(v::Slope, u::Union{Interval, Real}) = u * v
82+
*(v::Slope, u) = u * v
8283

83-
/(v::Slope, u::Union{Interval, Real}) = u / v
84+
/(v::Slope, u) = u / v
8485

8586
function sqr(u::Slope)
86-
Slope{Float64}(u.x ^ 2, u.c ^ 2, (u.x + u.c) * u.s)
87+
Slope(u.x ^ 2, u.c ^ 2, (u.x + u.c) * u.s)
8788
end
8889

8990
function ^(u::Slope, k::Integer)
9091
if k == 0
91-
return Slope{Float64}(1)
92+
return Slope(1)
9293
elseif k == 1
9394
return u
9495
elseif k == 2
@@ -107,7 +108,7 @@ function ^(u::Slope, k::Integer)
107108
i = u.x.lo - u.c.lo
108109
s = u.x.hi - u.c.hi
109110

110-
if ((i == 0) || (s == 0) || (k % 2 == 1 && Interval(0) u.x))
111+
if ((i == 0) || (s == 0) || (k % 2 == 1 && zero(u.x) u.x))
111112
h1 = k * (u.x ^ (k - 1))
112113
else
113114
if k % 2 == 0 || u.x.lo >= 0
@@ -116,12 +117,12 @@ function ^(u::Slope, k::Integer)
116117
h1 = interval((hxs.lo - hc.hi) / s, (hxi.lo - hc.hi) / i)
117118
end
118119
end
119-
return Slope{Float64}(hx, hc, h1 * u.s)
120+
return Slope(hx, hc, h1 * u.s)
120121
end
121122
end
122123

123124
function sqrt(u::Slope)
124-
Slope{Float64}(sqrt(u.x), sqrt(u.c), u.s / (sqrt(u.x) + sqrt(u.c)))
125+
Slope(sqrt(u.x), sqrt(u.c), u.s / (sqrt(u.x) + sqrt(u.c)))
125126
end
126127

127128
function exp(u::Slope)
@@ -137,7 +138,7 @@ function exp(u::Slope)
137138
h1 = interval((hx.lo - hc.lo) / i, (hx.hi - hc.hi) / s)
138139
end
139140

140-
Slope{Float64}(hx, hc, h1 * u.s)
141+
Slope(hx, hc, h1 * u.s)
141142
end
142143

143144
function log(u::Slope)
@@ -152,47 +153,47 @@ function log(u::Slope)
152153
else
153154
h1 = interval((hx.hi - hc.hi) / s, (hx.lo - hc.lo) / i)
154155
end
155-
Slope{Float64}(hx, hc, h1 * u.s)
156+
Slope(hx, hc, h1 * u.s)
156157
end
157158

158159
function sin(u::Slope) # Using derivative to upper bound the slope expansion for now
159160
hx = sin(u.x)
160161
hc = sin(u.c)
161162
hs = cos(u.x)
162-
Slope{Float64}(hx, hc, hs)
163+
Slope(hx, hc, hs)
163164
end
164165

165166
function cos(u::Slope) # Using derivative to upper bound the slope expansion for now
166167
hx = cos(u.x)
167168
hc = cos(u.c)
168169
hs = -sin(u.x)
169-
Slope{Float64}(hx, hc, hs)
170+
Slope(hx, hc, hs)
170171
end
171172

172173
function tan(u::Slope) # Using derivative to upper bound the slope expansion for now
173174
hx = tan(u.x)
174175
hc = tan(u.c)
175176
hs = (sec(u.x)) ^ 2
176-
Slope{Float64}(hx, hc, hs)
177+
Slope(hx, hc, hs)
177178
end
178179

179180
function asin(u::Slope)
180181
hx = asin(u.x)
181182
hc = asin(u.c)
182183
hs = 1 / sqrt(1 - (u.x ^ 2))
183-
Slope{Float64}(hx, hc, hs)
184+
Slope(hx, hc, hs)
184185
end
185186

186187
function acos(u::Slope)
187188
hx = acos(u.x)
188189
hc = acos(u.c)
189190
hs = -1 / sqrt(1 - (u.x ^ 2))
190-
Slope{Float64}(hx, hc, hs)
191+
Slope(hx, hc, hs)
191192
end
192193

193194
function atan(u::Slope)
194195
hx = atan(u.x)
195196
hc = atan(u.c)
196197
hs = 1 / 1 + (u.x ^ 2)
197-
Slope{Float64}(hx, hc, hs)
198+
Slope(hx, hc, hs)
198199
end

test/slopes.jl

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,37 @@ struct Slopes{T}
99
sol::Interval{T}
1010
end
1111

12-
@testset "Automatic slope expansion" begin
12+
@testset "Automatic slope expansion(Float64)" begin
1313

1414
s = interval(0.75, 1.75)
1515
rts = Slopes{Float64}[]
1616
push!(rts, Slopes(x->((x + sin(x)) * exp(-x^2)), s, mid(s), interval(-2.8, 0.1)))
1717
push!(rts, Slopes(x->(x^4 - 10x^3 + 35x^2 - 50x + 24), s, mid(s), interval(-44, 38.5)))
1818
push!(rts, Slopes(x->((log(x + 1.25) - 0.84x) ^ 2), s, mid(s), interval(-0.16, 0.44)))
19-
push!(rts, Slopes(x->(0.02x^2 - 0.03exp(-(20(x - 0.875))^2)), s, mid(s), interval(0.04, 0.33)))
19+
push!(rts, Slopes(x->(0.02x^2 - 0.03exp(-(20(x - 0.875))^2)), s, mid(s), interval(0.03, 0.33)))
2020
push!(rts, Slopes(x->(exp(x^2)), s, mid(s), interval(6.03, 33.23)))
2121
push!(rts, Slopes(x->(x^4 - 12x^3 + 47x^2 - 60x - 20exp(-x)), s, mid(s), interval(-39, 65.56)))
2222
push!(rts, Slopes(x->(x^6 - 15x^4 + 27x^2 + 250), s, mid(s), interval(-146.9, 67.1)))
23+
push!(rts, Slopes(x->(atan(cos(tan(x)))), s, mid(s), interval(1, 2)))
24+
push!(rts, Slopes(x->(asin(cos(acos(sin(x))))), s, mid(s), interval(1.36, ∞)))
25+
26+
for i in 1:length(rts)
27+
@test slope(rts[i].f, rts[i].x, rts[i].c) rts[i].sol
28+
end
29+
end
30+
31+
@testset "Automatic slope expansion(BigFloat)" begin
32+
s = interval(BigFloat(0.75), BigFloat(1.75))
33+
rts = Slopes{BigFloat}[]
34+
push!(rts, Slopes(x->((x + sin(x)) * exp(-x^2)), s, mid(s), interval(BigFloat(-2.8), BigFloat(0.1))))
35+
push!(rts, Slopes(x->(x^4 - 10x^3 + 35x^2 - 50x + 24), s, mid(s), interval(BigFloat(-44), BigFloat(38.5))))
36+
push!(rts, Slopes(x->((log(x + 1.25) - 0.84x) ^ 2), s, mid(s), interval(BigFloat(-0.16), BigFloat(0.44))))
37+
push!(rts, Slopes(x->(0.02x^2 - 0.03exp(-(20(x - 0.875))^2)), s, mid(s), interval(BigFloat(0.03), BigFloat(0.33))))
38+
push!(rts, Slopes(x->(exp(x^2)), s, mid(s), interval(BigFloat(6.03), BigFloat(33.23))))
39+
push!(rts, Slopes(x->(x^4 - 12x^3 + 47x^2 - 60x - 20exp(-x)), s, mid(s), interval(BigFloat(-39), BigFloat(65.56))))
40+
push!(rts, Slopes(x->(x^6 - 15x^4 + 27x^2 + 250), s, mid(s), interval(BigFloat(-146.9), BigFloat(67.1))))
41+
push!(rts, Slopes(x->(atan(cos(tan(x)))), s, mid(s), interval(BigFloat(1), BigFloat(2))))
42+
push!(rts, Slopes(x->(asin(cos(acos(sin(x))))), s, mid(s), interval(BigFloat(1.36), BigFloat(∞))))
2343

2444
for i in 1:length(rts)
2545
@test slope(rts[i].f, rts[i].x, rts[i].c) rts[i].sol

0 commit comments

Comments
 (0)