code wiki / (root) / nx_abstat_aa_gate.nx

nx_abstat_aa_gate.nx

buildroot/runtime/nx_abstat_aa_gate.nx

26668 B376 linesdepth 7pulls 11 transitivereach 0 importersview sourcekind gate/proof
docsdependenciesstructsconstsfunctions

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

nx_syscalls.nx nx_gate_verdict.nx nx_abstat_lib.nx nx_abstat_aa_gate.nx

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

main gv_ctr sys_mmap nxa_die sys_write sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ gv_puts sys_write ↻ sys_mmap ↻ ab_words aa_isqrt gv_check gv_puts ↻ aa_reject_count aa_trial ab_init ab_push ab_valid ab_base aa_sample aa_uniform aa_lcg ab_axis_verdict ab_axis_reason ab_n ab_valid ↻ ab_base ↻ ab_var_q10 ab_valid ↻

structs

none

consts

40const AA_LCG_MUL: i64 = 6364136223846793005
41const AA_LCG_INC: i64 = 1442695040888963407
42const AA_LCG_MASK: i64 = 0x7FFFFFFFFFFFFFFF
43const AA_SEED: i64 = 20260904 // the date this gate was written; any fixed seed is a fixture fact
44const AA_UNIFORM_W: i64 = 1000 // one uniform draw in [0, AA_UNIFORM_W)
45const AA_IH_K: i64 = 4 // Irwin-Hall order: sum of four uniforms, near-normal, integer
47const AA_TRIALS: i64 = 2000
48const AA_N_PER_ARM: i64 = 100
49const AA_AXES: i64 = 1 // one axis: alpha_each = 0.05, critical t 1.96 (the incumbent's table)
50const AA_ALPHA_PERMIL: i64 = 50 // the bar: about 5 percent of A/A runs reject
51const AA_ENVELOPE_SIGMAS: i64 = 3 // the envelope half-width in binomial standard deviations
52const AA_MDE_Q10: i64 = 1 // an MDE small enough never to turn a rejection into BELOW_MDE
54const AA_EFFECT: i64 = 405 // five standard errors: se_diff at N_PER_ARM is isqrt(2 x 333333 / 100) = 81 (derived below, printed)
55const AA_POWER_FLOOR_PERMIL: i64 = 900 // the paper's 90 percent power bar
57const KS_R: i64 = 2
58const KS_REV_SIGMA: i64 = 300000 // 30 dollars
59const KS_REV_MDE: i64 = 1875 // 5 percent of a 3.75 dollar mean
60const KS_REV_N: i64 = 1638400 // (4 x 2 x 30 / 0.1875)^2 = 1280^2, "over 1.6 million"
61const KS_CHK_SIGMA: i64 = 5000 // 0.5, the Bernoulli std-dev at p = 0.5
62const KS_CHK_MDE: i64 = 250 // 5 percent of 0.5
63const KS_CHK_N: i64 = 25600 // the paper's own figure
64const KS_CONV_SIGMA: i64 = 2179 // sqrt(0.05 x 0.95) = 0.2179
65const KS_CONV_MDE: i64 = 25 // 5 percent of 0.05
66const KS_CONV_BAR: i64 = 500000 // "less than 500,000 users"
67const KS_RELAX: i64 = 4 // relaxing the MDE by 4 drops n by 16: the square law the paper states
68const KS_SQUARE_LAW: i64 = 16
69const AA_I64_BYTES: i64 = 8
70const AA_Q10: i64 = 1024
75const KV_LN_TWO: i64 = 710 // ab_ln_q10(2048): ln 2 = 0.693147 x 1024 = 709.8, the lib's own rounding
76const KV_BAR_20: i64 = 3068 // ab_av_bar_q10(50) = ln 20 = 2.995732 x 1024 = 3067.6
77const KV_BAR_TOL: i64 = 4 // one integer-log rounding step either side
78const KV_A_NULL: i64 = 0 - 355 // d=0, V=1, tau2=1: (1/2) ln(1/2) = -0.346574 x 1024 = -354.9
79const 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
80const KV_A_WIDE: i64 = 0 - 114 // d=0, V=4, tau2=1: (1/2) ln(4/5) = -0.111572 x 1024 = -114.2
81const KV_TOL: i64 = 3
84const CV_THETA_EXPECT: i64 = 1024
85const CV_RHO2_EXPECT: i64 = 512
86const CV_IDENT_TOL_PERMIL: i64 = 30 // 3 percent: the identities hold on 400,000 pairs to well inside this
87const CV_EFFECT: i64 = 230 // two standard errors of the PLAIN contrast on Y (se_y = isqrt(4 x 333333 / 100) = 115):
89const CV_POWER_GAIN_FLOOR_PERMIL: i64 = 150 // the adjusted contrast must win by at least this much on the same samples
90const CV_XY_WORDS: i64 = 2
91const CV_OUT_WORDS: i64 = 2
92const CV_CNT_WORDS: i64 = 3
93const CV_CONST_X: i64 = 7 // the constant covariate of the neg-control
94const CV_CONST_N: i64 = 4

functions

96func 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
97func aa_uniform(st: *i64) -> i64 { return aa_lcg(st) % AA_UNIFORM_W }
called by 1: aa_sample calls 1: aa_lcg
98func aa_sample(st: *i64) -> i64
104func aa_isqrt(v: i64) -> i64
called by 1: main
111func aa_is_reject(v: i64) -> i64
118func aa_trial(st: *i64, reg: *i64, effect: i64) -> i64
129func aa_reject_count(st: *i64, reg: *i64, effect: i64, insuff: *i64) -> i64
called by 1: main calls 2: aa_trialaa_is_reject
145func aa_seq_trial(st: *i64, reg: *i64, effect: i64, tau2: i64, bar: i64, out: *i64) -> i64
167func aa_seq_counts(st: *i64, reg: *i64, effect: i64, tau2: i64, bar: i64, out: *i64, cnt: *i64) -> i64
called by 1: main calls 1: aa_seq_trial
181func aa_cv_pair(st: *i64, xy: *i64, effect: i64) -> i64
called by 1: aa_cv_trial calls 1: aa_sample
190func aa_cv_trial(st: *i64, cv: *i64, reg: *i64, cal: *i64, use_cal: i64, xy: *i64, effect: i64, out: *i64) -> i64
211func aa_cv_counts(st: *i64, cv: *i64, reg: *i64, cal: *i64, use_cal: i64, xy: *i64, effect: i64, out: *i64, cnt: *i64) -> i64
called by 1: main calls 2: aa_cv_trialaa_is_reject
226func aa_within_permil(a: i64, expected: i64, tol_permil: i64) -> i64
called by 1: main
235func main() -> i64