FAILURE MAP
← Case archive

FA-74521 / Experiment statistics / Open access

Per-user ratio metric variance: The metric averages per-user ratios · case 01

Light users with one session swing the metric as much as heavy users.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

R is the mean of clicks/sessions per user instead of total clicks over total sessions.

VERIFIED REPAIR

Use sum(clicks) / sum(sessions) as the arm ratio.

Unsuccessful approach: Averaging per-user ratios only over users with sessions is still a mean of ratios.

Case contract

Each user contributes [clicks, sessions]; the unit of randomisation is the user. The arm ratio is sum(clicks) / sum(sessions). Its delta-method variance is (var_x - 2 R cov_xy + R^2 var_y) / (n mean_y^2) with sample (n - 1) moments over users. Arms with fewer than two users or no sessions -> None. Return [R_control, R_treatment, standard error of the difference] rounded to 6.

Why this case matters

Click-through per session is analysed per user; treating sessions as independent understates variance.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(users_c, users_t):
    def stats(users):
        n = len(users)
        if n < 2:
            return None
        xs = [u[0] for u in users]
        ys = [u[1] for u in users]
        mx, my = sum(xs) / n, sum(ys) / n
        if my == 0:
            return None
        r = sum(x / y for x, y in zip(xs, ys) if y) / n
        vx = sum((x - mx) ** 2 for x in xs) / (n - 1)
        vy = sum((y - my) ** 2 for y in ys) / (n - 1)
        cxy = sum((x - mx) * (y - my) for x, y in zip(xs, ys)) / (n - 1)
        var = (vx - 2 * r * cxy + r * r * vy) / (n * my * my)
        return r, var
    a, b = stats(users_c), stats(users_t)
    if a is None or b is None:
        return None
    return [round(a[0], 6), round(b[0], 6), round(math.sqrt(max(a[1] + b[1], 0.0)), 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('user aggregate sample 1', [[[1, 2], [9, 10]], [[0, 0], [0, 2], [7, 10]]], [0.833333, 0.583333, 0.201748]),
  ('user aggregate sample 2',
   [[[0, 0], [1, 5], [1, 2], [0, 0]], [[0, 0], [1, 1], [7, 10], [10, 10]]],
   [0.285714, 0.857143, 0.153928]),
  ('user aggregate sample 3', [[[0, 10], [1, 1], [0, 2], [0, 0], [4, 5], [0, 0]], [[0, 0], [0, 0]]], None)],
 [('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 6',
   [[[1, 1], [5, 5], [1, 1], [3, 5], [10, 10]], [[0, 1], [1, 5], [0, 0], [0, 10], [1, 5], [1, 1]]],
   [0.909091, 0.136364, 0.126043]),
  ('user aggregate sample 7',
   [[[0, 1], [5, 10], [1, 5]], [[1, 2], [1, 2], [0, 1], [3, 5], [5, 5]]],
   [0.375, 0.666667, 0.184982]),
  ('user aggregate sample 8', [[[3, 5], [0, 1]], [[6, 10], [1, 1], [0, 5]]], [0.5, 0.4375, 0.270448])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 11',
   [[[7, 10], [0, 0]], [[1, 5], [0, 1], [0, 5], [1, 1], [1, 1], [2, 10]]],
   [0.7, 0.217391, 0.075178]),
  ('user aggregate sample 12',
   [[[0, 5], [5, 10], [0, 2], [0, 0]], [[5, 5], [0, 1], [10, 10], [7, 10], [1, 1], [0, 1]]],
   [0.294118, 0.821429, 0.203966]),
  ('user aggregate sample 13',
   [[[0, 0], [1, 5], [0, 2], [0, 2], [1, 2], [7, 10]], [[2, 10], [2, 10], [1, 1], [0, 0], [1, 1]]],
   [0.428571, 0.272727, 0.181987])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 16',
   [[[0, 0], [1, 1], [5, 5], [1, 1], [0, 1], [0, 10]], [[0, 0], [0, 2], [0, 0], [0, 10]]],
   [0.388889, 0.0, 0.306461]),
  ('user aggregate sample 21',
   [[[4, 5], [2, 2], [2, 2]], [[2, 5], [2, 2], [5, 5], [7, 10]]],
   [0.888889, 0.727273, 0.137879]),
  ('user aggregate sample 23',
   [[[0, 5], [1, 2], [0, 0], [0, 10], [0, 10]], [[1, 1], [0, 0], [3, 5], [4, 5]]],
   [0.037037, 0.727273, 0.093479])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 21',
   [[[4, 5], [2, 2], [2, 2]], [[2, 5], [2, 2], [5, 5], [7, 10]]],
   [0.888889, 0.727273, 0.137879]),
  ('user aggregate sample 28',
   [[[0, 2], [0, 1], [1, 2], [3, 5], [2, 5], [0, 1]], [[4, 5], [1, 1], [1, 1]]],
   [0.375, 0.857143, 0.118332]),
  ('user aggregate sample 30',
   [[[2, 2], [1, 1], [4, 10], [1, 1]], [[0, 0], [2, 2], [1, 1], [1, 5], [1, 1], [0, 5]]],
   [0.571429, 0.357143, 0.256851])]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
