UniqueKronecker.jl
UniqueKronecker.jl is a Julia package for computing non-redundant (unique) Kronecker products of vectors, generalizing to n dimensions and k-repeated products. It also provides efficient implementations of the Khatri-Rao (column-wise Kronecker) and face-splitting (row-wise Kronecker) products, along with their unique counterparts. The package includes utility functions to work with the associated coefficient matrices, enabling conversions between unique and standard products.
What is the Unique Kronecker Product?
The standard Kronecker product of a vector $\mathbf{x} \in \mathbb{R}^n$ with itself, $\text{kron}(\mathbf{x}, \mathbf{x}) = \mathbf{x} \otimes \mathbf{x}$, produces all possible pairwise products of its elements, resulting in redundant terms when $x_i x_j = x_j x_i$.
The unique Kronecker product, denoted here as $\text{uniquekron}(\mathbf{x},\mathbf{x}) = \mathbf{x} \oslash \mathbf{x}$, eliminates these redundancies by considering only unique combinations of indices. For example:
For $\mathbf{x} \in \mathbb{R}^2$:
- Standard Kronecker product:
\[ \mathbf{x} \otimes \mathbf{x} = \begin{bmatrix} x_1^2 \\ x_1 x_2 \\ x_2 x_1 \\ x_2^2 \end{bmatrix}\]
- Unique Kronecker product:
\[ \mathbf{x} \oslash \mathbf{x} = \begin{bmatrix} x_1^2 \\ x_1 x_2 \\ x_2^2 \end{bmatrix}\]
Here, $x_1 x_2$ and $x_2 x_1$ are considered the same and included only once.
Coefficient Matrices
The package provides functions to compute the associated coefficient matrices:
- Unique Kronecker Coefficient Matrix $\mathbf{A}_{2u} \in \mathbb{R}^{n \times \frac{n(n+1)}{2}}$: Represents the mapping of the unique Kronecker product back to the original vector $\mathbf{x}\in\mathbb{R}^2$.
- Kronecker Coefficient Matrix $\mathbf{A}_2 \in \mathbb{R}^{n \times n^2}$: Represents the mapping of the Kronecker product back to the original vector.
These matrices are useful for applications in polynomial regression, symmetric tensor computations, and vectorization of symmetric matrices.
Features
- Compute the unique Kronecker product for vectors of any dimension $n$ and any repeated (Kronecker) order $k$.
- Generate the associated polynomial and Kronecker coefficient matrices $\mathbf{A}_{2u}$ and $\mathbf{A}_2$.
- Convert between unique and standard Kronecker products.
- Khatri-Rao Product: Compute column-wise Kronecker products of matrices and their unique variants.
- Face-Splitting Product: Compute row-wise Kronecker products of matrices and their unique variants.
- Utility functions for polynomial modeling and symmetric tensor operations.
Installation
You can install it using the command
using Pkg
Pkg.add("UniqueKronecker")
using UniqueKroneckeror install it directly from GitHub:
using Pkg
Pkg.add(url="https://github.com/YourUsername/UniqueKronecker.jl")Replace YourUsername with the actual GitHub username or organization where the package is hosted.
Usage
Importing the Package
using UniqueKroneckerComputing the Unique Kronecker Product
Compute the $k$-th order unique Kronecker product of vector x:
x = [2.0, 3.0, 4.0] # Example vector in ℝ³
x_unique_kron = x ⊘ x
println(x_unique_kron)
# Output: [4.0, 6.0, 8.0, 9.0, 12.0, 16.0]
# Corresponding to [x₁², x₁x₂, x₁x₃, x₂², x₂x₃, x₃²]Computing Coefficient Matrices
Polynomial Matrix $\mathbf{A}_2$
Compute the polynomial coefficient matrix $\mathbf{A}_2$:
n = 3
H = zeros(n,n^2)
for i in 1:n
x = rand(n)
H[i,:] = kron(x,x)
end
println(H)
# Output: A matrix of size (3, 9) for this exampleUnique/Nonredundant Polynomial Coefficient Matrix $\mathbf{A}_{2u}$
Convert the polynomial matrix $\mathbf{A}_2$ into the unique polynomial coefficient matrix $\mathbf{A}_{2u}$:
A2u = eliminate(A2, 2)
println(A2u)
# Output: A matrix of size (3, 6) for this exampleThis can be converted back
A2 = duplicate(A2u, 2)
println(A2)
# Output: the H matrixTo make the coefficients symmetric for redundant terms use duplicate_symmetric
A2s = duplicate_symmetric(A2u, 2)
println(A2s)
# Output: the H matrix with symmetric coefficientsRelationship Between Matrices
The following relationship holds:
\[\mathbf{A}_{2u} \cdot (\mathbf{x} \oslash \mathbf{x}) = \mathbf{A}_2 \cdot (\mathbf{x} \otimes \mathbf{x})\]
This allows mapping between the unique Kronecker product space and the standard Kronecker product space.
Generalizing to Higher-Order Products
Compute higher-order unique Kronecker products by specifying a higher value of $k$:
k = 3 # Third-order product
x_unique_kron_k3 = unique_kronecker(x, k) # or ⊘(x,k)
println(x_unique_kron_k3)
# Output: Corresponding unique products of order 3Khatri-Rao Product
The Khatri-Rao product (also known as the column-wise Kronecker product) takes two matrices and performs the Kronecker product on corresponding columns:
A = [1 2; 3 4]
B = [5 6; 7 8]
# Standard Khatri-Rao product
kr = khatri_rao(A, B) # or A ⊙ B
# Column 1: kron([1,3], [5,7]) = [5,7,15,21]
# Column 2: kron([2,4], [6,8]) = [12,16,24,32]
# Unique Khatri-Rao product (eliminates redundancies in each column)
ukr = unique_khatri_rao(A, B) # or A ⨸ B
# Self-product with power
kr_power = khatri_rao(A, 3) # or A ⊙ 3
ukr_power = unique_khatri_rao(A, 3) # or A ⨸ 3The Khatri-Rao product is particularly useful in:
- Multilinear algebra
- Tensor decompositions
- Signal processing and array processing
- Machine learning feature engineering
Face-Splitting Product
The face-splitting product (also known as the row-wise Kronecker product) takes two matrices and performs the Kronecker product on corresponding rows:
A = [1 2; 3 4]
B = [5 6; 7 8]
# Standard face-splitting product
fs = face_split(A, B) # or A ⊖ B
# Row 1: kron([1,2], [5,6]) = [5,6,10,12]
# Row 2: kron([3,4], [7,8]) = [21,24,28,32]
# Unique face-splitting product (eliminates redundancies in each row)
ufs = unique_face_split(A, B) # or A ⧁ B
# Self-product with power
fs_power = face_split(A, 2) # or A ⊖ 2
ufs_power = unique_face_split(A, 2) # or A ⧁ 2The face-splitting product is useful in:
- Matrix polynomial operations
- Row-wise tensor computations
- Structured matrix operations
Circulant Kronecker Product
The circulant Kronecker product sums over all cyclic permutations of the Kronecker products. It's particularly useful for computing derivatives of Kronecker products:
x = [1, 2]
y = [3, 4]
# Circulant Kronecker product
ck = circulant_kronecker(x, y) # or x ⊛ y
# Result: (x ⊗ y) + (y ⊗ x)
# Three vectors
z = [5, 6]
ck3 = x ⊛ y ⊛ z
# Result: (x ⊗ y ⊗ z) + (y ⊗ z ⊗ x) + (z ⊗ x ⊗ y)The circulant Kronecker product is useful in:
- Computing derivatives of Kronecker products (e.g., $\frac{\partial (\mathbf{x}\otimes\mathbf{x})}{\partial \mathbf{x}} = \mathbf{I} \circledast \mathbf{x}$)
- Tensor calculus and differential operations
- Symmetric polynomial structures
- Applications requiring all cyclic permutations
Applications
- Polynomial Regression: Efficient computation of polynomial features without redundant terms.
- Symmetric Tensor Computations: Simplifies operations involving symmetric tensors.
- Model Reduction: Construction of reduced-order models with polynomial structures.
- Machine Learning: Feature engineering for higher-order interactions.
Contributing
Contributions are welcome! If you find a bug or have a feature request, please open an issue. If you'd like to contribute code, feel free to submit a pull request.
License
This project is licensed under the MIT License.