From 7f3e8dc7b8e3c6f760e3fdf730c2ee635a88792b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Thu, 29 Feb 2024 13:45:55 -0300 Subject: [PATCH 01/11] refac: remove some functions --- pallets/subspace/src/math.rs | 135 +++++------------------------------ 1 file changed, 17 insertions(+), 118 deletions(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index e0fd7b137..86dd918e0 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -4,28 +4,24 @@ use substrate_fixed::{ types::{I32F32, I64F64}, }; -#[allow(dead_code)] pub fn bottom_k_u16(vector: &Vec, k: usize) -> Vec { let mut vec_clone = vector.clone(); vec_clone.sort(); // Sorting in ascending order vec_clone.into_iter().take(k).collect() } -#[allow(dead_code)] pub fn top_k_u16(vector: &Vec, k: usize) -> Vec { let mut vec_clone = vector.clone(); vec_clone.sort(); // Sorting in ascending order vec_clone.into_iter().rev().take(k).collect() } -#[allow(dead_code)] pub fn top_k_u64(vector: &Vec, k: usize) -> Vec { let mut vec_clone = vector.clone(); vec_clone.sort(); // Sorting in ascending order vec_clone.into_iter().rev().take(k).collect() } -#[allow(dead_code)] pub fn top_percentile_u16(vector: &Vec, percentile: I32F32) -> Vec { let mut vec_clone = vector.clone(); vec_clone.sort(); // Sorting in ascending order @@ -33,102 +29,44 @@ pub fn top_percentile_u16(vector: &Vec, percentile: I32F32) -> Vec { vec_clone.into_iter().rev().take(k).collect() } -#[allow(dead_code)] -pub fn fixed(val: f32) -> I32F32 { - I32F32::from_num(val) -} - -#[allow(dead_code)] -pub fn fixed_to_u16(x: I32F32) -> u16 { - x.to_num::() -} - -#[allow(dead_code)] -pub fn fixed_to_u64(x: I32F32) -> u64 { - x.to_num::() -} - -#[allow(dead_code)] -pub fn fixed64_to_u64(x: I64F64) -> u64 { - x.to_num::() -} - -#[allow(dead_code)] -pub fn fixed64_to_fixed32(x: I64F64) -> I32F32 { - I32F32::from_num(x) -} - -#[allow(dead_code)] -pub fn u16_to_fixed(x: u16) -> I32F32 { - I32F32::from_num(x) -} - -#[allow(dead_code)] pub fn u16_proportion_to_fixed(x: u16) -> I32F32 { I32F32::from_num(x) / I32F32::from_num(u16::MAX) } -#[allow(dead_code)] pub fn fixed_proportion_to_u16(x: I32F32) -> u16 { - fixed_to_u16(x * I32F32::from_num(u16::MAX)) + (x * I32F32::from_num(u16::MAX)).to_num() } -#[allow(dead_code)] -pub fn vec_fixed64_to_fixed32(vec: Vec) -> Vec { - vec.into_iter().map(|e| fixed64_to_fixed32(e)).collect() -} - -#[allow(dead_code)] -pub fn vec_u16_proportions_to_fixed(vec: Vec) -> Vec { - vec.into_iter().map(|e| u16_proportion_to_fixed(e)).collect() -} - -#[allow(dead_code)] pub fn vec_fixed_proportions_to_u16(vec: Vec) -> Vec { vec.into_iter().map(|e| fixed_proportion_to_u16(e)).collect() } -#[allow(dead_code)] -pub fn sum(x: &Vec) -> I32F32 { - x.iter().sum() -} - // Return true when vector sum is zero. -#[allow(dead_code)] pub fn is_zero(vector: &Vec) -> bool { - let vector_sum: I32F32 = sum(&vector); + let vector_sum: I32F32 = vector.iter().sum(); vector_sum == I32F32::from_num(0) } // Exp safe function with I32F32 output of I32F32 input. -#[allow(dead_code)] pub fn exp_safe(input: I32F32) -> I32F32 { let min_input: I32F32 = I32F32::from_num(-20); // <= 1/exp(-20) = 485 165 195,4097903 let max_input: I32F32 = I32F32::from_num(20); // <= exp(20) = 485 165 195,4097903 - let mut safe_input: I32F32 = input; - if input < min_input { - safe_input = min_input; + let safe_input: I32F32 = if input < min_input { + min_input } else if max_input < input { - safe_input = max_input; - } - let output: I32F32; + max_input + } else { + input + }; match exp(safe_input) { - Ok(val) => { - output = val; - }, - Err(_err) => - if safe_input <= 0 { - output = I32F32::from_num(0); - } else { - output = I32F32::max_value(); - }, + Ok(val) => val, + Err(_) if safe_input <= 0 => I32F32::from_num(0), + Err(_) => I32F32::max_value(), } - output } // Sigmoid safe function with I32F32 output of I32F32 input with offset kappa and (recommended) // scaling 0 < rho <= 40. -#[allow(dead_code)] pub fn sigmoid_safe(input: I32F32, rho: I32F32, kappa: I32F32) -> I32F32 { let one: I32F32 = I32F32::from_num(1); let offset: I32F32 = input.saturating_sub(kappa); // (input - kappa) @@ -141,7 +79,6 @@ pub fn sigmoid_safe(input: I32F32, rho: I32F32, kappa: I32F32) -> I32F32 { } // Returns a bool vector where an item is true if the vector item is in topk values. -#[allow(dead_code)] pub fn is_topk(vector: &Vec, k: usize) -> Vec { let n: usize = vector.len(); let mut result: Vec = vec![true; n]; @@ -157,18 +94,16 @@ pub fn is_topk(vector: &Vec, k: usize) -> Vec { } // Returns a normalized (sum to 1 except 0) copy of the input vector. -#[allow(dead_code)] pub fn normalize(x: &Vec) -> Vec { - let x_sum: I32F32 = sum(x); - if x_sum != I32F32::from_num(0.0 as f32) { - return x.iter().map(|xi| xi / x_sum).collect() - } else { + let x_sum: I32F32 = x.iter().sum(); + if x_sum == I32F32::from_num(0.0 as f32) { x.clone() + } else { + x.iter().map(|xi| xi / x_sum).collect() } } // Normalizes (sum to 1 except 0) the input vector directly in-place. -#[allow(dead_code)] pub fn inplace_normalize(x: &mut Vec) { let x_sum: I32F32 = x.iter().sum(); if x_sum == I32F32::from_num(0.0) { @@ -180,7 +115,6 @@ pub fn inplace_normalize(x: &mut Vec) { } // Normalizes (sum to 1 except 0) the I64F64 input vector directly in-place. -#[allow(dead_code)] pub fn inplace_normalize_64(x: &mut Vec) { let x_sum: I64F64 = x.iter().sum(); if x_sum == I64F64::from_num(0) { @@ -192,7 +126,6 @@ pub fn inplace_normalize_64(x: &mut Vec) { } /// Returns x / y for input vectors x and y, if y == 0 return 0. -#[allow(dead_code)] pub fn vecdiv(x: &Vec, y: &Vec) -> Vec { assert_eq!(x.len(), y.len()); let n = x.len(); @@ -206,7 +139,6 @@ pub fn vecdiv(x: &Vec, y: &Vec) -> Vec { } // Normalizes (sum to 1 except 0) each row (dim=0) of a matrix in-place. -#[allow(dead_code)] pub fn inplace_row_normalize(x: &mut Vec>) { for i in 0..x.len() { let row_sum: I32F32 = x[i].iter().sum(); @@ -217,7 +149,6 @@ pub fn inplace_row_normalize(x: &mut Vec>) { } // Normalizes (sum to 1 except 0) each row (dim=0) of a sparse matrix in-place. -#[allow(dead_code)] pub fn inplace_row_normalize_sparse(sparse_matrix: &mut Vec>) { for sparse_row in sparse_matrix.iter_mut() { let row_sum: I32F32 = sparse_row.iter().map(|(_j, value)| *value).sum(); @@ -228,7 +159,6 @@ pub fn inplace_row_normalize_sparse(sparse_matrix: &mut Vec>) } // Sum across each row (dim=0) of a matrix. -#[allow(dead_code)] pub fn row_sum(x: &Vec>) -> Vec { if x.len() == 0 { return vec![] @@ -247,7 +177,6 @@ pub fn row_sum(x: &Vec>) -> Vec { } // Sum across each row (dim=0) of a sparse matrix. -#[allow(dead_code)] pub fn row_sum_sparse(sparse_matrix: &Vec>) -> Vec { let rows = sparse_matrix.len(); let mut result: Vec = vec![I32F32::from_num(0); rows]; @@ -260,7 +189,6 @@ pub fn row_sum_sparse(sparse_matrix: &Vec>) -> Vec { } // Sum across each column (dim=1) of a matrix. -#[allow(dead_code)] pub fn col_sum(x: &Vec>) -> Vec { if x.len() == 0 { return vec![] @@ -280,7 +208,6 @@ pub fn col_sum(x: &Vec>) -> Vec { } // Sum across each column (dim=1) of a sparse matrix. -#[allow(dead_code)] pub fn col_sum_sparse(sparse_matrix: &Vec>, columns: u16) -> Vec { let mut result: Vec = vec![I32F32::from_num(0); columns as usize]; for sparse_row in sparse_matrix.iter() { @@ -292,7 +219,6 @@ pub fn col_sum_sparse(sparse_matrix: &Vec>, columns: u16) -> } // Normalizes (sum to 1 except 0) each column (dim=1) of a sparse matrix in-place. -#[allow(dead_code)] pub fn inplace_col_normalize_sparse(sparse_matrix: &mut Vec>, columns: u16) { let mut col_sum: Vec = vec![I32F32::from_num(0.0); columns as usize]; // assume square matrix, rows=cols for sparse_row in sparse_matrix.iter() { @@ -311,7 +237,6 @@ pub fn inplace_col_normalize_sparse(sparse_matrix: &mut Vec>, } // Normalizes (sum to 1 except 0) each column (dim=1) of a matrix in-place. -#[allow(dead_code)] pub fn inplace_col_normalize(x: &mut Vec>) { if x.len() == 0 { return @@ -338,7 +263,6 @@ pub fn inplace_col_normalize(x: &mut Vec>) { } // Apply mask to vector, mask=true will mask out, i.e. set to 0. -#[allow(dead_code)] pub fn inplace_mask_vector(mask: &Vec, vector: &mut Vec) { if mask.len() == 0 { return @@ -353,7 +277,6 @@ pub fn inplace_mask_vector(mask: &Vec, vector: &mut Vec) { } // Apply mask to matrix, mask=true will mask out, i.e. set to 0. -#[allow(dead_code)] pub fn inplace_mask_matrix(mask: &Vec>, matrix: &mut Vec>) { if mask.len() == 0 { return @@ -373,7 +296,6 @@ pub fn inplace_mask_matrix(mask: &Vec>, matrix: &mut Vec>) } // Apply row mask to matrix, mask=true will mask out, i.e. set to 0. -#[allow(dead_code)] pub fn inplace_mask_rows(mask: &Vec, matrix: &mut Vec>) { let rows = matrix.len(); if rows == 0 { @@ -390,7 +312,6 @@ pub fn inplace_mask_rows(mask: &Vec, matrix: &mut Vec>) { } // Mask out the diagonal of the input matrix in-place. -#[allow(dead_code)] pub fn inplace_mask_diag(matrix: &mut Vec>) { if matrix.len() == 0 { return @@ -406,7 +327,6 @@ pub fn inplace_mask_diag(matrix: &mut Vec>) { } // Return a new sparse matrix that replaces masked rows with an empty vector placeholder. -#[allow(dead_code)] pub fn mask_rows_sparse( mask: &Vec, sparse_matrix: &Vec>, @@ -423,7 +343,6 @@ pub fn mask_rows_sparse( } // Return a new sparse matrix with a masked out diagonal of input sparse matrix. -#[allow(dead_code)] pub fn mask_diag_sparse(sparse_matrix: &Vec>) -> Vec> { let n: usize = sparse_matrix.len(); let mut result: Vec> = vec![vec![]; n]; @@ -438,7 +357,6 @@ pub fn mask_diag_sparse(sparse_matrix: &Vec>) -> Vec>, first_vector: &Vec, @@ -458,7 +376,6 @@ pub fn vec_mask_sparse_matrix( } // Row-wise matrix-vector hadamard product. -#[allow(dead_code)] pub fn row_hadamard(matrix: &Vec>, vector: &Vec) -> Vec> { if matrix.len() == 0 { return vec![vec![]] @@ -477,7 +394,6 @@ pub fn row_hadamard(matrix: &Vec>, vector: &Vec) -> Vec>, vector: &Vec, @@ -492,7 +408,6 @@ pub fn row_hadamard_sparse( } // Row-wise matrix-vector product, column-wise sum: result_j = SUM(i) vector_i * matrix_ij. -#[allow(dead_code)] pub fn matmul(matrix: &Vec>, vector: &Vec) -> Vec { if matrix.len() == 0 { return vec![] @@ -513,7 +428,6 @@ pub fn matmul(matrix: &Vec>, vector: &Vec) -> Vec { } // Column-wise matrix-vector product, row-wise sum: result_i = SUM(j) vector_j * matrix_ij. -#[allow(dead_code)] pub fn matmul_transpose(matrix: &Vec>, vector: &Vec) -> Vec { if matrix.len() == 0 { return vec![] @@ -535,7 +449,6 @@ pub fn matmul_transpose(matrix: &Vec>, vector: &Vec) -> Vec< } // Row-wise sparse_matrix-vector product, column-wise sum: result_j = SUM(i) vector_i * matrix_ij. -#[allow(dead_code)] pub fn matmul_sparse( sparse_matrix: &Vec>, vector: &Vec, @@ -553,7 +466,6 @@ pub fn matmul_sparse( } // Column-wise sparse_matrix-vector product, row-wise sum: result_i = SUM(j) vector_j * matrix_ij. -#[allow(dead_code)] pub fn matmul_transpose_sparse( sparse_matrix: &Vec>, vector: &Vec, @@ -571,7 +483,6 @@ pub fn matmul_transpose_sparse( } // Set inplace matrix values above column threshold to threshold value. -#[allow(dead_code)] pub fn inplace_col_clip(x: &mut Vec>, col_threshold: &Vec) { for i in 0..x.len() { for j in 0..x[i].len() { @@ -583,7 +494,6 @@ pub fn inplace_col_clip(x: &mut Vec>, col_threshold: &Vec) { } // Return sparse matrix with values above column threshold set to threshold value. -#[allow(dead_code)] pub fn col_clip_sparse( sparse_matrix: &Vec>, col_threshold: &Vec, @@ -604,7 +514,6 @@ pub fn col_clip_sparse( } // Set matrix values below threshold to lower, and equal-above to upper. -#[allow(dead_code)] pub fn clip( x: &Vec>, threshold: I32F32, @@ -627,7 +536,6 @@ pub fn clip( } // Set inplace matrix values below threshold to lower, and equal-above to upper. -#[allow(dead_code)] pub fn inplace_clip(x: &mut Vec>, threshold: I32F32, upper: I32F32, lower: I32F32) { for i in 0..x.len() { for j in 0..x[i].len() { @@ -642,7 +550,6 @@ pub fn inplace_clip(x: &mut Vec>, threshold: I32F32, upper: I32F32, // Set sparse matrix values below threshold to lower, and equal-above to upper. // Does not add missing elements (0 value assumed) when lower!=0. -#[allow(dead_code)] pub fn clip_sparse( sparse_matrix: &Vec>, threshold: I32F32, @@ -691,7 +598,6 @@ pub fn clip_sparse( // * 'median': ( I32F32 ): // - median via random pivot binary search. // -#[allow(dead_code)] pub fn weighted_median( stake: &Vec, score: &Vec, @@ -752,7 +658,6 @@ pub fn weighted_median( /// Column-wise weighted median, e.g. stake-weighted median scores per server (column) over all /// validators (rows). -#[allow(dead_code)] pub fn weighted_median_col( stake: &Vec, score: &Vec>, @@ -791,7 +696,6 @@ pub fn weighted_median_col( /// Column-wise weighted median, e.g. stake-weighted median scores per server (column) over all /// validators (rows). -#[allow(dead_code)] pub fn weighted_median_col_sparse( stake: &Vec, score: &Vec>, @@ -825,7 +729,6 @@ pub fn weighted_median_col_sparse( } // Element-wise product of two matrices. -#[allow(dead_code)] pub fn hadamard(mat1: &Vec>, mat2: &Vec>) -> Vec> { assert!(mat1.len() == mat2.len()); if mat1.len() == 0 { @@ -845,7 +748,6 @@ pub fn hadamard(mat1: &Vec>, mat2: &Vec>) -> Vec>, mat2: &Vec>, @@ -877,7 +779,6 @@ pub fn hadamard_sparse( // Return matrix exponential moving average: `alpha * a_ij + one_minus_alpha * b_ij`. // `alpha` is the EMA coefficient, how much to add of the new observation, typically small, // higher alpha discounts older observations faster. -#[allow(dead_code)] pub fn mat_ema(new: &Vec>, old: &Vec>, alpha: I32F32) -> Vec> { if new.len() == 0 { return vec![vec![]; 1] @@ -900,7 +801,6 @@ pub fn mat_ema(new: &Vec>, old: &Vec>, alpha: I32F32) -> // Return sparse matrix exponential moving average: `alpha * a_ij + one_minus_alpha * b_ij`. // `alpha` is the EMA coefficient, how much to add of the new observation, typically small, // higher alpha discounts older observations faster. -#[allow(dead_code)] pub fn mat_ema_sparse( new: &Vec>, old: &Vec>, @@ -929,7 +829,6 @@ pub fn mat_ema_sparse( } // Return sparse matrix only with elements >= threshold of an input sparse matrix. -#[allow(dead_code)] pub fn sparse_threshold(w: &Vec>, threshold: I32F32) -> Vec> { let mut sparse_threshold_result: Vec> = vec![vec![]; w.len()]; for (uid_i, weights_i) in w.iter().enumerate() { @@ -998,8 +897,8 @@ mod tests { } } - fn vec_to_fixed(vector: &Vec) -> Vec { - vector.iter().map(|x| I32F32::from_num(*x)).collect() + macro_rules! fixed_vec { + () => {}; } #[test] From 3310896090aa899374a2ba75c765707cbb7ec7b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Thu, 29 Feb 2024 21:08:11 -0300 Subject: [PATCH 02/11] fix: fix with .into() --- pallets/subspace/src/math.rs | 390 ++++++++++++++++------------------- 1 file changed, 173 insertions(+), 217 deletions(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index 5b4c9fac5..dddc79194 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -12,15 +12,9 @@ pub fn fixed_proportion_to_u16(x: I32F32) -> u16 { (x * I32F32::from_num(u16::MAX)).to_num() } -#[allow(dead_code)] -pub fn sum(x: &Vec) -> I32F32 { - x.iter().sum() -} - // Return true when vector sum is zero. pub fn is_zero(vector: &Vec) -> bool { - let vector_sum: I32F32 = vector.iter().sum(); - vector_sum == I32F32::from_num(0) + vector.iter().sum::() == I32F32::from_num(0) } // Exp safe function with I32F32 output of I32F32 input. @@ -879,8 +873,13 @@ mod tests { } } - fn vec_to_fixed(vector: &Vec) -> Vec { - vector.iter().map(|x| I32F32::from_num(*x)).collect() + macro_rules! fixed_vec { + () => { + vec![] + }; + ($($x:expr),+ $(,)?) => { + vec![$($x.into()),+] + }; } #[test] @@ -952,15 +951,9 @@ mod tests { #[test] fn test_math_vec_to_fixed() { - let vector: Vec = vec![0., 1., 2., 3.]; - let target: Vec = vec![ - I32F32::from_num(0.), - I32F32::from_num(1.), - I32F32::from_num(2.), - I32F32::from_num(3.), - ]; - let result = vec_to_fixed(&vector); - assert_vec_compare(&result, &target, I32F32::from_num(0)); + let vector: Vec = fixed_vec![0., 1., 2., 3.]; + let target: Vec = fixed_vec![0., 1., 2., 3.,]; + assert_vec_compare(&vector, &target, I32F32::from_num(0)); } // Reshape vector to matrix with specified number of rows, cast to I32F32. @@ -996,18 +989,7 @@ mod tests { #[test] fn test_math_vec_to_mat_fixed() { let vector: Vec = vec![0., 1., 2., 0., 10., 100.]; - let target: Vec> = vec![ - vec![ - I32F32::from_num(0.), - I32F32::from_num(1.), - I32F32::from_num(2.), - ], - vec![ - I32F32::from_num(0.), - I32F32::from_num(10.), - I32F32::from_num(100.), - ], - ]; + let target: Vec> = vec![fixed_vec![0., 1., 2.,], fixed_vec![0., 10., 100.,]]; let mat = vec_to_mat_fixed(&vector, 2, false); assert_mat_compare(&mat, &target, I32F32::from_num(0)); } @@ -1123,7 +1105,7 @@ mod tests { .iter() .map(|t: &I32F32| sigmoid_safe(*t, I32F32::max_value(), I32F32::max_value())) .collect(); - let target: Vec = vec_to_fixed(&vec![ + let target: Vec = fixed_vec![ 0.0000000019, 0.0000000019, 0.0000000019, @@ -1131,13 +1113,13 @@ mod tests { 0.0000000019, 0.0000000019, 0.5, - ]); + ]; assert_eq!(&consensus, &target); let consensus: Vec = trust .iter() .map(|t: &I32F32| sigmoid_safe(*t, I32F32::min_value(), I32F32::min_value())) .collect(); - let target: Vec = vec_to_fixed(&vec![ + let target: Vec = fixed_vec![ 0.5, 0.0000000019, 0.0000000019, @@ -1145,7 +1127,7 @@ mod tests { 0.0000000019, 0.0000000019, 0.0000000019, - ]); + ]; assert_eq!(&consensus, &target); let consensus: Vec = trust .iter() @@ -1162,8 +1144,7 @@ mod tests { ]; let target: Vec = target.iter().map(|c: &f64| I32F32::from_num(*c)).collect(); assert_eq!(&consensus, &target); - let trust: Vec = - vec_to_fixed(&vec![0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.]); + let trust: Vec = fixed_vec![0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.]; let consensus: Vec = trust .iter() .map(|t: &I32F32| sigmoid_safe(*t, I32F32::from_num(40), I32F32::from_num(0.5))) @@ -1187,11 +1168,11 @@ mod tests { #[test] fn test_math_is_topk() { - let vector: Vec = vec_to_fixed(&vec![]); + let vector: Vec = fixed_vec![]; let result = is_topk(&vector, 5); let target: Vec = vec![]; assert_eq!(&result, &target); - let vector: Vec = vec_to_fixed(&vec![0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]); + let vector: Vec = fixed_vec![0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]; let result = is_topk(&vector, 0); let target: Vec = vec![ false, false, false, false, false, false, false, false, false, false, @@ -1207,26 +1188,25 @@ mod tests { assert_eq!(&result, &target); let result = is_topk(&vector, 100); assert_eq!(&result, &target); - let vector: Vec = vec_to_fixed(&vec![9., 8., 7., 6., 5., 4., 3., 2., 1., 0.]); + let vector: Vec = fixed_vec![9., 8., 7., 6., 5., 4., 3., 2., 1., 0.]; let result = is_topk(&vector, 5); let target: Vec = vec![ true, true, true, true, true, false, false, false, false, false, ]; assert_eq!(&result, &target); - let vector: Vec = vec_to_fixed(&vec![9., 0., 8., 1., 7., 2., 6., 3., 5., 4.]); + let vector: Vec = fixed_vec![9., 0., 8., 1., 7., 2., 6., 3., 5., 4.]; let result = is_topk(&vector, 5); let target: Vec = vec![ true, false, true, false, true, false, true, false, true, false, ]; assert_eq!(&result, &target); - let vector: Vec = - vec_to_fixed(&vec![0.9, 0., 0.8, 0.1, 0.7, 0.2, 0.6, 0.3, 0.5, 0.4]); + let vector: Vec = fixed_vec![0.9, 0., 0.8, 0.1, 0.7, 0.2, 0.6, 0.3, 0.5, 0.4]; let result = is_topk(&vector, 5); let target: Vec = vec![ true, false, true, false, true, false, true, false, true, false, ]; assert_eq!(&result, &target); - let vector: Vec = vec_to_fixed(&vec![0., 1., 2., 3., 4., 5., 5., 5., 5., 6.]); + let vector: Vec = fixed_vec![0., 1., 2., 3., 4., 5., 5., 5., 5., 6.]; let result = is_topk(&vector, 5); let target: Vec = vec![ false, false, false, false, false, true, true, true, true, true, @@ -1236,21 +1216,9 @@ mod tests { #[test] fn test_math_sum() { - assert!(sum(&vec![]) == I32F32::from_num(0)); - assert!( - sum(&vec![ - I32F32::from_num(1.0), - I32F32::from_num(10.0), - I32F32::from_num(30.0) - ]) == I32F32::from_num(41) - ); - assert!( - sum(&vec![ - I32F32::from_num(-1.0), - I32F32::from_num(10.0), - I32F32::from_num(30.0) - ]) == I32F32::from_num(39) - ); + assert!(fixed_vec![].iter().sum::() == I32F32::from_num(0)); + assert!(fixed_vec![1.0, 10.0, 30.0].iter().sum::() == I32F32::from_num(41)); + assert!(fixed_vec![-1.0, 10.0, 30.0].iter().sum::() == I32F32::from_num(39)); } #[test] @@ -1259,63 +1227,35 @@ mod tests { let x: Vec = vec![]; let y: Vec = normalize(&x); assert_vec_compare(&x, &y, epsilon); - let x: Vec = vec![ - I32F32::from_num(1.0), - I32F32::from_num(10.0), - I32F32::from_num(30.0), - ]; + let x: Vec = fixed_vec![1.0, 10.0, 30.0,]; let y: Vec = normalize(&x); assert_vec_compare( &y, - &vec![ - I32F32::from_num(0.0243902437), - I32F32::from_num(0.243902439), - I32F32::from_num(0.7317073171), - ], + &fixed_vec![0.0243902437, 0.243902439, 0.7317073171,], epsilon, ); - assert_float_compare(sum(&y), I32F32::from_num(1.0), epsilon); - let x: Vec = vec![ - I32F32::from_num(-1.0), - I32F32::from_num(10.0), - I32F32::from_num(30.0), - ]; + assert_float_compare(y.iter().sum(), I32F32::from_num(1.0), epsilon); + let x: Vec = fixed_vec![-1.0, 10.0, 30.0]; let y: Vec = normalize(&x); assert_vec_compare( &y, - &vec![ - I32F32::from_num(-0.0256410255), - I32F32::from_num(0.2564102563), - I32F32::from_num(0.769230769), - ], + &fixed_vec![-0.0256410255, 0.2564102563, 0.769230769], epsilon, ); - assert_float_compare(sum(&y), I32F32::from_num(1.0), epsilon); + assert_float_compare(y.iter().sum(), I32F32::from_num(1.0), epsilon); } #[test] fn test_math_inplace_normalize() { let epsilon: I32F32 = I32F32::from_num(0.0001); - let mut x1: Vec = vec![ - I32F32::from_num(1.0), - I32F32::from_num(10.0), - I32F32::from_num(30.0), - ]; + let mut x1: Vec = fixed_vec![1.0, 10.0, 30.0,]; inplace_normalize(&mut x1); assert_vec_compare( &x1, - &vec![ - I32F32::from_num(0.0243902437), - I32F32::from_num(0.243902439), - I32F32::from_num(0.7317073171), - ], + &fixed_vec![0.0243902437, 0.243902439, 0.7317073171], epsilon, ); - let mut x2: Vec = vec![ - I32F32::from_num(-1.0), - I32F32::from_num(10.0), - I32F32::from_num(30.0), - ]; + let mut x2: Vec = fixed_vec![-1.0, 10.0, 30.0,]; inplace_normalize(&mut x2); assert_vec_compare( &x2, @@ -1339,11 +1279,7 @@ mod tests { inplace_normalize_64(&mut x1); assert_vec_compare_64( &x1, - &vec![ - I64F64::from_num(0.0243902437), - I64F64::from_num(0.243902439), - I64F64::from_num(0.7317073171), - ], + &fixed_vec![0.0243902437, 0.243902439, 0.7317073171], epsilon, ); let mut x2: Vec = vec![ @@ -1365,19 +1301,23 @@ mod tests { #[test] fn test_math_vecdiv() { - let x: Vec = vec_to_fixed(&vec![]); - let y: Vec = vec_to_fixed(&vec![]); - let result: Vec = vec_to_fixed(&vec![]); + let x: Vec = fixed_vec![]; + let y: Vec = fixed_vec![]; + let result: Vec = fixed_vec![]; assert_eq!(result, vecdiv(&x, &y)); - let x: Vec = vec_to_fixed(&vec![0., 1., 0., 1.]); - let y: Vec = vec_to_fixed(&vec![0., 1., 1., 0.]); - let result: Vec = vec_to_fixed(&vec![0., 1., 0., 0.]); + let x: Vec = fixed_vec![0., 1., 0., 1.]; + let y: Vec = fixed_vec![0., 1., 1., 0.]; + let result: Vec = fixed_vec![0., 1., 0., 0.]; assert_eq!(result, vecdiv(&x, &y)); - let x: Vec = vec_to_fixed(&vec![1., 1., 10.]); - let y: Vec = vec_to_fixed(&vec![2., 3., 2.]); - let result: Vec = vec![fixed(1.) / fixed(2.), fixed(1.) / fixed(3.), fixed(5.)]; + let x: Vec = fixed_vec![1., 1., 10.]; + let y: Vec = fixed_vec![2., 3., 2.]; + let result: Vec = vec![ + I32F32::from_num(1.) / I32F32::from_num(2.), + I32F32::from_num(1.) / I32F32::from_num(3.), + I32F32::from_num(5.), + ]; assert_eq!(result, vecdiv(&x, &y)); } @@ -1474,18 +1414,18 @@ mod tests { #[test] fn test_math_inplace_mask_vector() { let mask: Vec = vec![false, false, false]; - let mut vector: Vec = vec_to_fixed(&vec![0., 1., 2.]); - let target: Vec = vec_to_fixed(&vec![0., 1., 2.]); + let mut vector: Vec = fixed_vec![0., 1., 2.]; + let target: Vec = fixed_vec![0., 1., 2.]; inplace_mask_vector(&mask, &mut vector); assert_vec_compare(&vector, &target, I32F32::from_num(0)); let mask: Vec = vec![false, true, false]; - let mut vector: Vec = vec_to_fixed(&vec![0., 1., 2.]); - let target: Vec = vec_to_fixed(&vec![0., 0., 2.]); + let mut vector: Vec = fixed_vec![0., 1., 2.]; + let target: Vec = fixed_vec![0., 0., 2.]; inplace_mask_vector(&mask, &mut vector); assert_vec_compare(&vector, &target, I32F32::from_num(0)); let mask: Vec = vec![true, true, true]; - let mut vector: Vec = vec_to_fixed(&vec![0., 1., 2.]); - let target: Vec = vec_to_fixed(&vec![0., 0., 0.]); + let mut vector: Vec = fixed_vec![0., 1., 2.]; + let target: Vec = fixed_vec![0., 0., 0.]; inplace_mask_vector(&mask, &mut vector); assert_vec_compare(&vector, &target, I32F32::from_num(0)); } @@ -1697,7 +1637,7 @@ mod tests { #[test] fn test_math_row_hadamard() { - let vector: Vec = vec_to_fixed(&vec![1., 2., 3., 4.]); + let vector: Vec = fixed_vec![1., 2., 3., 4.]; let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_mat_fixed(&matrix, 4, false); let result = row_hadamard(&matrix, &vector); @@ -1708,7 +1648,7 @@ mod tests { #[test] fn test_math_row_hadamard_sparse() { - let vector: Vec = vec_to_fixed(&vec![1., 2., 3., 4.]); + let vector: Vec = fixed_vec![1., 2., 3., 4.]; let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = row_hadamard_sparse(&matrix, &vector); @@ -1734,7 +1674,7 @@ mod tests { let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_mat_fixed(&matrix, 4, false); let result = row_sum(&matrix); - let target: Vec = vec_to_fixed(&vec![6., 15., 24., 33.]); + let target: Vec = fixed_vec![6., 15., 24., 33.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); } @@ -1743,22 +1683,22 @@ mod tests { let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = row_sum_sparse(&matrix); - let target: Vec = vec_to_fixed(&vec![6., 15., 24., 33.]); + let target: Vec = fixed_vec![6., 15., 24., 33.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); let matrix: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = row_sum_sparse(&matrix); - let target: Vec = vec_to_fixed(&vec![5., 10., 15., 33.]); + let target: Vec = fixed_vec![5., 10., 15., 33.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); let matrix: Vec = vec![1., 2., 3., 0., 0., 0., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = row_sum_sparse(&matrix); - let target: Vec = vec_to_fixed(&vec![6., 0., 24., 33.]); + let target: Vec = fixed_vec![6., 0., 24., 33.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); let matrix: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = row_sum_sparse(&matrix); - let target: Vec = vec_to_fixed(&vec![0., 0., 0., 0.]); + let target: Vec = fixed_vec![0., 0., 0., 0.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); } @@ -1767,7 +1707,7 @@ mod tests { let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_mat_fixed(&matrix, 4, false); let result = col_sum(&matrix); - let target: Vec = vec_to_fixed(&vec![22., 26., 30.]); + let target: Vec = fixed_vec![22., 26., 30.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); } @@ -1776,62 +1716,62 @@ mod tests { let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = col_sum_sparse(&matrix, 3); - let target: Vec = vec_to_fixed(&vec![22., 26., 30.]); + let target: Vec = fixed_vec![22., 26., 30.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); let matrix: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = col_sum_sparse(&matrix, 3); - let target: Vec = vec_to_fixed(&vec![21., 21., 21.]); + let target: Vec = fixed_vec![21., 21., 21.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); let matrix: Vec = vec![1., 0., 3., 4., 0., 6., 7., 0., 9., 10., 0., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = col_sum_sparse(&matrix, 3); - let target: Vec = vec_to_fixed(&vec![22., 0., 30.]); + let target: Vec = fixed_vec![22., 0., 30.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); let matrix: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = col_sum_sparse(&matrix, 3); - let target: Vec = vec_to_fixed(&vec![0., 0., 0.]); + let target: Vec = fixed_vec![0., 0., 0.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); } #[test] fn test_math_matmul() { - let vector: Vec = vec_to_fixed(&vec![1., 2., 3., 4.]); + let vector: Vec = fixed_vec![1., 2., 3., 4.]; let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_mat_fixed(&matrix, 4, false); let result = matmul(&matrix, &vector); - let target: Vec = vec_to_fixed(&vec![70., 80., 90.]); + let target: Vec = fixed_vec![70., 80., 90.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); } #[test] fn test_math_matmul_transpose() { - let vector: Vec = vec_to_fixed(&vec![1., 2., 3.]); + let vector: Vec = fixed_vec![1., 2., 3.]; let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_mat_fixed(&matrix, 4, false); let result = matmul_transpose(&matrix, &vector); - let target: Vec = vec_to_fixed(&vec![14., 32., 50., 68.]); + let target: Vec = fixed_vec![14., 32., 50., 68.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); } #[test] fn test_math_sparse_matmul() { - let vector: Vec = vec_to_fixed(&vec![1., 2., 3., 4.]); + let vector: Vec = fixed_vec![1., 2., 3., 4.]; let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = matmul_sparse(&matrix, &vector, 3); - let target: Vec = vec_to_fixed(&vec![70., 80., 90.]); + let target: Vec = fixed_vec![70., 80., 90.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); let matrix: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = matmul_sparse(&matrix, &vector, 3); - let target: Vec = vec_to_fixed(&vec![69., 70., 63.]); + let target: Vec = fixed_vec![69., 70., 63.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); let matrix: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let result = matmul_sparse(&matrix, &vector, 3); - let target: Vec = vec_to_fixed(&vec![0., 0., 0.]); + let target: Vec = fixed_vec![0., 0., 0.]; assert_vec_compare(&result, &target, I32F32::from_num(0)); } @@ -1866,7 +1806,7 @@ mod tests { #[test] fn test_math_inplace_col_clip() { - let vector: Vec = vec_to_fixed(&vec![0., 5., 12.]); + let vector: Vec = fixed_vec![0., 5., 12.]; let matrix: Vec = vec![0., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let mut matrix = vec_to_mat_fixed(&matrix, 4, false); let target: Vec = vec![0., 2., 3., 0., 5., 6., 0., 5., 9., 0., 5., 12.]; @@ -1877,7 +1817,7 @@ mod tests { #[test] fn test_math_col_clip_sparse() { - let vector: Vec = vec_to_fixed(&vec![0., 5., 12.]); + let vector: Vec = fixed_vec![0., 5., 12.]; let matrix: Vec = vec![0., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); let target: Vec = vec![0., 2., 3., 0., 5., 6., 0., 5., 9., 0., 5., 12.]; @@ -1946,12 +1886,12 @@ mod tests { #[test] fn test_math_weighted_median() { let mut rng = thread_rng(); - let zero: I32F32 = fixed(0.); - let one: I32F32 = fixed(1.); + let zero: I32F32 = I32F32::from_num(0.); + let one: I32F32 = I32F32::from_num(1.); for _ in 0..100 { - let stake: Vec = vec_to_fixed(&vec![]); - let score: Vec = vec_to_fixed(&vec![]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![]; + let score: Vec = fixed_vec![]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( zero, weighted_median( @@ -1964,9 +1904,9 @@ mod tests { ) ); - let stake: Vec = normalize(&vec_to_fixed(&vec![0.51])); - let score: Vec = vec_to_fixed(&vec![1.]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = normalize(&fixed_vec![0.51]); + let score: Vec = fixed_vec![1.]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( one, weighted_median( @@ -1979,9 +1919,9 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.49, 0.51]); - let score: Vec = vec_to_fixed(&vec![0.5, 1.]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.49, 0.51]; + let score: Vec = fixed_vec![0.5, 1.]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( one, weighted_median( @@ -1994,11 +1934,11 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.51, 0.49]); - let score: Vec = vec_to_fixed(&vec![0.5, 1.]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.51, 0.49]; + let score: Vec = fixed_vec![0.5, 1.]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( - fixed(0.5), + I32F32::from_num(0.5), weighted_median( &stake, &score, @@ -2009,9 +1949,9 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.49, 0., 0.51]); - let score: Vec = vec_to_fixed(&vec![0.5, 0.7, 1.]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.49, 0., 0.51]; + let score: Vec = fixed_vec![0.5, 0.7, 1.]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( one, weighted_median( @@ -2024,11 +1964,11 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.49, 0.01, 0.5]); - let score: Vec = vec_to_fixed(&vec![0.5, 0.7, 1.]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.49, 0.01, 0.5]; + let score: Vec = fixed_vec![0.5, 0.7, 1.]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( - fixed(0.7), + I32F32::from_num(0.7), weighted_median( &stake, &score, @@ -2039,11 +1979,11 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.49, 0.51, 0.0]); - let score: Vec = vec_to_fixed(&vec![0.5, 0.7, 1.]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.49, 0.51, 0.0]; + let score: Vec = fixed_vec![0.5, 0.7, 1.]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( - fixed(0.7), + I32F32::from_num(0.7), weighted_median( &stake, &score, @@ -2054,9 +1994,9 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.0, 0.49, 0.51]); - let score: Vec = vec_to_fixed(&vec![0.5, 0.7, 1.]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.0, 0.49, 0.51]; + let score: Vec = fixed_vec![0.5, 0.7, 1.]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( one, weighted_median( @@ -2069,9 +2009,9 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.0, 0.49, 0.0, 0.51]); - let score: Vec = vec_to_fixed(&vec![0.5, 0.5, 1., 1.]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.0, 0.49, 0.0, 0.51]; + let score: Vec = fixed_vec![0.5, 0.5, 1., 1.]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( one, weighted_median( @@ -2084,9 +2024,9 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.0, 0.49, 0.0, 0.51, 0.0]); - let score: Vec = vec_to_fixed(&vec![0.5, 0.5, 1., 1., 0.5]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.0, 0.49, 0.0, 0.51, 0.0]; + let score: Vec = fixed_vec![0.5, 0.5, 1., 1., 0.5]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( one, weighted_median( @@ -2099,11 +2039,11 @@ mod tests { ) ); - let stake: Vec = vec_to_fixed(&vec![0.2, 0.2, 0.2, 0.2, 0.2]); - let score: Vec = vec_to_fixed(&vec![0.8, 0.2, 1., 0.6, 0.4]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.2, 0.2, 0.2, 0.2, 0.2]; + let score: Vec = fixed_vec![0.8, 0.2, 1., 0.6, 0.4]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( - fixed(0.6), + I32F32::from_num(0.6), weighted_median( &stake, &score, @@ -2114,13 +2054,11 @@ mod tests { ) ); - let stake: Vec = - vec_to_fixed(&vec![0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]); - let score: Vec = - vec_to_fixed(&vec![0.8, 0.8, 0.2, 0.2, 1.0, 1.0, 0.6, 0.6, 0.4, 0.4]); - let majority: I32F32 = fixed(0.51); + let stake: Vec = fixed_vec![0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]; + let score: Vec = fixed_vec![0.8, 0.8, 0.2, 0.2, 1.0, 1.0, 0.6, 0.6, 0.4, 0.4]; + let majority: I32F32 = I32F32::from_num(0.51); assert_eq!( - fixed(0.6), + I32F32::from_num(0.6), weighted_median( &stake, &score, @@ -2132,7 +2070,7 @@ mod tests { ); let n: usize = 100; - for majority in vec_to_fixed(&vec![ + for majority in fixed_vec![ 0., 0.0000001, 0.25, @@ -2145,7 +2083,7 @@ mod tests { 0.5100000000001, 0.9999999, 1., - ]) { + ] { for allow_equal in [false, true] { let mut stake: Vec = vec![]; let mut score: Vec = vec![]; @@ -2223,79 +2161,97 @@ mod tests { #[test] fn test_math_weighted_median_col() { - let stake: Vec = vec_to_fixed(&vec![]); + let stake: Vec = fixed_vec![]; let weights: Vec> = vec![vec![]]; - let median: Vec = vec_to_fixed(&vec![]); - assert_eq!(median, weighted_median_col(&stake, &weights, fixed(0.5))); + let median: Vec = fixed_vec![]; + assert_eq!( + median, + weighted_median_col(&stake, &weights, I32F32::from_num(0.5)) + ); - let stake: Vec = vec_to_fixed(&vec![0., 0.]); + let stake: Vec = fixed_vec![0., 0.]; let weights: Vec = vec![0., 0., 0., 0.]; let weights: Vec> = vec_to_mat_fixed(&weights, 2, false); - let median: Vec = vec_to_fixed(&vec![0., 0.]); - assert_eq!(median, weighted_median_col(&stake, &weights, fixed(0.5))); + let median: Vec = fixed_vec![0., 0.]; + assert_eq!( + median, + weighted_median_col(&stake, &weights, I32F32::from_num(0.5)) + ); - let stake: Vec = vec_to_fixed(&vec![0., 0.75, 0.25, 0.]); + let stake: Vec = fixed_vec![0., 0.75, 0.25, 0.]; let weights: Vec = vec![0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0.4, 0.5]; let weights: Vec> = vec_to_mat_fixed(&weights, 4, false); - let median: Vec = vec_to_fixed(&vec![0., 0.3, 0.4]); - assert_eq!(median, weighted_median_col(&stake, &weights, fixed(0.24))); - let median: Vec = vec_to_fixed(&vec![0., 0.2, 0.4]); - assert_eq!(median, weighted_median_col(&stake, &weights, fixed(0.26))); - let median: Vec = vec_to_fixed(&vec![0., 0.2, 0.1]); - assert_eq!(median, weighted_median_col(&stake, &weights, fixed(0.76))); - - let stake: Vec = vec_to_fixed(&vec![0., 0.3, 0.2, 0.5]); + let median: Vec = fixed_vec![0., 0.3, 0.4]; + assert_eq!( + median, + weighted_median_col(&stake, &weights, I32F32::from_num(0.24)) + ); + let median: Vec = fixed_vec![0., 0.2, 0.4]; + assert_eq!( + median, + weighted_median_col(&stake, &weights, I32F32::from_num(0.26)) + ); + let median: Vec = fixed_vec![0., 0.2, 0.1]; + assert_eq!( + median, + weighted_median_col(&stake, &weights, I32F32::from_num(0.76)) + ); + + let stake: Vec = fixed_vec![0., 0.3, 0.2, 0.5]; let weights: Vec = vec![0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0., 0.5]; let weights: Vec> = vec_to_mat_fixed(&weights, 4, false); - let median: Vec = vec_to_fixed(&vec![0., 0., 0.4]); - assert_eq!(median, weighted_median_col(&stake, &weights, fixed(0.51))); + let median: Vec = fixed_vec![0., 0., 0.4]; + assert_eq!( + median, + weighted_median_col(&stake, &weights, I32F32::from_num(0.51)) + ); } #[test] fn test_math_weighted_median_col_sparse() { - let stake: Vec = vec_to_fixed(&vec![]); + let stake: Vec = fixed_vec![]; let weights: Vec> = vec![vec![]]; - let median: Vec = vec_to_fixed(&vec![]); + let median: Vec = fixed_vec![]; assert_eq!( median, - weighted_median_col_sparse(&stake, &weights, 0, fixed(0.5)) + weighted_median_col_sparse(&stake, &weights, 0, I32F32::from_num(0.5)) ); - let stake: Vec = vec_to_fixed(&vec![0., 0.]); + let stake: Vec = fixed_vec![0., 0.]; let weights: Vec = vec![0., 0., 0., 0.]; let weights: Vec> = vec_to_sparse_mat_fixed(&weights, 2, false); - let median: Vec = vec_to_fixed(&vec![0., 0.]); + let median: Vec = fixed_vec![0., 0.]; assert_eq!( median, - weighted_median_col_sparse(&stake, &weights, 2, fixed(0.5)) + weighted_median_col_sparse(&stake, &weights, 2, I32F32::from_num(0.5)) ); - let stake: Vec = vec_to_fixed(&vec![0., 0.75, 0.25, 0.]); + let stake: Vec = fixed_vec![0., 0.75, 0.25, 0.]; let weights: Vec = vec![0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0.4, 0.5]; let weights: Vec> = vec_to_sparse_mat_fixed(&weights, 4, false); - let median: Vec = vec_to_fixed(&vec![0., 0.3, 0.4]); + let median: Vec = fixed_vec![0., 0.3, 0.4]; assert_eq!( median, - weighted_median_col_sparse(&stake, &weights, 3, fixed(0.24)) + weighted_median_col_sparse(&stake, &weights, 3, I32F32::from_num(0.24)) ); - let median: Vec = vec_to_fixed(&vec![0., 0.2, 0.4]); + let median: Vec = fixed_vec![0., 0.2, 0.4]; assert_eq!( median, - weighted_median_col_sparse(&stake, &weights, 3, fixed(0.26)) + weighted_median_col_sparse(&stake, &weights, 3, I32F32::from_num(0.26)) ); - let median: Vec = vec_to_fixed(&vec![0., 0.2, 0.1]); + let median: Vec = fixed_vec![0., 0.2, 0.1]; assert_eq!( median, - weighted_median_col_sparse(&stake, &weights, 3, fixed(0.76)) + weighted_median_col_sparse(&stake, &weights, 3, I32F32::from_num(0.76)) ); - let stake: Vec = vec_to_fixed(&vec![0., 0.3, 0.2, 0.5]); + let stake: Vec = fixed_vec![0., 0.3, 0.2, 0.5]; let weights: Vec = vec![0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0., 0.5]; let weights: Vec> = vec_to_sparse_mat_fixed(&weights, 4, false); - let median: Vec = vec_to_fixed(&vec![0., 0., 0.4]); + let median: Vec = fixed_vec![0., 0., 0.4]; assert_eq!( median, - weighted_median_col_sparse(&stake, &weights, 3, fixed(0.51)) + weighted_median_col_sparse(&stake, &weights, 3, I32F32::from_num(0.51)) ); } From 6eabd2a352ef57afe735995b6d77e1be07363c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Thu, 29 Feb 2024 21:10:42 -0300 Subject: [PATCH 03/11] refac: use ifs --- pallets/subspace/src/math.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index dddc79194..3680da8dd 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -2090,13 +2090,9 @@ mod tests { let mut last_score: I32F32 = zero; for i in 0..n { if allow_equal { - match rng.gen_range(0..2) { - 1 => stake.push(one), - _ => stake.push(zero), - } - match rng.gen_range(0..2) { - 1 => last_score += one, - _ => (), + stake.push(if rng.gen_range(0..2) == 1 { one } else { zero }); + if rng.gen_range(0..2) == 1 { + last_score += one; } score.push(last_score); } else { From 6cdb8ffd198d939b471df237221488fc371b7f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Fri, 1 Mar 2024 13:18:04 -0300 Subject: [PATCH 04/11] refac: remove all useless functions from math.rs --- pallets/subspace/src/math.rs | 2483 +++------------------------------- 1 file changed, 163 insertions(+), 2320 deletions(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index 3680da8dd..57228b2f2 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -1,78 +1,11 @@ use sp_std::{vec, vec::Vec}; -use substrate_fixed::{ - transcendental::exp, - types::{I32F32, I64F64}, -}; - -pub fn u16_proportion_to_fixed(x: u16) -> I32F32 { - I32F32::from_num(x) / I32F32::from_num(u16::MAX) -} - -pub fn fixed_proportion_to_u16(x: I32F32) -> u16 { - (x * I32F32::from_num(u16::MAX)).to_num() -} +use substrate_fixed::types::I32F32; // Return true when vector sum is zero. pub fn is_zero(vector: &Vec) -> bool { vector.iter().sum::() == I32F32::from_num(0) } -// Exp safe function with I32F32 output of I32F32 input. -pub fn exp_safe(input: I32F32) -> I32F32 { - let min_input: I32F32 = I32F32::from_num(-20); // <= 1/exp(-20) = 485 165 195,4097903 - let max_input: I32F32 = I32F32::from_num(20); // <= exp(20) = 485 165 195,4097903 - let safe_input: I32F32 = if input < min_input { - min_input - } else if max_input < input { - max_input - } else { - input - }; - match exp(safe_input) { - Ok(val) => val, - Err(_) if safe_input <= 0 => I32F32::from_num(0), - Err(_) => I32F32::max_value(), - } -} - -// Sigmoid safe function with I32F32 output of I32F32 input with offset kappa and (recommended) -// scaling 0 < rho <= 40. -pub fn sigmoid_safe(input: I32F32, rho: I32F32, kappa: I32F32) -> I32F32 { - let one: I32F32 = I32F32::from_num(1); - let offset: I32F32 = input.saturating_sub(kappa); // (input - kappa) - let neg_rho: I32F32 = rho.saturating_mul(-one); // -rho - let exp_input: I32F32 = neg_rho.saturating_mul(offset); // -rho*(input-kappa) - let exp_output: I32F32 = exp_safe(exp_input); // exp(-rho*(input-kappa)) - let denominator: I32F32 = exp_output.saturating_add(one); // 1 + exp(-rho*(input-kappa)) - let sigmoid_output: I32F32 = one.saturating_div(denominator); // 1 / (1 + exp(-rho*(input-kappa))) - sigmoid_output -} - -// Returns a bool vector where an item is true if the vector item is in topk values. -pub fn is_topk(vector: &Vec, k: usize) -> Vec { - let n: usize = vector.len(); - let mut result: Vec = vec![true; n]; - if n < k { - return result; - } - let mut idxs: Vec = (0..n).collect(); - idxs.sort_by_key(|&idx| &vector[idx]); // ascending stable sort - for &idx in &idxs[0..(n - k)] { - result[idx] = false; - } - result -} - -// Returns a normalized (sum to 1 except 0) copy of the input vector. -pub fn normalize(x: &Vec) -> Vec { - let x_sum: I32F32 = x.iter().sum(); - if x_sum == I32F32::from_num(0.0 as f32) { - x.clone() - } else { - x.iter().map(|xi| xi / x_sum).collect() - } -} - // Normalizes (sum to 1 except 0) the input vector directly in-place. pub fn inplace_normalize(x: &mut Vec) { let x_sum: I32F32 = x.iter().sum(); @@ -84,41 +17,29 @@ pub fn inplace_normalize(x: &mut Vec) { } } -// Normalizes (sum to 1 except 0) the I64F64 input vector directly in-place. -pub fn inplace_normalize_64(x: &mut Vec) { - let x_sum: I64F64 = x.iter().sum(); - if x_sum == I64F64::from_num(0) { - return; - } - for i in 0..x.len() { - x[i] = x[i] / x_sum; - } +pub fn u16_proportion_to_fixed(x: u16) -> I32F32 { + I32F32::from_num(x) / I32F32::from_num(u16::MAX) } -/// Returns x / y for input vectors x and y, if y == 0 return 0. -pub fn vecdiv(x: &Vec, y: &Vec) -> Vec { - assert_eq!(x.len(), y.len()); - let n = x.len(); - let mut result: Vec = vec![I32F32::from_num(0); n]; - for i in 0..n { - if y[i] != 0 { - result[i] = x[i] / y[i]; - } - } - result +pub fn fixed_proportion_to_u16(x: I32F32) -> u16 { + (x * I32F32::from_num(u16::MAX)).to_num() } -// Normalizes (sum to 1 except 0) each row (dim=0) of a matrix in-place. -pub fn inplace_row_normalize(x: &mut Vec>) { - for i in 0..x.len() { - let row_sum: I32F32 = x[i].iter().sum(); - if row_sum > I32F32::from_num(0.0 as f32) { - x[i].iter_mut().for_each(|x_ij: &mut I32F32| *x_ij /= row_sum); +// Return a new sparse matrix with a masked out diagonal of input sparse matrix. +pub fn mask_diag_sparse(sparse_matrix: &Vec>) -> Vec> { + let n: usize = sparse_matrix.len(); + let mut result: Vec> = vec![vec![]; n]; + for (i, sparse_row) in sparse_matrix.iter().enumerate() { + for (j, value) in sparse_row.iter() { + if i != (*j as usize) { + result[i].push((*j, *value)); + } } } + result } -// Normalizes (sum to 1 except 0) each row (dim=0) of a sparse matrix in-place. +/// Normalizes (sum to 1 except 0) each row (dim=0) of a sparse matrix in-place. pub fn inplace_row_normalize_sparse(sparse_matrix: &mut Vec>) { for sparse_row in sparse_matrix.iter_mut() { let row_sum: I32F32 = sparse_row.iter().map(|(_j, value)| *value).sum(); @@ -128,787 +49,145 @@ pub fn inplace_row_normalize_sparse(sparse_matrix: &mut Vec>) } } -// Sum across each row (dim=0) of a matrix. -pub fn row_sum(x: &Vec>) -> Vec { - if x.len() == 0 { - return vec![]; - } - if x[0].len() == 0 { - return vec![]; - } - let rows = x.len(); - let mut result: Vec = vec![I32F32::from_num(0); rows]; - for i in 0..x.len() { - for j in 0..x[i].len() { - result[i] += x[i][j]; - } - } - result -} - -// Sum across each row (dim=0) of a sparse matrix. -pub fn row_sum_sparse(sparse_matrix: &Vec>) -> Vec { - let rows = sparse_matrix.len(); - let mut result: Vec = vec![I32F32::from_num(0); rows]; - for (i, sparse_row) in sparse_matrix.iter().enumerate() { - for (_j, value) in sparse_row.iter() { - result[i] += value; - } - } - result -} - -// Sum across each column (dim=1) of a matrix. -pub fn col_sum(x: &Vec>) -> Vec { - if x.len() == 0 { - return vec![]; - } - if x[0].len() == 0 { - return vec![]; - } - let cols = x[0].len(); - let mut result: Vec = vec![I32F32::from_num(0); cols]; - for i in 0..x.len() { - assert_eq!(x[i].len(), cols); - for j in 0..cols { - result[j] += x[i][j]; - } - } - result -} +#[cfg(test)] +mod tests { + use crate::math::*; + use rand::{seq::SliceRandom, thread_rng, Rng}; + use substrate_fixed::{ + transcendental::exp, + types::{I32F32, I64F64, I96F32}, + }; -// Sum across each column (dim=1) of a sparse matrix. -pub fn col_sum_sparse(sparse_matrix: &Vec>, columns: u16) -> Vec { - let mut result: Vec = vec![I32F32::from_num(0); columns as usize]; - for sparse_row in sparse_matrix.iter() { - for (j, value) in sparse_row.iter() { - result[*j as usize] += value; - } + macro_rules! fixed_vec { + () => { + vec![] + }; + ($($x:expr),+ $(,)?) => { + vec![$($x.into()),+] + }; } - result -} -// Normalizes (sum to 1 except 0) each column (dim=1) of a sparse matrix in-place. -pub fn inplace_col_normalize_sparse(sparse_matrix: &mut Vec>, columns: u16) { - let mut col_sum: Vec = vec![I32F32::from_num(0.0); columns as usize]; // assume square matrix, rows=cols - for sparse_row in sparse_matrix.iter() { - for (j, value) in sparse_row.iter() { - col_sum[*j as usize] += value; - } - } - for sparse_row in sparse_matrix.iter_mut() { - for (j, value) in sparse_row.iter_mut() { - if col_sum[*j as usize] == I32F32::from_num(0.0 as f32) { - continue; + /// Reshape vector to sparse matrix with specified number of input rows, cast f32 to I32F32. + fn vec_to_sparse_mat_fixed( + vector: &Vec, + rows: usize, + transpose: bool, + ) -> Vec> { + assert!( + vector.len() % rows == 0, + "Vector of len {:?} cannot reshape to {rows} rows.", + vector.len() + ); + let cols: usize = vector.len() / rows; + let mut mat: Vec> = vec![]; + if transpose { + for col in 0..cols as usize { + let mut row_vec: Vec<(u16, I32F32)> = vec![]; + for row in 0..rows as usize { + if vector[row * cols + col] > 0. { + row_vec.push((row as u16, I32F32::from_num(vector[row * cols + col]))); + } + } + mat.push(row_vec); + } + } else { + for row in 0..rows as usize { + let mut row_vec: Vec<(u16, I32F32)> = vec![]; + for col in 0..cols as usize { + if vector[row * cols + col] > 0. { + row_vec.push((col as u16, I32F32::from_num(vector[row * cols + col]))); + } + } + mat.push(row_vec); } - *value /= col_sum[*j as usize]; } + mat } -} -// Normalizes (sum to 1 except 0) each column (dim=1) of a matrix in-place. -pub fn inplace_col_normalize(x: &mut Vec>) { - if x.len() == 0 { - return; - } - if x[0].len() == 0 { - return; - } - let cols = x[0].len(); - let mut col_sum: Vec = vec![I32F32::from_num(0.0); cols]; - for i in 0..x.len() { - assert_eq!(x[i].len(), cols); - for j in 0..cols { - col_sum[j] += x[i][j]; - } - } - for j in 0..cols { - if col_sum[j] == I32F32::from_num(0.0 as f32) { - continue; - } - for i in 0..x.len() { - x[i][j] /= col_sum[j]; + /// Returns a normalized (sum to 1 except 0) copy of the input vector. + fn normalize(x: &Vec) -> Vec { + let x_sum: I32F32 = x.iter().sum(); + if x_sum == I32F32::from_num(0.0 as f32) { + x.clone() + } else { + x.iter().map(|xi| xi / x_sum).collect() } } -} -// Apply mask to vector, mask=true will mask out, i.e. set to 0. -pub fn inplace_mask_vector(mask: &Vec, vector: &mut Vec) { - if mask.len() == 0 { - return; - } - assert_eq!(mask.len(), vector.len()); - let zero: I32F32 = I32F32::from_num(0.0); - for i in 0..mask.len() { - if mask[i] { - vector[i] = zero; - } + fn assert_float_compare(a: I32F32, b: I32F32, epsilon: I32F32) { + assert!(I32F32::abs(a - b) <= epsilon, "a({:?}) != b({:?})", a, b); } -} -// Apply mask to matrix, mask=true will mask out, i.e. set to 0. -pub fn inplace_mask_matrix(mask: &Vec>, matrix: &mut Vec>) { - if mask.len() == 0 { - return; - } - if mask[0].len() == 0 { - return; - } - assert_eq!(mask.len(), matrix.len()); - let zero: I32F32 = I32F32::from_num(0.0); - for i in 0..mask.len() { - for j in 0..mask[i].len() { - if mask[i][j] { - matrix[i][j] = zero; - } - } + fn assert_float_compare_64(a: I64F64, b: I64F64, epsilon: I64F64) { + assert!(I64F64::abs(a - b) <= epsilon, "a({:?}) != b({:?})", a, b); } -} -// Apply row mask to matrix, mask=true will mask out, i.e. set to 0. -pub fn inplace_mask_rows(mask: &Vec, matrix: &mut Vec>) { - let rows = matrix.len(); - if rows == 0 { - return; - } - let cols = matrix[0].len(); - assert_eq!(mask.len(), rows); - let zero: I32F32 = I32F32::from_num(0); - for i in 0..rows { - if mask[i] { - matrix[i] = vec![zero; cols]; + fn assert_vec_compare(va: &Vec, vb: &Vec, epsilon: I32F32) { + assert!(va.len() == vb.len()); + for i in 0..va.len() { + assert_float_compare(va[i], vb[i], epsilon); } } -} - -// Mask out the diagonal of the input matrix in-place. -pub fn inplace_mask_diag(matrix: &mut Vec>) { - if matrix.len() == 0 { - return; - } - if matrix[0].len() == 0 { - return; - } - assert_eq!(matrix.len(), matrix[0].len()); - let zero: I32F32 = I32F32::from_num(0.0); - for i in 0..matrix.len() { - matrix[i][i] = zero; - } -} -// Return a new sparse matrix that replaces masked rows with an empty vector placeholder. -pub fn mask_rows_sparse( - mask: &Vec, - sparse_matrix: &Vec>, -) -> Vec> { - let n: usize = sparse_matrix.len(); - assert_eq!(n, mask.len()); - let mut result: Vec> = vec![vec![]; n]; - for (i, sparse_row) in sparse_matrix.iter().enumerate() { - if !mask[i] { - result[i] = sparse_row.clone(); + fn assert_vec_compare_64(va: &Vec, vb: &Vec, epsilon: I64F64) { + assert!(va.len() == vb.len()); + for i in 0..va.len() { + assert_float_compare_64(va[i], vb[i], epsilon); } } - result -} -// Return a new sparse matrix with a masked out diagonal of input sparse matrix. -pub fn mask_diag_sparse(sparse_matrix: &Vec>) -> Vec> { - let n: usize = sparse_matrix.len(); - let mut result: Vec> = vec![vec![]; n]; - for (i, sparse_row) in sparse_matrix.iter().enumerate() { - for (j, value) in sparse_row.iter() { - if i != (*j as usize) { - result[i].push((*j, *value)); + fn assert_mat_compare(ma: &Vec>, mb: &Vec>, epsilon: I32F32) { + assert!(ma.len() == mb.len()); + for row in 0..ma.len() { + assert!(ma[row].len() == mb[row].len()); + for col in 0..ma[row].len() { + assert_float_compare(ma[row][col], mb[row][col], epsilon) } } } - result -} -// Remove cells from sparse matrix where the mask function of two vectors is true. -pub fn vec_mask_sparse_matrix( - sparse_matrix: &Vec>, - first_vector: &Vec, - second_vector: &Vec, - mask_fn: &dyn Fn(u64, u64) -> bool, -) -> Vec> { - let n: usize = sparse_matrix.len(); - let mut result: Vec> = vec![vec![]; n]; - for (i, sparse_row) in sparse_matrix.iter().enumerate() { - for (j, value) in sparse_row.iter() { - if !mask_fn(first_vector[i], second_vector[*j as usize]) { - result[i].push((*j, *value)); + fn assert_sparse_mat_compare( + ma: &Vec>, + mb: &Vec>, + epsilon: I32F32, + ) { + assert!(ma.len() == mb.len()); + for row in 0..ma.len() { + assert!(ma[row].len() == mb[row].len()); + for j in 0..ma[row].len() { + assert!(ma[row][j].0 == mb[row][j].0); // u16 + assert_float_compare(ma[row][j].1, mb[row][j].1, epsilon) // I32F32 } } } - result -} - -// Row-wise matrix-vector hadamard product. -pub fn row_hadamard(matrix: &Vec>, vector: &Vec) -> Vec> { - if matrix.len() == 0 { - return vec![vec![]]; - } - if matrix[0].len() == 0 { - return vec![vec![]]; - } - let mut result: Vec> = - vec![vec![I32F32::from_num(0.0); matrix[0].len()]; matrix.len()]; - for i in 0..matrix.len() { - for j in 0..matrix[i].len() { - result[i][j] = vector[i] * matrix[i][j]; - } - } - result -} - -// Row-wise sparse matrix-vector hadamard product. -pub fn row_hadamard_sparse( - sparse_matrix: &Vec>, - vector: &Vec, -) -> Vec> { - let mut result: Vec> = sparse_matrix.clone(); - for (i, sparse_row) in result.iter_mut().enumerate() { - for (_j, value) in sparse_row.iter_mut() { - *value *= vector[i]; - } - } - result -} - -// Row-wise matrix-vector product, column-wise sum: result_j = SUM(i) vector_i * matrix_ij. -pub fn matmul(matrix: &Vec>, vector: &Vec) -> Vec { - if matrix.len() == 0 { - return vec![]; - } - if matrix[0].len() == 0 { - return vec![]; - } - assert!(matrix.len() == vector.len()); - let mut result: Vec = vec![I32F32::from_num(0.0); matrix[0].len()]; - for i in 0..matrix.len() { - for j in 0..matrix[i].len() { - // Compute trust scores: t_j = SUM(i) w_ij * s_i - // result_j = SUM(i) vector_i * matrix_ij - result[j] += vector[i] * matrix[i][j]; - } - } - result -} -// Column-wise matrix-vector product, row-wise sum: result_i = SUM(j) vector_j * matrix_ij. -pub fn matmul_transpose(matrix: &Vec>, vector: &Vec) -> Vec { - if matrix.len() == 0 { - return vec![]; - } - if matrix[0].len() == 0 { - return vec![]; - } - assert!(matrix[0].len() == vector.len()); - let mut result: Vec = vec![I32F32::from_num(0.0); matrix.len()]; - for i in 0..matrix.len() { - for j in 0..matrix[i].len() { - // Compute dividends: d_j = SUM(i) b_ji * inc_i - // result_j = SUM(i) vector_i * matrix_ji - // result_i = SUM(j) vector_j * matrix_ij - result[i] += vector[j] * matrix[i][j]; - } - } - result -} - -// Row-wise sparse_matrix-vector product, column-wise sum: result_j = SUM(i) vector_i * matrix_ij. -pub fn matmul_sparse( - sparse_matrix: &Vec>, - vector: &Vec, - n: u16, -) -> Vec { - let mut result: Vec = vec![I32F32::from_num(0.0); n as usize]; - for (i, sparse_row) in sparse_matrix.iter().enumerate() { - for (j, value) in sparse_row.iter() { - // Compute trust scores: t_j = SUM(i) w_ij * s_i - // result_j = SUM(i) vector_i * matrix_ij - result[*j as usize] += vector[i] * value; - } - } - result -} - -// Column-wise sparse_matrix-vector product, row-wise sum: result_i = SUM(j) vector_j * matrix_ij. -pub fn matmul_transpose_sparse( - sparse_matrix: &Vec>, - vector: &Vec, -) -> Vec { - let mut result: Vec = vec![I32F32::from_num(0.0); vector.len()]; - for (i, sparse_row) in sparse_matrix.iter().enumerate() { - for (j, value) in sparse_row.iter() { - // Compute dividends: d_j = SUM(i) b_ji * inc_i - // result_j = SUM(i) vector_i * matrix_ji - // result_i = SUM(j) vector_j * matrix_ij - result[i] += vector[*j as usize] * value; - } - } - result -} - -// Set inplace matrix values above column threshold to threshold value. -pub fn inplace_col_clip(x: &mut Vec>, col_threshold: &Vec) { - for i in 0..x.len() { - for j in 0..x[i].len() { - if x[i][j] > col_threshold[j] { - x[i][j] = col_threshold[j]; - } - } - } -} - -// Return sparse matrix with values above column threshold set to threshold value. -pub fn col_clip_sparse( - sparse_matrix: &Vec>, - col_threshold: &Vec, -) -> Vec> { - let mut result: Vec> = vec![vec![]; sparse_matrix.len()]; - for (i, sparse_row) in sparse_matrix.iter().enumerate() { - for (j, value) in sparse_row.iter() { - if col_threshold[*j as usize] < *value { - if 0 < col_threshold[*j as usize] { - result[i].push((*j, col_threshold[*j as usize])); - } - } else { - result[i].push((*j, *value)); - } - } - } - result -} - -// Set matrix values below threshold to lower, and equal-above to upper. -pub fn clip( - x: &Vec>, - threshold: I32F32, - upper: I32F32, - lower: I32F32, -) -> Vec> { - // Check Nill length. - if x.len() == 0 { - return vec![vec![]]; - } - let mut result: Vec> = vec![vec![lower; x[0].len()]; x.len()]; - for i in 0..x.len() { - for j in 0..x[i].len() { - if x[i][j] >= threshold { - result[i][j] = upper; - } - } - } - result -} - -// Set inplace matrix values below threshold to lower, and equal-above to upper. -pub fn inplace_clip(x: &mut Vec>, threshold: I32F32, upper: I32F32, lower: I32F32) { - for i in 0..x.len() { - for j in 0..x[i].len() { - if x[i][j] >= threshold { - x[i][j] = upper; - } else { - x[i][j] = lower; - } - } - } -} - -// Set sparse matrix values below threshold to lower, and equal-above to upper. -// Does not add missing elements (0 value assumed) when lower!=0. -pub fn clip_sparse( - sparse_matrix: &Vec>, - threshold: I32F32, - upper: I32F32, - lower: I32F32, -) -> Vec> { - let mut result: Vec> = vec![vec![]; sparse_matrix.len()]; - for (i, sparse_row) in sparse_matrix.iter().enumerate() { - for (j, value) in sparse_row.iter() { - if *value < threshold { - result[i].push((*j, lower)); - } else { - result[i].push((*j, upper)); - } - } - } - result -} - -// Stake-weighted median score finding algorithm, based on a mid pivot binary search. -// Normally a random pivot is used, but to ensure full determinism the mid point is chosen instead. -// Assumes relatively random score order for efficiency, typically less than O(nlogn) complexity. -// -// # Args: -// * 'stake': ( &Vec ): -// - stake, assumed to be normalized. -// -// * 'score': ( &Vec ): -// - score for which median is sought, 0 <= score <= 1 -// -// * 'partition_idx' ( &Vec ): -// - indices as input partition -// -// * 'minority' ( I32F32 ): -// - minority_ratio = 1 - majority_ratio -// -// * 'partition_lo' ( I32F32 ): -// - lower edge of stake for partition, where partition is a segment [lo, hi] inside stake -// integral [0, 1]. -// -// * 'partition_hi' ( I32F32 ): -// - higher edge of stake for partition, where partition is a segment [lo, hi] inside stake -// integral [0, 1]. -// -// # Returns: -// * 'median': ( I32F32 ): -// - median via random pivot binary search. -// -pub fn weighted_median( - stake: &Vec, - score: &Vec, - partition_idx: &Vec, - minority: I32F32, - partition_lo: I32F32, - partition_hi: I32F32, -) -> I32F32 { - let n = partition_idx.len(); - if n == 0 { - return I32F32::from_num(0); - } - if n == 1 { - return score[partition_idx[0]]; - } - assert!(stake.len() == score.len()); - let mid_idx: usize = n / 2; - let pivot: I32F32 = score[partition_idx[mid_idx]]; - let mut lo_stake: I32F32 = I32F32::from_num(0); - let mut hi_stake: I32F32 = I32F32::from_num(0); - let mut lower: Vec = vec![]; - let mut upper: Vec = vec![]; - for &idx in partition_idx.iter() { - if score[idx] == pivot { - continue; - } - if score[idx] < pivot { - lo_stake += stake[idx]; - lower.push(idx); - } else { - hi_stake += stake[idx]; - upper.push(idx); - } - } - if (partition_lo + lo_stake <= minority) && (minority < partition_hi - hi_stake) { - return pivot; - } else if (minority < partition_lo + lo_stake) && (lower.len() > 0) { - return weighted_median( - stake, - score, - &lower, - minority, - partition_lo, - partition_lo + lo_stake, - ); - } else if (partition_hi - hi_stake <= minority) && (upper.len() > 0) { - return weighted_median( - stake, - score, - &upper, - minority, - partition_hi - hi_stake, - partition_hi, - ); - } - pivot -} - -/// Column-wise weighted median, e.g. stake-weighted median scores per server (column) over all -/// validators (rows). -pub fn weighted_median_col( - stake: &Vec, - score: &Vec>, - majority: I32F32, -) -> Vec { - let rows = stake.len(); - let columns = score[0].len(); - let zero: I32F32 = I32F32::from_num(0); - let mut median: Vec = vec![zero; columns]; - for c in 0..columns { - let mut use_stake: Vec = vec![]; - let mut use_score: Vec = vec![]; - for r in 0..rows { - assert_eq!(columns, score[r].len()); - if stake[r] > zero { - use_stake.push(stake[r]); - use_score.push(score[r][c]); - } - } - if use_stake.len() > 0 { - inplace_normalize(&mut use_stake); - let stake_sum: I32F32 = use_stake.iter().sum(); - let minority: I32F32 = stake_sum - majority; - median[c] = weighted_median( - &use_stake, - &use_score, - &(0..use_stake.len()).collect(), - minority, - zero, - stake_sum, - ); - } - } - median -} - -/// Column-wise weighted median, e.g. stake-weighted median scores per server (column) over all -/// validators (rows). -pub fn weighted_median_col_sparse( - stake: &Vec, - score: &Vec>, - columns: u16, - majority: I32F32, -) -> Vec { - let rows = stake.len(); - let zero: I32F32 = I32F32::from_num(0); - let mut use_stake: Vec = stake.iter().copied().filter(|&s| s > zero).collect(); - inplace_normalize(&mut use_stake); - let stake_sum: I32F32 = use_stake.iter().sum(); - let stake_idx: Vec = (0..use_stake.len()).collect(); - let minority: I32F32 = stake_sum - majority; - let mut use_score: Vec> = vec![vec![zero; use_stake.len()]; columns as usize]; - let mut median: Vec = vec![zero; columns as usize]; - let mut k: usize = 0; - for r in 0..rows { - if stake[r] <= zero { - continue; - } - for (c, val) in score[r].iter() { - use_score[*c as usize][k] = *val; - } - k += 1; - } - for c in 0..columns as usize { - median[c] = weighted_median( - &use_stake, - &use_score[c], - &stake_idx, - minority, - zero, - stake_sum, - ); - } - median -} - -// Element-wise product of two matrices. -pub fn hadamard(mat1: &Vec>, mat2: &Vec>) -> Vec> { - assert!(mat1.len() == mat2.len()); - if mat1.len() == 0 { - return vec![vec![]; 1]; - } - if mat1[0].len() == 0 { - return vec![vec![]; 1]; - } - let mut result: Vec> = vec![vec![I32F32::from_num(0); mat1[0].len()]; mat1.len()]; - for i in 0..mat1.len() { - assert!(mat1[i].len() == mat2[i].len()); - for j in 0..mat1[i].len() { - result[i][j] = mat1[i][j] * mat2[i][j]; - } - } - result -} - -// Element-wise product of two sparse matrices. -pub fn hadamard_sparse( - mat1: &Vec>, - mat2: &Vec>, - columns: u16, -) -> Vec> { - assert!(mat1.len() == mat2.len()); - let rows = mat1.len(); - let zero: I32F32 = I32F32::from_num(0); - let mut result: Vec> = vec![vec![]; rows]; - for i in 0..rows { - let mut row1: Vec = vec![zero; columns as usize]; - for (j, value) in mat1[i].iter() { - row1[*j as usize] += value; - } - let mut row2: Vec = vec![zero; columns as usize]; - for (j, value) in mat2[i].iter() { - row2[*j as usize] += value; - } - for j in 0..columns as usize { - let prod: I32F32 = row1[j] * row2[j]; - if zero < prod { - result[i].push((j as u16, prod)) - } - } - } - result -} - -// Return matrix exponential moving average: `alpha * a_ij + one_minus_alpha * b_ij`. -// `alpha` is the EMA coefficient, how much to add of the new observation, typically small, -// higher alpha discounts older observations faster. -pub fn mat_ema(new: &Vec>, old: &Vec>, alpha: I32F32) -> Vec> { - if new.len() == 0 { - return vec![vec![]; 1]; - } - if new[0].len() == 0 { - return vec![vec![]; 1]; - } - let one_minus_alpha: I32F32 = I32F32::from_num(1.0) - alpha; - let mut result: Vec> = vec![vec![I32F32::from_num(0.0); new[0].len()]; new.len()]; - assert!(new.len() == old.len()); - for i in 0..new.len() { - assert!(new[i].len() == old[i].len()); - for j in 0..new[i].len() { - result[i][j] = alpha * new[i][j] + one_minus_alpha * old[i][j] - } - } - result -} - -// Return sparse matrix exponential moving average: `alpha * a_ij + one_minus_alpha * b_ij`. -// `alpha` is the EMA coefficient, how much to add of the new observation, typically small, -// higher alpha discounts older observations faster. -pub fn mat_ema_sparse( - new: &Vec>, - old: &Vec>, - alpha: I32F32, -) -> Vec> { - assert!(new.len() == old.len()); - let n = new.len(); // assume square matrix, rows=cols - let zero: I32F32 = I32F32::from_num(0.0); - let one_minus_alpha: I32F32 = I32F32::from_num(1.0) - alpha; - let mut result: Vec> = vec![vec![]; n]; - for i in 0..new.len() { - let mut row: Vec = vec![zero; n]; - for (j, value) in new[i].iter() { - row[*j as usize] += alpha * value; - } - for (j, value) in old[i].iter() { - row[*j as usize] += one_minus_alpha * value; - } - for (j, value) in row.iter().enumerate() { - if *value > zero { - result[i].push((j as u16, *value)) - } - } - } - result -} - -// Return sparse matrix only with elements >= threshold of an input sparse matrix. -pub fn sparse_threshold(w: &Vec>, threshold: I32F32) -> Vec> { - let mut sparse_threshold_result: Vec> = vec![vec![]; w.len()]; - for (uid_i, weights_i) in w.iter().enumerate() { - for (uid_j, weight_ij) in weights_i.iter() { - if *weight_ij >= threshold { - sparse_threshold_result[uid_i as usize].push((*uid_j, *weight_ij)); - } - } - } - sparse_threshold_result -} - -#[cfg(test)] -mod tests { - use crate::math::*; - use rand::{seq::SliceRandom, thread_rng, Rng}; - use substrate_fixed::{ - transcendental::exp, - types::{I32F32, I64F64, I96F32}, - }; - - fn assert_float_compare(a: I32F32, b: I32F32, epsilon: I32F32) { - assert!(I32F32::abs(a - b) <= epsilon, "a({:?}) != b({:?})", a, b); - } - - fn assert_float_compare_64(a: I64F64, b: I64F64, epsilon: I64F64) { - assert!(I64F64::abs(a - b) <= epsilon, "a({:?}) != b({:?})", a, b); - } - - fn assert_vec_compare(va: &Vec, vb: &Vec, epsilon: I32F32) { - assert!(va.len() == vb.len()); - for i in 0..va.len() { - assert_float_compare(va[i], vb[i], epsilon); - } - } - - fn assert_vec_compare_64(va: &Vec, vb: &Vec, epsilon: I64F64) { - assert!(va.len() == vb.len()); - for i in 0..va.len() { - assert_float_compare_64(va[i], vb[i], epsilon); - } - } - - fn assert_mat_compare(ma: &Vec>, mb: &Vec>, epsilon: I32F32) { - assert!(ma.len() == mb.len()); - for row in 0..ma.len() { - assert!(ma[row].len() == mb[row].len()); - for col in 0..ma[row].len() { - assert_float_compare(ma[row][col], mb[row][col], epsilon) - } - } - } - - fn assert_sparse_mat_compare( - ma: &Vec>, - mb: &Vec>, - epsilon: I32F32, - ) { - assert!(ma.len() == mb.len()); - for row in 0..ma.len() { - assert!(ma[row].len() == mb[row].len()); - for j in 0..ma[row].len() { - assert!(ma[row][j].0 == mb[row][j].0); // u16 - assert_float_compare(ma[row][j].1, mb[row][j].1, epsilon) // I32F32 - } - } - } - - macro_rules! fixed_vec { - () => { - vec![] - }; - ($($x:expr),+ $(,)?) => { - vec![$($x.into()),+] - }; - } - - #[test] - fn test_math_u64_normalization() { - let min: u64 = 1; - let min32: u64 = 4_889_444; // 21_000_000_000_000_000 / 4_294_967_296 - let mid: u64 = 10_500_000_000_000_000; - let max: u64 = 21_000_000_000_000_000; - let min_64: I64F64 = I64F64::from_num(min); - let min32_64: I64F64 = I64F64::from_num(min32); - let mid_64: I64F64 = I64F64::from_num(mid); - let max_64: I64F64 = I64F64::from_num(max); - let max_sum: I64F64 = I64F64::from_num(max); - let min_frac: I64F64 = min_64 / max_sum; - assert_eq!(min_frac, I64F64::from_num(0.0000000000000000476)); - let min_frac_32: I32F32 = I32F32::from_num(min_frac); - assert_eq!(min_frac_32, I32F32::from_num(0)); - let min32_frac: I64F64 = min32_64 / max_sum; - assert_eq!(min32_frac, I64F64::from_num(0.00000000023283066664)); - let min32_frac_32: I32F32 = I32F32::from_num(min32_frac); - assert_eq!(min32_frac_32, I32F32::from_num(0.0000000002)); - let half: I64F64 = mid_64 / max_sum; - assert_eq!(half, I64F64::from_num(0.5)); - let half_32: I32F32 = I32F32::from_num(half); - assert_eq!(half_32, I32F32::from_num(0.5)); - let one: I64F64 = max_64 / max_sum; - assert_eq!(one, I64F64::from_num(1)); - let one_32: I32F32 = I32F32::from_num(one); - assert_eq!(one_32, I32F32::from_num(1)); + #[test] + fn test_math_u64_normalization() { + let min: u64 = 1; + let min32: u64 = 4_889_444; // 21_000_000_000_000_000 / 4_294_967_296 + let mid: u64 = 10_500_000_000_000_000; + let max: u64 = 21_000_000_000_000_000; + let min_64: I64F64 = I64F64::from_num(min); + let min32_64: I64F64 = I64F64::from_num(min32); + let mid_64: I64F64 = I64F64::from_num(mid); + let max_64: I64F64 = I64F64::from_num(max); + let max_sum: I64F64 = I64F64::from_num(max); + let min_frac: I64F64 = min_64 / max_sum; + assert_eq!(min_frac, I64F64::from_num(0.0000000000000000476)); + let min_frac_32: I32F32 = I32F32::from_num(min_frac); + assert_eq!(min_frac_32, I32F32::from_num(0)); + let min32_frac: I64F64 = min32_64 / max_sum; + assert_eq!(min32_frac, I64F64::from_num(0.00000000023283066664)); + let min32_frac_32: I32F32 = I32F32::from_num(min32_frac); + assert_eq!(min32_frac_32, I32F32::from_num(0.0000000002)); + let half: I64F64 = mid_64 / max_sum; + assert_eq!(half, I64F64::from_num(0.5)); + let half_32: I32F32 = I32F32::from_num(half); + assert_eq!(half_32, I32F32::from_num(0.5)); + let one: I64F64 = max_64 / max_sum; + assert_eq!(one, I64F64::from_num(1)); + let one_32: I32F32 = I32F32::from_num(one); + assert_eq!(one_32, I32F32::from_num(1)); } #[test] @@ -950,275 +229,42 @@ mod tests { } #[test] - fn test_math_vec_to_fixed() { - let vector: Vec = fixed_vec![0., 1., 2., 3.]; - let target: Vec = fixed_vec![0., 1., 2., 3.,]; - assert_vec_compare(&vector, &target, I32F32::from_num(0)); - } - - // Reshape vector to matrix with specified number of rows, cast to I32F32. - fn vec_to_mat_fixed(vector: &Vec, rows: usize, transpose: bool) -> Vec> { - assert!( - vector.len() % rows == 0, - "Vector of len {:?} cannot reshape to {rows} rows.", - vector.len() - ); - let cols: usize = vector.len() / rows; - let mut mat: Vec> = vec![]; - if transpose { - for col in 0..cols as usize { - let mut vals: Vec = vec![]; - for row in 0..rows as usize { - vals.push(I32F32::from_num(vector[row * cols + col])); - } - mat.push(vals); - } - } else { - for row in 0..rows as usize { - mat.push( - vector[row * cols..(row + 1) * cols] - .iter() - .map(|v| I32F32::from_num(*v)) - .collect(), - ); - } - } - mat - } - - #[test] - fn test_math_vec_to_mat_fixed() { - let vector: Vec = vec![0., 1., 2., 0., 10., 100.]; - let target: Vec> = vec![fixed_vec![0., 1., 2.,], fixed_vec![0., 10., 100.,]]; - let mat = vec_to_mat_fixed(&vector, 2, false); - assert_mat_compare(&mat, &target, I32F32::from_num(0)); - } - - // Reshape vector to sparse matrix with specified number of input rows, cast f32 to I32F32. - fn vec_to_sparse_mat_fixed( - vector: &Vec, - rows: usize, - transpose: bool, - ) -> Vec> { - assert!( - vector.len() % rows == 0, - "Vector of len {:?} cannot reshape to {rows} rows.", - vector.len() - ); - let cols: usize = vector.len() / rows; - let mut mat: Vec> = vec![]; - if transpose { - for col in 0..cols as usize { - let mut row_vec: Vec<(u16, I32F32)> = vec![]; - for row in 0..rows as usize { - if vector[row * cols + col] > 0. { - row_vec.push((row as u16, I32F32::from_num(vector[row * cols + col]))); - } - } - mat.push(row_vec); - } - } else { - for row in 0..rows as usize { - let mut row_vec: Vec<(u16, I32F32)> = vec![]; - for col in 0..cols as usize { - if vector[row * cols + col] > 0. { - row_vec.push((col as u16, I32F32::from_num(vector[row * cols + col]))); - } - } - mat.push(row_vec); - } - } - mat - } - - #[test] - fn test_math_vec_to_sparse_mat_fixed() { - let vector: Vec = vec![0., 1., 2., 0., 10., 100.]; - let target: Vec> = vec![ - vec![ - (1 as u16, I32F32::from_num(1.)), - (2 as u16, I32F32::from_num(2.)), - ], - vec![ - (1 as u16, I32F32::from_num(10.)), - (2 as u16, I32F32::from_num(100.)), - ], - ]; - let mat = vec_to_sparse_mat_fixed(&vector, 2, false); - assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); - let vector: Vec = vec![0., 0.]; - let target: Vec> = vec![vec![], vec![]]; - let mat = vec_to_sparse_mat_fixed(&vector, 2, false); - assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); - let vector: Vec = vec![0., 1., 2., 0., 10., 100.]; - let target: Vec> = vec![ - vec![], - vec![ - (0 as u16, I32F32::from_num(1.)), - (1 as u16, I32F32::from_num(10.)), - ], - vec![ - (0 as u16, I32F32::from_num(2.)), - (1 as u16, I32F32::from_num(100.)), - ], - ]; - let mat = vec_to_sparse_mat_fixed(&vector, 2, true); - assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); - let vector: Vec = vec![0., 0.]; - let target: Vec> = vec![vec![]]; - let mat = vec_to_sparse_mat_fixed(&vector, 2, true); - assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_exp_safe() { - let zero: I32F32 = I32F32::from_num(0); - let one: I32F32 = I32F32::from_num(1); - let target: I32F32 = exp(zero).unwrap(); - assert_eq!(exp_safe(zero), target); - let target: I32F32 = exp(one).unwrap(); - assert_eq!(exp_safe(one), target); - let min_input: I32F32 = I32F32::from_num(-20); // <= 1/exp(-20) = 485 165 195,4097903 - let max_input: I32F32 = I32F32::from_num(20); // <= exp(20) = 485 165 195,4097903 - let target: I32F32 = exp(min_input).unwrap(); - assert_eq!(exp_safe(min_input), target); - assert_eq!(exp_safe(min_input - one), target); - assert_eq!(exp_safe(I32F32::min_value()), target); - let target: I32F32 = exp(max_input).unwrap(); - assert_eq!(exp_safe(max_input), target); - assert_eq!(exp_safe(max_input + one), target); - assert_eq!(exp_safe(I32F32::max_value()), target); - } - - #[test] - fn test_math_sigmoid_safe() { - let trust: Vec = vec![ - I32F32::min_value(), - I32F32::from_num(0), - I32F32::from_num(0.4), - I32F32::from_num(0.5), - I32F32::from_num(0.6), - I32F32::from_num(1), - I32F32::max_value(), - ]; - let consensus: Vec = trust - .iter() - .map(|t: &I32F32| sigmoid_safe(*t, I32F32::max_value(), I32F32::max_value())) - .collect(); - let target: Vec = fixed_vec![ - 0.0000000019, - 0.0000000019, - 0.0000000019, - 0.0000000019, - 0.0000000019, - 0.0000000019, - 0.5, - ]; - assert_eq!(&consensus, &target); - let consensus: Vec = trust - .iter() - .map(|t: &I32F32| sigmoid_safe(*t, I32F32::min_value(), I32F32::min_value())) - .collect(); - let target: Vec = fixed_vec![ - 0.5, - 0.0000000019, - 0.0000000019, - 0.0000000019, - 0.0000000019, - 0.0000000019, - 0.0000000019, - ]; - assert_eq!(&consensus, &target); - let consensus: Vec = trust - .iter() - .map(|t: &I32F32| sigmoid_safe(*t, I32F32::from_num(30), I32F32::from_num(0.5))) - .collect(); - let target: Vec = vec![ - 0.0000000019, - 0.0000003057, - 0.0474258729, - 0.5, - 0.952574127, - 0.9999996943, - 0.9999999981, - ]; - let target: Vec = target.iter().map(|c: &f64| I32F32::from_num(*c)).collect(); - assert_eq!(&consensus, &target); - let trust: Vec = fixed_vec![0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.]; - let consensus: Vec = trust - .iter() - .map(|t: &I32F32| sigmoid_safe(*t, I32F32::from_num(40), I32F32::from_num(0.5))) - .collect(); - let target: Vec = vec![ - 0.0000000019, - 0.0000001125, - 0.0000061442, - 0.0003353502, - 0.017986214, - 0.5, - 0.9820138067, - 0.9996646498, - 0.9999938558, - 0.9999998875, - 0.9999999981, - ]; - let target: Vec = target.iter().map(|c: &f64| I32F32::from_num(*c)).collect(); - assert_eq!(&consensus, &target); - } - - #[test] - fn test_math_is_topk() { - let vector: Vec = fixed_vec![]; - let result = is_topk(&vector, 5); - let target: Vec = vec![]; - assert_eq!(&result, &target); - let vector: Vec = fixed_vec![0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]; - let result = is_topk(&vector, 0); - let target: Vec = vec![ - false, false, false, false, false, false, false, false, false, false, - ]; - assert_eq!(&result, &target); - let result = is_topk(&vector, 5); - let target: Vec = vec![ - false, false, false, false, false, true, true, true, true, true, - ]; - assert_eq!(&result, &target); - let result = is_topk(&vector, 10); - let target: Vec = vec![true, true, true, true, true, true, true, true, true, true]; - assert_eq!(&result, &target); - let result = is_topk(&vector, 100); - assert_eq!(&result, &target); - let vector: Vec = fixed_vec![9., 8., 7., 6., 5., 4., 3., 2., 1., 0.]; - let result = is_topk(&vector, 5); - let target: Vec = vec![ - true, true, true, true, true, false, false, false, false, false, - ]; - assert_eq!(&result, &target); - let vector: Vec = fixed_vec![9., 0., 8., 1., 7., 2., 6., 3., 5., 4.]; - let result = is_topk(&vector, 5); - let target: Vec = vec![ - true, false, true, false, true, false, true, false, true, false, - ]; - assert_eq!(&result, &target); - let vector: Vec = fixed_vec![0.9, 0., 0.8, 0.1, 0.7, 0.2, 0.6, 0.3, 0.5, 0.4]; - let result = is_topk(&vector, 5); - let target: Vec = vec![ - true, false, true, false, true, false, true, false, true, false, - ]; - assert_eq!(&result, &target); - let vector: Vec = fixed_vec![0., 1., 2., 3., 4., 5., 5., 5., 5., 6.]; - let result = is_topk(&vector, 5); - let target: Vec = vec![ - false, false, false, false, false, true, true, true, true, true, - ]; - assert_eq!(&result, &target); - } - - #[test] - fn test_math_sum() { - assert!(fixed_vec![].iter().sum::() == I32F32::from_num(0)); - assert!(fixed_vec![1.0, 10.0, 30.0].iter().sum::() == I32F32::from_num(41)); - assert!(fixed_vec![-1.0, 10.0, 30.0].iter().sum::() == I32F32::from_num(39)); + fn test_math_vec_to_sparse_mat_fixed() { + let vector: Vec = vec![0., 1., 2., 0., 10., 100.]; + let target: Vec> = vec![ + vec![ + (1 as u16, I32F32::from_num(1.)), + (2 as u16, I32F32::from_num(2.)), + ], + vec![ + (1 as u16, I32F32::from_num(10.)), + (2 as u16, I32F32::from_num(100.)), + ], + ]; + let mat = vec_to_sparse_mat_fixed(&vector, 2, false); + assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); + let vector: Vec = vec![0., 0.]; + let target: Vec> = vec![vec![], vec![]]; + let mat = vec_to_sparse_mat_fixed(&vector, 2, false); + assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); + let vector: Vec = vec![0., 1., 2., 0., 10., 100.]; + let target: Vec> = vec![ + vec![], + vec![ + (0 as u16, I32F32::from_num(1.)), + (1 as u16, I32F32::from_num(10.)), + ], + vec![ + (0 as u16, I32F32::from_num(2.)), + (1 as u16, I32F32::from_num(100.)), + ], + ]; + let mat = vec_to_sparse_mat_fixed(&vector, 2, true); + assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); + let vector: Vec = vec![0., 0.]; + let target: Vec> = vec![vec![]]; + let mat = vec_to_sparse_mat_fixed(&vector, 2, true); + assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); } #[test] @@ -1268,75 +314,6 @@ mod tests { ); } - #[test] - fn test_math_inplace_normalize_64() { - let epsilon: I64F64 = I64F64::from_num(0.0001); - let mut x1: Vec = vec![ - I64F64::from_num(1.0), - I64F64::from_num(10.0), - I64F64::from_num(30.0), - ]; - inplace_normalize_64(&mut x1); - assert_vec_compare_64( - &x1, - &fixed_vec![0.0243902437, 0.243902439, 0.7317073171], - epsilon, - ); - let mut x2: Vec = vec![ - I64F64::from_num(-1.0), - I64F64::from_num(10.0), - I64F64::from_num(30.0), - ]; - inplace_normalize_64(&mut x2); - assert_vec_compare_64( - &x2, - &vec![ - I64F64::from_num(-0.0256410255), - I64F64::from_num(0.2564102563), - I64F64::from_num(0.769230769), - ], - epsilon, - ); - } - - #[test] - fn test_math_vecdiv() { - let x: Vec = fixed_vec![]; - let y: Vec = fixed_vec![]; - let result: Vec = fixed_vec![]; - assert_eq!(result, vecdiv(&x, &y)); - - let x: Vec = fixed_vec![0., 1., 0., 1.]; - let y: Vec = fixed_vec![0., 1., 1., 0.]; - let result: Vec = fixed_vec![0., 1., 0., 0.]; - assert_eq!(result, vecdiv(&x, &y)); - - let x: Vec = fixed_vec![1., 1., 10.]; - let y: Vec = fixed_vec![2., 3., 2.]; - let result: Vec = vec![ - I32F32::from_num(1.) / I32F32::from_num(2.), - I32F32::from_num(1.) / I32F32::from_num(3.), - I32F32::from_num(5.), - ]; - assert_eq!(result, vecdiv(&x, &y)); - } - - #[test] - fn test_math_inplace_row_normalize() { - let epsilon: I32F32 = I32F32::from_num(0.0001); - let vector: Vec = vec![ - 0., 1., 2., 3., 4., 0., 10., 100., 1000., 10000., 0., 0., 0., 0., 0., 1., 1., 1., 1., - 1., - ]; - let mut mat = vec_to_mat_fixed(&vector, 4, false); - inplace_row_normalize(&mut mat); - let target: Vec = vec![ - 0., 0.1, 0.2, 0.3, 0.4, 0., 0.0009, 0.009, 0.09, 0.9, 0., 0., 0., 0., 0., 0.2, 0.2, - 0.2, 0.2, 0.2, - ]; - assert_mat_compare(&mat, &vec_to_mat_fixed(&target, 4, false), epsilon); - } - #[test] fn test_math_inplace_row_normalize_sparse() { let epsilon: I32F32 = I32F32::from_num(0.0001); @@ -1364,210 +341,6 @@ mod tests { ); } - #[test] - fn test_math_inplace_col_normalize() { - let epsilon: I32F32 = I32F32::from_num(0.0001); - let vector: Vec = vec![ - 0., 1., 2., 3., 4., 0., 10., 100., 1000., 10000., 0., 0., 0., 0., 0., 1., 1., 1., 1., - 1., - ]; - let mut mat = vec_to_mat_fixed(&vector, 4, true); - inplace_col_normalize(&mut mat); - let target: Vec = vec![ - 0., 0.1, 0.2, 0.3, 0.4, 0., 0.0009, 0.009, 0.09, 0.9, 0., 0., 0., 0., 0., 0.2, 0.2, - 0.2, 0.2, 0.2, - ]; - assert_mat_compare(&mat, &vec_to_mat_fixed(&target, 4, true), epsilon); - } - - #[test] - fn test_math_inplace_col_normalize_sparse() { - let epsilon: I32F32 = I32F32::from_num(0.0001); - let vector: Vec = vec![ - 0., 1., 0., 2., 0., 3., 4., 0., 1., 0., 2., 0., 3., 0., 1., 0., 0., 2., 0., 3., 4., 0., - 10., 0., 100., 1000., 0., 10000., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 1., - 1., - ]; - let mut mat = vec_to_sparse_mat_fixed(&vector, 6, true); - inplace_col_normalize_sparse(&mut mat, 6); - let target: Vec = vec![ - 0., 0.1, 0., 0.2, 0., 0.3, 0.4, 0., 0.166666, 0., 0.333333, 0., 0.5, 0., 0.1, 0., 0., - 0.2, 0., 0.3, 0.4, 0., 0.0009, 0., 0.009, 0.09, 0., 0.9, 0., 0., 0., 0., 0., 0., 0., - 0.142857, 0.142857, 0.142857, 0.142857, 0.142857, 0.142857, 0.142857, - ]; - assert_sparse_mat_compare(&mat, &vec_to_sparse_mat_fixed(&target, 6, true), epsilon); - let vector: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mut mat = vec_to_sparse_mat_fixed(&vector, 3, false); - inplace_col_normalize_sparse(&mut mat, 6); - assert_sparse_mat_compare( - &mat, - &vec_to_sparse_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let mut mat: Vec> = vec![]; - let target: Vec> = vec![]; - inplace_col_normalize_sparse(&mut mat, 0); - assert_sparse_mat_compare(&mat, &target, epsilon); - } - - #[test] - fn test_math_inplace_mask_vector() { - let mask: Vec = vec![false, false, false]; - let mut vector: Vec = fixed_vec![0., 1., 2.]; - let target: Vec = fixed_vec![0., 1., 2.]; - inplace_mask_vector(&mask, &mut vector); - assert_vec_compare(&vector, &target, I32F32::from_num(0)); - let mask: Vec = vec![false, true, false]; - let mut vector: Vec = fixed_vec![0., 1., 2.]; - let target: Vec = fixed_vec![0., 0., 2.]; - inplace_mask_vector(&mask, &mut vector); - assert_vec_compare(&vector, &target, I32F32::from_num(0)); - let mask: Vec = vec![true, true, true]; - let mut vector: Vec = fixed_vec![0., 1., 2.]; - let target: Vec = fixed_vec![0., 0., 0.]; - inplace_mask_vector(&mask, &mut vector); - assert_vec_compare(&vector, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_inplace_mask_matrix() { - let mask: Vec> = vec![ - vec![false, false, false], - vec![false, false, false], - vec![false, false, false], - ]; - let vector: Vec = vec![0., 1., 2., 3., 4., 5., 6., 7., 8.]; - let mut mat = vec_to_mat_fixed(&vector, 3, false); - inplace_mask_matrix(&mask, &mut mat); - assert_mat_compare( - &mat, - &vec_to_mat_fixed(&vector, 3, false), - I32F32::from_num(0), - ); - let mask: Vec> = vec![ - vec![true, false, false], - vec![false, true, false], - vec![false, false, true], - ]; - let target: Vec = vec![0., 1., 2., 3., 0., 5., 6., 7., 0.]; - let mut mat = vec_to_mat_fixed(&vector, 3, false); - inplace_mask_matrix(&mask, &mut mat); - assert_mat_compare( - &mat, - &vec_to_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let mask: Vec> = vec![ - vec![true, true, true], - vec![true, true, true], - vec![true, true, true], - ]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mut mat = vec_to_mat_fixed(&vector, 3, false); - inplace_mask_matrix(&mask, &mut mat); - assert_mat_compare( - &mat, - &vec_to_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - } - - #[test] - fn test_math_inplace_mask_rows() { - let input: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]; - let mask: Vec = vec![false, false, false]; - let target: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]; - let mut mat = vec_to_mat_fixed(&input, 3, false); - inplace_mask_rows(&mask, &mut mat); - assert_mat_compare( - &mat, - &vec_to_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let mask: Vec = vec![true, true, true]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mut mat = vec_to_mat_fixed(&input, 3, false); - inplace_mask_rows(&mask, &mut mat); - assert_mat_compare( - &mat, - &vec_to_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let mask: Vec = vec![true, false, true]; - let target: Vec = vec![0., 0., 0., 4., 5., 6., 0., 0., 0.]; - let mut mat = vec_to_mat_fixed(&input, 3, false); - inplace_mask_rows(&mask, &mut mat); - assert_mat_compare( - &mat, - &vec_to_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let input: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mut mat = vec_to_mat_fixed(&input, 3, false); - let mask: Vec = vec![false, false, false]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - inplace_mask_rows(&mask, &mut mat); - assert_mat_compare( - &mat, - &vec_to_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - } - - #[test] - fn test_math_inplace_mask_diag() { - let vector: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]; - let target: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0.]; - let mut mat = vec_to_mat_fixed(&vector, 3, false); - inplace_mask_diag(&mut mat); - assert_mat_compare( - &mat, - &vec_to_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - } - - #[test] - fn test_math_mask_rows_sparse() { - let input: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]; - let mat = vec_to_sparse_mat_fixed(&input, 3, false); - let mask: Vec = vec![false, false, false]; - let target: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]; - let result = mask_rows_sparse(&mask, &mat); - assert_sparse_mat_compare( - &result, - &vec_to_sparse_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let mask: Vec = vec![true, true, true]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let result = mask_rows_sparse(&mask, &mat); - assert_sparse_mat_compare( - &result, - &vec_to_sparse_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let mask: Vec = vec![true, false, true]; - let target: Vec = vec![0., 0., 0., 4., 5., 6., 0., 0., 0.]; - let result = mask_rows_sparse(&mask, &mat); - assert_sparse_mat_compare( - &result, - &vec_to_sparse_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let input: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mat = vec_to_sparse_mat_fixed(&input, 3, false); - let mask: Vec = vec![false, false, false]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let result = mask_rows_sparse(&mask, &mat); - assert_sparse_mat_compare( - &result, - &vec_to_sparse_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - } - #[test] fn test_math_mask_diag_sparse() { let vector: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]; @@ -1598,934 +371,4 @@ mod tests { I32F32::from_num(0), ); } - - #[test] - fn test_math_vec_mask_sparse_matrix() { - let vector: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9.]; - let target: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0.]; - let mat = vec_to_sparse_mat_fixed(&vector, 3, false); - let first_vector: Vec = vec![1, 2, 3]; - let second_vector: Vec = vec![1, 2, 3]; - let result = vec_mask_sparse_matrix(&mat, &first_vector, &second_vector, &|a, b| a == b); - assert_sparse_mat_compare( - &result, - &vec_to_sparse_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let target: Vec = vec![1., 0., 0., 4., 5., 0., 7., 8., 9.]; - let mat = vec_to_sparse_mat_fixed(&vector, 3, false); - let first_vector: Vec = vec![1, 2, 3]; - let second_vector: Vec = vec![1, 2, 3]; - let result = vec_mask_sparse_matrix(&mat, &first_vector, &second_vector, &|a, b| a < b); - assert_sparse_mat_compare( - &result, - &vec_to_sparse_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - let vector: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mat = vec_to_sparse_mat_fixed(&vector, 3, false); - let first_vector: Vec = vec![1, 2, 3]; - let second_vector: Vec = vec![1, 2, 3]; - let result = vec_mask_sparse_matrix(&mat, &first_vector, &second_vector, &|a, b| a == b); - assert_sparse_mat_compare( - &result, - &vec_to_sparse_mat_fixed(&target, 3, false), - I32F32::from_num(0), - ); - } - - #[test] - fn test_math_row_hadamard() { - let vector: Vec = fixed_vec![1., 2., 3., 4.]; - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_mat_fixed(&matrix, 4, false); - let result = row_hadamard(&matrix, &vector); - let target: Vec = vec![1., 2., 3., 8., 10., 12., 21., 24., 27., 40., 44., 48.]; - let target = vec_to_mat_fixed(&target, 4, false); - assert_mat_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_row_hadamard_sparse() { - let vector: Vec = fixed_vec![1., 2., 3., 4.]; - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = row_hadamard_sparse(&matrix, &vector); - let target: Vec = vec![1., 2., 3., 8., 10., 12., 21., 24., 27., 40., 44., 48.]; - let target = vec_to_sparse_mat_fixed(&target, 4, false); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = row_hadamard_sparse(&matrix, &vector); - let target: Vec = vec![0., 2., 3., 8., 0., 12., 21., 24., 0., 40., 44., 48.]; - let target = vec_to_sparse_mat_fixed(&target, 4, false); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = row_hadamard_sparse(&matrix, &vector); - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let target = vec_to_sparse_mat_fixed(&target, 4, false); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_row_sum() { - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_mat_fixed(&matrix, 4, false); - let result = row_sum(&matrix); - let target: Vec = fixed_vec![6., 15., 24., 33.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_row_sum_sparse() { - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = row_sum_sparse(&matrix); - let target: Vec = fixed_vec![6., 15., 24., 33.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = row_sum_sparse(&matrix); - let target: Vec = fixed_vec![5., 10., 15., 33.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![1., 2., 3., 0., 0., 0., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = row_sum_sparse(&matrix); - let target: Vec = fixed_vec![6., 0., 24., 33.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = row_sum_sparse(&matrix); - let target: Vec = fixed_vec![0., 0., 0., 0.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_col_sum() { - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_mat_fixed(&matrix, 4, false); - let result = col_sum(&matrix); - let target: Vec = fixed_vec![22., 26., 30.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_col_sum_sparse() { - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = col_sum_sparse(&matrix, 3); - let target: Vec = fixed_vec![22., 26., 30.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = col_sum_sparse(&matrix, 3); - let target: Vec = fixed_vec![21., 21., 21.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![1., 0., 3., 4., 0., 6., 7., 0., 9., 10., 0., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = col_sum_sparse(&matrix, 3); - let target: Vec = fixed_vec![22., 0., 30.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = col_sum_sparse(&matrix, 3); - let target: Vec = fixed_vec![0., 0., 0.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_matmul() { - let vector: Vec = fixed_vec![1., 2., 3., 4.]; - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_mat_fixed(&matrix, 4, false); - let result = matmul(&matrix, &vector); - let target: Vec = fixed_vec![70., 80., 90.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_matmul_transpose() { - let vector: Vec = fixed_vec![1., 2., 3.]; - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_mat_fixed(&matrix, 4, false); - let result = matmul_transpose(&matrix, &vector); - let target: Vec = fixed_vec![14., 32., 50., 68.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_sparse_matmul() { - let vector: Vec = fixed_vec![1., 2., 3., 4.]; - let matrix: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = matmul_sparse(&matrix, &vector, 3); - let target: Vec = fixed_vec![70., 80., 90.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = matmul_sparse(&matrix, &vector, 3); - let target: Vec = fixed_vec![69., 70., 63.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let result = matmul_sparse(&matrix, &vector, 3); - let target: Vec = fixed_vec![0., 0., 0.]; - assert_vec_compare(&result, &target, I32F32::from_num(0)); - } - - // #[test] - // fn test_math_sparse_matmul_transpose() { - // let vector:Vec = vec_to_fixed( &vec![ 1., 2., 3.] ); - // let matrix:Vec = vec![ 1., 2., 3., - // 4., 5., 6., - // 7., 8., 9., - // 10., 11., 12.]; - // let matrix = vec_to_sparse_mat_fixed(&matrix, 3, false); - // let result = matmul_transpose_sparse(&matrix, &vector); - // let target: Vec = vec_to_fixed( &vec![ 14., 32., 50., 68. ] ); - // assert_vec_compare(&result, &target, I32F32::from_num( 0 )); - // let matrix:Vec = vec![ 0., 2., 3., - // 4., 0., 6., - // 7., 8., 0., - // 10., 11., 12.]; - // let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - // let result = matmul_transpose_sparse(&matrix, &vector); - // let target: Vec = vec_to_fixed( &vec![ 13., 22., 23., 68. ] ); - // assert_vec_compare(&result, &target, I32F32::from_num( 0 )); - // let matrix:Vec = vec![ 0., 0., 0., - // 0., 0., 0., - // 0., 0., 0., - // 0., 0., 0.]; - // let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - // let result = matmul_transpose_sparse(&matrix, &vector); - // let target: Vec = vec_to_fixed( &vec![ 0., 0., 0., 0. ] ); - // assert_vec_compare(&result, &target, I32F32::from_num( 0 )); - // } - - #[test] - fn test_math_inplace_col_clip() { - let vector: Vec = fixed_vec![0., 5., 12.]; - let matrix: Vec = vec![0., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let mut matrix = vec_to_mat_fixed(&matrix, 4, false); - let target: Vec = vec![0., 2., 3., 0., 5., 6., 0., 5., 9., 0., 5., 12.]; - let target = vec_to_mat_fixed(&target, 4, false); - inplace_col_clip(&mut matrix, &vector); - assert_mat_compare(&matrix, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_col_clip_sparse() { - let vector: Vec = fixed_vec![0., 5., 12.]; - let matrix: Vec = vec![0., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let target: Vec = vec![0., 2., 3., 0., 5., 6., 0., 5., 9., 0., 5., 12.]; - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = col_clip_sparse(&matrix, &vector); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 2., 3., 4., 5., 6., 0., 0., 0., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let target: Vec = vec![0., 2., 3., 0., 5., 6., 0., 0., 0., 0., 5., 12.]; - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = col_clip_sparse(&matrix, &vector); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0)); - let matrix: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = col_clip_sparse(&matrix, &vector); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_clip_sparse() { - let matrix: Vec = vec![0., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_sparse_mat_fixed(&matrix, 4, false); - let target: Vec = vec![0., 1., 1., 1., 1., 1., 1., 100., 100., 100., 100., 100.]; - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = clip_sparse( - &matrix, - I32F32::from_num(8), - I32F32::from_num(100), - I32F32::from_num(1), - ); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_clip() { - let matrix: Vec = vec![0., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let matrix = vec_to_mat_fixed(&matrix, 4, false); - let target: Vec = vec![1., 1., 1., 1., 1., 1., 1., 100., 100., 100., 100., 100.]; - let target = vec_to_mat_fixed(&target, 4, false); - let result = clip( - &matrix, - I32F32::from_num(8), - I32F32::from_num(100), - I32F32::from_num(1), - ); - assert_mat_compare(&result, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_inplace_clip() { - let matrix: Vec = vec![0., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let mut matrix = vec_to_mat_fixed(&matrix, 4, false); - let target: Vec = vec![1., 1., 1., 1., 1., 1., 1., 100., 100., 100., 100., 100.]; - let target = vec_to_mat_fixed(&target, 4, false); - inplace_clip( - &mut matrix, - I32F32::from_num(8), - I32F32::from_num(100), - I32F32::from_num(1), - ); - assert_mat_compare(&matrix, &target, I32F32::from_num(0)); - } - - #[test] - fn test_math_weighted_median() { - let mut rng = thread_rng(); - let zero: I32F32 = I32F32::from_num(0.); - let one: I32F32 = I32F32::from_num(1.); - for _ in 0..100 { - let stake: Vec = fixed_vec![]; - let score: Vec = fixed_vec![]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - zero, - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = normalize(&fixed_vec![0.51]); - let score: Vec = fixed_vec![1.]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - one, - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.49, 0.51]; - let score: Vec = fixed_vec![0.5, 1.]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - one, - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.51, 0.49]; - let score: Vec = fixed_vec![0.5, 1.]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - I32F32::from_num(0.5), - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.49, 0., 0.51]; - let score: Vec = fixed_vec![0.5, 0.7, 1.]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - one, - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.49, 0.01, 0.5]; - let score: Vec = fixed_vec![0.5, 0.7, 1.]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - I32F32::from_num(0.7), - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.49, 0.51, 0.0]; - let score: Vec = fixed_vec![0.5, 0.7, 1.]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - I32F32::from_num(0.7), - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.0, 0.49, 0.51]; - let score: Vec = fixed_vec![0.5, 0.7, 1.]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - one, - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.0, 0.49, 0.0, 0.51]; - let score: Vec = fixed_vec![0.5, 0.5, 1., 1.]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - one, - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.0, 0.49, 0.0, 0.51, 0.0]; - let score: Vec = fixed_vec![0.5, 0.5, 1., 1., 0.5]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - one, - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.2, 0.2, 0.2, 0.2, 0.2]; - let score: Vec = fixed_vec![0.8, 0.2, 1., 0.6, 0.4]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - I32F32::from_num(0.6), - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let stake: Vec = fixed_vec![0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]; - let score: Vec = fixed_vec![0.8, 0.8, 0.2, 0.2, 1.0, 1.0, 0.6, 0.6, 0.4, 0.4]; - let majority: I32F32 = I32F32::from_num(0.51); - assert_eq!( - I32F32::from_num(0.6), - weighted_median( - &stake, - &score, - &(0..stake.len()).collect(), - one - majority, - zero, - stake.iter().sum() - ) - ); - - let n: usize = 100; - for majority in fixed_vec![ - 0., - 0.0000001, - 0.25, - 0.48999999999999, - 0.49, - 0.49000000000001, - 0.5, - 0.509999999999, - 0.51, - 0.5100000000001, - 0.9999999, - 1., - ] { - for allow_equal in [false, true] { - let mut stake: Vec = vec![]; - let mut score: Vec = vec![]; - let mut last_score: I32F32 = zero; - for i in 0..n { - if allow_equal { - stake.push(if rng.gen_range(0..2) == 1 { one } else { zero }); - if rng.gen_range(0..2) == 1 { - last_score += one; - } - score.push(last_score); - } else { - stake.push(one); - score.push(I32F32::from_num(i)); - } - } - inplace_normalize(&mut stake); - let total_stake: I32F32 = stake.iter().sum(); - let mut minority: I32F32 = total_stake - majority; - if minority < zero { - minority = zero; - } - let mut medians: Vec = vec![]; - let mut median_stake: I32F32 = zero; - let mut median_set = false; - let mut stake_sum: I32F32 = zero; - for i in 0..n { - stake_sum += stake[i]; - if !median_set && stake_sum >= minority { - median_stake = stake_sum; - median_set = true; - } - if median_set { - if median_stake < stake_sum { - if median_stake == minority && !medians.contains(&score[i]) { - medians.push(score[i]); - } - break; - } - if !medians.contains(&score[i]) { - medians.push(score[i]); - } - } - } - if medians.len() == 0 { - medians.push(zero); - } - let stake_idx: Vec = (0..stake.len()).collect(); - let result: I32F32 = - weighted_median(&stake, &score, &stake_idx, minority, zero, total_stake); - assert!(medians.contains(&result)); - for _ in 0..10 { - let mut permuted_uids: Vec = (0..n).collect(); - permuted_uids.shuffle(&mut thread_rng()); - stake = permuted_uids.iter().map(|&i| stake[i]).collect(); - score = permuted_uids.iter().map(|&i| score[i]).collect(); - let result: I32F32 = weighted_median( - &stake, - &score, - &stake_idx, - minority, - zero, - total_stake, - ); - assert!(medians.contains(&result)); - } - } - } - } - } - - #[test] - fn test_math_weighted_median_col() { - let stake: Vec = fixed_vec![]; - let weights: Vec> = vec![vec![]]; - let median: Vec = fixed_vec![]; - assert_eq!( - median, - weighted_median_col(&stake, &weights, I32F32::from_num(0.5)) - ); - - let stake: Vec = fixed_vec![0., 0.]; - let weights: Vec = vec![0., 0., 0., 0.]; - let weights: Vec> = vec_to_mat_fixed(&weights, 2, false); - let median: Vec = fixed_vec![0., 0.]; - assert_eq!( - median, - weighted_median_col(&stake, &weights, I32F32::from_num(0.5)) - ); - - let stake: Vec = fixed_vec![0., 0.75, 0.25, 0.]; - let weights: Vec = vec![0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0.4, 0.5]; - let weights: Vec> = vec_to_mat_fixed(&weights, 4, false); - let median: Vec = fixed_vec![0., 0.3, 0.4]; - assert_eq!( - median, - weighted_median_col(&stake, &weights, I32F32::from_num(0.24)) - ); - let median: Vec = fixed_vec![0., 0.2, 0.4]; - assert_eq!( - median, - weighted_median_col(&stake, &weights, I32F32::from_num(0.26)) - ); - let median: Vec = fixed_vec![0., 0.2, 0.1]; - assert_eq!( - median, - weighted_median_col(&stake, &weights, I32F32::from_num(0.76)) - ); - - let stake: Vec = fixed_vec![0., 0.3, 0.2, 0.5]; - let weights: Vec = vec![0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0., 0.5]; - let weights: Vec> = vec_to_mat_fixed(&weights, 4, false); - let median: Vec = fixed_vec![0., 0., 0.4]; - assert_eq!( - median, - weighted_median_col(&stake, &weights, I32F32::from_num(0.51)) - ); - } - - #[test] - fn test_math_weighted_median_col_sparse() { - let stake: Vec = fixed_vec![]; - let weights: Vec> = vec![vec![]]; - let median: Vec = fixed_vec![]; - assert_eq!( - median, - weighted_median_col_sparse(&stake, &weights, 0, I32F32::from_num(0.5)) - ); - - let stake: Vec = fixed_vec![0., 0.]; - let weights: Vec = vec![0., 0., 0., 0.]; - let weights: Vec> = vec_to_sparse_mat_fixed(&weights, 2, false); - let median: Vec = fixed_vec![0., 0.]; - assert_eq!( - median, - weighted_median_col_sparse(&stake, &weights, 2, I32F32::from_num(0.5)) - ); - - let stake: Vec = fixed_vec![0., 0.75, 0.25, 0.]; - let weights: Vec = vec![0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0.4, 0.5]; - let weights: Vec> = vec_to_sparse_mat_fixed(&weights, 4, false); - let median: Vec = fixed_vec![0., 0.3, 0.4]; - assert_eq!( - median, - weighted_median_col_sparse(&stake, &weights, 3, I32F32::from_num(0.24)) - ); - let median: Vec = fixed_vec![0., 0.2, 0.4]; - assert_eq!( - median, - weighted_median_col_sparse(&stake, &weights, 3, I32F32::from_num(0.26)) - ); - let median: Vec = fixed_vec![0., 0.2, 0.1]; - assert_eq!( - median, - weighted_median_col_sparse(&stake, &weights, 3, I32F32::from_num(0.76)) - ); - - let stake: Vec = fixed_vec![0., 0.3, 0.2, 0.5]; - let weights: Vec = vec![0., 0.1, 0., 0., 0.2, 0.4, 0., 0.3, 0.1, 0., 0., 0.5]; - let weights: Vec> = vec_to_sparse_mat_fixed(&weights, 4, false); - let median: Vec = fixed_vec![0., 0., 0.4]; - assert_eq!( - median, - weighted_median_col_sparse(&stake, &weights, 3, I32F32::from_num(0.51)) - ); - } - - #[test] - fn test_math_hadamard() { - let mat2: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let mat1: Vec = vec![ - 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110., 120., - ]; - let target: Vec = vec![ - 10., 40., 90., 160., 250., 360., 490., 640., 810., 1000., 1210., 1440., - ]; - let mat2 = vec_to_mat_fixed(&mat2, 4, false); - let mat1 = vec_to_mat_fixed(&mat1, 4, false); - let target = vec_to_mat_fixed(&target, 4, false); - let result = hadamard(&mat1, &mat2); - assert_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let mat2: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mat1: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mat2 = vec_to_mat_fixed(&mat2, 4, false); - let mat1 = vec_to_mat_fixed(&mat1, 4, false); - let target = vec_to_mat_fixed(&target, 4, false); - let result = hadamard(&mat1, &mat2); - assert_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let mat2: Vec = vec![1., 0., 0., 0., 2., 0., 0., 0., 3., 0., 0., 0.]; - let mat1: Vec = vec![0., 0., 4., 0., 5., 0., 6., 0., 0., 0., 0., 0.]; - let target: Vec = vec![0., 0., 0., 0., 10., 0., 0., 0., 0., 0., 0., 0.]; - let mat2 = vec_to_mat_fixed(&mat2, 4, false); - let mat1 = vec_to_mat_fixed(&mat1, 4, false); - let target = vec_to_mat_fixed(&target, 4, false); - let result = hadamard(&mat1, &mat2); - assert_mat_compare(&result, &target, I32F32::from_num(0.000001)); - } - - #[test] - fn test_math_hadamard_sparse() { - let mat2: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let mat1: Vec = vec![ - 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110., 120., - ]; - let target: Vec = vec![ - 10., 40., 90., 160., 250., 360., 490., 640., 810., 1000., 1210., 1440., - ]; - let mat2 = vec_to_sparse_mat_fixed(&mat2, 4, false); - let mat1 = vec_to_sparse_mat_fixed(&mat1, 4, false); - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = hadamard_sparse(&mat1, &mat2, 3); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let mat2: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mat1: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let mat2 = vec_to_sparse_mat_fixed(&mat2, 4, false); - let mat1 = vec_to_sparse_mat_fixed(&mat1, 4, false); - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = hadamard_sparse(&mat1, &mat2, 3); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let mat2: Vec = vec![1., 0., 0., 0., 2., 0., 0., 0., 3., 0., 0., 0.]; - let mat1: Vec = vec![0., 0., 4., 0., 5., 0., 6., 0., 0., 0., 0., 0.]; - let target: Vec = vec![0., 0., 0., 0., 10., 0., 0., 0., 0., 0., 0., 0.]; - let mat2 = vec_to_sparse_mat_fixed(&mat2, 4, false); - let mat1 = vec_to_sparse_mat_fixed(&mat1, 4, false); - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = hadamard_sparse(&mat1, &mat2, 3); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0.000001)); - } - - #[test] - fn test_math_mat_ema() { - let old: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let new: Vec = vec![ - 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110., 120., - ]; - let target: Vec = vec![ - 1.9, 3.8, 5.7, 7.6, 9.5, 11.4, 13.3, 15.2, 17.1, 19., 20.9, 22.8, - ]; - let old = vec_to_mat_fixed(&old, 4, false); - let new = vec_to_mat_fixed(&new, 4, false); - let target = vec_to_mat_fixed(&target, 4, false); - let result = mat_ema(&new, &old, I32F32::from_num(0.1)); - assert_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let old: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let new: Vec = vec![ - 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110., 120., - ]; - let target: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let old = vec_to_mat_fixed(&old, 4, false); - let new = vec_to_mat_fixed(&new, 4, false); - let target = vec_to_mat_fixed(&target, 4, false); - let result = mat_ema(&new, &old, I32F32::from_num(0)); - assert_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let old: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let new: Vec = vec![ - 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110., 120., - ]; - let target: Vec = vec![ - 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110., 120., - ]; - let old = vec_to_mat_fixed(&old, 4, false); - let new = vec_to_mat_fixed(&new, 4, false); - let target = vec_to_mat_fixed(&target, 4, false); - let result = mat_ema(&new, &old, I32F32::from_num(1)); - assert_mat_compare(&result, &target, I32F32::from_num(0.000001)); - } - - #[test] - fn test_math_sparse_mat_ema() { - let old: Vec = vec![1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; - let new: Vec = vec![ - 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 110., 120., - ]; - let target: Vec = vec![ - 1.9, 3.8, 5.7, 7.6, 9.5, 11.4, 13.3, 15.2, 17.1, 19., 20.9, 22.8, - ]; - let old = vec_to_sparse_mat_fixed(&old, 4, false); - let new = vec_to_sparse_mat_fixed(&new, 4, false); - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = mat_ema_sparse(&new, &old, I32F32::from_num(0.1)); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let old: Vec = vec![0., 2., 3., 4., 0., 6., 7., 8., 0., 10., 11., 12.]; - let new: Vec = vec![10., 20., 0., 40., 0., 60., 0., 80., 90., 100., 110., 120.]; - let target: Vec = vec![1., 3.8, 2.7, 7.6, 0., 11.4, 6.3, 15.2, 9., 19., 20.9, 22.8]; - let old = vec_to_sparse_mat_fixed(&old, 4, false); - let new = vec_to_sparse_mat_fixed(&new, 4, false); - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = mat_ema_sparse(&new, &old, I32F32::from_num(0.1)); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let old: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let new: Vec = vec![10., 20., 0., 40., 0., 60., 0., 80., 90., 100., 110., 120.]; - let target: Vec = vec![1., 2., 0., 4., 0., 6., 0., 8., 9., 10., 11., 12.]; - let old = vec_to_sparse_mat_fixed(&old, 4, false); - let new = vec_to_sparse_mat_fixed(&new, 4, false); - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = mat_ema_sparse(&new, &old, I32F32::from_num(0.1)); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let old: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let new: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let target: Vec = vec![0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let old = vec_to_sparse_mat_fixed(&old, 4, false); - let new = vec_to_sparse_mat_fixed(&new, 4, false); - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = mat_ema_sparse(&new, &old, I32F32::from_num(0.1)); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0.000001)); - let old: Vec = vec![1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; - let new: Vec = vec![0., 0., 0., 0., 2., 0., 0., 0., 0., 0., 0., 0.]; - let target: Vec = vec![0.9, 0., 0., 0., 0.2, 0., 0., 0., 0., 0., 0., 0.]; - let old = vec_to_sparse_mat_fixed(&old, 4, false); - let new = vec_to_sparse_mat_fixed(&new, 4, false); - let target = vec_to_sparse_mat_fixed(&target, 4, false); - let result = mat_ema_sparse(&new, &old, I32F32::from_num(0.1)); - assert_sparse_mat_compare(&result, &target, I32F32::from_num(0.000001)); - } - - #[test] - fn test_math_matmul2() { - let epsilon: I32F32 = I32F32::from_num(0.0001); - let w: Vec> = vec![vec![I32F32::from_num(1.0); 3]; 3]; - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(1.0); 3]), - &vec![ - I32F32::from_num(3), - I32F32::from_num(3), - I32F32::from_num(3), - ], - epsilon, - ); - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(2.0); 3]), - &vec![ - I32F32::from_num(6), - I32F32::from_num(6), - I32F32::from_num(6), - ], - epsilon, - ); - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(3.0); 3]), - &vec![ - I32F32::from_num(9), - I32F32::from_num(9), - I32F32::from_num(9), - ], - epsilon, - ); - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(-1.0); 3]), - &vec![ - I32F32::from_num(-3), - I32F32::from_num(-3), - I32F32::from_num(-3), - ], - epsilon, - ); - let w: Vec> = vec![vec![I32F32::from_num(-1.0); 3]; 3]; - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(1.0); 3]), - &vec![ - I32F32::from_num(-3), - I32F32::from_num(-3), - I32F32::from_num(-3), - ], - epsilon, - ); - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(2.0); 3]), - &vec![ - I32F32::from_num(-6), - I32F32::from_num(-6), - I32F32::from_num(-6), - ], - epsilon, - ); - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(3.0); 3]), - &vec![ - I32F32::from_num(-9), - I32F32::from_num(-9), - I32F32::from_num(-9), - ], - epsilon, - ); - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(-1.0); 3]), - &vec![ - I32F32::from_num(3), - I32F32::from_num(3), - I32F32::from_num(3), - ], - epsilon, - ); - let w: Vec> = vec![ - vec![I32F32::from_num(1.0); 3], - vec![I32F32::from_num(2.0); 3], - vec![I32F32::from_num(3.0); 3], - ]; - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(0.0); 3]), - &vec![ - I32F32::from_num(0.0), - I32F32::from_num(0.0), - I32F32::from_num(0.0), - ], - epsilon, - ); - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(2.0); 3]), - &vec![ - I32F32::from_num(12), - I32F32::from_num(12), - I32F32::from_num(12), - ], - epsilon, - ); - let w: Vec> = vec![ - vec![ - I32F32::from_num(1), - I32F32::from_num(2), - I32F32::from_num(3) - ]; - 3 - ]; - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(0.0); 3]), - &vec![ - I32F32::from_num(0.0), - I32F32::from_num(0.0), - I32F32::from_num(0.0), - ], - epsilon, - ); - assert_vec_compare( - &matmul(&w, &vec![I32F32::from_num(2.0); 3]), - &vec![ - I32F32::from_num(6), - I32F32::from_num(12), - I32F32::from_num(18), - ], - epsilon, - ); - } } From a1209b4fac46b0216966d0f7464b77e59756bf6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Fri, 1 Mar 2024 13:39:24 -0300 Subject: [PATCH 05/11] refac: fix clippy warnings --- pallets/subspace/src/math.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index 57228b2f2..bb2da3d42 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -2,18 +2,18 @@ use sp_std::{vec, vec::Vec}; use substrate_fixed::types::I32F32; // Return true when vector sum is zero. -pub fn is_zero(vector: &Vec) -> bool { +pub fn is_zero(vector: &[I32F32]) -> bool { vector.iter().sum::() == I32F32::from_num(0) } // Normalizes (sum to 1 except 0) the input vector directly in-place. -pub fn inplace_normalize(x: &mut Vec) { +pub fn inplace_normalize(x: &mut [I32F32]) { let x_sum: I32F32 = x.iter().sum(); if x_sum == I32F32::from_num(0.0) { return; } - for i in 0..x.len() { - x[i] = x[i] / x_sum; + for i in x.iter_mut() { + *i /= x_sum; } } @@ -26,7 +26,7 @@ pub fn fixed_proportion_to_u16(x: I32F32) -> u16 { } // Return a new sparse matrix with a masked out diagonal of input sparse matrix. -pub fn mask_diag_sparse(sparse_matrix: &Vec>) -> Vec> { +pub fn mask_diag_sparse(sparse_matrix: &[Vec<(u16, I32F32)>]) -> Vec> { let n: usize = sparse_matrix.len(); let mut result: Vec> = vec![vec![]; n]; for (i, sparse_row) in sparse_matrix.iter().enumerate() { @@ -40,7 +40,7 @@ pub fn mask_diag_sparse(sparse_matrix: &Vec>) -> Vec>) { +pub fn inplace_row_normalize_sparse(sparse_matrix: &mut [Vec<(u16, I32F32)>]) { for sparse_row in sparse_matrix.iter_mut() { let row_sum: I32F32 = sparse_row.iter().map(|(_j, value)| *value).sum(); if row_sum > I32F32::from_num(0.0) { @@ -52,11 +52,7 @@ pub fn inplace_row_normalize_sparse(sparse_matrix: &mut Vec>) #[cfg(test)] mod tests { use crate::math::*; - use rand::{seq::SliceRandom, thread_rng, Rng}; - use substrate_fixed::{ - transcendental::exp, - types::{I32F32, I64F64, I96F32}, - }; + use substrate_fixed::types::{I32F32, I64F64, I96F32}; macro_rules! fixed_vec { () => { From 65c274862a76e0266a59ad5d1b4ca69fe0597f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Fri, 1 Mar 2024 13:40:02 -0300 Subject: [PATCH 06/11] test: fix test --- pallets/subspace/src/math.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index bb2da3d42..a4f58943d 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -59,7 +59,7 @@ mod tests { vec![] }; ($($x:expr),+ $(,)?) => { - vec![$($x.into()),+] + vec![$(I32F32::from_num($x)),+] }; } From b875c0a99e7f0d13990e669ff38a027e7cfd9b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Fri, 1 Mar 2024 13:44:38 -0300 Subject: [PATCH 07/11] refac: fix test warnings --- pallets/subspace/src/math.rs | 83 ++++++++++++++---------------------- 1 file changed, 31 insertions(+), 52 deletions(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index a4f58943d..8da95dfcd 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -65,7 +65,7 @@ mod tests { /// Reshape vector to sparse matrix with specified number of input rows, cast f32 to I32F32. fn vec_to_sparse_mat_fixed( - vector: &Vec, + vector: &[f32], rows: usize, transpose: bool, ) -> Vec> { @@ -77,9 +77,9 @@ mod tests { let cols: usize = vector.len() / rows; let mut mat: Vec> = vec![]; if transpose { - for col in 0..cols as usize { + for col in 0..cols { let mut row_vec: Vec<(u16, I32F32)> = vec![]; - for row in 0..rows as usize { + for row in 0..rows { if vector[row * cols + col] > 0. { row_vec.push((row as u16, I32F32::from_num(vector[row * cols + col]))); } @@ -87,9 +87,9 @@ mod tests { mat.push(row_vec); } } else { - for row in 0..rows as usize { + for row in 0..rows { let mut row_vec: Vec<(u16, I32F32)> = vec![]; - for col in 0..cols as usize { + for col in 0..cols { if vector[row * cols + col] > 0. { row_vec.push((col as u16, I32F32::from_num(vector[row * cols + col]))); } @@ -101,10 +101,10 @@ mod tests { } /// Returns a normalized (sum to 1 except 0) copy of the input vector. - fn normalize(x: &Vec) -> Vec { + fn normalize(x: &[I32F32]) -> Vec { let x_sum: I32F32 = x.iter().sum(); - if x_sum == I32F32::from_num(0.0 as f32) { - x.clone() + if x_sum == I32F32::from_num(0.0) { + x.into() } else { x.iter().map(|xi| xi / x_sum).collect() } @@ -114,37 +114,16 @@ mod tests { assert!(I32F32::abs(a - b) <= epsilon, "a({:?}) != b({:?})", a, b); } - fn assert_float_compare_64(a: I64F64, b: I64F64, epsilon: I64F64) { - assert!(I64F64::abs(a - b) <= epsilon, "a({:?}) != b({:?})", a, b); - } - - fn assert_vec_compare(va: &Vec, vb: &Vec, epsilon: I32F32) { + fn assert_vec_compare(va: &[I32F32], vb: &[I32F32], epsilon: I32F32) { assert!(va.len() == vb.len()); for i in 0..va.len() { assert_float_compare(va[i], vb[i], epsilon); } } - fn assert_vec_compare_64(va: &Vec, vb: &Vec, epsilon: I64F64) { - assert!(va.len() == vb.len()); - for i in 0..va.len() { - assert_float_compare_64(va[i], vb[i], epsilon); - } - } - - fn assert_mat_compare(ma: &Vec>, mb: &Vec>, epsilon: I32F32) { - assert!(ma.len() == mb.len()); - for row in 0..ma.len() { - assert!(ma[row].len() == mb[row].len()); - for col in 0..ma[row].len() { - assert_float_compare(ma[row][col], mb[row][col], epsilon) - } - } - } - fn assert_sparse_mat_compare( - ma: &Vec>, - mb: &Vec>, + ma: &[Vec<(u16, I32F32)>], + mb: &[Vec<(u16, I32F32)>], epsilon: I32F32, ) { assert!(ma.len() == mb.len()); @@ -228,14 +207,8 @@ mod tests { fn test_math_vec_to_sparse_mat_fixed() { let vector: Vec = vec![0., 1., 2., 0., 10., 100.]; let target: Vec> = vec![ - vec![ - (1 as u16, I32F32::from_num(1.)), - (2 as u16, I32F32::from_num(2.)), - ], - vec![ - (1 as u16, I32F32::from_num(10.)), - (2 as u16, I32F32::from_num(100.)), - ], + vec![(1, I32F32::from_num(1.)), (2, I32F32::from_num(2.))], + vec![(1, I32F32::from_num(10.)), (2, I32F32::from_num(100.))], ]; let mat = vec_to_sparse_mat_fixed(&vector, 2, false); assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); @@ -246,14 +219,8 @@ mod tests { let vector: Vec = vec![0., 1., 2., 0., 10., 100.]; let target: Vec> = vec![ vec![], - vec![ - (0 as u16, I32F32::from_num(1.)), - (1 as u16, I32F32::from_num(10.)), - ], - vec![ - (0 as u16, I32F32::from_num(2.)), - (1 as u16, I32F32::from_num(100.)), - ], + vec![(0, I32F32::from_num(1.)), (1, I32F32::from_num(10.))], + vec![(0, I32F32::from_num(2.)), (1, I32F32::from_num(100.))], ]; let mat = vec_to_sparse_mat_fixed(&vector, 2, true); assert_sparse_mat_compare(&mat, &target, I32F32::from_num(0)); @@ -273,7 +240,11 @@ mod tests { let y: Vec = normalize(&x); assert_vec_compare( &y, - &fixed_vec![0.0243902437, 0.243902439, 0.7317073171,], + &[ + I32F32::from_num(0.0243902437), + I32F32::from_num(0.243902439), + I32F32::from_num(0.7317073171), + ], epsilon, ); assert_float_compare(y.iter().sum(), I32F32::from_num(1.0), epsilon); @@ -281,7 +252,11 @@ mod tests { let y: Vec = normalize(&x); assert_vec_compare( &y, - &fixed_vec![-0.0256410255, 0.2564102563, 0.769230769], + &[ + I32F32::from_num(-0.0256410255), + I32F32::from_num(0.2564102563), + I32F32::from_num(0.769230769), + ], epsilon, ); assert_float_compare(y.iter().sum(), I32F32::from_num(1.0), epsilon); @@ -294,14 +269,18 @@ mod tests { inplace_normalize(&mut x1); assert_vec_compare( &x1, - &fixed_vec![0.0243902437, 0.243902439, 0.7317073171], + &[ + I32F32::from_num(0.0243902437), + I32F32::from_num(0.243902439), + I32F32::from_num(0.7317073171), + ], epsilon, ); let mut x2: Vec = fixed_vec![-1.0, 10.0, 30.0,]; inplace_normalize(&mut x2); assert_vec_compare( &x2, - &vec![ + &[ I32F32::from_num(-0.0256410255), I32F32::from_num(0.2564102563), I32F32::from_num(0.769230769), From e465c9a710b147a1dd2c2fdac810f176d88fce4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Fri, 1 Mar 2024 13:45:29 -0300 Subject: [PATCH 08/11] refac: use zip instead of 2 loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Luiz Carvalho Signed-off-by: Gabrielle Guimarães de Oliveira --- pallets/subspace/src/math.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index 8da95dfcd..39ebd5460 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -116,7 +116,7 @@ mod tests { fn assert_vec_compare(va: &[I32F32], vb: &[I32F32], epsilon: I32F32) { assert!(va.len() == vb.len()); - for i in 0..va.len() { + for (a, b) in va.iter().zip(vb.iter()) { assert_float_compare(va[i], vb[i], epsilon); } } From 5e0a24dacfde6e4185061689a566a28efb088920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Fri, 1 Mar 2024 14:10:57 -0300 Subject: [PATCH 09/11] fix: fix compilation --- pallets/subspace/src/math.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index 39ebd5460..73c631552 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -117,7 +117,7 @@ mod tests { fn assert_vec_compare(va: &[I32F32], vb: &[I32F32], epsilon: I32F32) { assert!(va.len() == vb.len()); for (a, b) in va.iter().zip(vb.iter()) { - assert_float_compare(va[i], vb[i], epsilon); + assert_float_compare(*a, *b, epsilon); } } From 891cf26e4135652e74299d5ddc493bd6f6ea90fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Fri, 1 Mar 2024 14:24:37 -0300 Subject: [PATCH 10/11] refac: use to_vec() instead of into() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Luiz Carvalho Signed-off-by: Gabrielle Guimarães de Oliveira --- pallets/subspace/src/math.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index 73c631552..191db9f52 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -104,7 +104,7 @@ mod tests { fn normalize(x: &[I32F32]) -> Vec { let x_sum: I32F32 = x.iter().sum(); if x_sum == I32F32::from_num(0.0) { - x.into() + x.to_vec() } else { x.iter().map(|xi| xi / x_sum).collect() } From e9ad477900586cc0be4e909b8f4132f29f82ef61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Fri, 1 Mar 2024 14:25:01 -0300 Subject: [PATCH 11/11] refac: use interpolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Luiz Carvalho Signed-off-by: Gabrielle Guimarães de Oliveira --- pallets/subspace/src/math.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/subspace/src/math.rs b/pallets/subspace/src/math.rs index 191db9f52..7aa156ceb 100644 --- a/pallets/subspace/src/math.rs +++ b/pallets/subspace/src/math.rs @@ -111,7 +111,7 @@ mod tests { } fn assert_float_compare(a: I32F32, b: I32F32, epsilon: I32F32) { - assert!(I32F32::abs(a - b) <= epsilon, "a({:?}) != b({:?})", a, b); + assert!(I32F32::abs(a - b) <= epsilon, "a({a:?}) != b({b:?})"); } fn assert_vec_compare(va: &[I32F32], vb: &[I32F32], epsilon: I32F32) {