heavy user dominates the ratio of sums[0.75, 0.625, 0.450694][0.52381, 0.318182, 0.132002]Failed
correlated clicks and sessions[0.625, 0.711111, 0.180809][0.538462, 0.7, 0.172146]Failed
users with zero sessions count[0.416667, 0.333333, 0.200866][0.625, 0.4, 0.161613]Failed
single user armNoneNonePassed
no sessions in controlNoneNonePassed
user aggregate sample 1[0.7, 0.233333, 0.455928][0.833333, 0.583333, 0.201748]Failed
user aggregate sample 2[0.175, 0.675, 0.17094][0.285714, 0.857143, 0.153928]Failed
user aggregate sample 3NoneNonePassed

SHA-256 / bca3b0bb4335dd155ecb0892043ad0d814687da357bf74dc4eb19ba61b1ebf7c

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(users_c, users_t):
    def stats(users):
        n = len(users)
        if n < 2:
            return None
        xs = [u[0] for u in users]
        ys = [u[1] for u in users]
        mx, my = sum(xs) / n, sum(ys) / n
        if my == 0:
            return None
        r = sum(x / y for x, y in zip(xs, ys) if y) / sum(1 for y in ys if y)
        vx = sum((x - mx) ** 2 for x in xs) / (n - 1)
        vy = sum((y - my) ** 2 for y in ys) / (n - 1)
        cxy = sum((x - mx) * (y - my) for x, y in zip(xs, ys)) / (n - 1)
        var = (vx - 2 * r * cxy + r * r * vy) / (n * my * my)
        return r, var
    a, b = stats(users_c), stats(users_t)
    if a is None or b is None:
        return None
    return [round(a[0], 6), round(b[0], 6), round(math.sqrt(max(a[1] + b[1], 0.0)), 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('user aggregate sample 1', [[[1, 2], [9, 10]], [[0, 0], [0, 2], [7, 10]]], [0.833333, 0.583333, 0.201748]),
  ('user aggregate sample 2',
   [[[0, 0], [1, 5], [1, 2], [0, 0]], [[0, 0], [1, 1], [7, 10], [10, 10]]],
   [0.285714, 0.857143, 0.153928]),
  ('user aggregate sample 3', [[[0, 10], [1, 1], [0, 2], [0, 0], [4, 5], [0, 0]], [[0, 0], [0, 0]]], None)],
 [('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 6',
   [[[1, 1], [5, 5], [1, 1], [3, 5], [10, 10]], [[0, 1], [1, 5], [0, 0], [0, 10], [1, 5], [1, 1]]],
   [0.909091, 0.136364, 0.126043]),
  ('user aggregate sample 7',
   [[[0, 1], [5, 10], [1, 5]], [[1, 2], [1, 2], [0, 1], [3, 5], [5, 5]]],
   [0.375, 0.666667, 0.184982]),
  ('user aggregate sample 8', [[[3, 5], [0, 1]], [[6, 10], [1, 1], [0, 5]]], [0.5, 0.4375, 0.270448])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 11',
   [[[7, 10], [0, 0]], [[1, 5], [0, 1], [0, 5], [1, 1], [1, 1], [2, 10]]],
   [0.7, 0.217391, 0.075178]),
  ('user aggregate sample 12',
   [[[0, 5], [5, 10], [0, 2], [0, 0]], [[5, 5], [0, 1], [10, 10], [7, 10], [1, 1], [0, 1]]],
   [0.294118, 0.821429, 0.203966]),
  ('user aggregate sample 13',
   [[[0, 0], [1, 5], [0, 2], [0, 2], [1, 2], [7, 10]], [[2, 10], [2, 10], [1, 1], [0, 0], [1, 1]]],
   [0.428571, 0.272727, 0.181987])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 16',
   [[[0, 0], [1, 1], [5, 5], [1, 1], [0, 1], [0, 10]], [[0, 0], [0, 2], [0, 0], [0, 10]]],
   [0.388889, 0.0, 0.306461]),
  ('user aggregate sample 21',
   [[[4, 5], [2, 2], [2, 2]], [[2, 5], [2, 2], [5, 5], [7, 10]]],
   [0.888889, 0.727273, 0.137879]),
  ('user aggregate sample 23',
   [[[0, 5], [1, 2], [0, 0], [0, 10], [0, 10]], [[1, 1], [0, 0], [3, 5], [4, 5]]],
   [0.037037, 0.727273, 0.093479])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 21',
   [[[4, 5], [2, 2], [2, 2]], [[2, 5], [2, 2], [5, 5], [7, 10]]],
   [0.888889, 0.727273, 0.137879]),
  ('user aggregate sample 28',
   [[[0, 2], [0, 1], [1, 2], [3, 5], [2, 5], [0, 1]], [[4, 5], [1, 1], [1, 1]]],
   [0.375, 0.857143, 0.118332]),
  ('user aggregate sample 30',
   [[[2, 2], [1, 1], [4, 10], [1, 1]], [[0, 0], [2, 2], [1, 1], [1, 5], [1, 1], [0, 5]]],
   [0.571429, 0.357143, 0.256851])]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
