Multiplication
Kronecker.jl allows for efficient multiplication of large Kronecker systems by overloading the multiplication function *. We distinguish three cases:
- Kronecker-Kronecker multiplications yield again a type of
AbstractKroneckerProduct; - Kronecker-vector multiplications use the 'vec trick' and yield a vector;
- sampled Kronecker-vector multiplications use the sampled-vec trick to yield a vector.
Kronecker-kronecker multiplications
Multiplying two conformable Kronecker products of the same order yield a new Kronecker product, based on the mixed-product property:
\[(A \otimes B)(C \otimes D) = (AC) \otimes (BD),\]
A, B, C, D = randn(5, 5), randn(4, 4), randn(5, 4), randn(4, 4);
(A ⊗ B) * (C ⊗ D)20×16 Kronecker.KroneckerProduct{Float64, Matrix{Float64}, Matrix{Float64}}:
4.14885 -1.44107 4.38331 … 1.49164 -4.53712 -1.26053
2.69083 -0.681624 2.21182 0.705543 -2.28944 -1.9202
-4.84623 1.42667 0.914254 -1.47673 -0.946336 0.588926
-2.43663 -1.51151 -1.9276 1.56455 1.99525 2.23244
-5.52633 1.91953 -5.83864 0.991959 -3.01724 -0.838267
-3.58423 0.907934 -2.94618 … 0.469195 -1.5225 -1.27696
6.45525 -1.90034 -1.2178 -0.982043 -0.629325 0.391643
3.24562 2.01335 2.5676 1.04044 1.32686 1.4846
-4.5372 1.57596 -4.79361 1.39041 -4.22921 -1.17498
-2.94271 0.745428 -2.41886 0.65766 -2.13406 -1.78988
5.29986 -1.56021 -0.999833 … -1.37651 -0.882112 0.548957
2.66471 1.65299 2.10804 1.45837 1.85984 2.08093
-3.33709 1.15911 -3.52567 1.33659 -4.06551 -1.1295
-2.16434 0.548258 -1.77906 0.632205 -2.05146 -1.7206
3.89801 -1.14752 -0.735371 -1.32323 -0.847969 0.52771
1.95988 1.21576 1.55045 … 1.40192 1.78785 2.00039
1.07858 -0.374637 1.13953 -2.69055 8.18386 2.27369
0.699538 -0.177203 0.57501 -1.27263 4.12958 3.46357
-1.25988 0.370892 0.23768 2.66366 1.70696 -1.06228
-0.633453 -0.392948 -0.501122 -2.82206 -3.59894 -4.02678The Vec trick
Reshaping allows computing a product between a Kronecker product and vector as two matrix multiplications. This is the so-called vec trick which holds for any set of conformable matrices:
\[(A \otimes B) \text{vec}(X) = \text{vec}(B^\intercal X A).\]
Here, $\text{vec}(\cdot)$ is the vectorization operator, which stacks all columns of a matrix into a vector.
A, B = rand(10, 10), rand(5, 6);
x = randn(60);
(A ⊗ B) * x50-element Vector{Float64}:
-2.288615876653745
-4.6950726015817015
-3.360244020111282
-2.1400592519884727
-3.5795470770557807
-0.7053359020893049
-1.7432240700910726
-1.0309061508926907
-1.049179477566011
-0.809201382742677
⋮
-0.3744925336220022
-0.24973216851618263
0.06947807180545612
-0.31599864153680585
-0.5246896461176256
-2.129875957949822
-1.8585915722520754
-1.0086811065869492
-1.1241586235720518Note that this trick is extended to also work with matrices:
A, B = rand(10, 10), rand(5, 6);
x = randn(60, 2);
(A ⊗ B) * x50×2 Matrix{Float64}:
3.45506 -3.1162
4.90488 -1.57651
5.08942 -5.09294
3.08144 -5.81177
6.20885 -3.53238
4.4003 -4.28453
6.48055 -2.77907
5.56242 -3.78515
2.48352 -4.80394
6.24574 -3.89798
⋮
1.50495 -1.77981
-0.504583 -4.92037
-1.30422 -4.63929
-0.802639 -4.4299
3.02957 -4.41088
6.85321 -2.33172
4.29294 -4.09646
0.523117 -5.13116
3.1481 -5.09591The vec trick works with higher-order Kronecker products. However, at the moment this has a substantial overhead and likely be relatively slow.
Docstrings
Kronecker.mul_vec_trick! — Function
mul_vec_trick!(x::AbstractVector, K::AbstractKroneckerProduct, v::AbstractVector)Calculates the vector-matrix multiplication K * v and stores the result in x, overwriting its existing value.
LinearAlgebra.lmul! — Function
lmul!(a::Number, K::AbstractKroneckerProduct)Scale an AbstractKroneckerProduct K inplace by a factor a by rescaling the left matrix.
lmul!(a::Number, K::KroneckerPower)Scale an KroneckerPower K inplace by a factor a by rescaling the matrix the base matrix with a factor a^(1/N).
It is recommended to rewrite your Kronecker product rather as copy(A) ⊗ (A ⊗ n - 1) (note the copy) for numerical stability. This will only modify the first matrix, leaving the chain of Kronecker products alone.
LinearAlgebra.rmul! — Function
rmul!(K::AbstractKroneckerProduct, a::Number)Scale an AbstractKroneckerProduct K inplace by a factor a by rescaling the right matrix.
Sampled Kronecker-vector multiplications
See Indexed Kronecker products for the specifics.