code wiki / (root) / nx_validation.nx

nx_validation.nx source

↩ module page · 161 lines · 5062 B

1// nx_validation.nx -- GO-TO-MARKET / VERIFICATION & VALIDATION. Turns a 2// gated DESIGN into a falsifiable TEST PLAN: for each design claim it names 3// the measurement, pulls the model's PREDICTION straight from the organs, 4// sets an acceptance rule (a tolerance band, a safety ceiling, or a quality 5// floor), and decides pass/fail against a real measured value. When every 6// test passes on a built prototype, the technology is VALIDATED (TRL 3 -> 7// TRL 4) -- the physical proof the model was right. 8// 9// Composes nx_water_awg + nx_water_quality + nx_water_design so the test 10// targets are the ACTUAL predictions (not hand-typed): predicted yield = 11// wa_daily_yield_ml(...), predicted remineralized TDS = the designed 12// sample's TDS, etc. INTEGER-EXACT. Safety tests are zero-slack ceilings. 13// 14// THE exceed: the acceptance test is DERIVED from the model, so building 15// the prototype either confirms the design or falsifies a specific claim -- 16// a real V&V protocol, not a vague "see if it works". 17// 18// grounded: verification_and_validation + technology_readiness_level_4 19// genealogy_id: design_verification_validation + nishi_go_to_market 20 21import "nx_syscalls.nx" 22import "nx_water_awg.nx" 23import "nx_water_quality.nx" 24import "nx_water_design.nx" 25 26// ===== Acceptance rule kinds ====================================== 27 28const VAL_BAND: i64 = 0 // |actual - predicted| within tolerance percent 29const VAL_CEIL: i64 = 1 // actual <= predicted (safety / max limit) 30const VAL_FLOOR: i64 = 2 // actual >= predicted (a minimum quality) 31 32// ===== Measurement ids (for labeling) ============================= 33 34const VM_YIELD: i64 = 0 35const VM_ENERGY: i64 = 1 36const VM_COND_TDS: i64 = 2 37const VM_REMIN_TDS: i64 = 3 38const VM_TASTE: i64 = 4 39const VM_BACTERIA: i64 = 5 40const VM_LEAD: i64 = 6 41 42// ===== Struct: NxTestCase ========================================= 43 44struct NxTestCase { 45 measure_id: i64, 46 kind: i64, 47 predicted: i64, 48 tolerance_pct: i64, 49 trl: i64, 50 safety: i64, 51} 52 53// ===== The water bench-prototype validation plan (model-derived) == 54 55func val_water_count() -> i64 { 56 return 7 57} 58 59func val_water_case(i: i64) -> *NxTestCase { 60 let tc: *NxTestCase = (sys_mmap(64)) as *NxTestCase 61 tc.measure_id = i 62 tc.kind = VAL_BAND 63 tc.predicted = 0 64 tc.tolerance_pct = 20 65 tc.trl = 4 66 tc.safety = 0 67 if i == VM_YIELD { 68 tc.measure_id = VM_YIELD 69 tc.kind = VAL_BAND 70 tc.predicted = wa_daily_yield_ml(100, wa_extractable_x10(30, 70, 5)) 71 tc.tolerance_pct = 20 72 } 73 if i == VM_ENERGY { 74 tc.measure_id = VM_ENERGY 75 tc.kind = VAL_BAND 76 tc.predicted = wa_specific_energy_whl(wa_extractable_x10(30, 70, 5)) 77 tc.tolerance_pct = 25 78 } 79 if i == VM_COND_TDS { 80 tc.measure_id = VM_COND_TDS 81 tc.kind = VAL_CEIL 82 tc.predicted = 10 83 } 84 if i == VM_REMIN_TDS { 85 tc.measure_id = VM_REMIN_TDS 86 tc.kind = VAL_BAND 87 let best: *NxWaterSample = wd_design_best_water() 88 tc.predicted = best.tds 89 tc.tolerance_pct = 15 90 } 91 if i == VM_TASTE { 92 tc.measure_id = VM_TASTE 93 tc.kind = VAL_FLOOR 94 tc.predicted = 90 95 tc.trl = 5 96 } 97 if i == VM_BACTERIA { 98 tc.measure_id = VM_BACTERIA 99 tc.kind = VAL_CEIL 100 tc.predicted = 0 101 tc.safety = 1 102 } 103 if i == VM_LEAD { 104 tc.measure_id = VM_LEAD 105 tc.kind = VAL_CEIL 106 tc.predicted = WQ_LEAD_PPB 107 tc.safety = 1 108 } 109 return tc 110} 111 112// ===== Pass / fail ================================================= 113 114func val_pass(tc: *NxTestCase, actual: i64) -> i64 { 115 if tc.kind == VAL_CEIL { 116 if actual <= tc.predicted { return 1 } 117 return 0 118 } 119 if tc.kind == VAL_FLOOR { 120 if actual >= tc.predicted { return 1 } 121 return 0 122 } 123 // VAL_BAND: relative tolerance around the prediction. 124 var diff: i64 = actual - tc.predicted 125 if diff < 0 { diff = 0 - diff } 126 if diff * 100 <= tc.predicted * tc.tolerance_pct { return 1 } 127 return 0 128} 129 130// ===== Run the plan over measured values ========================== 131 132// measured[i] = the observed value for test case i. 133func val_run(measured: *i64) -> i64 { 134 var pass: i64 = 0 135 var i: i64 = 0 136 while i < val_water_count() { 137 let tc: *NxTestCase = val_water_case(i) 138 if val_pass(tc, measured[i]) == 1 { pass = pass + 1 } 139 i = i + 1 140 } 141 return pass 142} 143 144// Every safety-critical test must pass (a single safety failure is fatal). 145func val_critical_pass(measured: *i64) -> i64 { 146 var i: i64 = 0 147 while i < val_water_count() { 148 let tc: *NxTestCase = val_water_case(i) 149 if tc.safety == 1 { 150 if val_pass(tc, measured[i]) == 0 { return 0 } 151 } 152 i = i + 1 153 } 154 return 1 155} 156 157// Validated iff every test passes (and hence every safety test passes). 158func val_validated(measured: *i64) -> i64 { 159 if val_run(measured) != val_water_count() { return 0 } 160 return 1 161}