확률변수와 분포 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""확률변수와 분포 검증.

문서: 07.확률변수와 분포 (예시, 정의, 예제, 카드 C1~C3)
주장 1: 예시 — 동전 두 번의 앞면 수 X: PMF 1/4, 1/2, 1/4, CDF F(0) = 1/4, F(0.5) = 1/4, F(1) = 3/4, F(2) = 1.
주장 2: 정의 — CDF는 감소하지 않고 오른쪽 연속, 왼쪽 끝 0·오른쪽 끝 1. P(a < X <= b) = F(b) - F(a).
주장 3: 예제 — 두 주사위: X1, X2는 독립, X1과 합 S는 독립이 아니다. 지시 확률변수의 기댓값 = 확률.
주장 4: 카드 C1 — 두 주사위의 최댓값 PMF (2k - 1)/36. 카드 C2 — CDF의 점프에서 PMF 복원.
"""
from fractions import Fraction
from itertools import product


def main():
    coins = list(product((0, 1), repeat=2))
    X = lambda w: sum(w)
    pmf = {k: Fraction(sum(1 for w in coins if X(w) == k), 4) for k in range(3)}
    assert pmf == {0: Fraction(1, 4), 1: Fraction(1, 2), 2: Fraction(1, 4)}
    F = lambda x: sum(p for k, p in pmf.items() if k <= x)
    assert (F(0), F(0.5), F(1), F(2), F(-1), F(5)) == (Fraction(1, 4), Fraction(1, 4), Fraction(3, 4), 1, 0, 1)
    print("[OK] 주장 1: PMF와 CDF")

    xs = [i / 10 for i in range(-20, 41)]
    assert all(F(a) <= F(b) for a, b in zip(xs, xs[1:]))
    for k in range(3):
        assert F(k) == F(k + 1e-9)          # 오른쪽 연속
        assert F(k) - F(k - 1e-9) == pmf[k]  # 점프 크기 = PMF
    assert F(2) - F(0) == pmf[1] + pmf[2]
    print("[OK] 주장 2: CDF의 성질")

    omega = list(product(range(1, 7), repeat=2))
    P = lambda cond: Fraction(sum(1 for w in omega if cond(w)), 36)
    for a in range(1, 7):
        for b in range(1, 7):
            assert P(lambda w: w[0] == a and w[1] == b) == P(lambda w: w[0] == a) * P(lambda w: w[1] == b)
    assert P(lambda w: w[0] == 1 and sum(w) == 12) != P(lambda w: w[0] == 1) * P(lambda w: sum(w) == 12)
    ind = lambda w: 1 if sum(w) == 7 else 0
    assert sum(Fraction(ind(w), 36) for w in omega) == P(lambda w: sum(w) == 7)
    print("[OK] 주장 3: 독립과 지시 확률변수")

    for k in range(1, 7):
        assert P(lambda w: max(w) == k) == Fraction(2 * k - 1, 36)
    Fc = {0: Fraction(2, 10), 1: Fraction(5, 10), 3: Fraction(1)}
    pm = {0: Fc[0], 1: Fc[1] - Fc[0], 3: Fc[3] - Fc[1]}
    assert pm == {0: Fraction(1, 5), 1: Fraction(3, 10), 3: Fraction(1, 2)} and sum(pm.values()) == 1
    print("[OK] 주장 4: 카드 C1·C2")
    print("ALL CHECKS PASSED")


if __name__ == "__main__":
    main()