aprender-simulate 0.30.0

Unified Simulation Engine for the Sovereign AI Stack
Documentation
//! EDD TPS Test Case Validation Examples
//!
//! This example demonstrates the ten canonical TPS test cases that empirically
//! validate operations science equations against simulation data.
//!
//! Run with: cargo run --example edd_tps_validation

use simular::edd::{
    validate_cell_layout, validate_kanban_vs_dbr, validate_kingmans_curve, validate_littles_law,
    validate_push_vs_pull, validate_shojinka, validate_smed_setup, validate_square_root_law,
    TpsTestCase,
};

fn main() {
    println!("╔═══════════════════════════════════════════════════════════════╗");
    println!("║     TPS Simulation Test Cases: Empirical Validation           ║");
    println!("╚═══════════════════════════════════════════════════════════════╝\n");

    // Display all test case info
    println!("Ten Canonical Test Cases:");
    println!("┌────────┬────────────────────────────────┬─────────────────────────┐");
    println!("│   ID   │         TPS Principle          │    Governing Equation   │");
    println!("├────────┼────────────────────────────────┼─────────────────────────┤");
    for tc in TpsTestCase::all() {
        println!(
            "{:^6} │ {:^30} │ {:^23} │",
            tc.id(),
            tc.tps_principle(),
            tc.governing_equation_name()
        );
    }
    println!("└────────┴────────────────────────────────┴─────────────────────────┘\n");

    // Run validation examples
    run_tc1_push_vs_pull();
    run_tc3_littles_law();
    run_tc5_smed();
    run_tc6_shojinka();
    run_tc7_cell_layout();
    run_tc8_kingmans_curve();
    run_tc9_square_root();
    run_tc10_kanban_vs_dbr();

    println!("\n✓ All TPS test case validations completed!");
}

fn run_tc1_push_vs_pull() {
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("TC-1: Push vs Pull (CONWIP) Effectiveness");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("H₀: Push and Pull systems have equivalent performance\n");

    // Simulation results from spec
    let result = validate_push_vs_pull(
        24.5, 4.45, 5.4, // Push: WIP, TH, CT
        10.0, 4.42, 2.2,  // Pull: WIP, TH, CT
        0.01, // 1% throughput tolerance
    )
    .unwrap();

    println!("Results:");
    println!("  Push System:  WIP=24.5, TH=4.45, CT=5.4 hrs");
    println!("  Pull System:  WIP=10.0, TH=4.42, CT=2.2 hrs");
    println!(
        "\n  H₀ Rejected: {}",
        if result.h0_rejected { "YES ✓" } else { "NO" }
    );
    println!(
        "  Effect Size: {:.0}% cycle time reduction",
        result.effect_size * 100.0
    );
    println!("  Summary: {}\n", result.summary);
}

fn run_tc3_littles_law() {
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("TC-3: Little's Law Under Stochasticity");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("H₀: Cycle Time behaves non-linearly with WIP under stochasticity\n");

    // Test at various WIP levels
    let test_cases = [
        (10.0, 5.0, 2.0),  // WIP=10, TH=5, CT=2 (exact)
        (25.0, 5.0, 5.0),  // WIP=25, TH=5, CT=5 (exact)
        (50.0, 5.0, 10.0), // WIP=50, TH=5, CT=10 (exact)
    ];

    println!("Results:");
    for (wip, th, ct) in test_cases {
        let result = validate_littles_law(wip, th, ct, 0.05).unwrap();
        let status = if result.h0_rejected {
            "✓ L=λW holds"
        } else {
            "✗ Violated"
        };
        println!("  WIP={wip:>3.0}, TH={th}, CT={ct:>4.1}{status}");
    }

    println!("\n  Conclusion: Little's Law holds even under high stochasticity (R² > 0.98)\n");
}

fn run_tc5_smed() {
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("TC-5: SMED (Setup Time Reduction)");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("H₀: Setup reduction provides only linear capacity gains\n");

    // Classic SMED transformation
    let result = validate_smed_setup(
        30.0, 3.0, // Setup: 30min → 3min (90% reduction)
        100, 10, // Batch: 100 → 10 (enables one-piece flow)
        4.0, 4.0, // Throughput maintained
        0.05,
    )
    .unwrap();

    println!("SMED Transformation:");
    println!("  Before: 30 min setup, batch size 100");
    println!("  After:  3 min setup, batch size 10");
    println!(
        "\n  H₀ Rejected: {}",
        if result.h0_rejected { "YES ✓" } else { "NO" }
    );
    println!("  Summary: {}\n", result.summary);
}

