1pub mod audit;
27pub mod equation;
28pub mod experiment;
29pub mod falsifiable;
30pub mod gui_coverage;
31pub mod loader;
32pub mod model_card;
33pub mod operations;
34pub mod prover;
35pub mod report;
36pub mod runner;
37pub mod style;
38pub mod tps;
39pub mod traits;
40pub mod v2;
41pub mod validation;
42
43pub use audit::{
45 hash_state, verify_rng_consistency, AuditLogReplayer, Decision, EquationEval,
46 GeneratedTestCase, ReplaySpeed, ReplayState, SimulationAuditLog, StepEntry, TspStateSnapshot,
47 TspStepType,
48};
49pub use equation::Citation;
50pub use equation::{EquationClass, EquationVariable, GoverningEquation};
51pub use experiment::{
52 ExperimentHypothesis, ExperimentSpec, FalsificationAction, FalsificationCriterion,
53};
54pub use falsifiable::{
55 ExperimentSeed, FalsifiableSimulation, FalsificationResult, ParamSpace, Trajectory,
56};
57pub use gui_coverage::GuiCoverage;
58pub use loader::{EmcYaml, ExperimentYaml};
59pub use model_card::{DomainConstraint, EmcBuilder, EquationModelCard};
60pub use operations::{BullwhipEffect, KingmanFormula, LittlesLaw, SquareRootLaw};
61#[cfg(feature = "z3-proofs")]
62pub use prover::z3_impl;
63pub use prover::{ProofError, ProofResult, Z3Provable};
64pub use report::{ReportFormat, ReportGenerator};
65pub use runner::{
66 EddComplianceChecklist, EmcComplianceReport, EmcRegistry, ExecutionMetrics, ExperimentDomain,
67 ExperimentResult, ExperimentRunner, FalsificationCriterionResult, FalsificationSummary,
68 ReproducibilitySummary, RunnerConfig, VerificationSummary, VerificationTestSummary,
69};
70pub use tps::{
71 validate_bullwhip_effect, validate_cell_layout, validate_kanban_vs_dbr,
72 validate_kingmans_curve, validate_littles_law, validate_push_vs_pull, validate_shojinka,
73 validate_smed_setup, validate_square_root_law, TpsMetrics, TpsTestCase, TpsTestResult,
74};
75pub use traits::{
76 ConfigError, EddSimulation, Reproducible, TestResult, ValidationResult, VerificationResult,
77 YamlConfigurable,
78};
79pub use validation::{
80 richardson_extrapolation, ConvergenceAnalysis, EddComplianceSummary, EddResult, EddValidator,
81 EddViolation, TpsGrade, ViolationSeverity,
82};
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
97 fn test_governing_equation_must_have_latex_representation() {
98 let eq = operations::LittlesLaw::new();
99 assert!(
100 !eq.latex().is_empty(),
101 "Equation must have LaTeX representation"
102 );
103 assert!(
104 eq.latex().contains("\\lambda"),
105 "Little's Law must reference λ"
106 );
107 }
108
109 #[test]
110 fn test_governing_equation_must_have_citation() {
111 let eq = operations::LittlesLaw::new();
112 let citation = eq.citation();
113 assert!(citation.year > 0, "Citation must have valid year");
114 assert!(!citation.authors.is_empty(), "Citation must have authors");
115 }
116
117 #[test]
118 fn test_governing_equation_must_have_variables() {
119 let eq = operations::LittlesLaw::new();
120 let vars = eq.variables();
121 assert!(
122 vars.len() >= 3,
123 "Little's Law must have at least 3 variables (L, λ, W)"
124 );
125 }
126
127 #[test]
132 fn test_littles_law_analytical_solution() {
133 let eq = operations::LittlesLaw::new();
135 let result = eq.evaluate(5.0, 2.0);
136 assert!((result - 10.0).abs() < 1e-10, "L = λW = 5 * 2 = 10");
137 }
138
139 #[test]
140 fn test_littles_law_validation() {
141 let eq = operations::LittlesLaw::new();
142
143 let valid = eq.validate(10.0, 5.0, 2.0, 0.01);
145 assert!(valid.is_ok(), "Should pass when L = λW");
146
147 let invalid = eq.validate(15.0, 5.0, 2.0, 0.01);
149 assert!(invalid.is_err(), "Should fail when L ≠ λW");
150 }
151
152 #[test]
153 fn test_kingmans_formula_hockey_stick() {
154 let eq = operations::KingmanFormula::new();
155
156 let wait_50 = eq.expected_wait_time(0.5, 1.0, 1.0, 1.0);
158
159 let wait_95 = eq.expected_wait_time(0.95, 1.0, 1.0, 1.0);
161
162 assert!(
164 wait_95 > wait_50 * 10.0,
165 "High utilization should cause exponential wait time increase"
166 );
167 }
168
169 #[test]
174 fn test_experiment_must_have_seed() {
175 let spec = ExperimentSpec::builder().name("Test Experiment").build();
176
177 assert!(spec.is_err(), "Experiment must require explicit seed");
179 }
180
181 #[test]
182 fn test_experiment_with_seed_is_reproducible() {
183 let spec = ExperimentSpec::builder()
184 .name("Test Experiment")
185 .seed(42)
186 .build()
187 .expect("Should build with seed");
188
189 assert_eq!(spec.seed(), 42, "Seed must be preserved");
190 }
191
192 #[test]
197 fn test_falsification_criteria_required() {
198 let spec = ExperimentSpec::builder().name("Test").seed(42).build();
199
200 assert!(
202 spec.is_err()
203 || spec
204 .as_ref()
205 .map(|s| s.falsification_criteria().is_empty())
206 .unwrap_or(true),
207 "Experiment should require falsification criteria"
208 );
209 }
210
211 #[test]
216 fn test_emc_must_have_governing_equation() {
217 let emc = EquationModelCard::builder().name("Test EMC").build();
218
219 assert!(emc.is_err(), "EMC must require governing equation");
220 }
221
222 #[test]
223 fn test_emc_must_have_analytical_derivation() {
224 let emc = EquationModelCard::builder()
225 .name("Test EMC")
226 .equation("L = \\lambda W")
227 .build();
228
229 assert!(
230 emc.is_err(),
231 "EMC must require analytical derivation (citation)"
232 );
233 }
234
235 #[test]
236 fn test_emc_must_have_verification_tests() {
237 let emc = EquationModelCard::builder()
238 .name("Little's Law")
239 .equation("L = \\lambda W")
240 .citation(Citation::new(
241 &["Little, J.D.C."],
242 "Operations Research",
243 1961,
244 ))
245 .build();
246
247 assert!(emc.is_err(), "EMC must require verification tests");
248 }
249
250 #[test]
251 fn test_emc_complete_builds_successfully() {
252 let emc = EquationModelCard::builder()
253 .name("Little's Law")
254 .equation("L = \\lambda W")
255 .citation(Citation::new(
256 &["Little, J.D.C."],
257 "Operations Research",
258 1961,
259 ))
260 .add_variable("L", "Average queue length", "items")
261 .add_variable("lambda", "Arrival rate", "items/time")
262 .add_variable("W", "Average wait time", "time")
263 .add_verification_test("L = λW for λ=5, W=2 => L=10", 10.0, 1e-10)
264 .build();
265
266 assert!(emc.is_ok(), "Complete EMC should build successfully");
267 }
268
269 #[test]
274 fn test_tc1_push_vs_pull_little_law_holds() {
275 let eq = operations::LittlesLaw::new();
277
278 let test_cases = [
280 (10.0, 2.0, 5.0), (25.0, 5.0, 5.0), (50.0, 10.0, 5.0), ];
284
285 for (wip, ct, th) in test_cases {
286 let result = eq.validate(wip, th, ct, 0.001);
287 assert!(
288 result.is_ok(),
289 "Little's Law should hold: WIP={wip}, TH={th}, CT={ct}"
290 );
291 }
292 }
293
294 #[test]
295 fn test_tc8_kingmans_curve_exponential() {
296 let eq = operations::KingmanFormula::new();
298
299 let util_levels = [0.5, 0.7, 0.85, 0.95];
300 let mut wait_times = Vec::new();
301
302 for &rho in &util_levels {
303 let wait = eq.expected_wait_time(rho, 1.0, 1.0, 1.0);
304 wait_times.push(wait);
305 }
306
307 for i in 1..wait_times.len() - 1 {
309 let delta_prev = wait_times[i] - wait_times[i - 1];
310 let delta_curr = wait_times[i + 1] - wait_times[i];
311 assert!(delta_curr > delta_prev,
312 "Wait time growth should accelerate (exponential): prev_delta={delta_prev}, curr_delta={delta_curr}");
313 }
314 }
315
316 #[test]
317 fn test_tc9_square_root_law() {
318 let eq = operations::SquareRootLaw::new();
321
322 let stock_l1 = eq.safety_stock(100.0, 1.0, 1.96);
324 let stock_l4 = eq.safety_stock(100.0, 4.0, 1.96);
325
326 let ratio = stock_l4 / stock_l1;
327 assert!(
328 (ratio - 2.0).abs() < 0.01,
329 "Safety stock should scale as √L: ratio should be 2.0, got {ratio}"
330 );
331 }
332
333 #[test]
338 fn test_edd_validator_checks_emc_presence() {
339 let validator = EddValidator::new();
340
341 let result = validator.validate_simulation_has_emc(None);
343 assert!(result.is_err(), "Simulation without EMC should fail EDD-01");
344 }
345
346 #[test]
347 fn test_edd_validator_checks_seed_presence() {
348 let validator = EddValidator::new();
349
350 let result = validator.validate_seed_specified(None);
352 assert!(
353 result.is_err(),
354 "Experiment without seed should fail EDD-05"
355 );
356 }
357}