Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalise weights in Root Epoch Calculation #415

Merged
merged 4 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions pallets/subtensor/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,18 @@ pub fn inplace_normalize_64(x: &mut [I64F64]) {
x.iter_mut().for_each(|value| *value /= x_sum);
}

/// Normalizes (sum to 1 except 0) each row (dim=0) of a I64F64 matrix in-place.
#[allow(dead_code)]
pub fn inplace_row_normalize_64(x: &mut [Vec<I64F64>]) {
for row in x {
let row_sum: I64F64 = row.iter().sum();
if row_sum > I64F64::from_num(0.0_f64) {
row.iter_mut()
.for_each(|x_ij: &mut I64F64| *x_ij /= row_sum);
}
}
}

/// Returns x / y for input vectors x and y, if y == 0 return 0.
#[allow(dead_code)]
pub fn vecdiv(x: &[I32F32], y: &[I32F32]) -> Vec<I32F32> {
Expand Down
20 changes: 12 additions & 8 deletions pallets/subtensor/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ impl<T: Config> Pallet<T> {
// --- 0. The unique ID associated with the root network.
let root_netuid: u16 = Self::get_root_netuid();

// --- 3. Check if we should update the emission values based on blocks since emission was last set.
// --- 1. Check if we should update the emission values based on blocks since emission was last set.
let blocks_until_next_epoch: u64 =
Self::blocks_until_next_epoch(root_netuid, Self::get_tempo(root_netuid), block_number);
if blocks_until_next_epoch != 0 {
Expand All @@ -304,15 +304,15 @@ impl<T: Config> Pallet<T> {
return Err("");
}

// --- 1. Retrieves the number of root validators on subnets.
// --- 2. Retrieves the number of root validators on subnets.
let n: u16 = Self::get_num_root_validators();
log::debug!("n:\n{:?}\n", n);
if n == 0 {
// No validators.
return Err("No validators to validate emission values.");
}

// --- 2. Obtains the number of registered subnets.
// --- 3. Obtains the number of registered subnets.
let k: u16 = Self::get_all_subnet_netuids().len() as u16;
log::debug!("k:\n{:?}\n", k);
if k == 0 {
Expand Down Expand Up @@ -344,17 +344,21 @@ impl<T: Config> Pallet<T> {
inplace_normalize_64(&mut stake_i64);
log::debug!("S:\n{:?}\n", &stake_i64);

// --- 8. Retrieves the network weights in a 2D Vector format. Weights have shape
// --- 7. Retrieves the network weights in a 2D Vector format. Weights have shape
// n x k where is n is the number of registered peers and k is the number of subnets.
let weights: Vec<Vec<I64F64>> = Self::get_root_weights();
let mut weights: Vec<Vec<I64F64>> = Self::get_root_weights();
log::debug!("W:\n{:?}\n", &weights);

// --- 9. Calculates the rank of networks. Rank is a product of weights and stakes.
// Normalize weights.
inplace_row_normalize_64(&mut weights);
log::debug!("W(norm):\n{:?}\n", &weights);

// --- 8. Calculates the rank of networks. Rank is a product of weights and stakes.
// Ranks will have shape k, a score for each subnet.
let ranks: Vec<I64F64> = matmul_64(&weights, &stake_i64);
log::debug!("R:\n{:?}\n", &ranks);

// --- 10. Calculates the trust of networks. Trust is a sum of all stake with weights > 0.
// --- 9. Calculates the trust of networks. Trust is a sum of all stake with weights > 0.
// Trust will have shape k, a score for each subnet.
let total_networks = Self::get_num_subnets();
let mut trust = vec![I64F64::from_num(0); total_networks as usize];
Expand All @@ -381,7 +385,7 @@ impl<T: Config> Pallet<T> {
}
}

// --- 11. Calculates the consensus of networks. Consensus is a sigmoid normalization of the trust scores.
// --- 10. Calculates the consensus of networks. Consensus is a sigmoid normalization of the trust scores.
// Consensus will have shape k, a score for each subnet.
log::debug!("T:\n{:?}\n", &trust);
let one = I64F64::from_num(1);
Expand Down
32 changes: 22 additions & 10 deletions pallets/subtensor/tests/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,21 +594,33 @@ fn test_network_pruning() {
(i as u16) + 1
);
}
// Stakes
// 0 : 10_000
// 1 : 9_000
// 2 : 8_000
// 3 : 7_000
// 4 : 6_000
// 5 : 5_000
// 6 : 4_000
// 7 : 3_000
// 8 : 2_000
// 9 : 1_000

step_block(1);
assert_ok!(SubtensorModule::root_epoch(1_000_000_000));
assert_eq!(SubtensorModule::get_subnet_emission_value(0), 277_820_113);
assert_eq!(SubtensorModule::get_subnet_emission_value(1), 246_922_263);
assert_eq!(SubtensorModule::get_subnet_emission_value(2), 215_549_466);
assert_eq!(SubtensorModule::get_subnet_emission_value(3), 176_432_500);
assert_eq!(SubtensorModule::get_subnet_emission_value(4), 77_181_559);
assert_eq!(SubtensorModule::get_subnet_emission_value(5), 5_857_251);
assert_eq!(SubtensorModule::get_subnet_emission_value(0), 385_861_815);
assert_eq!(SubtensorModule::get_subnet_emission_value(1), 249_435_914);
assert_eq!(SubtensorModule::get_subnet_emission_value(2), 180_819_837);
assert_eq!(SubtensorModule::get_subnet_emission_value(3), 129_362_980);
assert_eq!(SubtensorModule::get_subnet_emission_value(4), 50_857_187);
assert_eq!(SubtensorModule::get_subnet_emission_value(5), 3_530_356);
step_block(1);
assert_eq!(SubtensorModule::get_pending_emission(0), 0); // root network gets no pending emission.
assert_eq!(SubtensorModule::get_pending_emission(1), 246_922_263);
assert_eq!(SubtensorModule::get_pending_emission(1), 249_435_914);
assert_eq!(SubtensorModule::get_pending_emission(2), 0); // This has been drained.
assert_eq!(SubtensorModule::get_pending_emission(3), 176_432_500);
assert_eq!(SubtensorModule::get_pending_emission(3), 129_362_980);
assert_eq!(SubtensorModule::get_pending_emission(4), 0); // This network has been drained.
assert_eq!(SubtensorModule::get_pending_emission(5), 5_857_251);
assert_eq!(SubtensorModule::get_pending_emission(5), 3_530_356);
step_block(1);
});
}
Expand Down Expand Up @@ -766,7 +778,7 @@ fn test_weights_after_network_pruning() {
/// Run this test using the following command:
/// `cargo test --package pallet-subtensor --test root test_issance_bounds`
#[test]
fn test_issance_bounds() {
fn test_issuance_bounds() {
new_test_ext(1).execute_with(|| {
// Simulate 100 halvings convergence to 21M. Note that the total issuance never reaches 21M because of rounding errors.
// We converge to 20_999_999_989_500_000 (< 1 TAO away).
Expand Down
Loading