diff --git a/pallets/subtensor/src/epoch.rs b/pallets/subtensor/src/epoch.rs index 8b405baf16..6acb9e23f9 100644 --- a/pallets/subtensor/src/epoch.rs +++ b/pallets/subtensor/src/epoch.rs @@ -215,7 +215,7 @@ impl Pallet { let cloned_consensus: Vec = consensus.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); let cloned_incentive: Vec = incentive.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); let cloned_dividends: Vec = dividends.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); - let cloned_pruning_scores: Vec = pruning_scores.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); + let cloned_pruning_scores: Vec = vec_max_upscale_to_u16(&pruning_scores); let cloned_validator_trust: Vec = validator_trust.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); Active::::insert( netuid, active.clone() ); Emission::::insert( netuid, cloned_emission ); @@ -485,7 +485,7 @@ impl Pallet { let cloned_consensus: Vec = consensus.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); let cloned_incentive: Vec = incentive.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); let cloned_dividends: Vec = dividends.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); - let cloned_pruning_scores: Vec = pruning_scores.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); + let cloned_pruning_scores: Vec = vec_max_upscale_to_u16(&pruning_scores); let cloned_validator_trust: Vec = validator_trust.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); Active::::insert( netuid, active.clone() ); Emission::::insert( netuid, cloned_emission ); diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index c2fb364213..294dea1a02 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -36,6 +36,29 @@ pub fn vec_u16_proportions_to_fixed( vec: Vec ) -> Vec { vec.into_i #[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)] +// Max-upscale vector and convert to u16 so max_value = u16::MAX. Assumes non-negative normalized input. +pub fn vec_max_upscale_to_u16( vec: &Vec ) -> Vec { + let u16_max: I32F32 = I32F32::from_num( u16::MAX ); + let threshold: I32F32 = I32F32::from_num( 32768 ); + let max_value: Option<&I32F32> = vec.iter().max(); + match max_value { + Some(val) => { + if *val == I32F32::from_num( 0 ) { + return vec.iter().map(|e: &I32F32| (e * u16_max).to_num::() ).collect() + } + if *val > threshold { + return vec.iter().map(|e: &I32F32| (e * (u16_max / *val)).round().to_num::() ).collect() + } + return vec.iter().map(|e: &I32F32| ((e * u16_max) / *val).round().to_num::() ).collect() + }, + None => { + let sum: I32F32 = vec.iter().sum(); + return vec.iter().map(|e: &I32F32| ((e * u16_max) / sum).to_num::() ).collect() + } + } +} + #[allow(dead_code)] pub fn sum( x: &Vec ) -> I32F32 { x.iter().sum() } @@ -782,6 +805,13 @@ mod tests { } } + fn assert_vec_compare_u16(va: &Vec, vb: &Vec) { + assert!(va.len() == vb.len()); + for i in 0..va.len(){ + assert_eq!(va[i], vb[i]); + } + } + fn assert_mat_compare(ma: &Vec>, mb: &Vec>, epsilon: I32F32) { assert!(ma.len() == mb.len()); for row in 0..ma.len() { @@ -807,6 +837,78 @@ mod tests { vector.iter().map( | x | I32F32::from_num( *x ) ).collect() } + #[test] + fn test_vec_max_upscale_to_u16() { + let vector: Vec = vec_to_fixed( &vec![] ); + let target: Vec = vec![]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0. ] ); + let target: Vec = vec![ 0 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0., 0. ] ); + let target: Vec = vec![ 0, 0 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0., 1. ] ); + let target: Vec = vec![ 0, 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0., 0.000000001 ] ); + let target: Vec = vec![ 0, 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0., 0.000016, 1. ] ); + let target: Vec = vec![ 0, 1, 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0.000000001, 0.000000001 ] ); + let target: Vec = vec![ 65535, 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0.000001, 0.000006, 0.000007, 0.0001, 0.001, 0.01, 0.1, 0.2, 0.3, 0.4] ); + let target: Vec = vec![ 0, 1, 1, 16, 164, 1638, 16384, 32768, 49151, 65535]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec![ I32F32::from_num(16384) ]; + let target: Vec = vec![ 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec![ I32F32::from_num(32768) ]; + let target: Vec = vec![ 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec![ I32F32::from_num(32769) ]; + let target: Vec = vec![ 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec![ I32F32::from_num(65535) ]; + let target: Vec = vec![ 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec![ I32F32::max_value() ]; + let target: Vec = vec![ 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0., 1., 65535. ] ); + let target: Vec = vec![ 0, 1, 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0., 0.5, 1., 1.5, 2., 32768. ] ); + let target: Vec = vec![ 0, 1, 2, 3, 4, 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec_to_fixed( &vec![ 0., 0.5, 1., 1.5, 2., 32768., 32769. ] ); + let target: Vec = vec![ 0, 1, 2, 3, 4, 65533, 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + let vector: Vec = vec![ I32F32::from_num(0), I32F32::from_num(1), I32F32::from_num(32768), I32F32::from_num(32769), I32F32::max_value() ]; + let target: Vec = vec![ 0, 0, 1, 1, 65535 ]; + let result: Vec = vec_max_upscale_to_u16( &vector ); + assert_vec_compare_u16(&result, &target); + } + #[test] fn test_math_fixed_overflow() { let max_32: I32F32 = I32F32::max_value(); diff --git a/pallets/subtensor/tests/epoch.rs b/pallets/subtensor/tests/epoch.rs index 77b2d226d4..d6758d1621 100644 --- a/pallets/subtensor/tests/epoch.rs +++ b/pallets/subtensor/tests/epoch.rs @@ -667,7 +667,8 @@ fn test_active_stake() { D: [0.55, 0.4499999997, 0, 0] nE: [0.275, 0.2249999999, 0.25, 0.25] E: [274999999, 224999999, 250000000, 250000000] - P: [0.275, 0.2249999999, 0.25, 0.25] */ + P: [0.275, 0.2249999999, 0.25, 0.25] + P (u16): [65535, 53619, 59577, 59577] */ let bonds = SubtensorModule::get_bonds( netuid ); assert_eq!( SubtensorModule::get_dividends_for_uid( netuid, 0 ), 36044 ); // Note D = floor((0.5 * 0.9 + 0.1) * 65_535) assert_eq!( SubtensorModule::get_emission_for_uid( netuid, 0 ), 274999999 ); // Note E = 0.5 * 0.55 * 1_000_000_000 = 275_000_000 (discrepancy) @@ -710,7 +711,8 @@ fn test_active_stake() { D: [0.5450041203, 0.4549958794, 0, 0] nE: [0.27250206, 0.2274979397, 0.25, 0.25] E: [272502060, 227497939, 250000000, 250000000] - P: [0.27250206, 0.2274979397, 0.25, 0.25] */ + P: [0.27250206, 0.2274979397, 0.25, 0.25] + P (u16): [65535, 54711, 60123, 60123] */ let bonds = SubtensorModule::get_bonds( netuid ); assert_eq!( SubtensorModule::get_dividends_for_uid( netuid, 0 ), 35716 ); // Note D = floor((0.55 * 0.9 + 0.5 * 0.1) * 65_535) assert_eq!( SubtensorModule::get_emission_for_uid( netuid, 0 ), 272502060 ); // Note E = 0.5 * (0.55 * 0.9 + 0.5 * 0.1) * 1_000_000_000 = 272_500_000 (discrepancy) @@ -787,7 +789,7 @@ fn test_outdated_weights() { nE: [0.25, 0.25, 0.3333333333, 0.1666666665] E: [250000000, 250000000, 333333333, 166666666] P: [0.25, 0.25, 0.3333333333, 0.1666666665] - n: 4 */ + P (u16): [49151, 49151, 65535, 32767] */ // === Dereg server2 at uid3 (least emission) + register new key over uid3 let new_key: u64 = n as u64; // register a new key while at max capacity, which means the least incentive uid will be deregistered @@ -831,7 +833,8 @@ fn test_outdated_weights() { D: [0.5, 0.5, 0, 0] nE: [0.25, 0.25, 0.5, 0] E: [250000000, 250000000, 500000000, 0] - P: [0.25, 0.25, 0.5, 0] */ + P: [0.25, 0.25, 0.5, 0] + P (u16): [32767, 32767, 65535, 0] */ let bonds = SubtensorModule::get_bonds( netuid ); assert_eq!( SubtensorModule::get_dividends_for_uid( netuid, 0 ), 32767 ); // Note D = floor(0.5 * 65_535) assert_eq!( SubtensorModule::get_emission_for_uid( netuid, 0 ), 250000000 ); // Note E = 0.5 * 0.5 * 1_000_000_000 = 249311245 diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 6bc8f22eb7..c752be7504 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -111,7 +111,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 115, + spec_version: 116, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,