Skip to content

Commit 7d8c402

Browse files
refactor alpha values
1 parent 794824a commit 7d8c402

File tree

4 files changed

+51
-184
lines changed

4 files changed

+51
-184
lines changed

pallets/subtensor/src/epoch/math.rs

Lines changed: 5 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,66 +1083,6 @@ pub fn hadamard_sparse(
10831083
result
10841084
}
10851085

1086-
// Return matrix exponential moving average: `alpha * a_ij + one_minus_alpha * b_ij`.
1087-
// `alpha` is the EMA coefficient, how much to add of the new observation, typically small,
1088-
// higher alpha discounts older observations faster.
1089-
#[allow(dead_code)]
1090-
pub fn mat_ema(new: &[Vec<I32F32>], old: &[Vec<I32F32>], alpha: I32F32) -> Vec<Vec<I32F32>> {
1091-
let Some(first_row) = new.first() else {
1092-
return vec![vec![]];
1093-
};
1094-
if first_row.is_empty() {
1095-
return vec![vec![]; 1];
1096-
}
1097-
let one_minus_alpha: I32F32 = I32F32::from_num(1.0).saturating_sub(alpha);
1098-
new.iter()
1099-
.zip(old)
1100-
.map(|(new_row, old_row)| {
1101-
new_row
1102-
.iter()
1103-
.zip(old_row)
1104-
.map(|(new_elem, old_elem)| {
1105-
alpha
1106-
.saturating_mul(*new_elem)
1107-
.saturating_add(one_minus_alpha.saturating_mul(*old_elem))
1108-
})
1109-
.collect()
1110-
})
1111-
.collect()
1112-
}
1113-
1114-
// Return sparse matrix exponential moving average: `alpha * a_ij + one_minus_alpha * b_ij`.
1115-
// `alpha` is the EMA coefficient, how much to add of the new observation, typically small,
1116-
// higher alpha discounts older observations faster.
1117-
#[allow(dead_code, clippy::indexing_slicing)]
1118-
pub fn mat_ema_sparse(
1119-
new: &[Vec<(u16, I32F32)>],
1120-
old: &[Vec<(u16, I32F32)>],
1121-
alpha: I32F32,
1122-
) -> Vec<Vec<(u16, I32F32)>> {
1123-
assert!(new.len() == old.len());
1124-
let n = new.len(); // assume square matrix, rows=cols
1125-
let zero: I32F32 = I32F32::from_num(0.0);
1126-
let one_minus_alpha: I32F32 = I32F32::from_num(1.0).saturating_sub(alpha);
1127-
let mut result: Vec<Vec<(u16, I32F32)>> = vec![vec![]; n];
1128-
for i in 0..new.len() {
1129-
let mut row: Vec<I32F32> = vec![zero; n];
1130-
for (j, value) in new[i].iter() {
1131-
row[*j as usize] = row[*j as usize].saturating_add(alpha.saturating_mul(*value));
1132-
}
1133-
for (j, value) in old[i].iter() {
1134-
row[*j as usize] =
1135-
row[*j as usize].saturating_add(one_minus_alpha.saturating_mul(*value));
1136-
}
1137-
for (j, value) in row.iter().enumerate() {
1138-
if *value > zero {
1139-
result[i].push((j as u16, *value))
1140-
}
1141-
}
1142-
}
1143-
result
1144-
}
1145-
11461086
// Return sparse matrix only with elements >= threshold of an input sparse matrix.
11471087
#[allow(dead_code)]
11481088
pub fn sparse_threshold(w: &[Vec<(u16, I32F32)>], threshold: I32F32) -> Vec<Vec<(u16, I32F32)>> {
@@ -1157,6 +1097,10 @@ pub fn sparse_threshold(w: &[Vec<(u16, I32F32)>], threshold: I32F32) -> Vec<Vec<
11571097
}
11581098

