@@ -1881,14 +1881,106 @@ function forward_connection(rng::AbstractRNG, ::Type{T}, dims::Integer...;
18811881 return return_init_as (Val (return_sparse), reservoir_matrix)
18821882end
18831883
1884+ @doc raw """
1885+ block_diagonal([rng], [T], dims...;
1886+ weight=1, block_size=1,
1887+ return_sparse=false)
1888+
1889+ Creates a block‐diagonal matrix consisting of square blocks of size
1890+ `block_size` along the main diagonal [Ma2023](@cite).
1891+ Each block may be filled with
1892+ - a single scalar
1893+ - a vector of per‐block weights (length = number of blocks)
1894+
1895+ # Equations
1896+
1897+ ```math
1898+ W_{i,j} =
1899+ \b egin{cases}
1900+ w_b, & \t ext{if }\l eft\l floor\f rac{i-1}{s}\r ight\r floor = \l eft\l floor\f rac{j-1}{s}\r ight\r floor = b,\;
1901+ s = \t ext{block\_ size},\; b=0,\d ots,nb-1, \\
1902+ 0, & \t ext{otherwise,}
1903+ \e nd{cases}
1904+ ```
1905+
1906+ # Arguments
1907+
1908+ - `rng`: Random number generator. Default is `Utils.default_rng()`.
1909+ - `T`: Element type of the matrix. Default is `Float32`.
1910+ - `dims`: Dimensions of the output matrix (must be two-dimensional).
1911+
1912+ # Keyword arguments
1913+
1914+ - `weight`:
1915+ - scalar: every block is filled with that value
1916+ - vector: length = number of blocks, one constant per block
1917+ Default is `1.0`.
1918+ - `block_size`: Size\( s\) of each square block on the diagonal. Default is `1.0`.
1919+ - `return_sparse`: If `true`, returns the matrix as sparse.
1920+ SparseArrays.jl must be lodead.
1921+ Default is `false`.
1922+
1923+ # Examples
1924+
1925+ ```jldoctest
1926+ # 4×4 with two 2×2 blocks of 1.0
1927+ julia> W1 = block_diagonal(4, 4; block_size=2)
1928+ 4×4 Matrix{Float32}:
1929+ 1.0 1.0 0.0 0.0
1930+ 1.0 1.0 0.0 0.0
1931+ 0.0 0.0 1.0 1.0
1932+ 0.0 0.0 1.0 1.0
1933+
1934+ # per-block weights [0.5, 2.0]
1935+ julia> W2 = block_diagonal(4, 4; block_size=2, weight=[0.5, 2.0])
1936+ 4×4 Matrix{Float32}:
1937+ 0.5 0.5 0.0 0.0
1938+ 0.5 0.5 0.0 0.0
1939+ 0.0 0.0 2.0 2.0
1940+ 0.0 0.0 2.0 2.0
1941+ ```
1942+ """
1943+ function block_diagonal (rng:: AbstractRNG , :: Type{T} , dims:: Integer... ;
1944+ weight:: Union{Number, AbstractVector} = T (1 ),
1945+ block_size:: Integer = 1 ,
1946+ return_sparse:: Bool = false ) where {T <: Number }
1947+ throw_sparse_error (return_sparse)
1948+ check_res_size (dims... )
1949+ n_rows, n_cols = dims
1950+ total = min (n_rows, n_cols)
1951+ num_blocks = fld (total, block_size)
1952+ remainder = total - num_blocks * block_size
1953+ if remainder != 0
1954+ @warn " \n
1955+ With block_size=$block_size on a $n_rows ×$n_cols matrix,
1956+ only $num_blocks block(s) of size $block_size fit,
1957+ leaving $remainder row(s)/column(s) unused.
1958+ \n "
1959+ end
1960+ weights = isa (weight, AbstractVector) ? T .(weight) : fill (T (weight), num_blocks)
1961+ @assert length (weights)== num_blocks "
1962+ weight vector must have length = number of blocks
1963+ "
1964+ reservoir_matrix = DeviceAgnostic. zeros (rng, T, n_rows, n_cols)
1965+ for block in 1 : num_blocks
1966+ row_start = (block - 1 ) * block_size + 1
1967+ row_end = row_start + block_size - 1
1968+ col_start = (block - 1 ) * block_size + 1
1969+ col_end = col_start + block_size - 1
1970+ @inbounds reservoir_matrix[row_start: row_end, col_start: col_end] .= weights[block]
1971+ end
1972+
1973+ return return_init_as (Val (return_sparse), reservoir_matrix)
1974+ end
1975+
18841976# ## fallbacks
18851977# fallbacks for initializers #eventually to remove once migrated to WeightInitializers.jl
18861978for initializer in (:rand_sparse , :delay_line , :delay_line_backward , :cycle_jumps ,
18871979 :simple_cycle , :pseudo_svd , :chaotic_init , :scaled_rand , :weighted_init ,
18881980 :weighted_minimal , :informed_init , :minimal_init , :chebyshev_mapping ,
18891981 :logistic_mapping , :modified_lm , :low_connectivity , :double_cycle , :selfloop_cycle ,
18901982 :selfloop_feedback_cycle , :selfloop_delayline_backward , :selfloop_forward_connection ,
1891- :forward_connection , :true_double_cycle )
1983+ :forward_connection , :true_double_cycle , :block_diagonal )
18921984 @eval begin
18931985 function ($ initializer)(dims:: Integer... ; kwargs... )
18941986 return $ initializer (Utils. default_rng (), Float32, dims... ; kwargs... )
0 commit comments