Skip to content

Commit

Permalink
run formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmul1114 committed Nov 7, 2024
1 parent 122a308 commit 4efec5e
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 67 deletions.
38 changes: 26 additions & 12 deletions src/symcpd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ struct SymCPD{T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}}
λ::Tλ
U::NTuple{K,TU}
S::NTuple{N,Int}
function SymCPD{T,N,K,Tλ,TU}(λ, U, S) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}}
function SymCPD{T,N,K,Tλ,TU}(
λ,
U,
S,
) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}}
Base.require_one_based_indexing(λ, U...)
if K > 0
minimum([S...]) == 1 && maximum([S...]) <= K || throw(
DimensionMismatch(
"Symmetric Groups must be numbered 1,2,... (max N)",
),
DimensionMismatch("Symmetric Groups must be numbered 1,2,... (max N)"),
)
end
for k in Base.OneTo(K)
Expand All @@ -41,8 +43,11 @@ struct SymCPD{T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}}
return new{T,N,K,Tλ,TU}(λ, U, S)
end
end
SymCPD::Tλ, U::NTuple{K,TU}, S::NTuple{N,Int}) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}} =
SymCPD{T,N,K,Tλ,TU}(λ, U, S)
SymCPD(
λ::Tλ,
U::NTuple{K,TU},
S::NTuple{N,Int},
) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}} = SymCPD{T,N,K,Tλ,TU}(λ, U, S)

"""
ncomps(M::SymCPD)
Expand All @@ -54,9 +59,13 @@ See also: `ndims`, `size`.
ncomps(M::SymCPD) = length(M.λ)
ndims(M::SymCPD) = length(M.S)

size(M::SymCPD{T,N,K,Tλ,TU}, dim::Integer) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}} = dim <= N ? size(M.U[M.S[dim]], 1) : 1
size(M::SymCPD{T,N,K,Tλ,TU}) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}} = ntuple(d -> size(M, d), N)

size(
M::SymCPD{T,N,K,Tλ,TU},
dim::Integer,
) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}} =
dim <= N ? size(M.U[M.S[dim]], 1) : 1
size(M::SymCPD{T,N,K,Tλ,TU}) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}} =
ntuple(d -> size(M, d), N)

"""
ngroups(M::SymCPD)
Expand All @@ -65,7 +74,10 @@ Return the number of symmetric groups in `M`.
"""
ngroups(M::SymCPD) = length(M.U)

function getindex(M::SymCPD{T,N,K,Tλ,TU}, I::Vararg{Int,N}) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}}
function getindex(
M::SymCPD{T,N,K,Tλ,TU},
I::Vararg{Int,N},
) where {T,N,K,Tλ<:AbstractVector{T},TU<:AbstractMatrix{T}}
@boundscheck Base.checkbounds_indices(Bool, axes(M), I) || Base.throw_boundserror(M, I)
val = zero(eltype(T))
for j in Base.OneTo(ncomps(M))
Expand All @@ -75,7 +87,10 @@ function getindex(M::SymCPD{T,N,K,Tλ,TU}, I::Vararg{Int,N}) where {T,N,K,Tλ<:A
end
getindex(M::SymCPD{T,N,K}, I::CartesianIndex{N}) where {T,N,K} = getindex(M, Tuple(I)...)

AbstractArray(A::SymCPD) = reshape(TensorKernels.khatrirao(reverse([A.U[A.S[k]] for k in 1:ndims(A)])...) * A.λ, size(A))
AbstractArray(A::SymCPD) = reshape(
TensorKernels.khatrirao(reverse([A.U[A.S[k]] for k in 1:ndims(A)])...) * A.λ,
size(A),
)
Array(A::SymCPD) = Array(AbstractArray(A))

norm(M::SymCPD, p::Real = 2) =
Expand Down Expand Up @@ -225,7 +240,6 @@ function permutecomps!(M::SymCPD, perm::Vector)
return M
end


"""
convertCPD(M::SymCPD)
Expand Down
109 changes: 56 additions & 53 deletions test/items/symcpd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,32 @@
U1, U2, U3 = U1full[:, 1:K], U2full[:, 1:K], U3full[:, 1:K]