11591099
/// Calculates the exponential moving average (EMA) for a sparse matrix using dynamic alpha values.
1100+
/// Return matrix exponential moving average: `alpha_j * a_ij + one_minus_alpha_j * b_ij`.
1101+
// `alpha` is the EMA coefficient, how much to add of the new observation, typically small,
1102+
// higher alpha discounts older observations faster.
1103+
// if liquid alpha off then the alpha vector will be constant
11601104
#[allow(dead_code)]
11611105
pub fn mat_ema_alpha_vec_sparse(
11621106
new: &[Vec<(u16, I32F32)>],
@@ -1244,6 +1188,7 @@ pub fn mat_ema_alpha_vec_sparse(
12441188

12451189
/// Return matrix exponential moving average: `alpha_j * a_ij + one_minus_alpha_j * b_ij`.
12461190
/// `alpha_` is the EMA coefficient passed as a vector per column.
1191+
// if liquid alpha off then the alpha vector will be constant
12471192
#[allow(dead_code)]
12481193
pub fn mat_ema_alpha_vec(
12491194
new: &[Vec<I32F32>],
@@ -1265,7 +1210,6 @@ pub fn mat_ema_alpha_vec(
12651210

12661211
// Iterate over each row of the matrices.
12671212
for (i, (new_row, old_row)) in new.iter().zip(old).enumerate() {
1268-
// Ensure the current row of the new and old matrices have the same length.
12691213
assert!(new_row.len() == old_row.len());
12701214

12711215
// Iterate over each column of the current row.

pallets/subtensor/src/epoch/run_epoch.rs

Lines changed: 34 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -167,18 +167,11 @@ impl<T: Config> Pallet<T> {
167167
inplace_col_normalize(&mut bonds); // sum_i b_ij = 1
168168
log::trace!("B:\n{:?}\n", &bonds);
169169

170+
// Get alpha values
171+
let alpha = Self::compute_liquid_alpha(netuid, consensus.clone());
172+
170173
// Compute the Exponential Moving Average (EMA) of bonds.
171-
// Check if Liquid Alpha is enabled, consensus is not empty, and contains non-zero values.
172-
let mut ema_bonds = if let Some(clamped_bonds_alpha) =
173-
Self::compute_liquid_alpha(netuid, consensus.clone())
174-
{
175-
// Compute the Exponential Moving Average (EMA) of bonds using the clamped alpha values.
176-
Self::compute_ema_bonds_with_liquid_alpha(&weights.clone(), &bonds, clamped_bonds_alpha)
177-
} else {
178-
log::trace!("Using Bonds Moving Average");
179-
// Compute the EMA of bonds using a normal alpha value.
180-
Self::compute_ema_bonds_normal(&weights.clone(), &bonds, netuid)
181-
};
174+
let mut ema_bonds = Self::compute_ema_bonds(&weights.clone(), &bonds, alpha);
182175
// Normalize EMA bonds.
183176
inplace_col_normalize(&mut ema_bonds); // sum_i b_ij = 1
184177
log::trace!("emaB:\n{:?}\n", &ema_bonds);
@@ -530,22 +523,11 @@ impl<T: Config> Pallet<T> {
530523
inplace_col_normalize_sparse(&mut bonds, n);
531524
log::trace!("B (mask+norm): {:?}", &bonds);
532525

533-
// Compute the Exponential Moving Average (EMA) of bonds.
534-
let mut ema_bonds = if let Some(clamped_bonds_alpha) =
535-
Self::compute_liquid_alpha(netuid, consensus.clone())
536-
{
537-
// Compute the Exponential Moving Average (EMA) of bonds using the clamped alpha values.
538-
Self::compute_ema_bonds_with_liquid_alpha_sparse(
539-
&weights.clone(),
540-
&bonds,
541-
clamped_bonds_alpha,
542-
)
543-
} else {
544-
log::trace!("Using Bonds Moving Average");
545-
// Compute the EMA of bonds using a normal alpha value.
546-
Self::compute_ema_bonds_normal_sparse(&weights.clone(), &bonds, netuid)
547-
};
526+
// Get alpha values
527+
let alpha = Self::compute_liquid_alpha(netuid, consensus.clone());
548528

529+
// Compute the Exponential Moving Average (EMA) of bonds.
530+
let mut ema_bonds = Self::compute_ema_bonds_sparse(&weights.clone(), &bonds, alpha);
549531
// Normalize EMA bonds.
550532
inplace_col_normalize_sparse(&mut ema_bonds, n); // sum_i b_ij = 1
551533
log::trace!("Exponential Moving Average Bonds: {:?}", &ema_bonds);
@@ -937,16 +919,16 @@ impl<T: Config> Pallet<T> {
937919
clamped_alpha
938920
}
939921

940-
/// Compute the Exponential Moving Average (EMA) of bonds using the clamped alpha values for a sparse matrix.
922+
/// Compute the Exponential Moving Average (EMA) of bonds using the alpha values for a sparse matrix.
941923
///
942924
/// # Args:
943925
/// * `bonds_delta` - A vector of bond deltas.
944926
/// * `bonds` - A vector of bonds.
945-
/// * `alpha` - A vector of clamped alpha values.
927+
/// * `alpha` - A vector of clamped alpha values (for liquid alpha) or constant alpha values.
946928
///
947929
/// # Returns:
948930
/// A vector of EMA bonds.
949-
pub fn compute_ema_bonds_with_liquid_alpha_sparse(
931+
pub fn compute_ema_bonds_sparse(
950932
bonds_delta: &[Vec<(u16, I32F32)>],
951933
bonds: &[Vec<(u16, I32F32)>],
952934
alpha: Vec<I32F32>,
@@ -955,25 +937,22 @@ impl<T: Config> Pallet<T> {
955937
let ema_bonds = mat_ema_alpha_vec_sparse(bonds_delta, bonds, &alpha);
956938

957939
// Log the computed EMA bonds for debugging purposes.
958-
log::trace!(
959-
"Exponential Moving Average Bonds Liquid Alpha: {:?}",
960-
ema_bonds
961-
);
940+
log::trace!("Exponential Moving Average Bonds: {:?}", ema_bonds);
962941

963942
// Return the computed EMA bonds.
964943
ema_bonds
965944
}
966945

967-
/// Compute the Exponential Moving Average (EMA) of bonds using the clamped alpha values.
946+
/// Compute the Exponential Moving Average (EMA) of bonds using the alpha values.
968947
///
969948
/// # Args:
970949
/// * `bonds_delta` - A vector of bond deltas.
971950
/// * `bonds` - A vector of bonds.
972-
/// * `alpha` - A vector of clamped alpha values.
951+
/// * `alpha` - A vector of clamped alpha values (for liquid alpha) or constant alpha values.
973952
///
974953
/// # Returns:
975954
/// A vector of EMA bonds.
976-
pub fn compute_ema_bonds_with_liquid_alpha(
955+
pub fn compute_ema_bonds(
977956
bonds_delta: &[Vec<I32F32>],
978957
bonds: &[Vec<I32F32>],
979958
alpha: Vec<I32F32>,
@@ -982,76 +961,7 @@ impl<T: Config> Pallet<T> {
982961
let ema_bonds = mat_ema_alpha_vec(bonds_delta, bonds, &alpha);
983962

984963
// Log the computed EMA bonds for debugging purposes.
985-
log::trace!(
986-
"Exponential Moving Average Bonds Liquid Alpha: {:?}",
987-
ema_bonds
988-
);
989-
990-
// Return the computed EMA bonds.
991-
ema_bonds
992-
}
993-
994-
/// Compute the Exponential Moving Average (EMA) of bonds using a normal alpha value for a sparse matrix.
995-
///
996-
/// # Args:
997-
/// * `bonds_delta` - A vector of bond deltas.
998-
/// * `bonds` - A vector of bonds.
999-
/// * `netuid` - The network ID.
1000-
///
1001-
/// # Returns:
1002-
/// A vector of EMA bonds.
1003-
pub fn compute_ema_bonds_normal_sparse(
1004-
bonds_delta: &[Vec<(u16, I32F32)>],
1005-
bonds: &[Vec<(u16, I32F32)>],
1006-
netuid: u16,
1007-
) -> Vec<Vec<(u16, I32F32)>> {
1008-
// Retrieve the bonds moving average for the given network ID and scale it down.
1009-
let bonds_moving_average: I64F64 = I64F64::from_num(Self::get_bonds_moving_average(netuid))
1010-
.saturating_div(I64F64::from_num(1_000_000));
1011-
1012-
// Calculate the alpha value for the EMA calculation.
1013-
// Alpha is derived by subtracting the scaled bonds moving average from 1.
1014-
let alpha: I32F32 =
1015-
I32F32::from_num(1).saturating_sub(I32F32::from_num(bonds_moving_average));
1016-
1017-
// Compute the Exponential Moving Average (EMA) of bonds using the calculated alpha value.
1018-
let ema_bonds = mat_ema_sparse(bonds_delta, bonds, alpha);
1019-
1020-
// Log the computed EMA bonds for debugging purposes.
1021-
log::trace!("Exponential Moving Average Bonds Normal: {:?}", ema_bonds);
1022-
1023-
// Return the computed EMA bonds.
1024-
ema_bonds
1025-
}
1026-
1027-
/// Compute the Exponential Moving Average (EMA) of bonds using a normal alpha value.
1028-
///
1029-
/// # Args:
1030-
/// * `bonds_delta` - A vector of bond deltas.
1031-
/// * `bonds` - A vector of bonds.
1032-
/// * `netuid` - The network ID.
1033-
///
1034-
/// # Returns:
1035-
/// A vector of EMA bonds.
1036-
pub fn compute_ema_bonds_normal(
1037-
bonds_delta: &[Vec<I32F32>],
1038-
bonds: &[Vec<I32F32>],
1039-
netuid: u16,
1040-
) -> Vec<Vec<I32F32>> {
1041-
// Retrieve the bonds moving average for the given network ID and scale it down.
1042-
let bonds_moving_average: I64F64 = I64F64::from_num(Self::get_bonds_moving_average(netuid))
1043-
.saturating_div(I64F64::from_num(1_000_000));
1044-
1045-
// Calculate the alpha value for the EMA calculation.
1046-
// Alpha is derived by subtracting the scaled bonds moving average from 1.
1047-
let alpha: I32F32 =
1048-
I32F32::from_num(1).saturating_sub(I32F32::from_num(bonds_moving_average));
1049-
1050-
// Compute the Exponential Moving Average (EMA) of bonds using the calculated alpha value.
1051-
let ema_bonds = mat_ema(bonds_delta, bonds, alpha);
1052-
1053-
// Log the computed EMA bonds for debugging purposes.
1054-
log::trace!("Exponential Moving Average Bonds Normal: {:?}", ema_bonds);
964+
log::trace!("Exponential Moving Average Bonds: {:?}", ema_bonds);
1055965

1056966
// Return the computed EMA bonds.
1057967
ema_bonds
@@ -1065,7 +975,7 @@ impl<T: Config> Pallet<T> {
1065975
///
1066976
/// # Returns:
1067977
/// A vector of alphas
1068-
pub fn compute_liquid_alpha(netuid: u16, consensus: Vec<I32F32>) -> Option<Vec<I32F32>> {
978+
pub fn compute_liquid_alpha(netuid: u16, consensus: Vec<I32F32>) -> Vec<I32F32> {
1069979
// Check if Liquid Alpha is enabled, consensus is not empty, and contains non-zero values.
1070980
if LiquidAlphaOn::<T>::get(netuid)
1071981
&& !consensus.is_empty()
@@ -1092,15 +1002,30 @@ impl<T: Config> Pallet<T> {
10921002
);
10931003

10941004
// Compute the alpha values using the logistic function parameters.
1005+
// alpha = 1 / (1 + math.e ** (-a * C + b)) # alpha to the old weight
10951006
let alpha = Self::compute_alpha_values(&consensus, a, b);
10961007

10971008
// Clamp the alpha values between alpha_high and alpha_low.
10981009
let clamped_alpha = Self::clamp_alpha_values(alpha, alpha_high, alpha_low);
10991010

1100-
return Some(clamped_alpha);
1011+
return clamped_alpha;
11011012
}
11021013
}
1103-
None
1014+
1015+
// Liquid Alpha is disabled
1016+
// or high and low consensus values do not meet the required conditions.
1017+
// return vector of constant alpha
1018+
1019+
// Retrieve the bonds moving average for the given network ID and scale it down.
1020+
let bonds_moving_average: I64F64 = I64F64::from_num(Self::get_bonds_moving_average(netuid))
1021+
.saturating_div(I64F64::from_num(1_000_000));
1022+
1023+
// Calculate the alpha value for the EMA calculation.
1024+
// Alpha is derived by subtracting the scaled bonds moving average from 1.
1025+
let alpha: I32F32 =
1026+
I32F32::from_num(1).saturating_sub(I32F32::from_num(bonds_moving_average));
1027+
1028+
vec![alpha; consensus.len()]
11041029
}
11051030

11061031
pub fn do_set_alpha_values(

pallets/subtensor/src/tests/epoch.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,7 +2513,7 @@ fn test_calculate_logistic_params_edge_cases() {
25132513
}
25142514

25152515
#[test]
2516-
fn test_compute_ema_bonds_with_liquid_alpha_sparse() {
2516+
fn test_compute_ema_bonds_sparse() {
25172517
// Define test inputs
25182518
let bonds_delta = vec![
25192519
vec![(0, I32F32::from_num(0.1)), (1, I32F32::from_num(0.2))],
@@ -2542,16 +2542,15 @@ fn test_compute_ema_bonds_with_liquid_alpha_sparse() {
25422542
];
25432543

25442544
// Call the function
2545-
let ema_bonds =
2546-
SubtensorModule::compute_ema_bonds_with_liquid_alpha_sparse(&bonds_delta, &bonds, alpha);
2545+
let ema_bonds = SubtensorModule::compute_ema_bonds_sparse(&bonds_delta, &bonds, alpha);
25472546

25482547
// Assert the results with an epsilon for approximate equality
25492548
let epsilon = I32F32::from_num(1e-6);
25502549
assert_approx_eq_vec_of_vec(&ema_bonds, &expected_ema_bonds, epsilon);
25512550
}
25522551

25532552
#[test]
2554-
fn test_compute_ema_bonds_with_liquid_alpha_sparse_empty() {
2553+
fn test_compute_ema_bonds_sparse_empty() {
25552554
// Test with empty inputs
25562555
let bonds_delta: Vec<Vec<(u16, I32F32)>> = vec![];
25572556
let bonds: Vec<Vec<(u16, I32F32)>> = vec![];
@@ -2561,8 +2560,7 @@ fn test_compute_ema_bonds_with_liquid_alpha_sparse_empty() {
25612560
let expected_ema_bonds: Vec<Vec<(u16, I32F32)>> = vec![];
25622561

25632562
// Call the function
2564-
let ema_bonds =
2565-
SubtensorModule::compute_ema_bonds_with_liquid_alpha_sparse(&bonds_delta, &bonds, alpha);
2563+
let ema_bonds = SubtensorModule::compute_ema_bonds_sparse(&bonds_delta, &bonds, alpha);
25662564

25672565
// Assert the results
25682566
assert_eq!(

0 commit comments

Comments
 (0)