Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve mince and add method for non-uniform partition of IntervalBox #467

Merged
merged 6 commits into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/intervals/arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -577,5 +577,5 @@ as a vector.
"""
function mince(x::Interval, n)
nodes = range(x.lo, x.hi, length = n+1)
return [Interval(nodes[i], nodes[i+1]) for i in 1:length(nodes)-1]
return @. Interval(nodes[1:n], nodes[2:n+1])
lbenet marked this conversation as resolved.
Show resolved Hide resolved
end
20 changes: 20 additions & 0 deletions src/multidim/intervalbox.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,26 @@ as a vector.
end
end

@generated function mince(x::IntervalBox{N,T}, tup::NTuple{N,Int}) where {N,T}
quote
n = maximum(tup)
nodes_matrix = Array{Interval{T},2}(undef, n, N)
fill!(nodes_matrix, emptyinterval(T))
lbenet marked this conversation as resolved.
Show resolved Hide resolved
for i in 1:N
nodes_matrix[1:tup[i],i] .= mince(x[i], tup[i])
end

nodes = IntervalBox{$N,T}[]
Base.Cartesian.@nloops $N i _->(1:n) begin
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this part requires carefull review? I am not familiar with the macros used, but I could delve into it if needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review @Kolaru and also for offering getting into the details of this part of the code.

Here, I simply used the original method, and adapt it to obtain the desired behavior; maybe there are better ways, but for the time being, this is good enough. The original code was inspired from this section of the manual, which admittedly I have mostly forgotten.

Copy link
Collaborator

@Kolaru Kolaru Jun 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounded like a fun multidimensional challenge so I spent some time on it and I believe the following is equivalent:

function mince(x::IntervalBox{N,T}, ncuts::NTuple{N,Int}) where {N,T}
    minced_intervals = [mince(x[i], ncuts[i]) for i in 1:N]
    minced_boxes = Vector{IntervalBox{N,T}}(undef, prod(ncuts))

    for (k, cut_indices) in enumerate(CartesianIndices(ncuts))
        minced_boxes[k] = IntervalBox([minced_intervals[i][cut_indices[i]] for i in 1:N])
    end
    return minced_boxes
end

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Kolaru for the suggestion! I am also changing the other method (avoiding then the @generated). I would like to include you as coauthor of this commit; is it ok with you? (I already have the commit ready, but prefer to wait for your reply before pushing it.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure let me know if it needs any input from my side.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed it, so you can have a look

Base.Cartesian.@nextract $N ival d->nodes_matrix[i_d, d]
ibox = Base.Cartesian.@ncall $N IntervalBox ival
isempty(ibox) || push!(nodes, ibox)
end
nodes
end
end


hull(a::IntervalBox{N,T}, b::IntervalBox{N,T}) where {N,T} = IntervalBox(hull.(a[:], b[:]))
hull(a::Vector{IntervalBox{N,T}}) where {N,T} = hull(a...)

Expand Down
10 changes: 10 additions & 0 deletions test/multidim_tests/multidim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -306,18 +306,28 @@ end
@test vb2 == vv
@test hull(vb2...) == ib2
@test hull(vb2) == ib2
@test mince(ib2, (4,4)) == vb2
@test mince(ib2, (1,4)) == [ (-1 .. 1)×(-1 .. -0.5), (-1 .. 1)×(-0.5 .. 0),
(-1 .. 1)×(0 .. 0.5), (-1 .. 1)×(0.5 .. 1)]
@test hull(mince(ib2, (1,4))) == ib2

ib3 = IntervalBox(-1..1, 3)
vb3 = mince(ib3, 4)
@test length(vb3) == 4^3
@test hull(vb3...) == ib3
@test hull(vb3) == ib3
@test mince(ib3, (4,4,4)) == vb3
@test mince(ib3, (2,1,1)) == [(-1 .. 0)×(-1 .. 1)×(-1 .. 1),
(0 .. 1)×(-1 .. 1)×(-1 .. 1)]
@test hull(mince(ib3, (2,1,1))) == ib3

ib4 = IntervalBox(-1..1, 4)
vb4 = mince(ib4, 4)
@test length(vb4) == 4^4
@test hull(vb4...) == ib4
@test hull(vb4) == ib4
@test mince(ib4,(4,4,4,4)) == vb4
@test mince(ib4,(1,1,1,1)) == [ib4]
end

@testset "Special box constructors" begin
Expand Down