# Check type for various orders
@test SymCPD{T,0,0,Vector{T},Matrix{T}}(λ, (), ()) isa SymCPD{T,0,0,Vector{T},Matrix{T}}
@test SymCPD{T,0,0,Vector{T},Matrix{T}}(λ, (), ()) isa
SymCPD{T,0,0,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1,), (1,)) isa SymCPD{T,1,1,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2), (1,2)) isa SymCPD{T,2,2,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2, U3), (1,2,3)) isa SymCPD{T,3,3,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2), (1, 2)) isa SymCPD{T,2,2,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2, U3), (1, 2, 3)) isa SymCPD{T,3,3,Vector{T},Matrix{T}}

# Check requirement of one-based indexing
O1, O2 = OffsetArray(U1, 0:1, 0:K-1), OffsetArray(U2, 0:0, 0:K-1)
@test_throws ArgumentError SymCPD(λ, (O1, O2), (1,2))
@test_throws ArgumentError SymCPD(λ, (O1, O2), (1, 2))

# Check dimension matching (for number of components)
@test_throws DimensionMismatch SymCPD(λfull, (U1, U2, U3), (1,2,3))
@test_throws DimensionMismatch SymCPD(λ, (U1full, U2, U3), (1,2,3))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2full, U3), (1,2,3))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2, U3full), (1,2,3))
@test_throws DimensionMismatch SymCPD(λfull, (U1, U2, U3), (1, 2, 3))
@test_throws DimensionMismatch SymCPD(λ, (U1full, U2, U3), (1, 2, 3))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2full, U3), (1, 2, 3))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2, U3full), (1, 2, 3))

# Check different symmetric cases
@test SymCPD(λ, (U1,), (1,1,1)) isa SymCPD{T,3,1,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2), (1,2,1)) isa SymCPD{T,3,2,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2), (1,1,2)) isa SymCPD{T,3,2,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2), (2,1,1)) isa SymCPD{T,3,2,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1,), (1, 1, 1)) isa SymCPD{T,3,1,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2), (1, 2, 1)) isa SymCPD{T,3,2,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2), (1, 1, 2)) isa SymCPD{T,3,2,Vector{T},Matrix{T}}
@test SymCPD(λ, (U1, U2), (2, 1, 1)) isa SymCPD{T,3,2,Vector{T},Matrix{T}}

# Check dimension matching for S
@test_throws DimensionMismatch SymCPD(λ, (U1, U2), (1,2,3))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2), (2,2,2))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2), (1,2,3))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2), (1, 2, 3))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2), (2, 2, 2))
@test_throws DimensionMismatch SymCPD(λ, (U1, U2), (1, 2, 3))
end
end

Expand All @@ -43,24 +44,26 @@ end
U1, U2, U3 = [1 2 3; 4 5 6], [-1 0 1], [1 2 3; 4 5 6; 7 8 9]

