Commit 597c2b90 authored by Bharat Garhewal's avatar Bharat Garhewal
Browse files

Refactor

parent cbe1121e
......@@ -5,7 +5,7 @@ use super::{
use crate::{
automatadefs::{
mealy::{InputSymbol, Mealy, OutputSymbol, State},
traits::FiniteStateMachine,
FiniteStateMachine,
},
util::data_structs::arena_tree::ArenaTree,
};
......@@ -252,7 +252,7 @@ mod tests {
use super::super::adaptive_distinguishing_seq;
use super::super::adaptive_distinguishing_seq::State;
use crate::automatadefs::traits::FiniteStateMachine;
use crate::automatadefs::FiniteStateMachine;
use crate::util::parsers::machine::read_mealy_from_file;
use std::path::Path;
......
use crate::automatadefs::mealy::{InputSymbol, Mealy, State};
use crate::automatadefs::traits::FiniteStateMachine;
use crate::automatadefs::FiniteStateMachine;
use crate::util::data_structs::arena_tree::ArenaTree;
use fnv::FnvHashMap;
use std::collections::VecDeque;
......
use super::utils::{compute_score, partition_on_output_reuse};
use crate::{
ads::traits::{AdaptiveDistinguishingSequence, AdsStatus},
automatadefs::{
mealy::{InputSymbol, OutputSymbol, State},
traits::ObservationTree,
},
learner::apartness::compute_witness,
automatadefs::mealy::{InputSymbol, OutputSymbol, State},
learner::{apartness::compute_witness, obs_tree::ObservationTree},
util::{data_structs::arena_tree::ArenaTree, toolbox},
};
use fnv::{FnvHashMap, FnvHashSet};
......@@ -13,6 +10,7 @@ use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeSet, VecDeque},
hash::BuildHasherDefault,
io::Write,
};
......@@ -37,7 +35,7 @@ impl AdsNode {
#[must_use]
fn leaf_node() -> Self {
Self {
children: FnvHashMap::with_capacity_and_hasher(0, Default::default()),
children: FnvHashMap::with_capacity_and_hasher(0, BuildHasherDefault::default()),
block_size: 1,
..Default::default()
}
......@@ -335,12 +333,12 @@ impl PartialEq for AdsTree {
#[cfg(test)]
mod tests {
use super::AdaptiveDistinguishingSequence;
use super::{AdsNode, AdsTree};
use crate::automatadefs::mealy::{InputSymbol, OutputSymbol, State};
use crate::automatadefs::traits::ObservationTree;
use crate::learner::obs_tree::array_tree::ObsTree;
use crate::util::data_structs::arena_tree::ArenaTree;
use super::{AdaptiveDistinguishingSequence, AdsNode, AdsTree};
use crate::{
automatadefs::mealy::{InputSymbol, OutputSymbol, State},
learner::obs_tree::{array_tree::ObsTree, ObservationTree},
util::data_structs::arena_tree::ArenaTree,
};
impl AdsNode {
fn add_child(&mut self, output: OutputSymbol, child_idx: usize) {
......
......@@ -2,13 +2,13 @@ use super::{
super::traits::{AdaptiveDistinguishingSequence, AdsStatus},
utils::{compute_score, partition_on_output},
};
use crate::automatadefs::{
mealy::{InputSymbol, OutputSymbol, State},
traits::ObservationTree,
use crate::{
automatadefs::mealy::{InputSymbol, OutputSymbol, State},
learner::obs_tree::ObservationTree,
};
use fnv::FnvHashMap;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use std::{collections::HashMap, sync::Arc};
use std::{collections::HashMap, hash::BuildHasherDefault, sync::Arc};
#[derive(Debug, Default)]
struct Node {
......@@ -30,7 +30,7 @@ impl Node {
fn leaf_node() -> Self {
Self {
input: None,
children: FnvHashMap::with_capacity_and_hasher(0, Default::default()),
children: FnvHashMap::with_capacity_and_hasher(0, BuildHasherDefault::default()),
score: 0.0,
// block_size: 1,
}
......
use crate::automatadefs::{
mealy::{InputSymbol, OutputSymbol, State},
traits::ObservationTree,
use crate::{
automatadefs::mealy::{InputSymbol, OutputSymbol, State},
learner::obs_tree::ObservationTree,
};
use fnv::FnvHashMap;
use std::collections::BTreeSet;
......
use super::traits::FiniteStateMachine;
use super::FiniteStateMachine;
use fnv::{FnvHashMap, FnvHashSet};
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use std::fmt;
/// Newtype for an input symbol: wraps a usize.
/// Newtype for an input symbol: wraps a u16.
#[derive(
Clone, Default, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize,
)]
......@@ -170,11 +170,11 @@ impl FiniteStateMachine for Mealy {
})
}
fn states(&self) -> fnv::FnvHashSet<State> {
fn states(&self) -> FnvHashSet<State> {
self.states.clone()
}
fn output_alphabet(&self) -> fnv::FnvHashSet<OutputSymbol> {
fn output_alphabet(&self) -> FnvHashSet<OutputSymbol> {
self.output_alphabet.clone()
}
}
......@@ -182,32 +182,35 @@ impl FiniteStateMachine for Mealy {
#[cfg(test)]
mod tests {
use crate::{
automatadefs::{mealy::State, traits::FiniteStateMachine},
automatadefs::{
mealy::{Mealy, State},
FiniteStateMachine,
},
util::parsers::machine::read_mealy_from_file,
};
use std::path::Path;
fn load_basic_fsm() -> Mealy {
let file_name = Path::new("example.dot");
read_mealy_from_file(file_name.to_str().expect("Safe")).0
}
/// Ensure that the initial state is set.
#[test]
fn fsm_initial_state_is_set() {
let file_name = Path::new("example.dot");
let (fsm, _, _) = read_mealy_from_file(file_name.to_str().unwrap());
let fsm = load_basic_fsm();
assert_ne!(fsm.initial_state(), State::new(u32::MAX));
}
/// Ensure that the set of states is set.
#[test]
fn fsm_states_loaded_correctly() {
let file_name = Path::new("example.dot");
let (fsm, _, _) = read_mealy_from_file(file_name.to_str().unwrap());
assert_eq!(fsm.states().len(), 6);
assert_eq!(load_basic_fsm().states().len(), 6);
}
/// FSM must be complete.
#[test]
fn fsm_is_complete() {
let file_name = Path::new("example.dot");
let (fsm, _, _) = read_mealy_from_file(file_name.to_str().unwrap());
assert!(fsm.is_complete());
assert!(load_basic_fsm().is_complete());
}
}
use crate::automatadefs::mealy::{InputSymbol, OutputSymbol, State};
pub mod mealy;
pub mod traits;
/**
Trait for interacting with an FSM during learning.
Modification of the FSM is illegal during the learning process.
*/
pub trait FiniteStateMachine {
/// Get states of the FSM
fn states(&self) -> fnv::FnvHashSet<State>;
/// Check if the FSM is complete.
fn is_complete(&self) -> bool;
/// Return a copy of the initial state of the FSM.
fn initial_state(&self) -> State;
/// Stateless single step from given state.
fn step_from(&self, src: State, i: InputSymbol) -> (State, OutputSymbol);
/// Stateless multi-step from given state.
fn trace_from(&self, src: State, i_word: &[InputSymbol]) -> (State, Box<[OutputSymbol]>);
/// Stateless multi-step from initial state.
fn trace(&self, i_word: &[InputSymbol]) -> (State, Box<[OutputSymbol]>);
/// Return a copy of the input alphabet of the FSM.
fn input_alphabet(&self) -> Vec<InputSymbol>;
/// Return a copy of the output alphabet of the FSM.
fn output_alphabet(&self) -> fnv::FnvHashSet<OutputSymbol>;
}
use crate::automatadefs::mealy::{InputSymbol, OutputSymbol, State};
/**
Trait for interacting with an FSM during learning.
Modification of the FSM is illegal during the learning process.
*/
pub trait FiniteStateMachine {
/// Get states of the FSM
fn states(&self) -> fnv::FnvHashSet<State>;
/// Check if the FSM is complete.
fn is_complete(&self) -> bool;
/// Return a copy of the initial state of the FSM.
fn initial_state(&self) -> State;
/// Stateless single step from given state.
fn step_from(&self, src: State, i: InputSymbol) -> (State, OutputSymbol);
/// Stateless multi-step from given state.
fn trace_from(&self, src: State, i_word: &[InputSymbol]) -> (State, Box<[OutputSymbol]>);
/// Stateless multi-step from initial state.
fn trace(&self, i_word: &[InputSymbol]) -> (State, Box<[OutputSymbol]>);
/// Return a copy of the input alphabet of the FSM.
fn input_alphabet(&self) -> Vec<InputSymbol>;
/// Return a copy of the output alphabet of the FSM.
fn output_alphabet(&self) -> fnv::FnvHashSet<OutputSymbol>;
}
/**
Trait for any struct acting as an observation tree.
The observation tree is the primary data-structure of L#.
Any struct which is an observation tree must implement
this trait. The default implementation is [`ObsTree`](crate::learner::obs_tree::map_tree::ObsTree).
*/
pub trait ObservationTree {
/// Constructor.
fn new(input_size: usize) -> Self;
/// Insert an observation, with an optional `start` state.
/// If `start` is None, inserts from root.
fn insert_observation(
&mut self,
start: Option<State>,
input_seq: &[InputSymbol],
output_seq: &[OutputSymbol],
) -> State;
// Getter methods now, a lot compared to insertion ;)
/// Get the access sequence for `state`, beginning at the root node.
fn get_access_seq(&self, state: State) -> Vec<InputSymbol>;
/// Get the transfer sequence from `from_state` to `to_state`.
fn get_transfer_seq(&self, to_state: State, from_state: State) -> Vec<InputSymbol>;
/// Given an optional `start` state, get the output sequence for `input_seq`,
/// if defined.
fn get_observation(
&self,
start: Option<State>,
input_seq: &[InputSymbol],
) -> Option<Vec<OutputSymbol>>;
/// Given a state and an input, return the output and successor state, if defined.
fn get_out_succ(&self, src: State, input: InputSymbol) -> Option<(OutputSymbol, State)>;
/// Given a state and an input, return the output, if defined.
fn get_out(&self, src: State, input: InputSymbol) -> Option<OutputSymbol>;
/// Given a state and an *input sequence*, return the successor state, if defined.
fn get_succ(&self, src: State, input: &[InputSymbol]) -> Option<State>;
/// Return an array of`(State, InputSymbol)` where &forall;q &in; `basis`, &forall;i &in; I : &delta;(q,i) is undefined.
fn no_succ_defined(&self, basis: &[State], sort: bool) -> Box<[(State, InputSymbol)]>;
// Utility methods
/// Size of the tree.
fn size(&self) -> usize;
/// Size of the input alphabet.
fn input_size(&self) -> usize;
}
use super::obs_tree::ObservationTree;
use crate::{
automatadefs::{
mealy::{InputSymbol, Mealy, State},
traits::{FiniteStateMachine, ObservationTree},
FiniteStateMachine,
},
util::toolbox,
};
......
use super::obs_tree::ObservationTree;
use crate::{
ads::{
lee_yannakakis::adaptive_distinguishing_seq::AdsTree as LyAds,
......@@ -5,7 +6,7 @@ use crate::{
},
automatadefs::{
mealy::{InputSymbol, Mealy, MealyBuilder, OutputSymbol, State},
traits::{FiniteStateMachine, ObservationTree},
FiniteStateMachine,
},
learner::apartness::{compute_witness, states_are_apart},
oracles::{equivalence::equivalence_trait::CounterExample, membership::Oracle as OutputOracle},
......
use crate::{
automatadefs::{
mealy::{InputSymbol, Mealy, OutputSymbol},
traits::FiniteStateMachine,
FiniteStateMachine,
},
learner::{l_sharp::Lsharp, obs_tree::map_tree::ObsTree as ObsMapTree},
oracles::{
......@@ -17,7 +17,7 @@ use crate::{
},
membership::Oracle as OQOracle,
},
sul::{simulator::Simulator, system_under_learning::SystemUnderLearning},
sul::simulator::Simulator,
util::{
learning_config::{EqOracle, LearnResult, Rule2, Rule3},
writers::overall as MealyWriter,
......@@ -110,7 +110,7 @@ pub fn learn_fsm(
options.use_ly_ads,
);
let mut idx = 1;
let learned: bool;
let success: bool;
let mut learn_inputs: usize = 0;
let mut learn_resets: usize = 0;
let mut test_inputs: usize = 0;
......@@ -140,7 +140,7 @@ pub fn learn_fsm(
MealyWriter::write_machine(writer_config, &hypothesis, &rev_input_map, &rev_output_map);
let ideal_ce = perfect_oracle.find_counterexample(&hypothesis);
if ideal_ce.is_none() {
learned = true;
success = true;
println!("Learning finished!");
break;
}
......@@ -192,9 +192,9 @@ pub fn learn_fsm(
learner.process_cex(ce, &hypothesis);
} else {
println!("No CE found.");
learned = EqOracle::Internal == options.oracle_choice
success = EqOracle::Internal == options.oracle_choice
|| None == perfect_oracle.find_counterexample(&hypothesis);
println!("Model learned: {}", learned);
println!("Model learned: {}", success);
break;
}
idx += 1;
......@@ -214,14 +214,14 @@ pub fn learn_fsm(
"NOK"
}
};
log::info!("Equivalent : {}", equivalent(learned));
log::info!("Equivalent : {}", equivalent(success));
let ads_score = learner.get_ads_score();
LearnResult {
learn_inputs,
learn_resets,
eq_oracle: options.oracle_choice.clone(),
rounds: idx,
success: learned,
success,
test_inputs,
test_resets,
num_inputs: rev_input_map.len(),
......
use super::ObservationTree;
use crate::{
automatadefs::{
mealy::{InputSymbol, OutputSymbol, State},
traits::ObservationTree,
},
automatadefs::mealy::{InputSymbol, OutputSymbol, State},
util::data_structs::arena_tree::ArenaTree,
};
use itertools::iproduct;
use std::convert::TryInto;
#[derive(Debug)]
pub enum TreeErr {
AbsentEntry,
}
/**
Each edge is an array, indexed by [`InputSymbol`].
If the content is `None`, then the transition undefined.
......
use super::ObservationTree;
use crate::{
automatadefs::{
mealy::{InputSymbol, OutputSymbol, State},
traits::ObservationTree,
},
automatadefs::mealy::{InputSymbol, OutputSymbol, State},
util::data_structs::arena_tree::ArenaTree,
};
use itertools::Itertools;
......
use crate::automatadefs::mealy::{InputSymbol, OutputSymbol, State};
pub mod array_tree;
pub mod map_tree;
/// Trait for any struct acting as an observation tree.
///
/// The observation tree is the primary data-structure of L#.
/// Any struct which is an observation tree must implement
/// this trait. The default implementation is [`ObsTree`](crate::learner::obs_tree::map_tree::ObsTree).
pub trait ObservationTree {
/// Constructor.
fn new(input_size: usize) -> Self;
/// Insert an observation, with an optional `start` state.
/// If `start` is None, inserts from root.
fn insert_observation(
&mut self,
start: Option<State>,
input_seq: &[InputSymbol],
output_seq: &[OutputSymbol],
) -> State;
// Getter methods now, a lot compared to insertion ;)
/// Get the access sequence for `state`, beginning at the root node.
fn get_access_seq(&self, state: State) -> Vec<InputSymbol>;
/// Get the transfer sequence from `from_state` to `to_state`.
fn get_transfer_seq(&self, to_state: State, from_state: State) -> Vec<InputSymbol>;
/// Given an optional `start` state, get the output sequence for `input_seq`,
/// if defined.
fn get_observation(
&self,
start: Option<State>,
input_seq: &[InputSymbol],
) -> Option<Vec<OutputSymbol>>;
/// Given a state and an input, return the output and successor state, if defined.
fn get_out_succ(&self, src: State, input: InputSymbol) -> Option<(OutputSymbol, State)>;
/// Given a state and an input, return the output, if defined.
fn get_out(&self, src: State, input: InputSymbol) -> Option<OutputSymbol>;
/// Given a state and an *input sequence*, return the successor state, if defined.
fn get_succ(&self, src: State, input: &[InputSymbol]) -> Option<State>;
/// Return an array of`(State, InputSymbol)` where &forall;q &in; `basis`, &forall;i &in; I : &delta;(q,i) is undefined.
fn no_succ_defined(&self, basis: &[State], sort: bool) -> Box<[(State, InputSymbol)]>;
// Utility methods
/// Size of the tree.
fn size(&self) -> usize;
/// Size of the input alphabet.
fn input_size(&self) -> usize;
}
#[derive(Debug)]
pub enum TreeErr {
AbsentEntry,
}
use super::equivalence_trait::CounterExample;
use crate::automatadefs::{mealy::State, traits::FiniteStateMachine};
use crate::automatadefs::{mealy::State, FiniteStateMachine};
use fnv::FnvHashSet;
use std::collections::VecDeque;
......
use super::{automata, equivalence_trait::CounterExample};
use crate::automatadefs::traits::FiniteStateMachine;
use crate::automatadefs::FiniteStateMachine;
/**
Breadth-First Search Equivalence Oracle
......
......@@ -11,7 +11,7 @@ pub type CounterExample = Option<(Vec<InputSymbol>, Vec<OutputSymbol>)>;
/**
Trait for equivalence oracles.
`T` is the type for the Observation Tree, i.e., if a different type of
`Tree` is the type for the Observation Tree, i.e., if a different type of
data structure is used to construct the observation tree, that will work
as well.
*/
......
......@@ -2,8 +2,9 @@ use super::equivalence_trait::{CounterExample, EquivalenceOracle, ExternalEquiva
use crate::{
automatadefs::{
mealy::{InputSymbol, Mealy, OutputSymbol},
traits::{FiniteStateMachine, ObservationTree},
FiniteStateMachine,
},
learner::obs_tree::ObservationTree,
oracles::membership::Oracle as OQOracle,
util::writers::overall as MealyWriter,
};
......
......@@ -3,9 +3,9 @@ use crate::{
ads::traits::AdaptiveDistinguishingSequence,
automatadefs::{
mealy::{InputSymbol, Mealy, State},
traits::{FiniteStateMachine, ObservationTree},
FiniteStateMachine,
},
learner::apartness::states_are_apart,
learner::{apartness::states_are_apart, obs_tree::ObservationTree},
oracles::{
equivalence::{
automata::shortest_separating_sequence,
......@@ -331,9 +331,8 @@ mod tests {
use rstest::rstest;
use super::random_access_map;
use crate::{
automatadefs::traits::FiniteStateMachine, util::parsers::machine::read_mealy_from_file,
};
use crate::automatadefs::FiniteStateMachine;
use crate::util::parsers::machine::read_mealy_from_file;
use std::collections::HashSet;
#[rstest]
......
......@@ -3,7 +3,7 @@ use crate::{
ads::traits::{AdaptiveDistinguishingSequence, AdsStatus},
automatadefs::{
mealy::{InputSymbol, Mealy, OutputSymbol, State},
traits::FiniteStateMachine,
FiniteStateMachine,
},
util::data_structs::arena_tree::ArenaTree,
};
......
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