karma 1.0.0

A sophisticated Hidden Markov Model (HMM) implementation using the Baum-Welch algorithm
Documentation
use karma::HiddenMarkovModel;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("HMM Pattern Classification Example\n");
    println!("===================================\n");

    // We'll train an HMM to distinguish between three types of sequences:
    // Type A: Alternating pattern (0,1,0,1,...)
    // Type B: Sequential pattern (0,1,2,3,...)
    // Type C: Random-ish pattern

    let n_states = 15;
    let n_observations = 4;

    println!(
        "Creating HMM with {} states and {} observations...\n",
        n_states, n_observations
    );
    let mut hmm = HiddenMarkovModel::builder()
        .states(n_states)
        .observations(n_observations)
        .randomize(true)
        .build()?;

    // Type A training data: alternating patterns
    println!("Training on Type A (alternating patterns)...");
    let type_a_sequences = vec![
        vec![0, 1, 0, 1, 0, 1, 0, 1],
        vec![1, 0, 1, 0, 1, 0, 1, 0],
        vec![2, 3, 2, 3, 2, 3, 2, 3],
        vec![0, 1, 0, 1, 0, 1],
        vec![1, 0, 1, 0, 1, 0],
    ];

    for sequence in &type_a_sequences {
        for _ in 0..5 {
            hmm.train(sequence, Some(0.1))?;
        }
    }

    // Type B training data: sequential patterns
    println!("Training on Type B (sequential patterns)...");
    let type_b_sequences = vec![
        vec![0, 1, 2, 3, 0, 1, 2, 3],
        vec![3, 2, 1, 0, 3, 2, 1, 0],
        vec![0, 1, 2, 3],
        vec![1, 2, 3, 0],
        vec![2, 3, 0, 1],
    ];

    for sequence in &type_b_sequences {
        for _ in 0..5 {
            hmm.train(sequence, Some(0.1))?;
        }
    }

    // Type C training data: random-ish patterns
    println!("Training on Type C (random-ish patterns)...");
    let type_c_sequences = vec![
        vec![0, 2, 1, 3, 0, 3, 1, 2],
        vec![3, 1, 0, 2, 3, 0, 2, 1],
        vec![1, 3, 0, 2],
        vec![2, 0, 3, 1],
        vec![0, 3, 2, 1],
    ];

    for sequence in &type_c_sequences {
        for _ in 0..5 {
            hmm.train(sequence, Some(0.1))?;
        }
    }

    println!("\nTraining complete!");
    println!("\nClassifying test sequences:");
    println!("{:-<70}", "");

    // Test sequences
    let test_cases = vec![
        ("Type A (alternating)", vec![0, 1, 0, 1, 0, 1]),
        ("Type A (alternating)", vec![2, 3, 2, 3]),
        ("Type B (sequential)", vec![0, 1, 2, 3]),
        ("Type B (sequential)", vec![1, 2, 3, 0]),
        ("Type C (random-ish)", vec![0, 3, 1, 2]),
        ("Type C (random-ish)", vec![3, 0, 2, 1]),
        ("Unknown pattern", vec![0, 0, 0, 0]),
        ("Unknown pattern", vec![3, 3, 3, 3]),
    ];

    for (label, sequence) in test_cases {
        let probability = hmm.evaluate(&sequence)?;
        println!(
            "{:20} | Sequence: {:?} | P = {:.6e}",
            label, sequence, probability
        );
    }

    println!("{:-<70}", "");
    println!("\nHigher probabilities indicate sequences similar to training data.");
    println!("The model has learned to recognize the patterns!");

    Ok(())
}