1use rust_lstar::knowledge_base::{KnowledgeBaseStats, KnowledgeBaseTrait};
3use rust_lstar::query::OutputQuery;
4use rust_lstar::*;
5use std::collections::HashMap;
6use std::sync::{Arc, Mutex};
7use std::time::Instant;
8
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10 println!("=== Performance Benchmark ===\n");
11
12 let mut kb = BenchmarkKnowledgeBase::new();
14
15 kb.add_transition("s0", "a", "0", "s1");
18 kb.add_transition("s0", "b", "1", "s2");
19 kb.add_transition("s0", "c", "0", "s0");
20
21 kb.add_transition("s1", "a", "1", "s2");
22 kb.add_transition("s1", "b", "0", "s3");
23 kb.add_transition("s1", "c", "1", "s1");
24
25 kb.add_transition("s2", "a", "0", "s3");
26 kb.add_transition("s2", "b", "1", "s0");
27 kb.add_transition("s2", "c", "0", "s2");
28
29 kb.add_transition("s3", "a", "1", "s0");
30 kb.add_transition("s3", "b", "0", "s1");
31 kb.add_transition("s3", "c", "1", "s3");
32
33 let knowledge_base = Arc::new(Mutex::new(kb));
34 let vocabulary = vec!["a".to_string(), "b".to_string(), "c".to_string()];
35
36 println!("Learning 4-state automaton with 3-symbol alphabet...\n");
37
38 let start = Instant::now();
39 let mut lstar = LSTAR::new(vocabulary, knowledge_base.clone(), 6, None, None);
40 let automata = lstar.learn()?;
41 let duration = start.elapsed();
42
43 println!("\n=== Results ===" );
44 println!("Learning time: {:.2?}", duration);
45 println!("States learned: {}", automata.get_states().len());
46 println!("Transitions: {}", automata.transitions.len());
47
48 let kb_guard = knowledge_base.lock().unwrap();
49 println!("\nQuery Statistics:");
50 println!(" Total queries: {}", kb_guard.stats.nb_query());
51 println!(" Total letters processed: {}", kb_guard.stats.nb_letter());
52 println!(" Avg letters per query: {:.2}",
53 kb_guard.stats.nb_letter() as f64 / kb_guard.stats.nb_query() as f64);
54
55 println!("\n=== Optimization Benefits ===");
56 println!("✓ Cached transition index: Fast automata playback");
57 println!("✓ SmallVec: Reduced allocations for short words");
58 println!("✓ Enum Letter: Optimized single-symbol storage");
59 println!("✓ HashSet dedup: O(1) query deduplication");
60 println!("✓ Pre-allocated collections: Fewer reallocations");
61
62 Ok(())
63}
64
65struct BenchmarkKnowledgeBase {
66 transitions: HashMap<(String, String), (String, String)>,
67 current_state: String,
68 stats: KnowledgeBaseStats,
69}
70
71impl BenchmarkKnowledgeBase {
72 fn new() -> Self {
73 Self {
74 transitions: HashMap::new(),
75 current_state: "s0".to_string(),
76 stats: KnowledgeBaseStats::new(),
77 }
78 }
79
80 fn add_transition(&mut self, from_state: &str, input: &str, output: &str, to_state: &str) {
81 self.transitions.insert(
82 (from_state.to_string(), input.to_string()),
83 (output.to_string(), to_state.to_string()),
84 );
85 }
86}
87
88impl KnowledgeBaseTrait for BenchmarkKnowledgeBase {
89 fn resolve_query(&mut self, query: &mut OutputQuery) -> Result<(), String> {
90 self.stats.increment_nb_query();
91 self.stats.add_nb_letter(query.input_word.len());
92 self.stats.increment_nb_submitted_query();
93 self.stats.add_nb_submitted_letter(query.input_word.len());
94
95 self.current_state = "s0".to_string();
96 let mut output_letters = Vec::new();
97
98 for input_letter in query.input_word.letters() {
99 let input = input_letter.symbols();
100 let key = (self.current_state.clone(), input);
101 let (output, next_state) = self
102 .transitions
103 .get(&key)
104 .cloned()
105 .ok_or_else(|| format!("No transition for ({}, {})", key.0, key.1))?;
106
107 output_letters.push(Letter::new(output));
108 self.current_state = next_state;
109 }
110
111 query.set_result(Word::from_letters(output_letters));
112 Ok(())
113 }
114
115 fn add_word(&mut self, _input_word: &Word, _output_word: &Word) -> Result<(), String> {
116 Ok(())
117 }
118}