heavy user dominates the ratio of sums[0.75, 0.625, 0.450694][0.52381, 0.318182, 0.132002]Failed
correlated clicks and sessions[0.625, 0.711111, 0.180809][0.538462, 0.7, 0.172146]Failed
users with zero sessions count[0.625, 0.333333, 0.171746][0.625, 0.4, 0.161613]Failed
single user armNoneNonePassed
no sessions in controlNoneNonePassed
user aggregate sample 1[0.7, 0.35, 0.381426][0.833333, 0.583333, 0.201748]Failed
user aggregate sample 2[0.35, 0.9, 0.17582][0.285714, 0.857143, 0.153928]Failed
user aggregate sample 3NoneNonePassed

SHA-256 / 8774f430b8159735f84a7f5c731064d9aca425eec6064ed9a99dcef126f9b752

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(users_c, users_t):
    def stats(users):
        n = len(users)
        if n < 2:
            return None
        xs = [u[0] for u in users]
        ys = [u[1] for u in users]
        mx, my = sum(xs) / n, sum(ys) / n
        if my == 0:
            return None
        r = mx / my
        vx = sum((x - mx) ** 2 for x in xs) / (n - 1)
        vy = sum((y - my) ** 2 for y in ys) / (n - 1)
        cxy = sum((x - mx) * (y - my) for x, y in zip(xs, ys)) / (n - 1)
        var = (vx - 2 * r * cxy + r * r * vy) / (n * my * my)
        return r, var
    a, b = stats(users_c), stats(users_t)
    if a is None or b is None:
        return None
    return [round(a[0], 6), round(b[0], 6), round(math.sqrt(max(a[1] + b[1], 0.0)), 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('user aggregate sample 1', [[[1, 2], [9, 10]], [[0, 0], [0, 2], [7, 10]]], [0.833333, 0.583333, 0.201748]),
  ('user aggregate sample 2',
   [[[0, 0], [1, 5], [1, 2], [0, 0]], [[0, 0], [1, 1], [7, 10], [10, 10]]],
   [0.285714, 0.857143, 0.153928]),
  ('user aggregate sample 3', [[[0, 10], [1, 1], [0, 2], [0, 0], [4, 5], [0, 0]], [[0, 0], [0, 0]]], None)],
 [('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 6',
   [[[1, 1], [5, 5], [1, 1], [3, 5], [10, 10]], [[0, 1], [1, 5], [0, 0], [0, 10], [1, 5], [1, 1]]],
   [0.909091, 0.136364, 0.126043]),
  ('user aggregate sample 7',
   [[[0, 1], [5, 10], [1, 5]], [[1, 2], [1, 2], [0, 1], [3, 5], [5, 5]]],
   [0.375, 0.666667, 0.184982]),
  ('user aggregate sample 8', [[[3, 5], [0, 1]], [[6, 10], [1, 1], [0, 5]]], [0.5, 0.4375, 0.270448])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 11',
   [[[7, 10], [0, 0]], [[1, 5], [0, 1], [0, 5], [1, 1], [1, 1], [2, 10]]],
   [0.7, 0.217391, 0.075178]),
  ('user aggregate sample 12',
   [[[0, 5], [5, 10], [0, 2], [0, 0]], [[5, 5], [0, 1], [10, 10], [7, 10], [1, 1], [0, 1]]],
   [0.294118, 0.821429, 0.203966]),
  ('user aggregate sample 13',
   [[[0, 0], [1, 5], [0, 2], [0, 2], [1, 2], [7, 10]], [[2, 10], [2, 10], [1, 1], [0, 0], [1, 1]]],
   [0.428571, 0.272727, 0.181987])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('single user arm', [[[1, 2]], [[1, 2], [2, 3]]], None),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 16',
   [[[0, 0], [1, 1], [5, 5], [1, 1], [0, 1], [0, 10]], [[0, 0], [0, 2], [0, 0], [0, 10]]],
   [0.388889, 0.0, 0.306461]),
  ('user aggregate sample 21',
   [[[4, 5], [2, 2], [2, 2]], [[2, 5], [2, 2], [5, 5], [7, 10]]],
   [0.888889, 0.727273, 0.137879]),
  ('user aggregate sample 23',
   [[[0, 5], [1, 2], [0, 0], [0, 10], [0, 10]], [[1, 1], [0, 0], [3, 5], [4, 5]]],
   [0.037037, 0.727273, 0.093479])],
 [('heavy user dominates the ratio of sums',
   [[[1, 1], [10, 20]], [[2, 2], [5, 20]]],
   [0.52381, 0.318182, 0.132002]),
  ('correlated clicks and sessions',
   [[[1, 2], [2, 4], [3, 6], [1, 1]], [[2, 2], [4, 5], [1, 3]]],
   [0.538462, 0.7, 0.172146]),
  ('users with zero sessions count',
   [[[0, 0], [2, 4], [3, 4]], [[1, 2], [1, 2], [0, 1]]],
   [0.625, 0.4, 0.161613]),
  ('no sessions in control', [[[0, 0], [0, 0]], [[1, 2], [2, 3]]], None),
  ('identical arms', [[[1, 4], [3, 4]], [[1, 4], [3, 4]]], [0.5, 0.5, 0.353553]),
  ('user aggregate sample 21',
   [[[4, 5], [2, 2], [2, 2]], [[2, 5], [2, 2], [5, 5], [7, 10]]],
   [0.888889, 0.727273, 0.137879]),
  ('user aggregate sample 28',
   [[[0, 2], [0, 1], [1, 2], [3, 5], [2, 5], [0, 1]], [[4, 5], [1, 1], [1, 1]]],
   [0.375, 0.857143, 0.118332]),
  ('user aggregate sample 30',
   [[[2, 2], [1, 1], [4, 10], [1, 1]], [[0, 0], [2, 2], [1, 1], [1, 5], [1, 1], [0, 5]]],
   [0.571429, 0.357143, 0.256851])]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
heavy user dominates the ratio of sums[0.52381, 0.318182, 0.132002][0.52381, 0.318182, 0.132002]Passed
correlated clicks and sessions[0.538462, 0.7, 0.172146][0.538462, 0.7, 0.172146]Passed
users with zero sessions count[0.625, 0.4, 0.161613][0.625, 0.4, 0.161613]Passed
single user armNoneNonePassed
no sessions in controlNoneNonePassed
user aggregate sample 1[0.833333, 0.583333, 0.201748][0.833333, 0.583333, 0.201748]Passed
user aggregate sample 2[0.285714, 0.857143, 0.153928][0.285714, 0.857143, 0.153928]Passed
user aggregate sample 3NoneNonePassed

SHA-256 / 999c914660f26e84769e13a9365ae93bc669ddd0d14ebb6274234a15b14ae241

Verification & scope

A deterministic toy experiment-analysis model with a stipulated contract; results are rounded and are not a substitute for a validated statistics package. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:48:57.649694+00:00.

Case digest / 405b9f343cb7a3aa010a8ebfcd7bf6b55525f03e4ea85603d24d3203cff3caac