@test ncomps(SymCPD(λ, (U1,), (1,))) ==
ncomps(SymCPD(λ, (U1, U2), (1,2))) ==
ncomps(SymCPD(λ, (U1, U2, U3), (1,2,3,3))) ==
ncomps(SymCPD(λ, (U1, U2, U3), (2,1,1,2,3))) ==
ncomps(SymCPD(λ, (U1, U2), (1, 2))) ==
ncomps(SymCPD(λ, (U1, U2, U3), (1, 2, 3, 3))) ==
ncomps(SymCPD(λ, (U1, U2, U3), (2, 1, 1, 2, 3))) ==
3
@test ncomps(SymCPD(λ[1:2], (U1[:, 1:2],), (1,))) ==
ncomps(SymCPD(λ[1:2], (U1[:, 1:2], U2[:, 1:2]), (1,2))) ==
ncomps(SymCPD(λ[1:2], (U1[:, 1:2], U2[:, 1:2], U3[:, 1:2]), (1,2,3))) ==
ncomps(SymCPD(λ[1:2], (U1[:, 1:2], U2[:, 1:2], U3[:, 1:2]), (3,1,1,2,3)))
2
ncomps(SymCPD(λ[1:2], (U1[:, 1:2], U2[:, 1:2]), (1, 2))) ==
ncomps(SymCPD(λ[1:2], (U1[:, 1:2], U2[:, 1:2], U3[:, 1:2]), (1, 2, 3))) ==
ncomps(SymCPD(λ[1:2], (U1[:, 1:2], U2[:, 1:2], U3[:, 1:2]), (3, 1, 1, 2, 3)))
2
@test ncomps(SymCPD(λ[1:1], (U1[:, 1:1],), (1,))) ==
ncomps(SymCPD(λ[1:1], (U1[:, 1:1], U2[:, 1:1]), (1,2))) ==
ncomps(SymCPD(λ[1:1], (U1[:, 1:1], U2[:, 1:1], U3[:, 1:1]), (1,2,3))) ==
ncomps(SymCPD(λ[1:1], (U1[:, 1:1], U2[:, 1:1], U3[:, 1:1]), (3,1,1,2,3,1)))
1
ncomps(SymCPD(λ[1:1], (U1[:, 1:1], U2[:, 1:1]), (1, 2))) ==
ncomps(SymCPD(λ[1:1], (U1[:, 1:1], U2[:, 1:1], U3[:, 1:1]), (1, 2, 3))) ==
ncomps(SymCPD(λ[1:1], (U1[:, 1:1], U2[:, 1:1], U3[:, 1:1]), (3, 1, 1, 2, 3, 1)))
1
@test ncomps(SymCPD(λ[1:0], (U1[:, 1:0],), (1,))) ==
ncomps(SymCPD(λ[1:0], (U1[:, 1:0], U2[:, 1:0]), (1,2))) ==
ncomps(SymCPD(λ[1:0], (U1[:, 1:0], U2[:, 1:0], U3[:, 1:0]), (1,2,3))) ==
ncomps(SymCPD(λ[1:0], (U1[:, 1:0], U2[:, 1:0], U3[:, 1:0]), (1,2,3,2,2,2))) ==
ncomps(SymCPD(λ[1:0], (U1[:, 1:0], U2[:, 1:0]), (1, 2))) ==
ncomps(SymCPD(λ[1:0], (U1[:, 1:0], U2[:, 1:0], U3[:, 1:0]), (1, 2, 3))) ==
ncomps(
SymCPD(λ[1:0], (U1[:, 1:0], U2[:, 1:0], U3[:, 1:0]), (1, 2, 3, 2, 2, 2)),
) ==
0
end

Expand All @@ -70,21 +73,22 @@ end

@test ndims(SymCPD{Int,0,0,Vector{Int},Matrix{Int}}(λ, (), ())) == 0
@test ndims(SymCPD(λ, (U1,), (1,))) == 1
@test ndims(SymCPD(λ, (U1, U2), (1,2))) == 2
@test ndims(SymCPD(λ, (U1, U2, U3), (1,2,3))) == 3
@test ndims(SymCPD(λ, (U1, U2), (1,2,2))) == 3
@test ndims(SymCPD(λ, (U1,), (1,1,1))) == 3
@test ndims(SymCPD(λ, (U1, U2), (1, 2))) == 2
@test ndims(SymCPD(λ, (U1, U2, U3), (1, 2, 3))) == 3
@test ndims(SymCPD(λ, (U1, U2), (1, 2, 2))) == 3
@test ndims(SymCPD(λ, (U1,), (1, 1, 1))) == 3
end

@testitem "size" begin
λ = [1, 100, 10000]
U1, U2, U3 = [1 2 3; 4 5 6], [-1 0 1], [1 2 3; 4 5 6; 7 8 9]

@test size(SymCPD(λ, (U1,), (1,))) == (size(U1, 1),)
@test size(SymCPD(λ, (U1, U2), (1,2))) == (size(U1, 1), size(U2, 1))
@test size(SymCPD(λ, (U1, U2, U3), (1,2,3))) == (size(U1, 1), size(U2, 1), size(U3, 1))
@test size(SymCPD(λ, (U1, U2), (1, 2))) == (size(U1, 1), size(U2, 1))
@test size(SymCPD(λ, (U1, U2, U3), (1, 2, 3))) ==
(size(U1, 1), size(U2, 1), size(U3, 1))

