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.