WORK IN PROGRESS

`KroneckerTools`

computes chains of Kronecker
products as described in Kamenik (2005).

The following computations are performed

- c = (I
_{p}⊗ A ⊗ I_{q})*b - c = (I
_{p}⊗ A^{T}⊗ I_{q})*b - c = (A ⊗ A ⊗ ... ⊗ A)*b
- d = (A
^{T}⊗ A^{T}⊗ ... ⊗ A^{T}⊗ B)*c - C = A * (B ⊗ B ⊗ .... ⊗ B)
- D = A * B * (C ⊗ C ⊗ .... ⊗ C)
- D = A
^{T}* B * (C ⊗ C ⊗ .... ⊗ C) - E = A
*B*(C ⊗ D ⊗ ... ⊗ D)

```
julia> using Pkg
julia> Pkg.add("KroneckerTools")
```

We exploit the following property of the Kronecker product:
vec(A * B * C) = (C^{T} ⊗ A) * vec(B), so as never to form the
matrix corresponding to the Kronecker product and whenever possible
use matrix product instead.

Let A, a m * n matrix, B, a matrix whose size depends on the context, and b = vec(B). It follows that

- c = (I
_{p}⊗ A) * b = vec(A * B), where B is a n * p matrix. - c = (A ⊗ I
_{q}) * b = vec(B * A^{T}), where B is a q * m matrix - c = (I
_{p}⊗ A ⊗ I_{q}) * b is computed in p blocks c_{i}= vec(B_{i}* A^{T}), i = 1, ..., p where B_{i}is the i^{th}block of q * n elements of vector b

A chain of Kronecker products, (A_{1} ⊗ A_{2} ⊗ ... ⊗
A_{n}) * b can be written as
(A_{1} ⊗ I_{p1})*
(I_{p2} ⊗ A_{2} ⊗ I_{p2})* ... *
(I_{pn} ⊗ A_{n})b where b is a vector and p_{1>}, p_{2}, ..., p_{n}, q_{1}, q_{2}, ...,q_{n} are such as making each group in brackets conformable.

O. Kamenik (2005), "Solving SDGE models: A new algorithm for the Sylvester
equation", *Computational Economics 25*, 167--187.