Skip to content
Draft
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
11 changes: 2 additions & 9 deletions src/group/stabchain/base_change_builder/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<P, A = SimpleApplication<P>>
where
Expand All @@ -40,19 +35,17 @@ where
V: TransversalResolver<P, A>,
{
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()
.iter()
.cloned()
.map(StabchainRecord::trivial_record)
.collect::<Vec<_>>();
//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() {
Expand Down
42 changes: 42 additions & 0 deletions src/group/stabchain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<R>(&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<R>(&self, rng: &mut R) -> P
where
R: rand::Rng,
{
self.random_element_from_layer(0, rng)
}
}

impl<P, A> Stabchain<P, FactoredTransversalResolver<A>, A>
Expand Down