rust-lstar 0.2.0

L* (Angluin's) Grammatical Inference Algorithm for learning Deterministic Finite Automata
Documentation
# Quick Start Guide - rust-lstar


Get started with the L* learning algorithm in 5 minutes!

## Installation


You need Rust. If you don't have it, install from [https://rustup.rs/](https://rustup.rs/)

```bash
# Clone or download the repository

cd rust-lstar

# Build the project

cargo build --release

# Run the demo

cargo run
```

## Basic Usage


### 1. Create a Knowledge Base


Implement the `KnowledgeBase` trait to define your system:

```rust
use rust_lstar::{KnowledgeBase, OutputQuery, Word, Letter};
use std::sync::Arc;

struct MySystem;

impl KnowledgeBase for MySystem {
    fn resolve_query(&self, query: &mut OutputQuery) -> Result<(), String> {
        // For each input, produce an output
        let outputs: Vec<Letter> = query.input_word
            .letters()
            .iter()
            .map(|_| Letter::new("output"))
            .collect();
        
        query.set_result(Word::from_letters(outputs));
        Ok(())
    }
}
```

### 2. Define Your Alphabet


```rust
let vocabulary = vec![
    "a".to_string(),
    "b".to_string(),
    "c".to_string(),
];
```

### 3. Run the Learner


```rust
use rust_lstar::LSTAR;
use std::sync::Arc;

let kb = Arc::new(MySystem);
let mut lstar = LSTAR::new(vocabulary, kb, 10); // max 10 states

match lstar.learn() {
    Ok(automata) => {
        println!("{}", automata.build_dot_code());
    }
    Err(e) => eprintln!("Error: {}", e),
}
```

## Running Examples


Three examples are provided:

```bash
# Simple vending machine simulation

cargo run --example vending_machine

# Using random walk equivalence testing

cargo run --example random_walk_eq

# Custom knowledge base (ATM protocol)

cargo run --example custom_kb
```

## Complete Minimal Example


```rust
use rust_lstar::*;
use std::sync::Arc;

// Simple knowledge base that echoes 'X' for each input
struct EchoKB;

impl KnowledgeBase for EchoKB {
    fn resolve_query(&self, query: &mut OutputQuery) -> Result<(), String> {
        let outputs = query.input_word
            .letters()
            .iter()
            .map(|_| Letter::new("X"))
            .collect::<Vec<_>>();
        query.set_result(Word::from_letters(outputs));
        Ok(())
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let kb = Arc::new(EchoKB);
    let vocab = vec!["a".to_string(), "b".to_string()];
    
    let mut lstar = LSTAR::new(vocab, kb, 5);
    let automata = lstar.learn()?;
    
    println!("{}", automata.build_dot_code());
    Ok(())
}
```

## Key Concepts


### Knowledge Base

Represents your "System Under Learning" - something you want to model

### Vocabulary

The alphabet of input commands your system understands

### Automata

The learned state machine - outputs in Graphviz DOT format

### Equivalence Test

Strategy for checking if the learned automaton is correct:
- **W-method**: Exhaustive (default)
- **RandomWalk**: Probabilistic (faster)

## Customizing Equivalence Testing


Use a different equivalence test:

```rust
use rust_lstar::equivalence_test::RandomWalkMethod;

let input_letters = vocab.iter().map(|s| Letter::new(s)).collect();
let random_walk = RandomWalkMethod::new(
    kb.clone(), 
    input_letters,
    100,    // num_tries
    2.0,    // walk_length_ratio
);

let mut lstar = LSTAR::new(vocab, kb, 5)
    .with_equivalence_test(Arc::new(random_walk));
```

## Testing


Run all tests:
```bash
cargo test
```

Run only library tests:
```bash
cargo test --lib
```

Run a specific example:
```bash
cargo test --example vending_machine
```

## Output


The learned automaton is printed in Graphviz DOT format:

```dot
digraph "Automata" {
    "0" [shape=doubleoctagon, ...];
    "1" [shape=ellipse, ...];
    "0" -> "1" [label="a / output", ...];
}
```

### Visualize the automaton:

```bash
# Save to graphviz

cargo run > automata.dot

# Convert to image (requires graphviz)

dot -Tpng automata.dot -o automata.png
```

## Debugging


Enable detailed logging:
```bash
RUST_LOG=info cargo run
```

## Common Issues


### "No initial state found"

The observation table couldn't build a valid automaton. Usually means:
- System is not deterministic
- Vocabulary is incomplete
- Max states too small

### "Query execution failed"

The knowledge base returned an error:
- Check your `resolve_query()` implementation
- Ensure it produces output for all inputs

### Learning takes too long

Try:
- Reducing max_states
- Using RandomWalkMethod instead of W-method
- Checking if system is actually learnable

## Next Steps


1. **Read the README**: `README.md` for full documentation
2. **Explore Examples**: Check `examples/` directory
3. **Review Design**: `DESIGN.md` for architecture details
4. **Implement Your System**: Create custom knowledge base

## Tips & Tricks


### Performance (v0.2.0+)

```rust
// Optimizations are automatic:
// - Cached transition lookups (30-50% faster)
// - SmallVec for short words (no heap allocation)
// - Reduced cloning (20-30% fewer allocations)
// Overall: 2-3x faster for large automata
```

### Faster Learning

```rust
// Use random walk instead of W-method
let random_walk = RandomWalkMethod::new(kb, letters, 50, 1.5);
let lstar = LSTAR::new(vocab, kb, states)
    .with_equivalence_test(Arc::new(random_walk));
```

### Better Understanding

```rust
// Enable logging
env_logger::init();
RUST_LOG=info cargo run
```

### Testing Your System

```rust
// Use FakeKnowledgeBase until you're ready
let kb = Arc::new(FakeKnowledgeBase::new());
```

### Exporting Results

```rust
// Print automaton
println!("{}", automata.build_dot_code());

// Access internal structure
for state in &automata.states {
    println!("State: {}", state.name);
    for transition in &state.transitions {
        println!("  {} -> {}", transition.input_letter, transition.output_letter);
    }
}
```

## Resources


- [L* Algorithm Paper]https://dl.acm.org/doi/10.1016/0890-5401(8790052-6)
- [Graphviz Visualization]https://graphviz.org/
- [Original pylstar]https://github.com/gbossert/pylstar

## Getting Help


- Check examples in `examples/` directory
- Read `README.md` for detailed documentation
- Review `DESIGN.md` for architecture understanding
- Look at unit tests in `src/` for usage patterns

Happy learning! 🚀