1
- using IntervalRootFinding, IntervalArithmetic, StaticArrays, ForwardDiff, BenchmarkTools, Compat, IntervalOptimisation, DataStructures, IntervalConstraintProgramming
2
-
3
- import Base. isless
4
-
5
- struct IntervalMinima{T<: Real }
6
- intval:: Interval{T}
7
- global_minimum:: T
1
+ struct IntervalMinimum{T<: Real }
2
+ interval:: Interval{T}
3
+ minimum:: T
8
4
end
9
5
10
- function isless (a:: IntervalMinima{T} , b:: IntervalMinima{T} ) where {T<: Real }
11
- return isless (a. global_minimum, b. global_minimum)
12
- end
6
+ Base. isless (a:: IntervalMinimum{T} , b:: IntervalMinimum{T} ) where {T<: Real } = isless (a. minimum, b. minimum)
13
7
14
- function minimise1d (f:: Function , x:: Interval{T} ; reltol= 1e-3 , abstol= 1e-3 ) where {T<: Real }
8
+ function minimise1d (f:: Function , x:: Interval{T} ; reltol= 1e-3 , abstol= 1e-3 , use_deriv = false , use_second_deriv = false ) where {T<: Real }
15
9
16
- Q = binary_minheap (IntervalMinima {T})
10
+ Q = binary_minheap (IntervalMinimum {T})
17
11
18
12
global_minimum = f (interval (mid (x))). hi
19
13
20
14
arg_minima = Interval{T}[]
21
15
22
- push! (Q, IntervalMinima (x, global_minimum))
16
+ push! (Q, IntervalMinimum (x, global_minimum))
23
17
24
18
while ! isempty (Q)
25
19
26
20
p = pop! (Q)
27
21
28
- if isempty (p. intval)
29
- continue
30
- end
31
-
32
- if p. global_minimum > global_minimum
22
+ if isempty (p. interval)
33
23
continue
34
24
end
35
25
36
- current_minimum = f (interval (mid (p. intval))). hi
37
-
38
- if current_minimum < global_minimum
39
- global_minimum = current_minimum
40
- end
41
-
42
- if diam (p. intval) < abstol
43
- push! (arg_minima, p. intval)
44
- else
45
- x1, x2 = bisect (p. intval)
46
- push! (Q, IntervalMinima (x1, f (x1). lo), IntervalMinima (x2, f (x2). lo))
47
- end
48
- end
49
- lb = minimum (inf .(f .(arg_minima)))
50
-
51
- return lb.. global_minimum, arg_minima
52
- end
53
-
54
- function minimise1d_deriv (f:: Function , x:: Interval{T} ; reltol= 1e-3 , abstol= 1e-3 ) where {T<: Real }
55
-
56
- Q = binary_minheap (IntervalMinima{T})
57
-
58
- global_minimum = f (interval (mid (x))). hi
59
-
60
- arg_minima = Interval{T}[]
61
-
62
- push! (Q, IntervalMinima (x, global_minimum))
63
-
64
- while ! isempty (Q)
65
-
66
- p = pop! (Q)
67
-
68
- if isempty (p. intval)
26
+ if p. minimum > global_minimum
69
27
continue
70
28
end
71
29
72
- if p. global_minimum > global_minimum
73
- continue
30
+ if use_deriv
31
+ deriv = ForwardDiff. derivative (f, p. interval)
32
+ if 0 ∉ deriv
33
+ continue
34
+ end
74
35
end
75
36
76
- deriv = ForwardDiff. derivative (f, p. intval)
77
- if 0 ∉ deriv
78
- continue
79
- end
80
37
# Second derivative contractor
81
- # doublederiv = ForwardDiff.derivative(x->ForwardDiff.derivative(f, x), p.intval)
82
- # if doublederiv < 0
83
- # continue
84
- # end
85
-
86
- m = mid (p . intval)
38
+ if use_second_deriv
39
+ doublederiv = ForwardDiff . derivative (x -> ForwardDiff . derivative (f, x), p . interval)
40
+ if doublederiv < 0
41
+ continue
42
+ end
43
+ end
87
44
45
+ m = mid (p. interval)
88
46
current_minimum = f (interval (m)). hi
89
47
90
48
if current_minimum < global_minimum
@@ -93,33 +51,24 @@ function minimise1d_deriv(f::Function, x::Interval{T}; reltol=1e-3, abstol=1e-3)
93
51
94
52
95
53
# Contractor 1
96
- x = m .+ extended_div ((interval (- ∞, global_minimum) - f (m)), deriv)
97
-
98
- x = x .∩ p. intval
54
+ if use_deriv
55
+ x = m .+ extended_div ((interval (- ∞, global_minimum) - f (m)), deriv)
99
56
100
- # # Contractor 2 (Second derivative, expanding more on the Taylor Series, not beneficial in practice)
101
- # x = m .+ quadratic_roots(doublederiv/2, ForwardDiff.derivative(f, interval(m)), f(m) - interval(-∞, global_minimum))
102
- #
103
- # x = x .∩ p.intval
57
+ x = x .∩ p. interval
58
+ end
104
59
105
- if diam (p. intval ) < abstol
106
- push! (arg_minima, p. intval )
60
+ if diam (p. interval ) < abstol
61
+ push! (arg_minima, p. interval )
107
62
else
108
- if isempty (x[2 ])
63
+
64
+ if use_deriv && isempty (x[2 ])
109
65
x1, x2 = bisect (x[1 ])
110
- push! (Q, IntervalMinima (x1, f (x1). lo), IntervalMinima (x2, f (x2). lo))
111
- else
112
- push! (Q, IntervalMinima .(x, inf .(f .(x)))... )
66
+ push! (Q, IntervalMinimum (x1, f (x1). lo), IntervalMinimum (x2, f (x2). lo))
67
+ continue
113
68
end
114
69
115
- # Second Deriv contractor
116
- # if isempty(x[2])
117
- # x1, x2 = bisect(x[1])
118
- # push!(Q, IntervalMinima(x1, f(x1).lo), IntervalMinima(x2, f(x2).lo))
119
- # else
120
- # x1, x2, x3 = x
121
- # push!(Q, IntervalMinima(x1, f(x1).lo), IntervalMinima(x2, f(x2).lo), IntervalMinima(x3, f(x3).lo))
122
- # end
70
+ x1, x2 = bisect (p. interval)
71
+ push! (Q, IntervalMinimum (x1, f (x1). lo), IntervalMinimum (x2, f (x2). lo))
123
72
end
124
73
end
125
74
lb = minimum (inf .(f .(arg_minima)))
@@ -128,63 +77,62 @@ function minimise1d_deriv(f::Function, x::Interval{T}; reltol=1e-3, abstol=1e-3)
128
77
end
129
78
130
79
131
-
132
-
133
- struct IntervalBoxMinima{N, T<: Real }
134
- intval:: IntervalBox{N, T}
135
- global_minimum:: T
80
+ struct IntervalBoxMinimum{N, T<: Real }
81
+ interval:: IntervalBox{N, T}
82
+ minimum:: T
136
83
end
137
84
138
- struct constraint{T<: Real }
139
- f:: Function
85
+ """
86
+ Datatype to provide constraints to Global Optimisation such as:
87
+ ```
88
+ Constraint(x->(x^2 - 10), -∞..1)
89
+ ```
90
+ """
91
+ struct Constraint{F, T<: Real }
92
+ f:: F
140
93
c:: Interval{T}
141
94
end
142
95
143
- function isless (a:: IntervalBoxMinima{N, T} , b:: IntervalBoxMinima{N, T} ) where {N, T<: Real }
144
- return isless (a. global_minimum, b. global_minimum)
145
- end
96
+ Base. isless (a:: IntervalBoxMinimum{N, T} , b:: IntervalBoxMinimum{N, T} ) where {N, T<: Real } = isless (a. minimum, b. minimum)
146
97
147
98
function minimise_icp (f:: Function , x:: IntervalBox{N, T} ; reltol= 1e-3 , abstol= 1e-3 ) where {N, T<: Real }
148
99
149
- Q = binary_minheap (IntervalBoxMinima {N, T})
100
+ Q = binary_minheap (IntervalBoxMinimum {N, T})
150
101
151
102
global_minimum = ∞
152
103
153
104
x = icp (f, x, - ∞.. global_minimum)
154
105
155
106
arg_minima = IntervalBox{N, T}[]
156
107
157
- push! (Q, IntervalBoxMinima (x, global_minimum))
108
+ push! (Q, IntervalBoxMinimum (x, global_minimum))
158
109
159
110
while ! isempty (Q)
160
111
161
112
p = pop! (Q)
162
113
163
- if isempty (p. intval )
114
+ if isempty (p. interval )
164
115
continue
165
116
end
166
117
167
- if p. global_minimum > global_minimum
118
+ if p. minimum > global_minimum
168
119
continue
169
120
end
170
121
171
- current_minimum = f (interval .(mid (p. intval ))). hi
122
+ current_minimum = f (interval .(mid (p. interval ))). hi
172
123
173
124
if current_minimum < global_minimum
174
125
global_minimum = current_minimum
175
126
end
176
- # if all(0 .∉ ForwardDiff.gradient(f, p.intval.v))
177
- # continue
178
- # end
179
127
180
- X = icp (f, p. intval , - ∞.. global_minimum)
128
+ X = icp (f, p. interval , - ∞.. global_minimum)
181
129
182
- if diam (p. intval ) < abstol
183
- push! (arg_minima, p. intval )
130
+ if diam (p. interval ) < abstol
131
+ push! (arg_minima, p. interval )
184
132
185
133
else
186
134
x1, x2 = bisect (X)
187
- push! (Q, IntervalBoxMinima (x1, f (x1). lo), IntervalBoxMinima (x2, f (x2). lo))
135
+ push! (Q, IntervalBoxMinimum (x1, f (x1). lo), IntervalBoxMinimum (x2, f (x2). lo))
188
136
end
189
137
end
190
138
@@ -193,9 +141,9 @@ function minimise_icp(f::Function, x::IntervalBox{N, T}; reltol=1e-3, abstol=1e-
193
141
return lb.. global_minimum, arg_minima
194
142
end
195
143
196
- function minimise_icp_constrained (f:: Function , x:: IntervalBox{N, T} , constraints:: Vector{constraint {T}} = Vector {constraint {T}} (); reltol= 1e-3 , abstol= 1e-3 ) where {N, T<: Real }
144
+ function minimise_icp_constrained (f:: Function , x:: IntervalBox{N, T} , constraints:: Vector{Constraint {T}} = Vector {Constraint {T}} (); reltol= 1e-3 , abstol= 1e-3 ) where {N, T<: Real }
197
145
198
- Q = binary_minheap (IntervalBoxMinima {N, T})
146
+ Q = binary_minheap (IntervalBoxMinimum {N, T})
199
147
200
148
global_minimum = ∞
201
149
@@ -207,40 +155,38 @@ function minimise_icp_constrained(f::Function, x::IntervalBox{N, T}, constraints
207
155
208
156
arg_minima = IntervalBox{N, T}[]
209
157
210
- push! (Q, IntervalBoxMinima (x, global_minimum))
158
+ push! (Q, IntervalBoxMinimum (x, global_minimum))
211
159
212
160
while ! isempty (Q)
213
161
214
162
p = pop! (Q)
215
163
216
- if isempty (p. intval )
164
+ if isempty (p. interval )
217
165
continue
218
166
end
219
167
220
- if p. global_minimum > global_minimum
168
+ if p. minimum > global_minimum
221
169
continue
222
170
end
223
171
224
- # current_minimum = f(interval.(mid(p.intval ))).hi
225
- current_minimum = f (p. intval ). hi
172
+ # current_minimum = f(interval.(mid(p.interval ))).hi
173
+ current_minimum = f (p. interval ). hi
226
174
227
175
if current_minimum < global_minimum
228
176
global_minimum = current_minimum
229
177
end
230
- # if 0 .∉ ForwardDiff.gradient(f, p.intval.v)
231
- # continue
232
- # end
233
- X = icp (f, p. intval, - ∞.. global_minimum)
178
+
179
+ X = icp (f, p. interval, - ∞.. global_minimum)
234
180
235
181
for t in constraints
236
182
X = icp (t. f, X, t. c)
237
183
end
238
184
239
- if diam (p. intval ) < abstol
240
- push! (arg_minima, p. intval )
185
+ if diam (p. interval ) < abstol
186
+ push! (arg_minima, p. interval )
241
187
else
242
188
x1, x2 = bisect (X)
243
- push! (Q, IntervalBoxMinima (x1, f (x1). lo), IntervalBoxMinima (x2, f (x2). lo))
189
+ push! (Q, IntervalBoxMinimum (x1, f (x1). lo), IntervalBoxMinimum (x2, f (x2). lo))
244
190
end
245
191
end
246
192
lb = minimum (inf .(f .(arg_minima)))
0 commit comments