M = SymCPD(λ, (U1, U2, U3), (1,2,3,3))
M = SymCPD(λ, (U1, U2, U3), (1, 2, 3, 3))
@test size(M, 1) == 2
@test size(M, 2) == 1
@test size(M, 3) == 3
Expand All @@ -100,7 +104,7 @@ end
λ = λfull[1:K]
U1, U2, U3 = U1full[:, 1:K], U2full[:, 1:K], U3full[:, 1:K]

M = SymCPD(λ, (U1, U2, U3), (1,2,3))
M = SymCPD(λ, (U1, U2, U3), (1, 2, 3))
for i1 in axes(U1, 1), i2 in axes(U2, 1), i3 in axes(U3, 1)
Mi = sum.* U1[i1, :] .* U2[i2, :] .* U3[i3, :])
@test Mi == M[i1, i2, i3]
Expand All @@ -110,7 +114,7 @@ end
@test_throws BoundsError M[1, size(U2, 1)+1, 1]
@test_throws BoundsError M[1, 1, size(U3, 1)+1]

M = SymCPD(λ, (U1, U2), (1,2))
M = SymCPD(λ, (U1, U2), (1, 2))
for i1 in axes(U1, 1), i2 in axes(U2, 1)
Mi = sum.* U1[i1, :] .* U2[i2, :])
@test Mi == M[i1, i2]
Expand All @@ -128,7 +132,7 @@ end
@test_throws BoundsError M[size(U1, 1)+1]

# Symmetric cases
M = SymCPD(λ, (U3,), (1,1,1))
M = SymCPD(λ, (U3,), (1, 1, 1))
for i1 in axes(U3, 1), i2 in axes(U3, 1), i3 in axes(U3, 1)
Mi = sum.* U3[i1, :] .* U3[i2, :] .* U3[i3, :])
@test Mi == M[i1, i2, i3]
Expand All @@ -138,7 +142,7 @@ end
@test_throws BoundsError M[1, size(U3, 1)+1, 1]
@test_throws BoundsError M[1, 1, size(U3, 1)+1]

M = SymCPD(λ, (U2, U3), (1,2,1))
M = SymCPD(λ, (U2, U3), (1, 2, 1))
for i1 in axes(U2, 1), i2 in axes(U3, 1), i3 in axes(U2, 1)
Mi = sum.* U2[i1, :] .* U3[i2, :] .* U2[i3, :])
@test Mi == M[i1, i2, i3]
Expand All @@ -157,7 +161,7 @@ end
U1full, U2full, U3full = T[1 2 3; 4 5 6], T[-1 0 1], T[1 2 3; 4 5 6; 7 8 9]
λ = λfull[1:K]
U = (U1full[:, 1:K], U2full[:, 1:K], U3full[:, 1:K])[1:N]
M = SymCPD(λ, U, (1,2,3)[1:N])
M = SymCPD(λ, U, (1, 2, 3)[1:N])

X = Array(M)
@test all(I -> M[I] == X[I], CartesianIndices(X))
Expand All @@ -168,11 +172,11 @@ end
λ = T[1, 100, 10000]
U1, U2 = T[1 2 3; 4 5 6], T[1 2 3; 4 5 6; 7 8 9]

M = SymCPD(λ, (U1,), (1,1,1))
M = SymCPD(λ, (U1,), (1, 1, 1))
X = Array(M)
@test all(I -> M[I] == X[I], CartesianIndices(X))

M = SymCPD(λ, (U1, U2), (1,2,1))
M = SymCPD(λ, (U1, U2), (1, 2, 1))
X = Array(M)
@test all(I -> M[I] == X[I], CartesianIndices(X))
end
Expand All @@ -187,15 +191,15 @@ end
λ = λfull[1:K]
U1, U2, U3 = U1full[:, 1:K], U2full[:, 1:K], U3full[:, 1:K]

