Commit 2649163c authored by Bharat Garhewal's avatar Bharat Garhewal
Browse files

Moved RandomIG and FixedIG to utils

parent e27f8db0
......@@ -5,16 +5,19 @@ use crate::{
mealy::{InputSymbol, Mealy, State},
traits::{FiniteStateMachine, ObservationTree},
},
learner::apartness::{states_are_apart, tree_and_hyp_states_apart},
learner::apartness::states_are_apart,
oracles::{
equivalence::{
automata::shortest_separating_sequence,
equivalence_trait::{CounterExample, EquivalenceOracle, InternalEquivalenceOracle},
incomplete::{iads::infix_generator::RandomInfixGenerator, tree::TreeCons},
incomplete::tree::TreeCons,
},
membership::Oracle as OQOracle,
},
util::toolbox,
util::{
sequences::{FixedInfixGenerator, Order, RandomInfixGenerator},
toolbox,
},
};
use fnv::{FnvHashMap, FnvHashSet};
use itertools::Itertools;
......@@ -86,7 +89,7 @@ where
self.frontier_trans = self.frontier_transitions(hyp);
let access_map = self.access_map(hyp);
// let access_map = random_access_map(hyp, self.seed);
let rig = RandomInfixGenerator::new(self.seed, hyp.input_alphabet().len(), lookahead);
let rig = RandomInfixGenerator::new(self.seed, hyp.input_alphabet().len(), 0, lookahead);
log::info!("Running AIC sequences.");
let splitting_tree =
TreeCons::construct(hyp, &hyp_states.iter().copied().collect_vec(), false);
......@@ -385,16 +388,15 @@ where
// A will contain only the empty sequence,
// since we are already in the initial state;
// Therefore, the only thing left is I<=(n+1)
let input_size = hyp.input_alphabet().len();
let input_alphabet = toolbox::inputs_iterator(input_size).collect_vec();
let lookahead_range = (0..=self.lookahead + 1).into_iter().collect_vec();
let infix_closure = || {
Iterator::flatten(lookahead_range.iter().map(|&n| {
itertools::repeat_n(input_alphabet.iter().copied(), n as _)
.multi_cartesian_product()
}))
};
infix_closure().find_map(|seq| self.run_test(hyp, &seq))
let input_alphabet = hyp.input_alphabet().into_iter().sorted().collect_vec();
let fig = FixedInfixGenerator::new(input_alphabet, self.lookahead + 1, Order::ASC);
for seq in fig.generate() {
let res = self.run_test(hyp, &seq);
if res.is_some() {
return res;
}
}
None
}
/// Run a single test sequence and return whether it is a CE or not.
......@@ -522,66 +524,3 @@ mod tests {
assert_eq!(fsm.states(), access_states)
}
}
////////////////////////////// Random Infix Generator //////////////////////////////
mod infix_generator {
use crate::automatadefs::mealy::InputSymbol;
use rand::{prelude::StdRng, SeedableRng};
use rand_distr::{Distribution, Geometric, Uniform};
pub(super) struct RandomInfixGenerator {
rng: StdRng,
num_inputs: usize,
max_len: usize,
}
impl RandomInfixGenerator {
pub fn new(seed: u64, num_inputs: usize, max_len: usize) -> Self {
Self {
num_inputs,
max_len,
rng: SeedableRng::seed_from_u64(seed),
}
}
pub fn generate(self) -> impl Iterator<Item = Vec<InputSymbol>> {
let prob = 1f64 / (self.max_len as f64);
let geo = Geometric::new(prob).expect("Safe");
RandomInfixIterator::new(self.rng, self.num_inputs, geo, self.max_len)
}
}
struct RandomInfixIterator {
rng: StdRng,
geo: Geometric,
k_min: usize,
inputs_dist: Uniform<usize>,
}
impl RandomInfixIterator {
fn new(rng: StdRng, inputs: usize, geo: Geometric, lookahead: usize) -> Self {
Self {
rng,
geo,
k_min: lookahead,
inputs_dist: Uniform::new(0, inputs),
}
}
}
impl Iterator for RandomInfixIterator {
type Item = Vec<InputSymbol>;
fn next(&mut self) -> Option<Self::Item> {
let lookahead = self.geo.sample(&mut self.rng) as usize;
// let lookahead = lookahead + self.k_min;
let input_seq: Vec<_> = self
.inputs_dist
.map(InputSymbol::from)
.sample_iter(&mut self.rng)
.take(lookahead)
.collect();
Some(input_seq)
}
}
}
use crate::automatadefs::mealy::InputSymbol;
use itertools::Itertools;
use rand::{prelude::StdRng, SeedableRng};
use rand_distr::{Distribution, Geometric, Uniform};
/// Generates random vectors of symbols.
pub struct RandomInfixGenerator {
rng: StdRng,
min_inputs: usize,
num_inputs: usize,
expected_inputs: usize,
}
impl RandomInfixGenerator {
/// Construct a generator with `seed`, `num_inputs` number of inputs,
/// `min_inputs` minimum length, and `expected_inputs` being the expected
/// length of the random portion.
pub fn new(seed: u64, num_inputs: usize, min_inputs: usize, expected_inputs: usize) -> Self {
Self {
min_inputs,
num_inputs,
expected_inputs,
rng: SeedableRng::seed_from_u64(seed),
}
}
pub fn generate(self) -> impl Iterator<Item = Vec<InputSymbol>> {
let prob = 1f64 / (self.expected_inputs as f64);
let geo = Geometric::new(prob).expect("Safe");
RandomInfixIterator::new(self.rng, self.num_inputs, geo, self.min_inputs)
}
}
struct RandomInfixIterator {
rng: StdRng,
geo: Geometric,
k_min: usize,
inputs_dist: Uniform<usize>,
}
impl RandomInfixIterator {
fn new(rng: StdRng, inputs: usize, geo: Geometric, k_min: usize) -> Self {
Self {
rng,
geo,
k_min,
inputs_dist: Uniform::new(0, inputs),
}
}
}
impl Iterator for RandomInfixIterator {
type Item = Vec<InputSymbol>;
fn next(&mut self) -> Option<Self::Item> {
let lookahead = self.geo.sample(&mut self.rng) as usize;
let lookahead = lookahead + self.k_min;
let input_seq: Vec<_> = self
.inputs_dist
.map(InputSymbol::from)
.sample_iter(&mut self.rng)
.take(lookahead)
.collect();
Some(input_seq)
}
}
#[derive(PartialEq, Eq)]
pub enum Order {
ASC,
DESC,
}
pub struct FixedInfixGenerator<T> {
input_alphabet: Vec<T>,
range: Vec<usize>,
}
impl<T: Clone> FixedInfixGenerator<T> {
pub fn new(input_alphabet: Vec<T>, length: usize, order: Order) -> Self {
let mut x = (0..=length + 1).into_iter().collect_vec();
Self {
input_alphabet,
range: if order == Order::ASC {
x
} else {
x.reverse();
x
},
}
}
pub fn generate(&self) -> impl Iterator<Item = Vec<T>> + '_ {
let infix_closure = || {
Iterator::flatten(self.range.clone().into_iter().map(|n| {
itertools::repeat_n(self.input_alphabet.clone().into_iter(), n)
.multi_cartesian_product()
}))
};
infix_closure()
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment