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