M = SymCPD(λ, (U1, U2, U3), (1,2,3))
M = SymCPD(λ, (U1, U2, U3), (1, 2, 3))
@test norm(M) ==
norm(M, 2) ==
sqrt(sum(abs2, M[I] for I in CartesianIndices(size(M))))
@test norm(M, 1) == sum(abs, M[I] for I in CartesianIndices(size(M)))
@test norm(M, 3) ==
(sum(m -> abs(m)^3, M[I] for I in CartesianIndices(size(M))))^(1 / 3)

M = SymCPD(λ, (U1, U2), (1,2))
M = SymCPD(λ, (U1, U2), (1, 2))
@test norm(M) ==
norm(M, 2) ==
sqrt(sum(abs2, M[I] for I in CartesianIndices(size(M))))
Expand All @@ -212,15 +216,15 @@ end
(sum(m -> abs(m)^3, M[I] for I in CartesianIndices(size(M))))^(1 / 3)

# Symmetric Cases
M = SymCPD(λ, (U1,), (1,1,1))
M = SymCPD(λ, (U1,), (1, 1, 1))
@test norm(M) ==
norm(M, 2) ==
sqrt(sum(abs2, M[I] for I in CartesianIndices(size(M))))
@test norm(M, 1) == sum(abs, M[I] for I in CartesianIndices(size(M)))
@test norm(M, 3) ==
(sum(m -> abs(m)^3, M[I] for I in CartesianIndices(size(M))))^(1 / 3)

M = SymCPD(λ, (U1, U2), (1,2,1))
M = SymCPD(λ, (U1, U2), (1, 2, 1))
@test norm(M) ==
norm(M, 2) ==
sqrt(sum(abs2, M[I] for I in CartesianIndices(size(M))))
Expand All @@ -242,7 +246,7 @@ end
U1, U2, U3 = U1full[:, 1:K], U2full[:, 1:K], U3full[:, 1:K]

@testset "p=$p" for p in [1, 2, Inf]
M = SymCPD(λ, (U1, U2, U3), (1,2,3))
M = SymCPD(λ, (U1, U2, U3), (1, 2, 3))
Mback = deepcopy(M)
Mnorm = normalizecomps(M, p)

Expand Down Expand Up @@ -337,7 +341,7 @@ end
U1full, U2full, U3full = T[1 2 3; 4 5 6], T[-1 0 1], T[1 2 3; 4 5 6; 7 8 9]
λ = λfull[1:K]
U = (U1full[:, 1:K], U2full[:, 1:K], U3full[:, 1:K])[1:N]
M = SymCPD(λ, U, (1,2,3)[1:N])
M = SymCPD(λ, U, (1, 2, 3)[1:N])

@testset "perm=$perm" for perm in permutations(1:K)
Mback = deepcopy(M)
Expand All @@ -363,20 +367,19 @@ end
λ = [1, 100, 10000]
U1, U2, = [1 2 3; 4 5 6], [1 2 3; 4 5 6; 7 8 9]

M_symcpd = SymCPD(λ, (U1, U2), (1,2,1))
M_symcpd = SymCPD(λ, (U1, U2), (1, 2, 1))
M_cpd = convertCPD(M_symcpd)

@test ncomps(M_symcpd) == ncomps(M_cpd)
@test ndims(M_symcpd) == ndims(M_cpd)
@test size(M_symcpd) == size(M_cpd)

print(size(M_symcpd))
for i in Base.OneTo(size(M_symcpd)[1])
for j in Base.OneTo(size(M_symcpd)[2])
for k in Base.OneTo(size(M_symcpd)[3])
@test M_symcpd[i,j,k] == M_cpd[i,j,k]
@test M_symcpd[i, j, k] == M_cpd[i, j, k]
end
end
end

end
4 changes: 2 additions & 2 deletions test/items/tensor-kernels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ end
end

@test checksym(X, (1, 1, 1)) == true
@test checksym(X, (1, 2, 3)) == true
@test checksym(X, (1, 2, 2)) == true
@test checksym(X, (1, 2, 3)) == true
@test checksym(X, (1, 2, 2)) == true
@test checksym(X, (2, 2, 1)) == true

# Partially symmetric
Expand Down

0 comments on commit 4efec5e

Please sign in to comment.