@@ -282,9 +282,7 @@ function _create_irrational(irrational::Irrational, start::Int, res_size::Int,
282282 return T .(input_matrix)
283283end
284284
285-
286285"""
287-
288286 chebyshev_mapping([rng], [T], dims...;
289287 amplitude=one(T), sine_divisor=one(T),
290288 chebyshev_parameter=one(T), return_sparse=true)
@@ -297,21 +295,24 @@ via the Chebyshev mapping. The first row is defined as:
297295 w(1, j) = amplitude * sin(j * π / (sine_divisor * n_cols))
298296```
299297
300- for j = 1, 2, …, n_cols (with n_cols typically equal to K+1, where K is the number of input layer neurons).
298+ for j = 1, 2, …, n_cols (with n_cols typically equal to K+1, where K is the number of input layer neurons).
301299Subsequent rows are generated by applying the mapping:
300+
302301```math
303302 w(i+1, j) = cos(chebyshev_parameter * acos(w(i, j)))
304303```
305304
306305# Arguments
306+
307307 - `rng`: Random number generator. Default is `Utils.default_rng()`
308308 from WeightInitializers.
309309 - `T`: Type of the elements in the reservoir matrix.
310310 Default is `Float32`.
311311 - `dims`: Dimensions of the matrix. Should follow `res_size x in_size`. Here, res_size is assumed to be K+1.
312312
313- # Keyword arguments
314- - `amplitude`: Scaling factor used to initialize the first row.
313+ # Keyword arguments
314+
315+ - `amplitude`: Scaling factor used to initialize the first row.
315316 This parameter adjusts the amplitude of the sine function. Default value is one.
316317 - `sine_divisor`: Divisor applied in the sine function's phase. Default value is one.
317318 - `chebyshev_parameter`: Control parameter for the Chebyshev mapping in
@@ -334,7 +335,6 @@ julia> input_matrix = chebyshev_mapping(10, 3)
334335 0.866025 0.866025 -4.37114f-8
335336 0.866025 0.866025 -4.37114f-8
336337 0.866025 0.866025 -4.37114f-8
337-
338338```
339339
340340[^xie2024]: Xie, Minzhi, Qianxue Wang, and Simin Yu.
@@ -343,25 +343,25 @@ julia> input_matrix = chebyshev_mapping(10, 3)
343343 Neural Processing Letters 56.1 (2024): 30.
344344"""
345345function chebyshev_mapping (rng:: AbstractRNG , :: Type{T} , dims:: Integer... ;
346- amplitude:: AbstractFloat = one (T), sine_divisor:: AbstractFloat = one (T),
347- chebyshev_parameter:: AbstractFloat = one (T),
348- return_sparse:: Bool = false ) where {T <: Number }
346+ amplitude:: AbstractFloat = one (T), sine_divisor:: AbstractFloat = one (T),
347+ chebyshev_parameter:: AbstractFloat = one (T),
348+ return_sparse:: Bool = false ) where {T <: Number }
349349 input_matrix = DeviceAgnostic. zeros (rng, T, dims... )
350350 n_rows, n_cols = dims[1 ], dims[2 ]
351-
351+
352352 for idx_cols in 1 : n_cols
353353 input_matrix[1 , idx_cols] = amplitude * sin (idx_cols * pi / (sine_divisor * n_cols))
354354 end
355355 for idx_rows in 2 : n_rows
356356 for idx_cols in 1 : n_cols
357- input_matrix[idx_rows, idx_cols] = cos (chebyshev_parameter * acos (input_matrix[idx_rows - 1 , idx_cols]))
357+ input_matrix[idx_rows, idx_cols] = cos (chebyshev_parameter * acos (input_matrix[
358+ idx_rows - 1 , idx_cols]))
358359 end
359360 end
360361
361362 return return_sparse ? sparse (input_matrix) : input_matrix
362363end
363364
364-
365365# ## reservoirs
366366
367367"""
@@ -752,22 +752,21 @@ function get_sparsity(M, dim)
752752 return size (M[M .!= 0 ], 1 ) / (dim * dim - size (M[M .!= 0 ], 1 )) # nonzero/zero elements
753753end
754754
755-
756755function digital_chaotic_adjacency (rng:: AbstractRNG , bit_precision:: Integer ;
757- extra_edge_probability:: AbstractFloat = 0.1 )
758- matrix_order = 2 ^ (2 * bit_precision)
759- adjacency_matrix = zeros (Int, matrix_order, matrix_order)
760- for row_index in 1 : (matrix_order - 1 )
761- adjacency_matrix[row_index, row_index + 1 ] = 1
762- end
763- adjacency_matrix[matrix_order, 1 ] = 1
764- for row_index in 1 : matrix_order, column_index in 1 : matrix_order
765- if row_index != column_index && rand (rng) < extra_edge_probability
766- adjacency_matrix[row_index, column_index] = 1
767- end
768- end
769-
770- return adjacency_matrix
756+ extra_edge_probability:: AbstractFloat = 0.1 )
757+ matrix_order = 2 ^ (2 * bit_precision)
758+ adjacency_matrix = zeros (Int, matrix_order, matrix_order)
759+ for row_index in 1 : (matrix_order - 1 )
760+ adjacency_matrix[row_index, row_index + 1 ] = 1
761+ end
762+ adjacency_matrix[matrix_order, 1 ] = 1
763+ for row_index in 1 : matrix_order, column_index in 1 : matrix_order
764+ if row_index != column_index && rand (rng) < extra_edge_probability
765+ adjacency_matrix[row_index, column_index] = 1
766+ end
767+ end
768+
769+ return adjacency_matrix
771770end
772771
773772"""
@@ -779,17 +778,19 @@ Construct a chaotic reservoir matrix using a digital chaotic system [^xie2024].
779778
780779The matrix topology is derived from a strongly connected adjacency
781780matrix based on a digital chaotic system operating at finite precision.
782- If the requested matrix order does not exactly match a valid order the
781+ If the requested matrix order does not exactly match a valid order the
783782closest valid order is used.
784783
785784# Arguments
785+
786786 - `rng`: Random number generator. Default is `Utils.default_rng()`
787787 from WeightInitializers.
788788 - `T`: Type of the elements in the reservoir matrix.
789789 Default is `Float32`.
790790 - `dims`: Dimensions of the reservoir matrix.
791791
792792# Keyword arguments
793+
793794 - `extra_edge_probability`: Probability of adding extra random edges in
794795 the adjacency matrix to enhance connectivity. Default is 0.1.
795796 - `desired_spectral_radius`: The target spectral radius for the
@@ -812,8 +813,7 @@ julia> res_matrix = chaotic_init(8, 8)
812813 ⋅ -0.600945 ⋅ ⋅
813814 ⋅ ⋅ 0.132667 2.21354
814815 ⋅ -2.60383 ⋅ -2.90391
815- -0.578156 ⋅ ⋅ ⋅
816-
816+ -0.578156 ⋅ ⋅ ⋅
817817```
818818
819819[^xie2024]: Xie, Minzhi, Qianxue Wang, and Simin Yu.
@@ -822,9 +822,8 @@ julia> res_matrix = chaotic_init(8, 8)
822822 Neural Processing Letters 56.1 (2024): 30.
823823"""
824824function chaotic_init (rng:: AbstractRNG , :: Type{T} , dims:: Integer... ;
825- extra_edge_probability:: AbstractFloat = T (0.1 ), spectral_radius:: AbstractFloat = one (T),
826- return_sparse_matrix:: Bool = true ) where {T <: Number }
827-
825+ extra_edge_probability:: AbstractFloat = T (0.1 ), spectral_radius:: AbstractFloat = one (T),
826+ return_sparse_matrix:: Bool = true ) where {T <: Number }
828827 requested_order = first (dims)
829828 if length (dims) > 1 && dims[2 ] != requested_order
830829 @warn """ \n
@@ -833,10 +832,11 @@ function chaotic_init(rng::AbstractRNG, ::Type{T}, dims::Integer...;
833832 end
834833 d_estimate = log2 (requested_order) / 2
835834 d_floor = max (floor (Int, d_estimate), 1 )
836- d_ceil = ceil (Int, d_estimate)
835+ d_ceil = ceil (Int, d_estimate)
837836 candidate_order_floor = 2 ^ (2 * d_floor)
838- candidate_order_ceil = 2 ^ (2 * d_ceil)
839- chosen_bit_precision = abs (candidate_order_floor - requested_order) <= abs (candidate_order_ceil - requested_order) ? d_floor : d_ceil
837+ candidate_order_ceil = 2 ^ (2 * d_ceil)
838+ chosen_bit_precision = abs (candidate_order_floor - requested_order) <=
839+ abs (candidate_order_ceil - requested_order) ? d_floor : d_ceil
840840 actual_matrix_order = 2 ^ (2 * chosen_bit_precision)
841841 if actual_matrix_order != requested_order
842842 @warn """ \n
@@ -846,8 +846,10 @@ function chaotic_init(rng::AbstractRNG, ::Type{T}, dims::Integer...;
846846 """
847847 end
848848
849- random_weight_matrix = T (2 ) * rand (rng, T, actual_matrix_order, actual_matrix_order) .- T (1 )
850- adjacency_matrix = digital_chaotic_adjacency (rng, chosen_bit_precision; extra_edge_probability = extra_edge_probability)
849+ random_weight_matrix = T (2 ) * rand (rng, T, actual_matrix_order, actual_matrix_order) .-
850+ T (1 )
851+ adjacency_matrix = digital_chaotic_adjacency (
852+ rng, chosen_bit_precision; extra_edge_probability= extra_edge_probability)
851853 reservoir_matrix = random_weight_matrix .* adjacency_matrix
852854 current_spectral_radius = maximum (abs, eigvals (reservoir_matrix))
853855 if current_spectral_radius != 0
0 commit comments