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
84end
95
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)
137
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 }
159
16- Q = binary_minheap (IntervalMinima {T})
10+ Q = binary_minheap (IntervalMinimum {T})
1711
1812 global_minimum = f (interval (mid (x))). hi
1913
2014 arg_minima = Interval{T}[]
2115
22- push! (Q, IntervalMinima (x, global_minimum))
16+ push! (Q, IntervalMinimum (x, global_minimum))
2317
2418 while ! isempty (Q)
2519
2620 p = pop! (Q)
2721
28- if isempty (p. intval)
29- continue
30- end
31-
32- if p. global_minimum > global_minimum
22+ if isempty (p. interval)
3323 continue
3424 end
3525
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
6927 continue
7028 end
7129
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
7435 end
7536
76- deriv = ForwardDiff. derivative (f, p. intval)
77- if 0 ∉ deriv
78- continue
79- end
8037 # 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
8744
45+ m = mid (p. interval)
8846 current_minimum = f (interval (m)). hi
8947
9048 if current_minimum < global_minimum
@@ -93,33 +51,24 @@ function minimise1d_deriv(f::Function, x::Interval{T}; reltol=1e-3, abstol=1e-3)
9351
9452
9553 # 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)
9956
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
10459
105- if diam (p. intval ) < abstol
106- push! (arg_minima, p. intval )
60+ if diam (p. interval ) < abstol
61+ push! (arg_minima, p. interval )
10762 else
108- if isempty (x[2 ])
63+
64+ if use_deriv && isempty (x[2 ])
10965 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
11368 end
11469
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))
12372 end
12473 end
12574 lb = minimum (inf .(f .(arg_minima)))
@@ -128,63 +77,62 @@ function minimise1d_deriv(f::Function, x::Interval{T}; reltol=1e-3, abstol=1e-3)
12877end
12978
13079
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
13683end
13784
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
14093 c:: Interval{T}
14194end
14295
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)
14697
14798function minimise_icp (f:: Function , x:: IntervalBox{N, T} ; reltol= 1e-3 , abstol= 1e-3 ) where {N, T<: Real }
14899
149- Q = binary_minheap (IntervalBoxMinima {N, T})
100+ Q = binary_minheap (IntervalBoxMinimum {N, T})
150101
151102 global_minimum = ∞
152103
153104 x = icp (f, x, - ∞.. global_minimum)
154105
155106 arg_minima = IntervalBox{N, T}[]
156107
157- push! (Q, IntervalBoxMinima (x, global_minimum))
108+ push! (Q, IntervalBoxMinimum (x, global_minimum))
158109
159110 while ! isempty (Q)
160111
161112 p = pop! (Q)
162113
163- if isempty (p. intval )
114+ if isempty (p. interval )
164115 continue
165116 end
166117
167- if p. global_minimum > global_minimum
118+ if p. minimum > global_minimum
168119 continue
169120 end
170121
171- current_minimum = f (interval .(mid (p. intval ))). hi
122+ current_minimum = f (interval .(mid (p. interval ))). hi
172123
173124 if current_minimum < global_minimum
174125 global_minimum = current_minimum
175126 end
176- # if all(0 .∉ ForwardDiff.gradient(f, p.intval.v))
177- # continue
178- # end
179127
180- X = icp (f, p. intval , - ∞.. global_minimum)
128+ X = icp (f, p. interval , - ∞.. global_minimum)
181129
182- if diam (p. intval ) < abstol
183- push! (arg_minima, p. intval )
130+ if diam (p. interval ) < abstol
131+ push! (arg_minima, p. interval )
184132
185133 else
186134 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))
188136 end
189137 end
190138
@@ -193,9 +141,9 @@ function minimise_icp(f::Function, x::IntervalBox{N, T}; reltol=1e-3, abstol=1e-
193141 return lb.. global_minimum, arg_minima
194142end
195143
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 }
197145
198- Q = binary_minheap (IntervalBoxMinima {N, T})
146+ Q = binary_minheap (IntervalBoxMinimum {N, T})
199147
200148 global_minimum = ∞
201149
@@ -207,40 +155,38 @@ function minimise_icp_constrained(f::Function, x::IntervalBox{N, T}, constraints
207155
208156 arg_minima = IntervalBox{N, T}[]
209157
210- push! (Q, IntervalBoxMinima (x, global_minimum))
158+ push! (Q, IntervalBoxMinimum (x, global_minimum))
211159
212160 while ! isempty (Q)
213161
214162 p = pop! (Q)
215163
216- if isempty (p. intval )
164+ if isempty (p. interval )
217165 continue
218166 end
219167
220- if p. global_minimum > global_minimum
168+ if p. minimum > global_minimum
221169 continue
222170 end
223171
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
226174
227175 if current_minimum < global_minimum
228176 global_minimum = current_minimum
229177 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)
234180
235181 for t in constraints
236182 X = icp (t. f, X, t. c)
237183 end
238184
239- if diam (p. intval ) < abstol
240- push! (arg_minima, p. intval )
185+ if diam (p. interval ) < abstol
186+ push! (arg_minima, p. interval )
241187 else
242188 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))
244190 end
245191 end
246192 lb = minimum (inf .(f .(arg_minima)))
0 commit comments