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