Skip to content

Commit b364c38

Browse files
yashvardhan747dpsanders
authored andcommitted
Adding HeapedVector.jl (#28)
* Adding HeapedVector.jl and adding benchmarks * trying to import Strategy.jl but cant do it * Error:In Extending the function of StrategyBase.jl * Tests and some bugs are fixed * Benchmarks is shift to another branch * .DS_store is removedand made few changes in Heaped and SortedVector * All .DS_Store files are removed
1 parent 93a6cdb commit b364c38

File tree

9 files changed

+224
-49
lines changed

9 files changed

+224
-49
lines changed

src/HeapedVectors.jl

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
__precompile__()
2+
3+
module HeapedVectors
4+
5+
import Base: getindex, length, push!, isempty,
6+
pop!, filter!, popfirst!
7+
8+
export HeapedVector
9+
10+
import ..StrategyBase:filter_elements!
11+
using ..StrategyBase
12+
13+
struct HeapedVector{T, F<:Function} <: Strategy
14+
data::Vector{T}
15+
by::F
16+
function HeapedVector(v::Vector{T}, by::F) where {T, F}
17+
new{T, F}(heaping(v, by), by)
18+
end
19+
end
20+
21+
HeapedVector(data::Vector{T}) where {T} = HeapedVector(data, identity)
22+
23+
24+
function heaping(v, by)
25+
ar = typeof(v[1])[]
26+
for i = 1:length(v)
27+
insert!(ar, i, v[i])
28+
floatup!(ar, length(ar), by)
29+
end
30+
return ar
31+
end
32+
33+
function floatup!(ar, index, by)
34+
par = convert(Int, floor(index/2))
35+
if index <= 1
36+
return ar
37+
end
38+
if by(ar[index]) < by(ar[par])
39+
ar[par], ar[index] = ar[index], ar[par]
40+
end
41+
floatup!(ar, par, by)
42+
end
43+
44+
45+
function push!(v::HeapedVector{T}, x::T) where {T}
46+
insert!(v.data, length(v.data)+1, x)
47+
floatup!(v.data, length(v.data), v.by)
48+
return v
49+
end
50+
51+
52+
isempty(v::HeapedVector) = isempty(v.data)
53+
54+
55+
function popfirst!(v::HeapedVector{T}) where {T}
56+
if length(v.data) == 0
57+
return
58+
end
59+
60+
if length(v.data) > 2
61+
v.data[length(v.data)], v.data[1] = v.data[1], v.data[length(v.data)]
62+
minm = pop!(v.data)
63+
bubbledown!(v::HeapedVector{T}, 1)
64+
65+
elseif length(v.data) == 2
66+
v.data[length(v.data)], v.data[1] = v.data[1], v.data[length(v.data)]
67+
minm = pop!(v.data)
68+
else
69+
minm = pop!(v.data)
70+
end
71+
return minm
72+
end
73+
74+
75+
function bubbledown!(v::HeapedVector{T}, index) where{T}
76+
left = index*2
77+
right = index*2+1
78+
smallest = index
79+
80+
if length(v.data)+1 > left && v.by(v.data[smallest]) > v.by(v.data[left])
81+
smallest = left
82+
end
83+
84+
if length(v.data)+1 > right && v.by(v.data[smallest]) > v.by(v.data[right])
85+
smallest = right
86+
end
87+
88+
if smallest != index
89+
v.data[index], v.data[smallest] = v.data[smallest], v.data[index]
90+
bubbledown!(v, smallest)
91+
end
92+
end
93+
94+
function filter_elements!(A::HeapedVector{T}, x::T) where{T}
95+
func(y) = A.by(y) < A.by(x)
96+
filter!(func, A.data)
97+
98+
if length(A.data) == 0
99+
return A
100+
end
101+
102+
heaping(A.data, A.by)
103+
return A
104+
105+
end
106+
107+
end

src/IntervalOptimisation.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
2-
31
module IntervalOptimisation
42

53
export minimise, maximise,
64
minimize, maximize
5+
export HeapedVector, SortedVector
6+
7+
include("StrategyBase.jl")
8+
using .StrategyBase
79

810
include("SortedVectors.jl")
911
using .SortedVectors
1012

11-
using IntervalArithmetic, IntervalRootFinding
13+
include("HeapedVectors.jl")
14+
using .HeapedVectors
1215

16+
using IntervalArithmetic, IntervalRootFinding
1317

1418
include("optimise.jl")
1519

20+
1621
const minimize = minimise
1722
const maximize = maximise
1823

src/SortedVectors.jl

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,29 @@ __precompile__()
33
module SortedVectors
44

55
import Base: getindex, length, push!, isempty,
6-
pop!, resize!, popfirst!
6+
pop!, popfirst!
77

88
export SortedVector
99

10-
"""
11-
A `SortedVector` behaves like a standard Julia `Vector`, except that its elements are stored in sorted order, with an optional function `by` that determines the sorting order in the same way as `Base.searchsorted`.
12-
"""
13-
struct SortedVector{T, F<:Function}
10+
import ..StrategyBase:filter_elements!
11+
using ..StrategyBase
12+
13+
struct SortedVector{T, F<:Function} <: Strategy
14+
1415
data::Vector{T}
1516
by::F
1617

1718
function SortedVector(data::Vector{T}, by::F) where {T,F}
18-
new{T,F}(sort(data,by=by), by)
19+
new{T,F}(sort(data, by = by), by)
1920
end
2021
end
2122

22-
2323
SortedVector(data::Vector{T}) where {T} = SortedVector(data, identity)
2424

2525
function show(io::IO, v::SortedVector)
2626
print(io, "SortedVector($(v.data))")
2727
end
2828

29-
30-
3129
getindex(v::SortedVector, i::Int) = v.data[i]
3230
length(v::SortedVector) = length(v.data)
3331

@@ -43,9 +41,9 @@ pop!(v::SortedVector) = pop!(v.data)
4341

4442
popfirst!(v::SortedVector) = popfirst!(v.data)
4543

46-
47-
function resize!(v::SortedVector, n::Int)
48-
resize!(v.data, n)
44+
function filter_elements!(v::SortedVector{T}, x::T) where {T}
45+
cutoff = searchsortedfirst(v.data, x, by=v.by)
46+
resize!(v.data, cutoff-1)
4947
return v
5048
end
5149

src/StrategyBase.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module StrategyBase
2+
3+
export filter_elements!, Strategy
4+
abstract type Strategy end
5+
function filter_elements!(s::Strategy)end
6+
7+
end

src/optimise.jl

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1+
"""
2+
minimise(f, X, structure = SortedVector, tol=1e-3)
3+
or
4+
minimise(f, X, structure = HeapedVector, tol=1e-3)
5+
or
6+
minimise(f, X, tol=1e-3) in this case the default value of "structure" is "HeapedVector"
17
2-
"""
3-
minimise(f, X, tol=1e-3)
4-
5-
Find the global minimum of the function `f` over the `Interval` or `IntervalBox` `X` using the Moore-Skelboe algorithm.
8+
Find the global minimum of the function `f` over the `Interval` or `IntervalBox` `X` using the Moore-Skelboe algorithm. By specifing the way in which vector element are kept arranged which is in heaped array or in sorted array. If you not specify any particular strategy to keep vector elements arranged then by default heaped array is used.
69
710
For higher-dimensional functions ``f:\\mathbb{R}^n \\to \\mathbb{R}``, `f` must take a single vector argument.
811
912
Returns an interval containing the global minimum, and a list of boxes that contain the minimisers.
1013
"""
11-
function minimise(f, X::T, tol=1e-3) where {T}
1214

13-
# list of boxes with corresponding lower bound, ordered by increasing lower bound:
14-
working = SortedVector([(X, ∞)], x->x[2])
1515

16+
function minimise(f, X::T ; structure = HeapedVector, tol=1e-3 ) where {T}
17+
18+
# list of boxes with corresponding lower bound, arranged according to selected structure :
19+
working = structure([(X, ∞)], x->x[2])
1620
minimizers = T[]
1721
global_min =# upper bound
1822

@@ -34,17 +38,14 @@ function minimise(f, X::T, tol=1e-3) where {T}
3438
end
3539

3640
# Remove all boxes whose lower bound is greater than the current one:
37-
# Since they are ordered, just find the first one that is too big
38-
39-
cutoff = searchsortedfirst(working.data, (X, global_min), by=x->x[2])
40-
resize!(working, cutoff-1)
41+
filter_elements!(working , (X, global_min) )
4142

4243
if diam(X) < tol
4344
push!(minimizers, X)
44-
4545
else
4646
X1, X2 = bisect(X)
47-
push!( working, (X1, inf(f(X1))), (X2, inf(f(X2))) )
47+
push!( working, (X1, inf(f(X1))) )
48+
push!( working, (X2, inf(f(X2))) )
4849
num_bisections += 1
4950
end
5051

@@ -56,7 +57,7 @@ function minimise(f, X::T, tol=1e-3) where {T}
5657
end
5758

5859

59-
function maximise(f, X::T, tol=1e-3) where {T}
60-
bound, minimizers = minimise(x -> -f(x), X, tol)
60+
function maximise(f, X::T; structure = HeapedVector, tol=1e-3 ) where {T}
61+
bound, minimizers = minimise(x -> -f(x), X, structure, tol)
6162
return -bound, minimizers
6263
end

test/heaped_vector.jl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using IntervalOptimisation
2+
using Test
3+
4+
const HeapedVector = IntervalOptimisation.HeapedVector
5+
6+
@testset "heap" begin
7+
8+
@testset "with standard heaping " begin
9+
10+
h=HeapedVector([9, 7, 5, 2, 3])
11+
12+
@test h.data == [2, 3, 7, 9, 5]
13+
14+
push!(h, 1)
15+
@test h.data == [1, 3, 2, 9, 5, 7]
16+
17+
popfirst!(h)
18+
@test h.data == [2, 3, 7, 9, 5]
19+
20+
end
21+
22+
@testset "with ordering function" begin
23+
24+
h=HeapedVector( [(9,"f"), (7,"c"), (5,"e"), (2,"d"), (3,"b")] , x->x[2])
25+
26+
@test h.data == [(3, "b"), (7, "c"), (5, "e"), (9, "f"), (2, "d")]
27+
28+
push!(h, (1,"a"))
29+
@test h.data == [(1, "a"), (7, "c"), (3, "b"), (9, "f"), (2, "d"), (5, "e")]
30+
31+
popfirst!(h)
32+
@test h.data == [(3, "b"), (7, "c"), (5, "e"), (9, "f"), (2, "d")]
33+
34+
end
35+
36+
end

test/optimise.jl

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,62 @@
1-
using IntervalArithmetic, IntervalOptimisation
1+
using IntervalArithmetic, IntervalOptimisation
22
using Test
33

44
@testset "IntervalOptimisation tests" begin
55

6-
@testset "Minimise in 1D" begin
6+
@testset "Minimise in 1D using default data structure i.e HeapedVector" begin
77
global_min, minimisers = minimise(x->x, -10..10)
88
@test global_min -10 .. -9.999
99
@test length(minimisers) == 1
1010
@test minimisers[1] -10 .. -9.999
1111

12-
global_min, minimisers = minimise(x->x^2, -10..11, 1e-10)
12+
global_min, minimisers = minimise(x->x^2, -10..11, tol = 1e-10)
1313
@test global_min 0..1e-20
1414
@test length(minimisers) == 1
1515
@test minimisers[1] -0.1..0.1
1616

1717
global_min, minimisers = minimise(x->(x^2-2)^2, -10..11)
1818
@test global_min 0..1e-7
1919
@test length(minimisers) == 2
20-
@test sqrt(2) minimisers[1]
20+
@test sqrt(2) minimisers[2]
2121
end
2222

23+
for Structure in (SortedVector, HeapedVector)
2324

24-
@testset "Discontinuous function in 1D" begin
25+
@testset "Minimise in 1D using SoretedVector" begin
26+
global_min, minimisers = minimise(x->x, -10..10, structure = Structure)
27+
@test global_min -10 .. -9.999
28+
@test length(minimisers) == 1
29+
@test minimisers[1] -10 .. -9.999
2530

26-
H(x) = (sign(x) + 1) / 2 # Heaviside function except at 0, where H(0) = 0.5
31+
global_min, minimisers = minimise(x->x^2, -10..11, tol=1e-10, structure = Structure)
32+
@test global_min 0..1e-20
33+
@test length(minimisers) == 1
34+
@test minimisers[1] -0.1..0.1
2735

28-
global_min, minimisers = minimise(x -> abs(x) + H(x) - 1, -10..11, 1e-5)
29-
@test global_min -1 .. -0.9999
30-
@test length(minimisers) == 1
31-
@test 0 minimisers[1]
32-
@test diam(minimisers[1]) <= 1e-5
33-
end
36+
global_min, minimisers = minimise(x->(x^2-2)^2, -10..11, structure = Structure)
37+
@test global_min 0..1e-7
38+
@test length(minimisers) == 2
39+
@test sqrt(2) max(minimisers[1], minimisers[2])
40+
end
3441

3542

36-
@testset "Smooth function in 2D" begin
37-
global_min, minimisers = minimise( X -> ( (x,y) = X; x^2 + y^2 ), (-10..10) × (-10..10) )
38-
@test global_min 0..1e-7
39-
@test all(X (-1e-3..1e3) × (-1e-3..1e-3) for X in minimisers)
43+
@testset "Discontinuous function in 1D" begin
44+
45+
H(x) = (sign(x) + 1) / 2 # Heaviside function except at 0, where H(0) = 0.5
46+
global_min, minimisers = minimise(x -> abs(x) + H(x) - 1, -10..11, tol=1e-5, structure = Structure)
47+
@test global_min -1 .. -0.9999
48+
@test length(minimisers) == 1
49+
@test 0 minimisers[1]
50+
@test diam(minimisers[1]) <= 1e-5
51+
end
52+
53+
54+
@testset "Smooth function in 2D" begin
55+
global_min, minimisers = minimise( X -> ( (x,y) = X; x^2 + y^2 ), (-10..10) × (-10..10), structure = Structure )
56+
@test global_min 0..1e-7
57+
@test all(X (-1e-3..1e3) × (-1e-3..1e-3) for X in minimisers)
58+
end
59+
4060
end
4161

42-
end
62+
end

test/runtests.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ using IntervalOptimisation
22
using Test
33

44
include("sorted_vector.jl")
5-
include("optimise.jl")
5+
include("heaped_vector.jl")
6+
include("optimise.jl")

test/sorted_vector.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ const SortedVector = IntervalOptimisation.SortedVector
4747
@test v.data == [(1, "a"), (4, "c"), (3, "x"), (5, "y"), (2, "z")]
4848
end
4949

50-
end
50+
end

0 commit comments

Comments
 (0)