Lower Triangular Topology

ReservoirComputing.lower_triangularFunction
lower_triangular([rng], [T], dims...; radius=1.0, sparsity=0.9, return_sparse=false)

Create and return a sparse reservoir matrix with a lower triangular topology (Cossu et al., Oct 2024). This function populates the main diagonal and the immediately adjacent lower sub-diagonals with random uniform weights in the range (-1, 1) until the target sparsity is reached. It guarantees structural symmetry by only adding complete diagonals.

Arguments

  • rng: Random number generator. Default is Utils.default_rng() from WeightInitializers.
  • T: Type of the elements in the reservoir matrix. Default is Float32.
  • dims: Dimensions of the reservoir matrix. Must be square.

Keyword arguments

  • radius: The desired spectral radius of the reservoir. Defaults to 1.0.
  • sparsity: The exact target fraction of zero elements in the matrix. To hit this target precisely while preventing spatial bias, any remaining weights needed for the final partial sub-diagonal are randomly distributed across its indices. Defaults to 0.9.
  • return_sparse: Flag for returning a SparseMatrixCSC instead of a dense matrix. Setting to true requires SparseArrays to be loaded. Defaults to false.

Examples

Default call:

julia> W = lower_triangular(MersenneTwister(123), 5, 5);

julia> size(W) == (5, 5) && eltype(W) == Float32 && all(iszero, W[i, j] for i in axes(W, 1) for j in (i + 1):size(W, 2))
true

Returning a SparseMatrixCSC:

julia> W_sparse = lower_triangular(MersenneTwister(123), 6, 6; sparsity=0.8, return_sparse=true);

julia> W_sparse isa SparseMatrixCSC{Float32} && size(W_sparse) == (6, 6)
true

Scaling to a custom spectral radius:

julia> W_scaled = lower_triangular(MersenneTwister(123), Float16, 4, 4; radius=2.5);

julia> size(W_scaled) == (4, 4) && eltype(W_scaled) == Float16 && count(!iszero, W_scaled) >= 4
true
source