From f785a53126fc7fe973c3cf6676d182bab70af67b Mon Sep 17 00:00:00 2001 From: Ewan Gilligan Date: Tue, 1 Sep 2020 16:35:58 +0100 Subject: [PATCH 1/3] add new method of creating random elements --- src/group/stabchain/mod.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/group/stabchain/mod.rs b/src/group/stabchain/mod.rs index a56d392a24..74896e70c5 100644 --- a/src/group/stabchain/mod.rs +++ b/src/group/stabchain/mod.rs @@ -12,6 +12,7 @@ use crate::perm::*; use base::Base; use base_change_builder::{BaseChangeBuilder, BaseChangeBuilderStrategy}; use builder::{Builder, BuilderStrategy}; +use rand::seq::IteratorRandom; use crate::DetHashMap; @@ -145,6 +146,38 @@ where builder.set_base(self, base); builder.build() } + + /// Get a random element of the group at a specific layer of the chain. + pub fn random_element_from_layer(&self, layer: usize, rng: &mut R) -> P + where + R: rand::Rng, + { + self.get_chain_at_layer(layer) + .map(|record| { + record + .resolver() + .representative( + &record.transversal, + record.base.clone(), + record + .transversal + .keys() + .choose(rng) + .unwrap_or(&record.base) + .clone(), + ) + .unwrap() + }) + .fold(P::id(), |accum, product| accum.multiply(&product)) + } + + /// Get a random element of the group this chain represents. + pub fn random_element(&self, rng: &mut R) -> P + where + R: rand::Rng, + { + self.random_element_from_layer(0, rng) + } } impl Stabchain, A> From 54f26c3761afeb6c0e611033bb6baeabb200ef98 Mon Sep 17 00:00:00 2001 From: Ewan Gilligan Date: Tue, 1 Sep 2020 16:54:44 +0100 Subject: [PATCH 2/3] add doctest --- src/group/stabchain/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/group/stabchain/mod.rs b/src/group/stabchain/mod.rs index 74896e70c5..bd71c3ccce 100644 --- a/src/group/stabchain/mod.rs +++ b/src/group/stabchain/mod.rs @@ -148,6 +148,7 @@ where } /// Get a random element of the group at a specific layer of the chain. + /// This will generate elements uniformly, assuming the given RNG also does. pub fn random_element_from_layer(&self, layer: usize, rng: &mut R) -> P where R: rand::Rng, @@ -172,6 +173,14 @@ where } /// Get a random element of the group this chain represents. + /// This will generate elements uniformly, assuming the given RNG also does. + /// ``` + /// use stabchain::group::Group; + /// let g = Group::symmetric(4); + /// let chain = g.stabchain(); + /// let p = chain.random_element(&mut rand::thread_rng()); + /// assert!(chain.in_group(&p)); + ///``` pub fn random_element(&self, rng: &mut R) -> P where R: rand::Rng, From 7033aa5d9a8dd7c86c78e5c9e3143270a7ef076f Mon Sep 17 00:00:00 2001 From: Ewan Gilligan Date: Tue, 1 Sep 2020 16:58:18 +0100 Subject: [PATCH 3/3] update to use new random --- src/group/stabchain/base_change_builder/random.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/group/stabchain/base_change_builder/random.rs b/src/group/stabchain/base_change_builder/random.rs index 6d1623a2a1..6853b91742 100644 --- a/src/group/stabchain/base_change_builder/random.rs +++ b/src/group/stabchain/base_change_builder/random.rs @@ -3,17 +3,12 @@ use crate::DetHashSet; use crate::{ group::{ orbit::abstraction::{FactoredTransversalResolver, TransversalResolver}, - random_perm::RandPerm, stabchain::{base::Base, Stabchain, StabchainRecord}, - Group, }, perm::{actions::SimpleApplication, Action, Permutation}, }; use num::BigUint; -const MIN_SIZE: usize = 11; -const INITIAL_RUNS: usize = 50; - /// Helper struct, used to build the stabilizer chain pub struct RandomBaseChangeBuilder> where @@ -40,7 +35,6 @@ where V: TransversalResolver, { let target_order = chain.order(); - let sgs = Group::from_list(chain.strong_generating_set()); // Create the trivial chain with all the new base points. self.chain = base .base() @@ -48,11 +42,10 @@ where .cloned() .map(StabchainRecord::trivial_record) .collect::>(); - //Random permutation generator. - let mut rand_perm = RandPerm::new(MIN_SIZE, &sgs, INITIAL_RUNS, rand::thread_rng()); + let mut rng = rand::thread_rng(); //Loop till the new chain has the correct order. while self.current_chain_order() < target_order { - let g = rand_perm.random_permutation(); + let g = chain.random_element(&mut rng); let (g_dash, i) = self.residue_with_dropout(g); //If the permutation doesn't sift through then add it as a new generator at level i. if i < base.base().len() {