1- using IntervalRootFinding, IntervalArithmetic, StaticArrays, ForwardDiff, BenchmarkTools, Compat, IntervalOptimisation, DataStructures
1+ using IntervalRootFinding, IntervalArithmetic, StaticArrays, ForwardDiff, BenchmarkTools, Compat, IntervalOptimisation, DataStructures, IntervalConstraintProgramming
22
33import Base. isless
44
55struct IntervalMinima{T<: Real }
66 intval:: Interval{T}
7- minima :: T
7+ global_minimum :: T
88end
99
1010function 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 )
1212end
1313
1414function minimise1d (f:: Function , x:: Interval{T} ; reltol= 1e-3 , abstol= 1e-3 ) where {T<: Real }
1515
1616 Q = binary_minheap (IntervalMinima{T})
1717
18- minima = f (interval (mid (x))). hi
18+ global_minimum = f (interval (mid (x))). hi
1919
2020 arg_minima = Interval{T}[]
2121
22- push! (Q, IntervalMinima (x, minima ))
22+ push! (Q, IntervalMinima (x, global_minimum ))
2323
2424 while ! isempty (Q)
2525
@@ -29,51 +29,90 @@ function minimise1d(f::Function, x::Interval{T}; reltol=1e-3, abstol=1e-3) where
2929 continue
3030 end
3131
32- if p. minima > minima
32+ if p. global_minimum > global_minimum
3333 continue
3434 end
3535
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)
4065
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
4373 continue
4474 end
4575
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+
4686 m = mid (p. intval)
4787
48- current_minima = f (interval (m)). hi
88+ current_minimum = f (interval (m)). hi
4989
50- if current_minima < minima
51- minima = current_minima
90+ if current_minimum < global_minimum
91+ global_minimum = current_minimum
5292 end
5393
5494
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)
6597
6698 x = x .∩ p. intval
6799
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+
68105 if diam (p. intval) < abstol
69106 push! (arg_minima, p. intval)
70107 else
71- if length (x) == 1
108+ if isempty (x[ 2 ])
72109 x1, x2 = bisect (x[1 ])
73110 push! (Q, IntervalMinima (x1, f (x1). lo), IntervalMinima (x2, f (x2). lo))
74111 else
75112 push! (Q, IntervalMinima .(x, inf .(f .(x)))... )
76113 end
114+
115+ # Second Deriv contractor
77116 # if isempty(x[2])
78117 # x1, x2 = bisect(x[1])
79118 # 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
83122 # end
84123 end
85124 end
125+ lb = minimum (inf .(f .(arg_minima)))
86126
87- return minima , arg_minima
127+ return lb .. global_minimum , arg_minima
88128end
89129
90130
91- function minimise1d_noderiv (f:: Function , x:: Interval{T} ; reltol= 1e-3 , abstol= 1e-3 ) where {T<: Real }
92131
93- Q = binary_minheap (IntervalMinima{T})
94132
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)
97154
98- push! (Q, IntervalMinima (x, minima))
155+ arg_minima = IntervalBox{N, T}[]
156+
157+ push! (Q, IntervalBoxMinima (x, global_minimum))
99158
100159 while ! isempty (Q)
101160
102161 p = pop! (Q)
103162
104- if p . minima > minima
163+ if isempty (p . intval)
105164 continue
106165 end
107- #
108- # if 0 ∉ ForwardDiff.derivative(f, p.intval)
109- # continue
110- # end
111166
112- # current_minima = f(p.intval).lo
167+ if p. global_minimum > global_minimum
168+ continue
169+ end
113170
114- current_minima = f (interval (mid (p. intval))). hi
171+ current_minimum = f (interval . (mid (p. intval))). hi
115172
116- if current_minima < minima
117- minima = current_minima
173+ if current_minimum < global_minimum
174+ global_minimum = current_minimum
118175 end
176+ # if all(0 .∉ ForwardDiff.gradient(f, p.intval.v))
177+ # continue
178+ # end
179+
180+ X = icp (f, p. intval, - ∞.. global_minimum)
119181
120182 if diam (p. intval) < abstol
121183 push! (arg_minima, p. intval)
184+
122185 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))
125188 end
126189 end
127190
128- return minima, arg_minima
129- end
191+ lb = minimum (inf .(f .(arg_minima)))
130192
193+ return lb.. global_minimum, arg_minima
194+ end
131195
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 }
132197
133- struct IntervalBoxMinima{N, T<: Real }
134- intval:: IntervalBox{N, T}
135- minima:: T
136- end
198+ Q = binary_minheap (IntervalBoxMinima{N, T})
137199
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 = ∞
141201
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
143205
144- Q = binary_minheap (IntervalBoxMinima{N, T} )
206+ x = icp (f, x, - ∞ .. global_minimum )
145207
146- minima = f (x). lo
147208 arg_minima = IntervalBox{N, T}[]
148209
149- push! (Q, IntervalBoxMinima (x, minima ))
210+ push! (Q, IntervalBoxMinima (x, global_minimum ))
150211
151212 while ! isempty (Q)
152213
153214 p = pop! (Q)
154215
155- if p . minima > minima
216+ if isempty (p . intval)
156217 continue
157218 end
158219
159- if 0 .∉ ForwardDiff . gradient (f, p . intval)
220+ if p . global_minimum > global_minimum
160221 continue
161222 end
162223
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)
165237 end
166238
167239 if diam (p. intval) < abstol
168240 push! (arg_minima, p. intval)
169241 else
170- x1, x2 = bisect (p . intval )
242+ x1, x2 = bisect (X )
171243 push! (Q, IntervalBoxMinima (x1, f (x1). lo), IntervalBoxMinima (x2, f (x2). lo))
172244 end
173245 end
174-
175- return minima , arg_minima
246+ lb = minimum ( inf .( f .(arg_minima)))
247+ return lb .. global_minimum , arg_minima
176248end
0 commit comments