Home > Back-end >  The inverse operation of tensor circular unfolding in Julia
The inverse operation of tensor circular unfolding in Julia

Time:01-17

I implemented Tensor Circular Unfolding (TCU) defined in this document (See Definition 2). The TCU reshapes a tensor (or multidimensional array) X into a matrix (or two-dimensional array). By using TensorToolbox, I implemented that as follows:

using TensorToolbox
function TCU(X,d,k)
    N = ndims(X)
    @assert d < N
    if d <= k
        a = k-d 1
    else
        a = k-d 1 N
    end
    tenmat(permutedims(X,circshift(1:N,-a 1)),row=1:d)
end

for positive integers d<N and k≦N where N is the depth of input tensor X. The function tenmat comes from TensorToolbox.jl and it is for matricization of a tensor. Please see ReadMe file in TensorToolbox.jl.

Here I put an example with N=4.

X = rand(1:9,3,4,2,2)
#3×4×2×2 Array{Int64, 4}:
#[:, :, 1, 1] =
# 5  7  2  6
# 4  5  6  2
# 6  8  9  1
#
#[:, :, 2, 1] =
# 4  3  7  5
# 8  3  3  1
# 8  2  4  7
#
#[:, :, 1, 2] =
# 4  3  9  6
# 7  4  9  2
# 6  7  2  4
#
#[:, :, 2, 2] =
# 9  2  1  7
# 8  2  1  3
# 6  2  4  9

M = TCU(X, 2, 3)
#8×6 Matrix{Int64}:
# 5  4  4  7  6  6
# 7  3  5  4  8  7
# 2  9  6  9  9  2
# 6  6  2  2  1  4
# 4  9  8  8  8  6
# 3  2  3  2  2  2
# 7  1  3  1  4  4
# 5  7  1  3  7  9

What I need

I would like to write the reverse operation of the above function. That is, I need the function InvTCU that satisfies

X == InvTCU( TCU(X, d, k), d, k )

If we need, InvTCU can require the original tensor size size(X)

X == InvTCU( TCU(X, d, k), d, k, size(X) )

The reason why I need InvTCU

It is required in Equation (18) in the document to implement the algorithm named PTRC. In this situation, the size of the original tensor size(X) are available information.

EDIT

I added the description about tenmat. I added the description that InvTCU can require the original tensor size.

CodePudding user response:

Before giving the function, it might be noted that to get the matrixfied tensor, it is possible to use views instead of permuting the dimensions, which might be more efficient (depending on processing later). This can be done (I think) with the TrasmuteDims or TensorCast packages (https://docs.juliahub.com/TransmuteDims/NIYrh/0.1.15/).

Here is an attempt at a permutedims approach:

function invTCU(M,d,k, presize)
    N = length(presize)
    a = d<=k ? k-d 1 : k-d 1 N
    X = reshape(M,Tuple(circshift(collect(presize),1-a)))
    permutedims(X,circshift(1:N,a-1))
end

with this definition:

julia> X = reshape(1:48,3,4,2,2)
3×4×2×2 reshape(::UnitRange{Int64}, 3, 4, 2, 2) with eltype Int64:
[:, :, 1, 1] =
 1  4  7  10
...

julia> X == invTCU(TCU(X, 2, 3), 2, 3, size(X))
true

seems to recover original tensor.

  • Related