SymmetricTensors.jl provides the SymmetricTensors{T, N}
type used to store fully symmetric tensors in more efficient way,
without most of redundant repetitions. It uses blocks of Array{T, N}
stored in Union{Array{Float,N}, Nothing}
structure.
Repeated blocks are replaced by Void
. The module introduces SymmetricTensors{T, N}
type and some basic operations on this type.
As of 01/01/2017 @kdomino is the lead maintainer of this package.
Within Julia, just use run
pkg> add SymmetricTensors
to install the files. Julia 1.0 or later is required.
julia> data = ones(4,4);
julia> SymmetricTensor{Float64,2}(Union{Nothing, Array{Float64,2}}[[1.0 1.0; 1.0 1.0] [1.0 1.0; 1.0 1.0]; nothing [1.0 1.0; 1.0 1.0]], 2, 2, 4, true)
From Array{T, N}
to SymmetricTensors{T, N}
julia> SymmetricTensors(data::Array{T, N}, bls::Int = 2)
where bls is the size of a block. It is a parameter affecting the compuational speed of cumulants. The block size must fulfill bls ∈ {1, 2,..., dats}
where dats = size(data, 1) = ... = size(data, N)
otherwise error is risen.
julia> data = ones(4,4);
julia> convert(SymmetricTensor, data, 2)
SymmetricTensor{Float64,2}(Union{Nothing, Array{Float64,2}}[[1.0 1.0; 1.0 1.0] [1.0 1.0; 1.0 1.0]; nothing [1.0 1.0; 1.0 1.0]], 2, 2, 4, true)
From SymmetricTensors{T, N}
to Array{T, N}
julia> Array(st::SymmetricTensors{T, N})
Wrong block size:
julia> SymmetricTensor(ones(4,4), 5)
ERROR: DimensionMismatch("bad block size 5 > 4")
frame::ArrayNArrays{T,N}
: stores data, where ArrayNArrays{T,N} = Array{Union{Array{T, N}, Nothing}, N}
bls::Int
: size of a block,bln::Int
: number of blocks,dats::Int
: size of data,sqr::Bool
: shows if the last block is squared.Elementwise addition: +, -
is supported between many SymmetricTensors{T, N}
while elementwise substraction: -
between two SymmetricTensors{T, N}
. Addition substraction multiplication and division +, -, *, /
is supported between SymmetricTensors{T, N}
and a number.
julia> x = SymmetricTensor(ones(4,4));
julia> y = SymmetricTensor(2*ones(4,4));
julia> x+y
SymmetricTensor{Float64,2}(Union{Nothing, Array{Float64,2}}[[3.0 3.0; 3.0 3.0] [3.0 3.0; 3.0 3.0]; #undef [3.0 3.0; 3.0 3.0]], 2, 2, 4, true)
julia> x*10
SymmetricTensor{Float64,2}(Union{Nothing, Array{Float64,2}}[[10.0 10.0; 10.0 10.0] [10.0 10.0; 10.0 10.0]; #undef [10.0 10.0; 10.0 10.0]], 2, 2, 4, true)
The function diag returns a Vector{T}, of all super-diagonal elements of a SymmetricTensor.
julia> data = ones(5,5,5,5);
julia> st = SymmetricTensor(data);
julia> diag(st)
5-element Array{Float64,1}:
1.0
1.0
1.0
1.0
1.0
To generate random Symmetric Tensor with random elements of typer T
form a uniform distribution on [0,1)
use rand(SymmetricTensor{T, N}, n::Int, b::Int = 2)
. Here n denotes data size and b denotes block size.
julia> using Random
julia> Random.seed!(42)
julia> rand(SymmetricTensor{Float64, 2}, 2)
SymmetricTensor{Float64,2}(Union{Nothing, Array{Float64,2}}[[0.533183 0.454029; 0.454029 0.0176868]], 2, 1, 2, true)
julia> using Random
julia> Random.seed!(42)
julia> st = rand(SymmetricTensor{Float64, 2}, 2)
SymmetricTensor{Float64,2}(Union{Nothing, Array{Float64,2}}[[0.533183 0.454029; 0.454029 0.0176868]], 2, 1, 2, true)
julia> st[1,2]
0.4540291355871424
julia> st[2,1]
0.4540291355871424
setindex!(st::SymmetricTensor, x::Float, mulind::Int...)
changes all symmetric tensor's elements indexed by mulind
to x
.
julia> st[1,2] = 10.
julia> convert(Array, st)
2×2 Array{Float64,2}:
0.533183 10.0
10.0 0.0176868
julia> unfold(data::Array{T,N}, mode::Int)
unfolds data
in a given mode
julia> a = reshape(collect(1.:8.), (2,2,2))
2×2×2 Array{Float64,3}:
[:, :, 1] =
1.0 3.0
2.0 4.0
[:, :, 2] =
5.0 7.0
6.0 8.0
julia> unfold(a, 1)
2×4 Array{Float64,2}:
1.0 3.0 5.0 7.0
2.0 4.0 6.0 8.0
julia> unfold(a, 2)
2×4 Array{Float64,2}:
1.0 2.0 5.0 6.0
3.0 4.0 7.0 8.0
julia> unfold(a, 3)
2×4 Array{Float64,2}:
1.0 2.0 3.0 4.0
5.0 6.0 7.0 8.0
The block usage is motivated by the paper M. D. Schatz, T. M. Low, R. A. van de Geijn, and T. G. Kolda, "Exploiting symmetry in tensors for high performance: Multiplication with symmetric tensors", SIAM Journal on Scientific Computing, 36 (2014), pp. C453–C479 https://doi.org/10.1137/130907215. There only the meaningful part of the symmetric tensor is stored in blocks to decrease the memory and computational overhead. The selection of the optimal block size is not straight forward, however in most cases concerning cumulants one can use 2
or 3
.
This project was partially financed by the National Science Centre, Poland – project number 2014/15/B/ST6/05204.
01/16/2017
about 2 months ago
146 commits