fn run_tc6_shojinka() {
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("TC-6: Shojinka (Cross-Training / Flexible Workforce)");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("H₀: Specialist workers are more efficient than cross-trained workers\n");

    let result = validate_shojinka(
        4.0, 0.85, 2.5, // Specialists: TH, util, wait
        4.1, 0.80, 1.5, // Flexible: TH (slight gain), util, wait (40% reduction)
        0.05,
    )
    .unwrap();

    println!("Comparison:");
    println!("  Specialists: TH=4.0, Util=85%, Wait=2.5 hrs");
    println!("  Flexible:    TH=4.1, Util=80%, Wait=1.5 hrs");
    println!(
        "\n  H₀ Rejected: {}",
        if result.h0_rejected { "YES ✓" } else { "NO" }
    );
    println!(
        "  Effect Size: {:.0}% wait time reduction",
        result.effect_size * 100.0
    );
    println!("  Summary: {}\n", result.summary);
}

fn run_tc7_cell_layout() {
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("TC-7: Cell Layout Design");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("H₀: Physical layout has no significant impact on performance\n");

    let result = validate_cell_layout(
        10.0, 0.25, // Linear: CT, balance delay
        8.0, 0.10, // U-Cell: CT (20% better), balance delay (60% better)
        4.0, 4.5, // Throughput: linear, cell (12.5% better)
    )
    .unwrap();

    println!("Layout Comparison:");
    println!("  Linear Layout: CT=10.0, Balance Delay=25%, TH=4.0");
    println!("  U-Cell Layout: CT=8.0,  Balance Delay=10%, TH=4.5");
    println!(
        "\n  H₀ Rejected: {}",
        if result.h0_rejected { "YES ✓" } else { "NO" }
    );
    println!("  Summary: {}\n", result.summary);
}

fn run_tc8_kingmans_curve() {
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("TC-8: Kingman's Hockey Stick Curve");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("H₀: Queue waiting time increases linearly with utilization\n");

    let utilizations = vec![0.5, 0.7, 0.85, 0.95];
    let wait_times = vec![1.0, 2.33, 5.67, 19.0]; // Exponential growth

    let result = validate_kingmans_curve(&utilizations, &wait_times).unwrap();

    println!("Observed Wait Times:");
    for (rho, wait) in utilizations.iter().zip(wait_times.iter()) {
        println!("  ρ={:.0}% → Wait={:.2}", rho * 100.0, wait);
    }
    println!(
        "\n  H₀ Rejected: {}",
        if result.h0_rejected { "YES ✓" } else { "NO" }
    );
    println!("  Summary: {}\n", result.summary);
}

fn run_tc9_square_root() {
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("TC-9: Square Root Law (Safety Stock)");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("H₀: Safety stock requirements scale linearly with demand variability\n");

    // If demand std quadruples (100→400), safety stock should double (196→392)
    let result = validate_square_root_law(
        100.0, 196.0, // σ_D=100, SS=196
        400.0, 392.0, // σ_D=400 (4x), SS=392 (2x, as √4=2)
        0.01,
    )
    .unwrap();

    println!("Scaling Test:");
    println!("  Demand σ_D=100 → Safety Stock=196");
    println!("  Demand σ_D=400 → Safety Stock=392 (linear would be 784)");
    println!(
        "\n  H₀ Rejected: {}",
        if result.h0_rejected { "YES ✓" } else { "NO" }
    );
    println!("  Summary: {}\n", result.summary);
}

fn run_tc10_kanban_vs_dbr() {
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("TC-10: Kanban vs DBR (Drum-Buffer-Rope)");
    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    println!("H₀: Kanban and DBR produce equivalent performance in all environments\n");

    // Test on unbalanced line (ratio 1.5)
    let result = validate_kanban_vs_dbr(
        4.0, 20.0, 5.0, // Kanban: TH, WIP, CT
        4.3, 15.0, 3.5, // DBR: better on unbalanced line
        1.5, // Unbalanced line (bottleneck ratio)
    )
    .unwrap();

    println!("Unbalanced Line Test (balance ratio=1.5):");
    println!("  Kanban: TH=4.0, WIP=20.0, CT=5.0 hrs");
    println!("  DBR:    TH=4.3, WIP=15.0, CT=3.5 hrs");
    println!(
        "\n  H₀ Rejected: {}",
        if result.h0_rejected { "YES ✓" } else { "NO" }
    );
    println!("  Summary: {}", result.summary);

    // Test on balanced line
    let balanced_result = validate_kanban_vs_dbr(
        4.0, 15.0, 3.75, 4.0, 15.0, 3.75, 1.0, // Perfectly balanced
    )
    .unwrap();

    println!("\nBalanced Line Test (balance ratio=1.0):");
    println!("  Both systems: TH=4.0, WIP=15.0, CT=3.75 hrs");
    println!(
        "  H₀ Rejected: {}",
        if balanced_result.h0_rejected {
            "YES"
        } else {
            "NO ✓ (expected)"
        }
    );
    println!("  Conclusion: Systems are equivalent on balanced lines\n");
}