nx_abstat_aa_gate.nx
buildroot/runtime/nx_abstat_aa_gate.nx
about
nx_abstat_aa_gate.nx -- A/A CALIBRATION, A-PRIORI SAMPLE SIZE, ALWAYS-VALID MONITORING and CUPED for the
contrast core (gameengine GE51): the four published requirements for an honest improvement claim, each read
from a mirrored primary source and each proven here by a seeded fixture with a KNOWN effect.
(1) the A/A bar -- "the null hypothesis should be rejected about 5 percent of the time when a 95 percent
confidence level is used" (Kohavi et al., KDD 2007, ref ge-expguide). nx_abstat_gate carries ONE
same-distribution trial; one trial cannot measure a RATE. This gate runs thousands of synthetic
experiments from a SEEDED generator and asserts the rejection rate sits inside a binomial envelope
DERIVED from the trial count -- a rate that is too HIGH is a lying instrument, a rate that is too LOW is
a blunt one, and both fail here.
(2) a-priori sample size -- n = (4 r sigma / Delta)^2 at 95 percent confidence and 90 percent power, gated
against the paper's own worked examples (over 1.6 million; 25,600; under 500,000) so the number the
acceptance page prints before reading the arms is the number the field would compute.
(3) ALWAYS-VALID INFERENCE (Johari, Pekelis, Walsh, ref ge-alwaysvalid) -- the same A/A experiments are now
MONITORED CONTINUOUSLY, one look per pushed pair from the sample floor to the end, and two rules are
consulted at every look: the fixed-horizon verdict (the practice the paper measures at "fivefold"
Type I inflation) and ab_always_valid (the mSPRT statistic, rejecting when its running maximum reaches
ln(1/alpha)). The bar: the always-valid rate stays inside the honest envelope while the peeked
fixed-horizon rate leaves it -- a positive and a negative control on the SAME sample stream, so the
discrimination is measured, never assumed. The mixing variance is derived from the planted effect the
way the estate derives it from the pre-declared MDE; the closed form is KAT-checked against values
derived by hand from the formula before any rate is trusted.
(4) CUPED (Deng, Xu, Kohavi, Walker, ref ge-cuped) -- paired fixtures (a pre-period covariate X and a
metric Y = X + independent noise, so the correlation is KNOWN: rho^2 = 1/2 and theta = 1) prove the
estimator's identities from the paper (theta, rho^2, var(Ycv) = var(Y)(1 - rho^2)) on 400,000 pairs,
then the A/A rate of the adjusted contrast stays in the envelope, and the POWER of the adjusted
contrast at a planted effect exceeds the plain contrast's power on the SAME samples -- the paper's
claim ("the same power from half the users") measured as a rate, not asserted.
plus a POWER control for the plain test: the same generator with a planted effect must reject almost
always, or the A/A rate is cheap for the wrong reason (a test that never rejects has a perfect
false-positive rate).
DETERMINISTIC BY CONSTRUCTION: the estate's nofloat gates' LCG (seeded), so every rate is reproducible and a
RED is an arithmetic change, never a dice roll. Samples are Irwin-Hall-4 (the sum of four uniforms), whose
variance is derived from the uniform's width rather than typed. license_tier: ORIGINAL No hw writes.
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nxnx_abstat_lib.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 40 | const AA_LCG_MUL: i64 = 6364136223846793005 |
| 41 | const AA_LCG_INC: i64 = 1442695040888963407 |
| 42 | const AA_LCG_MASK: i64 = 0x7FFFFFFFFFFFFFFF |
| 43 | const AA_SEED: i64 = 20260904 // the date this gate was written; any fixed seed is a fixture fact |
| 44 | const AA_UNIFORM_W: i64 = 1000 // one uniform draw in [0, AA_UNIFORM_W) |
| 45 | const AA_IH_K: i64 = 4 // Irwin-Hall order: sum of four uniforms, near-normal, integer |
| 47 | const AA_TRIALS: i64 = 2000 |
| 48 | const AA_N_PER_ARM: i64 = 100 |
| 49 | const AA_AXES: i64 = 1 // one axis: alpha_each = 0.05, critical t 1.96 (the incumbent's table) |
| 50 | const AA_ALPHA_PERMIL: i64 = 50 // the bar: about 5 percent of A/A runs reject |
| 51 | const AA_ENVELOPE_SIGMAS: i64 = 3 // the envelope half-width in binomial standard deviations |
| 52 | const AA_MDE_Q10: i64 = 1 // an MDE small enough never to turn a rejection into BELOW_MDE |
| 54 | const AA_EFFECT: i64 = 405 // five standard errors: se_diff at N_PER_ARM is isqrt(2 x 333333 / 100) = 81 (derived below, printed) |
| 55 | const AA_POWER_FLOOR_PERMIL: i64 = 900 // the paper's 90 percent power bar |
| 57 | const KS_R: i64 = 2 |
| 58 | const KS_REV_SIGMA: i64 = 300000 // 30 dollars |
| 59 | const KS_REV_MDE: i64 = 1875 // 5 percent of a 3.75 dollar mean |
| 60 | const KS_REV_N: i64 = 1638400 // (4 x 2 x 30 / 0.1875)^2 = 1280^2, "over 1.6 million" |
| 61 | const KS_CHK_SIGMA: i64 = 5000 // 0.5, the Bernoulli std-dev at p = 0.5 |
| 62 | const KS_CHK_MDE: i64 = 250 // 5 percent of 0.5 |
| 63 | const KS_CHK_N: i64 = 25600 // the paper's own figure |
| 64 | const KS_CONV_SIGMA: i64 = 2179 // sqrt(0.05 x 0.95) = 0.2179 |
| 65 | const KS_CONV_MDE: i64 = 25 // 5 percent of 0.05 |
| 66 | const KS_CONV_BAR: i64 = 500000 // "less than 500,000 users" |
| 67 | const KS_RELAX: i64 = 4 // relaxing the MDE by 4 drops n by 16: the square law the paper states |
| 68 | const KS_SQUARE_LAW: i64 = 16 |
| 69 | const AA_I64_BYTES: i64 = 8 |
| 70 | const AA_Q10: i64 = 1024 |
| 75 | const KV_LN_TWO: i64 = 710 // ab_ln_q10(2048): ln 2 = 0.693147 x 1024 = 709.8, the lib's own rounding |
| 76 | const KV_BAR_20: i64 = 3068 // ab_av_bar_q10(50) = ln 20 = 2.995732 x 1024 = 3067.6 |
| 77 | const KV_BAR_TOL: i64 = 4 // one integer-log rounding step either side |
| 78 | const KV_A_NULL: i64 = 0 - 355 // d=0, V=1, tau2=1: (1/2) ln(1/2) = -0.346574 x 1024 = -354.9 |
| 79 | const KV_A_TWO: i64 = 669 // d=2, V=1, tau2=1: -0.346574 + 1 x 4 / (2 x 1 x 2) = 0.653426 x 1024 = 669.1 |
| 80 | const KV_A_WIDE: i64 = 0 - 114 // d=0, V=4, tau2=1: (1/2) ln(4/5) = -0.111572 x 1024 = -114.2 |
| 81 | const KV_TOL: i64 = 3 |
| 84 | const CV_THETA_EXPECT: i64 = 1024 |
| 85 | const CV_RHO2_EXPECT: i64 = 512 |
| 86 | const CV_IDENT_TOL_PERMIL: i64 = 30 // 3 percent: the identities hold on 400,000 pairs to well inside this |
| 87 | const CV_EFFECT: i64 = 230 // two standard errors of the PLAIN contrast on Y (se_y = isqrt(4 x 333333 / 100) = 115): |
| 89 | const CV_POWER_GAIN_FLOOR_PERMIL: i64 = 150 // the adjusted contrast must win by at least this much on the same samples |
| 90 | const CV_XY_WORDS: i64 = 2 |
| 91 | const CV_OUT_WORDS: i64 = 2 |
| 92 | const CV_CNT_WORDS: i64 = 3 |
| 93 | const CV_CONST_X: i64 = 7 // the constant covariate of the neg-control |
| 94 | const CV_CONST_N: i64 = 4 |
functions
| 96 | func aa_lcg(st: *i64) -> i64 { st[0] = (st[0] * AA_LCG_MUL + AA_LCG_INC) & AA_LCG_MASK; return st[0] } called by 1: aa_uniform |
| 97 | func aa_uniform(st: *i64) -> i64 { return aa_lcg(st) % AA_UNIFORM_W } |
| 98 | func aa_sample(st: *i64) -> i64 |
| 104 | func aa_isqrt(v: i64) -> i64 called by 1: main |
| 111 | func aa_is_reject(v: i64) -> i64 |
| 118 | func aa_trial(st: *i64, reg: *i64, effect: i64) -> i64 |
| 129 | func aa_reject_count(st: *i64, reg: *i64, effect: i64, insuff: *i64) -> i64 |
| 145 | func aa_seq_trial(st: *i64, reg: *i64, effect: i64, tau2: i64, bar: i64, out: *i64) -> i64 |
| 167 | func aa_seq_counts(st: *i64, reg: *i64, effect: i64, tau2: i64, bar: i64, out: *i64, cnt: *i64) -> i64 |
| 181 | func aa_cv_pair(st: *i64, xy: *i64, effect: i64) -> i64 |
| 190 | func aa_cv_trial(st: *i64, cv: *i64, reg: *i64, cal: *i64, use_cal: i64, xy: *i64, effect: i64, out: *i64) -> i64 called by 2: aa_cv_countsmain calls 8: ab_cuped_initab_initaa_cv_pairab_cupedab_pushab_cuped_theta_q10+2 |
| 211 | func aa_cv_counts(st: *i64, cv: *i64, reg: *i64, cal: *i64, use_cal: i64, xy: *i64, effect: i64, out: *i64, cnt: *i64) -> i64 |
| 226 | func aa_within_permil(a: i64, expected: i64, tol_permil: i64) -> i64 called by 1: main |
| 235 | func main() -> i64 |