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

add mergeID #3027

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions docs/src/lib/sets/SparsePolynomialZonotope.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ independent_genmat(::SparsePolynomialZonotope)
expmat(::SparsePolynomialZonotope)
indexvector(P::SparsePolynomialZonotope)
uniqueID(::Int)
mergeID(::SparsePolynomialZonotope, ::SparsePolynomialZonotope)
dim(::SparsePolynomialZonotope)
ndependentgens(::SparsePolynomialZonotope)
nindependentgens(::SparsePolynomialZonotope)
Expand Down
38 changes: 37 additions & 1 deletion src/Sets/SparsePolynomialZonotope.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export SparsePolynomialZonotope, expmat, nparams, ndependentgens, nindependentgens,
dependent_genmat, independent_genmat, indexvector, exact_sum, ⊞,
dependent_genmat, independent_genmat, indexvector, mergeID, exact_sum, ⊞,
linear_map, quadratic_map, remove_redundant_generators

"""
Expand Down Expand Up @@ -207,6 +207,42 @@ indexvector(P::SPZ) = P.idx
Returns a collection of n unique identifiers (intergers 1, …, n).
"""
uniqueID(n::Int) = 1:n

"""
mergeID(P1::SparsePolynomialZonotope, P2::SparsePolynomialZonotope)

Returns two polynomial zonotopes equivalent to the correspondent input but with the same
index vector.

### Input

- `P1` -- sparse polynomial zonotope
- `P2` -- sprase polynomial zonotope
lucaferranti marked this conversation as resolved.
Show resolved Hide resolved

### Output

two polynomial zonotopes with the same index vector
"""
function mergeID(P1::SparsePolynomialZonotope, P2::SparsePolynomialZonotope)

idx1 = indexvector(P1)
idx2 = indexvector(P2)
idx1 == idx2 && return (P1, P2)

H = setdiff(idx2, idx1)
idx_new = vcat(idx1, H)
Comment on lines +232 to +233
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure this is correct. It seems non-symmetric. Does the test still work in the other order?

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 think it's symmetric up to permutation. That is the merged zonotopes will have the same parameters, but these will not necessarily ordered by index (i.e. the index vector is not ordered). If one also sorted the index vector, then it would be symmetric I think

Copy link
Member Author

Choose a reason for hiding this comment

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

at least looking at the algorithm description on page 35 of Niklas' thesis, the algorithm doesn't seem to be symmetric (because it doesn't fix the order)

Copy link
Member

Choose a reason for hiding this comment

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

So when you do mergeID(PZ2, PZ1) in the test case, you get the IDs [2, 4, 1, 3]. Is this acceptable or should the indices be sorted?

Copy link
Member Author

Choose a reason for hiding this comment

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

based on today's conversation, should we normalize the order?

Copy link
Member Author

@lucaferranti lucaferranti Aug 8, 2022

Choose a reason for hiding this comment

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

if in functions that require the same idvector (quadratic map, exact sum) you so something like

indexvector(PZ1) == indexvector(PZ2) || (PZ1, PZ2 = mergeID(PZ1, PZ2)

I think even without normalizing the order it would be correct, because calling mergeID would not change PZ1, PZ2 as setdiff(idx2, idx1) would be empty on the other hand, I don't see harm in normalizing the order either

Copy link
Member

Choose a reason for hiding this comment

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

I would not be surprised if some operations assume the same order after mergeID. So I would sort.

E1 = vcat(expmat(P1), zeros(Int, length(H), ndependentgens(P1)))
E2 = zeros(Int, length(idx1) + length(H), ndependentgens(P2))
E2_old = expmat(P2)
@inbounds for (i, idx) in enumerate(idx_new)
j = findfirst(isequal(idx), idx2)
!isnothing(j) && (E2[i, :] .= E2_old[j, :])
end
P1_new = SparsePolynomialZonotope(center(P1), dependent_genmat(P1), independent_genmat(P1), E1, idx_new)
mforets marked this conversation as resolved.
Show resolved Hide resolved
P2_new = SparsePolynomialZonotope(center(P2), dependent_genmat(P2), independent_genmat(P2), E2, idx_new)
return (P1_new, P2_new)
end

"""
linear_map(M::AbstractMatrix, P::SparsePolynomialZonotope)

Expand Down
17 changes: 17 additions & 0 deletions test/Sets/SparsePolynomialZonotope.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,20 @@ for Z in [rand(Zonotope), rand(Hyperrectangle)]
@test isempty(independent_genmat(ZS))
@test expmat(ZS) == I
end

E1 = [1 2 3; 4 5 6;7 8 9]
E2 = [1 2 0;1 1 1]
PZ1 = SparsePolynomialZonotope(rand(2), rand(2, 3), rand(2, 2), E1, 1:3)
PZ2 = SparsePolynomialZonotope(rand(2), rand(2, 3), rand(2, 2), E2, [2, 4])

mPZ1, mPZ2 = mergeID(PZ1, PZ2)
@test indexvector(mPZ1) == [1, 2, 3, 4]
@test indexvector(mPZ2) == [1, 2, 3, 4]

for f in (:center, :dependent_genmat, :independent_genmat)
@eval @test $f(mPZ1) == $f(PZ1)
@eval @test $f(mPZ2) == $f(PZ2)
end

@test expmat(mPZ1) == [1 2 3;4 5 6;7 8 9;0 0 0]
@test expmat(mPZ2) == [0 0 0;1 2 0;0 0 0;1 1 1]