From 10cc3e21b6e9bbc6fbeaf4a356b94a721c386180 Mon Sep 17 00:00:00 2001 From: opentaco Date: Fri, 31 Mar 2023 18:28:02 +0200 Subject: [PATCH 1/6] Add vec_max_upscale_to_u16 --- pallets/subtensor/src/math.rs | 60 +++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index c2fb364213..0f20fc126a 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -36,6 +36,23 @@ 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)] +pub fn vec_max_upscale_to_u16( vec: &Vec ) -> Vec { + let u16_max: I32F32 = I32F32::from_num( u16::MAX ); + 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() + } + return vec.iter().map(|e: &I32F32| (e * u16_max / *val).to_num::() ).collect() + }, + None => { + return vec.iter().map(|e: &I32F32| (e * u16_max).to_num::() ).collect() + } + } +} + #[allow(dead_code)] pub fn sum( x: &Vec ) -> I32F32 { x.iter().sum() } @@ -782,6 +799,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 +831,42 @@ 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, 0, 1, 16, 163, 1638, 16383, 32767, 49151, 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(); From 02226c9a998251233f5b4c40ef4e6f6f1c540355 Mon Sep 17 00:00:00 2001 From: opentaco Date: Fri, 31 Mar 2023 18:28:46 +0200 Subject: [PATCH 2/6] Do max-upscale pruning_scores --- pallets/subtensor/src/epoch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 ); From 851b3871bf3b6c6a7e0904dd69707ac116eb31a2 Mon Sep 17 00:00:00 2001 From: opentaco Date: Fri, 31 Mar 2023 18:53:07 +0200 Subject: [PATCH 3/6] Add epoch test log details for u16 pruning_scores --- pallets/subtensor/tests/epoch.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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 From a5d1dd3feb5063e73154ec4ec0a9e6addba91dd2 Mon Sep 17 00:00:00 2001 From: opentaco Date: Mon, 3 Apr 2023 18:54:31 +0200 Subject: [PATCH 4/6] Norm when no max --- pallets/subtensor/src/math.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index 0f20fc126a..418910eeb8 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -48,7 +48,8 @@ pub fn vec_max_upscale_to_u16( vec: &Vec ) -> Vec { return vec.iter().map(|e: &I32F32| (e * u16_max / *val).to_num::() ).collect() }, None => { - return vec.iter().map(|e: &I32F32| (e * u16_max).to_num::() ).collect() + let sum: I32F32 = vec.iter().sum(); + return vec.iter().map(|e: &I32F32| (e * u16_max / sum).to_num::() ).collect() } } } From 16ae36b5148d2ca216cf7d4193db289791b0aced Mon Sep 17 00:00:00 2001 From: opentaco Date: Tue, 4 Apr 2023 21:08:02 +0200 Subject: [PATCH 5/6] Added max-upscaling unnormalized handling --- pallets/subtensor/src/math.rs | 47 ++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index 418910eeb8..294dea1a02 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -37,19 +37,24 @@ pub fn vec_u16_proportions_to_fixed( vec: Vec ) -> Vec { vec.into_i 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() } - return vec.iter().map(|e: &I32F32| (e * u16_max / *val).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() + return vec.iter().map(|e: &I32F32| ((e * u16_max) / sum).to_num::() ).collect() } } } @@ -863,7 +868,43 @@ mod tests { 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, 0, 1, 16, 163, 1638, 16383, 32767, 49151, 65535]; + 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); } From 73240a2a85e21ab6292a0db5824f15018ec7011c Mon Sep 17 00:00:00 2001 From: opentaco Date: Tue, 4 Apr 2023 21:57:18 +0200 Subject: [PATCH 6/6] Update spec_version to 116 --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index bad97b69bc..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: 114, + spec_version: 116, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,