pub struct LSTAR {
pub input_vocabulary: Vec<Letter>,
pub knowledge_base: Arc<Mutex<dyn KnowledgeBaseTrait>>,
pub tmp_dir: Option<String>,
pub observation_table: Option<ObservationTable>,
pub max_states: usize,
pub equivalence_test: Arc<dyn EquivalenceTest>,
/* private fields */
}Expand description
The L* algorithm implementation
Fields§
§input_vocabulary: Vec<Letter>§knowledge_base: Arc<Mutex<dyn KnowledgeBaseTrait>>§tmp_dir: Option<String>§observation_table: Option<ObservationTable>§max_states: usize§equivalence_test: Arc<dyn EquivalenceTest>Implementations§
Source§impl LSTAR
impl LSTAR
Sourcepub fn new(
input_vocabulary: Vec<String>,
knowledge_base: Arc<Mutex<dyn KnowledgeBaseTrait>>,
max_states: usize,
tmp_dir: Option<String>,
eq_test: Option<Arc<dyn EquivalenceTest>>,
) -> Self
pub fn new( input_vocabulary: Vec<String>, knowledge_base: Arc<Mutex<dyn KnowledgeBaseTrait>>, max_states: usize, tmp_dir: Option<String>, eq_test: Option<Arc<dyn EquivalenceTest>>, ) -> Self
Create a new LSTAR learner
Examples found in repository?
examples/vending_machine.rs (line 21)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 println!("=== Vending Machine Learning Example ===\n");
9
10 // Create a vending machine knowledge base (SUL)
11 let kb = Arc::new(Mutex::new(VendingMachineKB::new()));
12
13 // Define input vocabulary
14 let vocabulary = vec![
15 "INSERT_COIN".to_string(),
16 "PRESS_A".to_string(),
17 "PRESS_B".to_string(),
18 ];
19
20 // Run L* learner
21 let mut learner = LSTAR::new(vocabulary, kb.clone(), 4, None, None);
22 match learner.learn() {
23 Ok(automata) => {
24 println!("\n=== Learned Vending Machine ===\n");
25 println!("{}", automata.build_dot_code());
26 }
27 Err(e) => eprintln!("Learning error: {}", e),
28 }
29
30 let kb_guard = kb.lock().unwrap();
31 println!("\nKnowledge Base Statistics:\n{}", kb_guard.stats);
32
33 Ok(())
34}More examples
examples/custom_kb.rs (line 23)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 println!("=== Custom Knowledge Base Example ===");
11 println!("Simulating a banking ATM protocol\n");
12
13 let kb = Arc::new(Mutex::new(ATMKnowledgeBase::new()));
14
15 let vocabulary = vec![
16 "INSERT_CARD".to_string(),
17 "ENTER_PIN".to_string(),
18 "REQUEST_WITHDRAW".to_string(),
19 "EJECT_CARD".to_string(),
20 "TIMEOUT".to_string(),
21 ];
22
23 let mut lstar = LSTAR::new(vocabulary, kb.clone(), 8, None, None);
24
25 match lstar.learn() {
26 Ok(automata) => {
27 println!("\n=== Learned ATM Protocol ===");
28 println!("{}", automata.build_dot_code());
29 println!("\nATM protocol learned successfully!");
30 }
31 Err(e) => eprintln!("Error: {}", e),
32 }
33
34 let kb_guard = kb.lock().unwrap();
35 println!("\nKnowledge Base Stats:\n{}", kb_guard.stats);
36
37 Ok(())
38}examples/memory_kb.rs (line 31)
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 println!("=== Memory Knowledge Base Learning Example ===\n");
12
13 let input_symbols = vec!["a", "b", "c"];
14 let output_symbols = vec!["0", "1", "2", "3"];
15 let target_state_count = 5;
16 let max_states = 8;
17
18 let target = build_random_machine(target_state_count, &input_symbols, &output_symbols);
19 println!(
20 "Random target generated (states={}, transitions={})",
21 target.get_states().len(),
22 target.transitions.len()
23 );
24
25 let kb = Arc::new(Mutex::new(RandomMachineKnowledgeBase::new(target.clone())));
26 let vocabulary = input_symbols
27 .iter()
28 .map(|symbol| symbol.to_string())
29 .collect::<Vec<_>>();
30
31 let mut learner = LSTAR::new(vocabulary, kb.clone(), max_states, None, None);
32 let learned = learner.learn()?;
33
34 println!("\n=== Learned Automaton ===");
35 println!("{}", learned.build_dot_code());
36
37 let kb_guard = kb.lock().unwrap();
38 println!("\nKnowledge Base Statistics:\n{}", kb_guard.stats());
39
40 Ok(())
41}examples/network_custom_kb.rs (line 31)
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13 println!("=== Network Custom KB (ATM) Example ===\n");
14
15 // Expects an independent ATM server running
16 // (see examples/custom_kb_server.rs).
17 let kb = NetworkActiveKnowledgeBase::new("127.0.0.1".to_string(), 3001, Duration::from_secs(5));
18
19 let vocabulary = vec![
20 "INSERT_CARD".to_string(),
21 "ENTER_PIN".to_string(),
22 "REQUEST_WITHDRAW".to_string(),
23 "EJECT_CARD".to_string(),
24 "TIMEOUT".to_string(),
25 ];
26
27 println!("Target Host: {}", kb.target_host());
28 println!("Target Port: {}\n", kb.target_port());
29
30 let kb: Arc<Mutex<dyn KnowledgeBaseTrait>> = Arc::new(Mutex::new(kb));
31 let mut learner = LSTAR::new(vocabulary, kb, 8, None, None);
32
33 match learner.learn() {
34 Ok(automata) => {
35 println!("\n=== Learned ATM Automaton from Network Target ===\n");
36 println!("{}", automata.build_dot_code());
37 println!(
38 "\nStates: {}\nTransitions: {}",
39 automata.get_states().len(),
40 automata.transitions.len()
41 );
42 }
43 Err(e) => {
44 eprintln!("Learning error: {}", e);
45 println!("\nTo run this example with a real connection:");
46 println!(" 1. Start ATM server: cargo run --example custom_kb_server");
47 println!(" 2. Run this example again: cargo run --example network_custom_kb");
48 }
49 }
50
51 Ok(())
52}examples/network_kb.rs (line 31)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 println!("=== Network Active Knowledge Base Example ===\n");
11
12 // This example expects an independent coffee server running
13 // (see examples/coffee_server.rs).
14 let kb = NetworkActiveKnowledgeBase::new("127.0.0.1".to_string(), 3000, Duration::from_secs(5));
15
16 // Define input vocabulary
17 let vocabulary = vec![
18 "REFILL_WATER".to_string(),
19 "REFILL_COFFEE".to_string(),
20 "PRESS_BUTTON_A".to_string(),
21 "PRESS_BUTTON_B".to_string(),
22 "PRESS_BUTTON_C".to_string(),
23 ];
24
25 println!("Target Host: {}", kb.target_host());
26 println!("Target Port: {}\n", kb.target_port());
27
28 let kb: Arc<Mutex<dyn KnowledgeBaseTrait>> = Arc::new(Mutex::new(kb));
29
30 // Create learner. The network KB connects per submitted word.
31 let mut learner = LSTAR::new(vocabulary, kb, 4, None, None);
32
33 match learner.learn() {
34 Ok(automata) => {
35 println!("\n=== Learned Automaton from Network Target ===\n");
36 println!("{}", automata.build_dot_code());
37 println!(
38 "\nStates: {}\nTransitions: {}",
39 automata.get_states().len(),
40 automata.transitions.len()
41 );
42 }
43 Err(e) => {
44 eprintln!("Learning error: {}", e);
45 println!("\nTo run this example with a real connection:");
46 println!(" 1. Start a coffee server: cargo run --example coffee_server");
47 println!(" 2. Run this example again");
48 }
49 }
50
51 Ok(())
52}examples/all_eqtests_custom_kb.rs (line 85)
68fn run_strategy(name: &str, builder: &EqBuilder) -> StrategyReport {
69 let vocabulary = vec![
70 "INSERT_CARD".to_string(),
71 "ENTER_PIN".to_string(),
72 "REQUEST_WITHDRAW".to_string(),
73 "EJECT_CARD".to_string(),
74 "TIMEOUT".to_string(),
75 ];
76 let input_letters = vocabulary
77 .iter()
78 .map(|s| Letter::new(s))
79 .collect::<Vec<_>>();
80 let max_states = 8;
81
82 let kb = Arc::new(Mutex::new(ATMKnowledgeBase::new()));
83 let knowledge_base: SharedKb = kb.clone();
84 let eqtest = builder(knowledge_base.clone(), input_letters, max_states);
85 let mut learner = LSTAR::new(vocabulary, knowledge_base, max_states, None, Some(eqtest));
86
87 println!("\n--- Running {name} ---");
88 let started = Instant::now();
89 let learn_result = learner.learn();
90 let elapsed_ms = started.elapsed().as_millis();
91
92 let stats = {
93 let kb_guard = kb.lock().unwrap();
94 StatsSnapshot::from_stats(&kb_guard.stats)
95 };
96
97 match learn_result {
98 Ok(automata) => {
99 let state_count = automata.get_states().len();
100 let transition_count = automata.transitions.len();
101 println!("{name}: success (states={state_count}, transitions={transition_count})");
102 StrategyReport {
103 name: name.to_string(),
104 elapsed_ms,
105 state_count: Some(state_count),
106 transition_count: Some(transition_count),
107 error: None,
108 stats,
109 }
110 }
111 Err(err) => {
112 println!("{name}: failed ({err})");
113 StrategyReport {
114 name: name.to_string(),
115 elapsed_ms,
116 state_count: None,
117 transition_count: None,
118 error: Some(err),
119 stats,
120 }
121 }
122 }
123}Additional examples can be found in:
Sourcepub fn with_equivalence_test(self, eq_test: Arc<dyn EquivalenceTest>) -> Self
pub fn with_equivalence_test(self, eq_test: Arc<dyn EquivalenceTest>) -> Self
Set a custom equivalence test
Examples found in repository?
examples/random_walk_eq.rs (line 51)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 println!("=== Random Walk Equivalence Test Example ===\n");
11
12 // Create a simple system
13 let mut kb = DemoKnowledgeBase::new();
14
15 // Define a simple state machine:
16 // S0 -a/0-> S1 (initial state)
17 // S0 -b/1-> S0
18 // S1 -a/0-> S2
19 // S1 -b/1-> S0
20 // S2 -a/0-> S2
21 // S2 -b/1-> S1
22
23 // Make outputs state-dependent so learner must distinguish states
24 kb.add_transition("s0", "a", "0", "s1");
25 kb.add_transition("s0", "b", "1", "s0");
26 kb.add_transition("s1", "a", "1", "s2");
27 kb.add_transition("s1", "b", "0", "s0");
28 kb.add_transition("s2", "a", "1", "s2");
29 kb.add_transition("s2", "b", "0", "s1");
30
31 let knowledge_base = Arc::new(Mutex::new(kb));
32
33 // Create vocabulary
34 let vocabulary = vec!["a".to_string(), "b".to_string()];
35
36 // Create learner
37 let mut lstar = LSTAR::new(vocabulary.clone(), knowledge_base.clone(), 5, None, None);
38
39 // Use random walk equivalence test instead of W-method
40 let input_letters = vocabulary
41 .iter()
42 .map(|s| Letter::new(s))
43 .collect::<Vec<_>>();
44 let random_walk = RandomWalkMethod::new(
45 knowledge_base.clone(),
46 input_letters,
47 10000, // max_steps: 10000 steps
48 0.75, // restart_probability: 75%
49 );
50
51 lstar = lstar.with_equivalence_test(Arc::new(random_walk));
52
53 // Run learning
54 match lstar.learn() {
55 Ok(automata) => {
56 println!("\n=== Learned Automaton (Random Walk Test) ===\n");
57 println!("{}", automata.build_dot_code());
58 println!("\nLearning completed successfully!");
59
60 // Print statistics
61 println!("\nStatistics:");
62 println!(" Number of states: {}", automata.get_states().len());
63 println!(" Number of transitions: {}", automata.transitions.len());
64 }
65 Err(e) => eprintln!("Error during learning: {}", e),
66 }
67
68 let kb_guard = knowledge_base.lock().unwrap();
69 println!("\nKnowledge Base Statistics:\n{}", kb_guard.stats);
70
71 Ok(())
72}Sourcepub fn learn(&mut self) -> Result<Automata, String>
pub fn learn(&mut self) -> Result<Automata, String>
Run the L* algorithm
Examples found in repository?
examples/vending_machine.rs (line 22)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8 println!("=== Vending Machine Learning Example ===\n");
9
10 // Create a vending machine knowledge base (SUL)
11 let kb = Arc::new(Mutex::new(VendingMachineKB::new()));
12
13 // Define input vocabulary
14 let vocabulary = vec![
15 "INSERT_COIN".to_string(),
16 "PRESS_A".to_string(),
17 "PRESS_B".to_string(),
18 ];
19
20 // Run L* learner
21 let mut learner = LSTAR::new(vocabulary, kb.clone(), 4, None, None);
22 match learner.learn() {
23 Ok(automata) => {
24 println!("\n=== Learned Vending Machine ===\n");
25 println!("{}", automata.build_dot_code());
26 }
27 Err(e) => eprintln!("Learning error: {}", e),
28 }
29
30 let kb_guard = kb.lock().unwrap();
31 println!("\nKnowledge Base Statistics:\n{}", kb_guard.stats);
32
33 Ok(())
34}More examples
examples/custom_kb.rs (line 25)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 println!("=== Custom Knowledge Base Example ===");
11 println!("Simulating a banking ATM protocol\n");
12
13 let kb = Arc::new(Mutex::new(ATMKnowledgeBase::new()));
14
15 let vocabulary = vec![
16 "INSERT_CARD".to_string(),
17 "ENTER_PIN".to_string(),
18 "REQUEST_WITHDRAW".to_string(),
19 "EJECT_CARD".to_string(),
20 "TIMEOUT".to_string(),
21 ];
22
23 let mut lstar = LSTAR::new(vocabulary, kb.clone(), 8, None, None);
24
25 match lstar.learn() {
26 Ok(automata) => {
27 println!("\n=== Learned ATM Protocol ===");
28 println!("{}", automata.build_dot_code());
29 println!("\nATM protocol learned successfully!");
30 }
31 Err(e) => eprintln!("Error: {}", e),
32 }
33
34 let kb_guard = kb.lock().unwrap();
35 println!("\nKnowledge Base Stats:\n{}", kb_guard.stats);
36
37 Ok(())
38}examples/memory_kb.rs (line 32)
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 println!("=== Memory Knowledge Base Learning Example ===\n");
12
13 let input_symbols = vec!["a", "b", "c"];
14 let output_symbols = vec!["0", "1", "2", "3"];
15 let target_state_count = 5;
16 let max_states = 8;
17
18 let target = build_random_machine(target_state_count, &input_symbols, &output_symbols);
19 println!(
20 "Random target generated (states={}, transitions={})",
21 target.get_states().len(),
22 target.transitions.len()
23 );
24
25 let kb = Arc::new(Mutex::new(RandomMachineKnowledgeBase::new(target.clone())));
26 let vocabulary = input_symbols
27 .iter()
28 .map(|symbol| symbol.to_string())
29 .collect::<Vec<_>>();
30
31 let mut learner = LSTAR::new(vocabulary, kb.clone(), max_states, None, None);
32 let learned = learner.learn()?;
33
34 println!("\n=== Learned Automaton ===");
35 println!("{}", learned.build_dot_code());
36
37 let kb_guard = kb.lock().unwrap();
38 println!("\nKnowledge Base Statistics:\n{}", kb_guard.stats());
39
40 Ok(())
41}examples/network_custom_kb.rs (line 33)
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13 println!("=== Network Custom KB (ATM) Example ===\n");
14
15 // Expects an independent ATM server running
16 // (see examples/custom_kb_server.rs).
17 let kb = NetworkActiveKnowledgeBase::new("127.0.0.1".to_string(), 3001, Duration::from_secs(5));
18
19 let vocabulary = vec![
20 "INSERT_CARD".to_string(),
21 "ENTER_PIN".to_string(),
22 "REQUEST_WITHDRAW".to_string(),
23 "EJECT_CARD".to_string(),
24 "TIMEOUT".to_string(),
25 ];
26
27 println!("Target Host: {}", kb.target_host());
28 println!("Target Port: {}\n", kb.target_port());
29
30 let kb: Arc<Mutex<dyn KnowledgeBaseTrait>> = Arc::new(Mutex::new(kb));
31 let mut learner = LSTAR::new(vocabulary, kb, 8, None, None);
32
33 match learner.learn() {
34 Ok(automata) => {
35 println!("\n=== Learned ATM Automaton from Network Target ===\n");
36 println!("{}", automata.build_dot_code());
37 println!(
38 "\nStates: {}\nTransitions: {}",
39 automata.get_states().len(),
40 automata.transitions.len()
41 );
42 }
43 Err(e) => {
44 eprintln!("Learning error: {}", e);
45 println!("\nTo run this example with a real connection:");
46 println!(" 1. Start ATM server: cargo run --example custom_kb_server");
47 println!(" 2. Run this example again: cargo run --example network_custom_kb");
48 }
49 }
50
51 Ok(())
52}examples/network_kb.rs (line 33)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 println!("=== Network Active Knowledge Base Example ===\n");
11
12 // This example expects an independent coffee server running
13 // (see examples/coffee_server.rs).
14 let kb = NetworkActiveKnowledgeBase::new("127.0.0.1".to_string(), 3000, Duration::from_secs(5));
15
16 // Define input vocabulary
17 let vocabulary = vec![
18 "REFILL_WATER".to_string(),
19 "REFILL_COFFEE".to_string(),
20 "PRESS_BUTTON_A".to_string(),
21 "PRESS_BUTTON_B".to_string(),
22 "PRESS_BUTTON_C".to_string(),
23 ];
24
25 println!("Target Host: {}", kb.target_host());
26 println!("Target Port: {}\n", kb.target_port());
27
28 let kb: Arc<Mutex<dyn KnowledgeBaseTrait>> = Arc::new(Mutex::new(kb));
29
30 // Create learner. The network KB connects per submitted word.
31 let mut learner = LSTAR::new(vocabulary, kb, 4, None, None);
32
33 match learner.learn() {
34 Ok(automata) => {
35 println!("\n=== Learned Automaton from Network Target ===\n");
36 println!("{}", automata.build_dot_code());
37 println!(
38 "\nStates: {}\nTransitions: {}",
39 automata.get_states().len(),
40 automata.transitions.len()
41 );
42 }
43 Err(e) => {
44 eprintln!("Learning error: {}", e);
45 println!("\nTo run this example with a real connection:");
46 println!(" 1. Start a coffee server: cargo run --example coffee_server");
47 println!(" 2. Run this example again");
48 }
49 }
50
51 Ok(())
52}examples/all_eqtests_custom_kb.rs (line 89)
68fn run_strategy(name: &str, builder: &EqBuilder) -> StrategyReport {
69 let vocabulary = vec![
70 "INSERT_CARD".to_string(),
71 "ENTER_PIN".to_string(),
72 "REQUEST_WITHDRAW".to_string(),
73 "EJECT_CARD".to_string(),
74 "TIMEOUT".to_string(),
75 ];
76 let input_letters = vocabulary
77 .iter()
78 .map(|s| Letter::new(s))
79 .collect::<Vec<_>>();
80 let max_states = 8;
81
82 let kb = Arc::new(Mutex::new(ATMKnowledgeBase::new()));
83 let knowledge_base: SharedKb = kb.clone();
84 let eqtest = builder(knowledge_base.clone(), input_letters, max_states);
85 let mut learner = LSTAR::new(vocabulary, knowledge_base, max_states, None, Some(eqtest));
86
87 println!("\n--- Running {name} ---");
88 let started = Instant::now();
89 let learn_result = learner.learn();
90 let elapsed_ms = started.elapsed().as_millis();
91
92 let stats = {
93 let kb_guard = kb.lock().unwrap();
94 StatsSnapshot::from_stats(&kb_guard.stats)
95 };
96
97 match learn_result {
98 Ok(automata) => {
99 let state_count = automata.get_states().len();
100 let transition_count = automata.transitions.len();
101 println!("{name}: success (states={state_count}, transitions={transition_count})");
102 StrategyReport {
103 name: name.to_string(),
104 elapsed_ms,
105 state_count: Some(state_count),
106 transition_count: Some(transition_count),
107 error: None,
108 stats,
109 }
110 }
111 Err(err) => {
112 println!("{name}: failed ({err})");
113 StrategyReport {
114 name: name.to_string(),
115 elapsed_ms,
116 state_count: None,
117 transition_count: None,
118 error: Some(err),
119 stats,
120 }
121 }
122 }
123}Additional examples can be found in:
Auto Trait Implementations§
impl Freeze for LSTAR
impl !RefUnwindSafe for LSTAR
impl !Send for LSTAR
impl !Sync for LSTAR
impl Unpin for LSTAR
impl UnsafeUnpin for LSTAR
impl !UnwindSafe for LSTAR
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more