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() {
diff --git a/src/group/stabchain/mod.rs b/src/group/stabchain/mod.rs
index a56d392a24..bd71c3ccce 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,47 @@ where
builder.set_base(self, base);
builder.build()
}
+
+ /// 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,
+ {
+ 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.
+ /// 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,
+ {
+ self.random_element_from_layer(0, rng)
+ }
}
impl Stabchain
, A>