Skip to main content

simular/demos/
mod.rs

1//! EDD Showcase Demos - Interactive demonstrations of the EDD methodology.
2//!
3//! This module provides interactive demonstrations that embody the
4//! Equation-Driven Development methodology. Each demo follows the complete cycle:
5//!
6//! 1. **Equation** - Define the governing equation
7//! 2. **Failing Test** - Write a test that fails without implementation
8//! 3. **Implementation** - Implement the simulation
9//! 4. **Verification** - Test passes, equation verified
10//! 5. **Falsification** - Demonstrate conditions that break the equation
11//!
12//! # Architecture (SIMULAR-DEMO-001)
13//!
14//! All demos implement the [`DemoEngine`] trait which ensures:
15//! - **YAML-first**: Single source of truth for configuration
16//! - **Deterministic replay**: Same seed → same output
17//! - **Renderer independence**: TUI/WASM produce identical state sequences
18//! - **Metamorphic testing**: Per Chen et al. (2018)
19//! - **Falsification criteria**: Per Popperian methodology
20//!
21//! # Demos
22//!
23//! 1. [`harmonic_oscillator`] - Energy conservation with symplectic integrators
24//! 2. [`littles_law_factory`] - WIP = Throughput × Cycle Time
25//! 3. [`monte_carlo_pi`] - O(n^{-1/2}) convergence rate
26//! 4. [`kingmans_hockey`] - Queue wait times at high utilization
27//! 5. [`kepler_orbit`] - Orbital mechanics conservation laws
28//! 6. [`tsp_grasp`] - TSP with randomized greedy + 2-opt (GRASP)
29//!
30//! # WASM Compatibility
31//!
32//! All demos compile to `wasm32-unknown-unknown` and export a standard interface
33//! for integration with web frontends.
34
35pub mod engine;
36pub mod harmonic_oscillator;
37pub mod kepler_orbit;
38pub mod kingmans_hockey;
39pub mod littles_law_factory;
40pub mod monte_carlo_pi;
41pub mod orbit_engine;
42pub mod tsp_engine;
43pub mod tsp_grasp;
44pub mod tsp_instance;
45
46// WASM modules: DOM operations require unwrap/expect - if elements don't exist, app can't run.
47#[cfg(feature = "wasm")]
48#[allow(clippy::unwrap_used)]
49#[allow(clippy::expect_used)]
50#[allow(clippy::missing_panics_doc)]
51#[allow(clippy::missing_errors_doc)]
52#[allow(clippy::cast_lossless)]
53#[allow(clippy::redundant_closure_for_method_calls)]
54#[allow(clippy::manual_let_else)]
55pub mod tsp_wasm_app;
56
57#[cfg(feature = "wasm")]
58#[allow(clippy::unwrap_used)]
59#[allow(clippy::expect_used)]
60#[allow(clippy::missing_panics_doc)]
61#[allow(clippy::missing_errors_doc)]
62#[allow(clippy::cast_lossless)]
63#[allow(clippy::redundant_closure_for_method_calls)]
64#[allow(clippy::manual_let_else)]
65pub mod orbit_wasm_app;
66
67// Re-exports for convenience
68pub use engine::{
69    CriterionResult, DemoEngine, DemoError, DemoMeta, DeterministicReplay, FalsificationCriterion,
70    MetamorphicRelation, MrResult, RendererIndependent, Severity,
71};
72pub use harmonic_oscillator::HarmonicOscillatorDemo;
73pub use kepler_orbit::KeplerOrbitDemo;
74pub use kingmans_hockey::KingmanHockeyDemo;
75pub use littles_law_factory::LittlesLawFactoryDemo;
76pub use monte_carlo_pi::MonteCarloPlDemo;
77pub use orbit_engine::{OrbitConfig, OrbitalEngine, OrbitalState, OrbitalStepResult};
78pub use tsp_engine::{TspConfig, TspEngine, TspState, TspStepResult};
79pub use tsp_grasp::TspGraspDemo;
80pub use tsp_instance::{
81    Coords, TspAlgorithmConfig, TspCity, TspInstanceError, TspInstanceYaml, TspMeta, TspParams,
82};
83
84use serde::{Deserialize, Serialize};
85
86/// Common trait for all EDD demos.
87pub trait EddDemo {
88    /// Demo name for display.
89    fn name(&self) -> &'static str;
90
91    /// EMC reference path.
92    fn emc_ref(&self) -> &'static str;
93
94    /// Advance the simulation by one timestep.
95    fn step(&mut self, dt: f64);
96
97    /// Check if the governing equation is currently verified.
98    fn verify_equation(&self) -> bool;
99
100    /// Get the current falsification status.
101    fn get_falsification_status(&self) -> FalsificationStatus;
102
103    /// Reset the demo to initial conditions.
104    fn reset(&mut self);
105}
106
107/// Falsification status for a demo.
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct FalsificationStatus {
110    /// Whether the equation is currently verified.
111    pub verified: bool,
112    /// List of falsification criteria and their status.
113    pub criteria: Vec<CriterionStatus>,
114    /// Overall message.
115    pub message: String,
116}
117
118/// Status of a single falsification criterion.
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct CriterionStatus {
121    /// Criterion ID (e.g., "HO-ENERGY").
122    pub id: String,
123    /// Criterion name.
124    pub name: String,
125    /// Whether it passed.
126    pub passed: bool,
127    /// Current value.
128    pub value: f64,
129    /// Threshold for passing.
130    pub threshold: f64,
131}
132
133/// Integrator type for physics simulations.
134#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
135pub enum IntegratorType {
136    /// Störmer-Verlet symplectic integrator (energy-conserving).
137    #[default]
138    StormerVerlet,
139    /// Runge-Kutta 4th order (non-symplectic, energy drifts).
140    RK4,
141    /// Euler method (1st order, for demonstration of failure).
142    Euler,
143}
144
145#[cfg(test)]
146mod tests {
147    use super::*;
148
149    #[test]
150    fn test_integrator_type_default() {
151        assert_eq!(IntegratorType::default(), IntegratorType::StormerVerlet);
152    }
153
154    #[test]
155    fn test_falsification_status_serialization() {
156        let status = FalsificationStatus {
157            verified: true,
158            criteria: vec![CriterionStatus {
159                id: "TEST-001".to_string(),
160                name: "Test criterion".to_string(),
161                passed: true,
162                value: 0.0,
163                threshold: 1e-10,
164            }],
165            message: "All criteria passed".to_string(),
166        };
167
168        let json = serde_json::to_string(&status).expect("serialize");
169        assert!(json.contains("TEST-001"));
170    }
171}