اگر از سی درخواستِ فرضی، دو درخواست خطا داشته باشد، نسبتِ دو به سی را می‌توان دقیق شمرد. اما احتمالِ خطای فرایندِ تولیدکننده با همین نسبت معلوم نمی‌شود. این درس بازهٔ Wilson را محاسبه می‌کند و پوششِ آن را در یک مدلِ دوجمله‌ایِ کوچک می‌سنجد. همهٔ شمارها ساختگی‌اند؛ هیچ سرویس یا ترافیکِ واقعی اندازه‌گیری نمی‌شود.

۱. شمارِ خطا با احتمالِ ثابت یکی نیست

شمارِ مشاهده و پارامترِ ناشناخته
تصویر مفهومی: شمارِ مشاهده و پارامترِ ناشناخته؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

n تعدادِ درخواست‌ها و x تعدادِ درخواست‌های خطادار است. برای نمونهٔ اصلی، n سی و x دو است؛ نسبتِ نمونه یک‌پانزدهم می‌شود. خطا فقط یک برچسبِ دودوییِ ازپیش‌تعریف‌شده است. timeout، پاسخِ ناقص و تلاشِ مجدد را خودکار به این برچسب تبدیل نمی‌کنیم و معنای خطا باید بیرون از محاسبه مشخص باشد.

مدلِ دوجمله‌ای، آزمون‌های مستقل با احتمالِ ثابتِ p را فرض می‌کند. برای درخواست‌های هم‌بسته در یک قطعیِ مشترک، این فرض لزوماً برقرار نیست. شمارِ زیادِ پیام‌های یک رخداد، الزاماً همان مقدار اطلاعاتِ درخواست‌های مستقل را نمی‌دهد. کد فقط حسابِ مدل را انجام می‌دهد؛ استقلال یا ثباتِ احتمال را از دو عددِ ورودی اثبات نمی‌کند.

صفحهٔ توزیعِ دوجمله‌ایِ NIST، جرمِ احتمالِ شمار را با ضریبِ ترکیب و احتمال‌های موفقیت و شکست تعریف می‌کند. در نام‌گذاریِ این درس، رخدادِ موردِ شمارش «خطا» است. این انتخابِ واژه، فرمول را عوض نمی‌کند. p، نسبتِ نمونه و مرزهای بازه همگی بی‌بُعدند؛ درصد، نمایشِ صدبرابریِ همین نسبت است.

در محاسبهٔ P95 تأخیر، توزیعِ مدت‌ها و قراردادِ صدک موضوع بود. اینجا هیچ میلی‌ثانیه‌ای نداریم؛ فقط تعدادِ خطا و کلِ درخواست‌ها آمده است. داشتنِ بازه برای نسبتِ خطا، صدکِ تأخیر را تعیین نمی‌کند و یک صدک نیز جایِ این دو شمار را نمی‌گیرد.

۲. بازهٔ Wilson از وارونه‌کردنِ آزمون امتیاز

دو مرز برای یک نسبت
تصویر مفهومی: دو مرز برای یک نسبت؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

برای هر احتمالِ نامزدِ p، فاصلهٔ نسبتِ نمونه از آن را می‌سنجیم. صورتِ بدونِ تقسیمِ خطرناک چنین است: مربعِ اختلافِ نسبت و p نباید از z به توانِ دو، ضربدر p و یک‌منهای p، تقسیم بر n بیشتر باشد. مجموعهٔ احتمال‌هایی که این نامساوی را پاس می‌کنند، بازهٔ امتیاز را می‌سازد.

بخشِ ۷٫۲٫۴٫۱ راهنمایِ NIST، فرمولِ Wilson را از وارونه‌کردنِ آزمون توضیح می‌دهد. کدِ ما مرکز و نیم‌عرضِ معادل را با شمارها می‌نویسد: مخرج n به‌اضافهٔ مربعِ z است. خودِ صفحه روشِ بازهٔ دقیقِ دوجمله‌ای را نیز دارد؛ آن روشِ دیگر را اینجا پیاده نکرده‌ایم.

z را دو انتخاب کرده‌ایم. با توزیعِ نرمالِ استاندارد، سطحِ اسمیِ متناظر حدودِ ۹۵٫۴۵ درصد است؛ بنابراین آن را دقیقاً «بازهٔ ۹۵ درصد» نمی‌نامیم. انتخابِ سطحِ اسمی باید پیش از دیدنِ پاسخ ثبت شود. بزرگ‌کردنِ دلخواهِ z پس از مشاهده، پرسش و قراردادِ گزارش را عوض می‌کند.

در تفسیرِ تکرارِ فرضیِ آزمایش، پوشش می‌پرسد چه سهمی از بازه‌های ساخته‌شده پارامترِ ثابت را دربر می‌گیرند. این با نسبت‌دادنِ احتمالِ ۹۵٫۴۵ درصد به پارامترِ ثابت، پس از دیدنِ همین بازه، یکی نیست. همچنین پوششِ واقعیِ یک روشِ تقریبی در n متناهی لازم نیست با سطحِ اسمی برابر باشد.

۳. کد کاملِ بازه و پوششِ فرضی

محاسبهٔ محدود و قابلِ تکرار
تصویر مفهومی: محاسبهٔ محدود و قابلِ تکرار؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

تابعِ بازه، x و n را int واقعی می‌خواهد؛ bool و اعشار تبدیلِ ضمنی نمی‌شوند. n از یک تا یک‌میلیون و x از صفر تا n است. z باید int یا float واقعی، متناهی و در بازهٔ بستهٔ ۰٫۱ تا هشت باشد. این دامنه، انتخابِ محدودِ آموزشی برای حسابِ شناور است.

در صفر خطا، کرانِ پایین را دقیقاً صفر و در همه‌خطا، کرانِ بالا را دقیقاً یک می‌گذاریم. بقیهٔ مرزها تقریبیِ ممیزِ شناورند. برای کنترلِ فرمول، مرجعِ جدا ضرایبِ معادلهٔ درجه‌دو در p را می‌سازد و با Decimal هشتادرقمی ریشه می‌گیرد. اختلافِ عددی با تلورانسِ اعلام‌شده در خودِ آزمون سنجیده می‌شود.

تابعِ پوششِ دقیق قراردادِ کوچک‌تری دارد: n حداکثر شصت است و p و z باید Fraction واقعی با مخرجِ حداکثر هزار باشند. عضویت با نامساویِ کسریِ دقیق بررسی می‌شود، نه با مقایسهٔ p با مرزهای گرد‌شدهٔ تابعِ شناور. سپس احتمالِ تمامِ شمارهای پذیرفته‌شده جمع می‌شود.

کدِ کامل با Python 3.14.5 و کتابخانهٔ استاندارد اجرا شده است. نمونه‌گیریِ تصادفی انجام نمی‌دهد؛ همهٔ حالت‌های موردِ نیاز را می‌شمارد. NormalDist.cdf در مستنداتِ پایتون فقط برای مرجعِ اسمیِ نرمال به کار رفته است؛ داده‌ای برازش یا سرویسِ تشخیصی اجرا نشده است.

"""Own bounded Wilson interval and exact hypothetical binomial coverage."""
from decimal import Decimal,localcontext
from fractions import Fraction
from itertools import product
from math import comb,isfinite,sqrt
from statistics import NormalDist
import json
import platform


def counts(x,n):
    if type(x)is not int or type(n)is not int:raise TypeError('actual int counts required')
    if not 1<=n<=1_000_000 or not 0<=x<=n:raise ValueError('counts outside own profile')


def wilson(x,n,z=2.0):
    counts(x,n)
    if type(z)not in (int,float):raise TypeError('actual int/float z required')
    if not 0.1<=z<=8 or not isfinite(z):raise ValueError('z must be finite within own0.1..8profile')
    z=float(z);denominator=n+z*z
    center=(x+z*z/2)/denominator
    half=z*sqrt(x*(1-x/n)+z*z/4)/denominator
    lower=0.0 if x==0 else max(0.0,center-half)
    upper=1.0 if x==n else min(1.0,center+half)
    return lower,upper


def decimal_score_roots(x,n,z):
    """Independent80-digit quadratic in p from the count-form score inequality."""
    with localcontext()as ctx:
        ctx.prec=80
        N=Decimal(n);X=Decimal(x);Z=Decimal(str(z))
        a=N+Z*Z;b=-(2*X+Z*Z);c=X*X/N
        discriminant=(b*b-4*a*c).sqrt()
        return float((-b-discriminant)/(2*a)),float((-b+discriminant)/(2*a))


def exact_profile(n,p,z):
    counts(0,n)
    if type(p)is not Fraction or type(z)is not Fraction:raise TypeError('actual Fraction p/z required')
    if n>60 or not 0<=p<=1 or p.denominator>1000 or not Fraction(1,10)<=z<=8 or z.denominator>1000:
        raise ValueError('outside finite exact-coverage profile')


def exact_coverage(n,p,z=Fraction(2)):
    """Coverage of the ideal score interval, not rounded-float membership."""
    exact_profile(n,p,z)
    accepted=tuple(x for x in range(n+1)if (Fraction(x,n)-p)**2<=z*z*p*(1-p)/n)
    probability=sum((Fraction(comb(n,x))*p**x*(1-p)**(n-x)for x in accepted),Fraction(0))
    return accepted,probability


def event_space_oracle(n,p,z):
    """Enumerate complete independent Bernoulli sequences; no comb or coverage call."""
    probability=Fraction(0)
    for sequence in product((0,1),repeat=n):
        weight=Fraction(1)
        for bit in sequence:weight*=p if bit else 1-p
        x=sum(sequence)
        if (x-n*p)**2<=z*z*n*p*(1-p):probability+=weight
    return probability


def convolution_mass(n,p):
    mass=[Fraction(1)]
    for _ in range(n):
        following=[Fraction(0)]*(len(mass)+1)
        for x,weight in enumerate(mass):
            following[x]+=weight*(1-p);following[x+1]+=weight*p
        mass=following
    return mass


def rejects(function,*args):
    try:function(*args)
    except (TypeError,ValueError):return True
    return False


def run_example():
    x,n,z=2,30,2.0;interval=wilson(x,n,z)
    accepted,coverage=exact_coverage(30,Fraction(1,20))
    nominal=NormalDist().cdf(z)-NormalDist().cdf(-z)
    checks={}
    expected=decimal_score_roots(x,n,z)
    checks['own_two_failures_thirty_requests_score_roots']=all(abs(a-b)<1e-14 for a,b in zip(interval,expected))
    checks['zero_failures_not_zero_upper_uncertainty']=(wilson(0,30)==(0.0,float(Fraction(2,17))))
    checks['all_failures_upper_exact_one']=(wilson(30,30)[1]==1.0 and abs(wilson(30,30)[0]-float(Fraction(15,17)))<1e-15)
    checks['failure_complement_symmetry']=all(abs(wilson(k,30)[0]-(1-wilson(30-k,30)[1]))<2e-15 for k in range(31))
    wider=wilson(2,30);narrower=wilson(20,300)
    checks['same_rate_larger_selected_sample_narrows_interval']=(narrower[1]-narrower[0]<wider[1]-wider[0])
    intervals=[wilson(2,30,value)for value in (0.5,2,4)]
    checks['larger_z_nested_intervals']=all(intervals[i+1][0]<=intervals[i][0]and intervals[i][1]<=intervals[i+1][1]for i in range(2))
    checks['count_types_and_bounds']=all(rejects(wilson,*args)for args in [(True,30),(1,False),(1.0,30),(1,0),(-1,30),(31,30),(0,1_000_001)])
    checks['z_type_and_numeric_profile']=all(rejects(wilson,2,30,value)for value in (True,'2',Fraction(2),0,0.01,8.1,float('nan'),float('inf'),10**1000))
    comparisons=0;roots_ok=True
    for sample in range(1,41):
        for failed in range(sample+1):
            for score in (0.1,0.5,2,8):
                actual=wilson(failed,sample,score);oracle=decimal_score_roots(failed,sample,score)
                roots_ok=roots_ok and all(0<=a<=1 and abs(a-b)<2e-14 for a,b in zip(actual,oracle));comparisons+=1
    checks['independent80digit_quadratic_roots_ONE_group']=bool(roots_ok)
    mass_cases=0;mass_ok=True
    for sample in range(1,13):
        for p in (Fraction(0),Fraction(1,10),Fraction(1,2),Fraction(9,10),Fraction(1)):
            mass=sum((comb(sample,k)*p**k*(1-p)**(sample-k)for k in range(sample+1)),Fraction(0))
            mass_ok=mass_ok and mass==1;mass_cases+=1
    checks['exact_binomial_probability_mass_normalizes_ONE_group']=bool(mass_ok)
    event_cases=0;event_ok=True
    for sample in range(1,9):
        for p in (Fraction(1,3),Fraction(3,5)):
            for score in (Fraction(1),Fraction(2)):
                event_ok=event_ok and exact_coverage(sample,p,score)[1]==event_space_oracle(sample,p,score);event_cases+=1
    checks['independent_complete_event_space_coverage_ONE_group']=bool(event_ok)
    mass=convolution_mass(30,Fraction(1,20))
    checks['hand_accepted_counts_and_independent_convolution']=(accepted==(0,1,2,3)and coverage==sum(mass[:4]))
    checks['exact_coverage_endpoints_and_resource_contract']=(exact_coverage(60,Fraction(0))[1]==1 and exact_coverage(60,Fraction(1))[1]==1
        and all(rejects(exact_coverage,*args)for args in [(61,Fraction(1,2)),(10,0.5),(10,Fraction(-1,2)),(10,Fraction(1,1001)),(10,Fraction(1,2),2.0)]))
    checks['finite_coverage_is_distinct_from_nominal_reference']=(0<float(coverage)<nominal<1 and abs(nominal-0.9544997361036416)<1e-15)
    assert all(type(value)is bool and value for value in checks.values()),checks
    return dict(python=platform.python_version(),dependencies='standard library only',
        scope='synthetic fixed-n independent Bernoulli model only; no service measurements or empirical coverage',
        failures=x,requests=n,observed_synthetic_fraction=str(Fraction(x,n)),z=z,wilson_interval=interval,
        zero_failure_interval=wilson(0,n,z),hypothetical_true_p='1/20',accepted_failure_counts=accepted,
        exact_ideal_score_coverage_fraction=str(coverage),exact_ideal_score_coverage_float=float(coverage),
        nominal_normal_reference=nominal,decimal_root_comparisons_inside_ONE_group=comparisons,
        binomial_mass_cases_inside_ONE_group=mass_cases,event_space_configurations_inside_ONE_group=event_cases,
        random_trials_performed=0,service_requests_performed=0,checks=checks)

if __name__=='__main__':print(json.dumps(run_example(),ensure_ascii=False,indent=2))

۴. مرجعِ کسری و محدودیتِ تعدادِ کم

پوششِ فرضی با مرجعِ دقیق
تصویر مفهومی: پوششِ فرضی با مرجعِ دقیق؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

بازهٔ نمونهٔ دو خطا از سی درخواست، تقریباً از ۰٫۰۱۸۰۵ تا ۰٫۲۱۷۲۴ است. این دو عدد، نتیجهٔ فرمول برای دادهٔ ساختگی‌اند و حدِ مجازِ کیفیتِ یک محصول نیستند. برای صفر خطا از سی، کرانِ بالا دو‌هفدهم، حدودِ ۰٫۱۱۷۶۵ است؛ صفر مشاهده، احتمالِ خطای شناخته‌شدهٔ صفر تولید نمی‌کند.

{
  "python": "3.14.5",
  "dependencies": "standard library only",
  "scope": "synthetic fixed-n independent Bernoulli model only; no service measurements or empirical coverage",
  "failures": 2,
  "requests": 30,
  "observed_synthetic_fraction": "1/15",
  "z": 2.0,
  "wilson_interval": [
    0.01805156784940945,
    0.21724254979764937
  ],
  "zero_failure_interval": [
    0.0,
    0.11764705882352941
  ],
  "hypothetical_true_p": "1/20",
  "accepted_failure_counts": [
    0,
    1,
    2,
    3
  ],
  "exact_ideal_score_coverage_fraction": "504244428456510947979000052154080905973/536870912000000000000000000000000000000",
  "exact_ideal_score_coverage_float": 0.9392284386912565,
  "nominal_normal_reference": 0.9544997361036417,
  "decimal_root_comparisons_inside_ONE_group": 3440,
  "binomial_mass_cases_inside_ONE_group": 60,
  "event_space_configurations_inside_ONE_group": 32,
  "random_trials_performed": 0,
  "service_requests_performed": 0,
  "checks": {
    "own_two_failures_thirty_requests_score_roots": true,
    "zero_failures_not_zero_upper_uncertainty": true,
    "all_failures_upper_exact_one": true,
    "failure_complement_symmetry": true,
    "same_rate_larger_selected_sample_narrows_interval": true,
    "larger_z_nested_intervals": true,
    "count_types_and_bounds": true,
    "z_type_and_numeric_profile": true,
    "independent80digit_quadratic_roots_ONE_group": true,
    "exact_binomial_probability_mass_normalizes_ONE_group": true,
    "independent_complete_event_space_coverage_ONE_group": true,
    "hand_accepted_counts_and_independent_convolution": true,
    "exact_coverage_endpoints_and_resource_contract": true,
    "finite_coverage_is_distinct_from_nominal_reference": true
  }
}

اکنون پارامترِ فرضی را یک‌بیستم و تعداد را سی می‌گذاریم؛ این پارامتر برای محاسبه معلوم فرض شده است. نامساویِ دقیق فقط شمارهای صفر، یک، دو و سه را می‌پذیرد. جمعِ احتمالِ این چهار حالت حدودِ ۰٫۹۳۹۲۳ است؛ از مرجعِ اسمیِ حدودِ ۰٫۹۵۴۵۰ کمتر است. هیچ آزمایشِ واقعی برای به‌دست‌آوردنِ این پوشش تکرار نشده است.

مرجعِ مستقلِ دیگر، برای اندازه‌های کوچک تمامِ دنباله‌های صفر و یک را می‌سازد و احتمالِ هر دنباله را مستقیماً ضرب می‌کند؛ از ضریبِ ترکیب استفاده نمی‌کند. ۳۲ ترکیبِ پارامتر در یک گروه با آن مقایسه شده‌اند. برای نمونهٔ سی‌تایی، توزیع با افزودنِ پیاپیِ یک آزمونِ برنولی نیز جدا ساخته و جمعِ چهار احتمال کنترل می‌شود.

چهارده گروهِ نام‌دار گذشتند. ۳۴۴۰ مقایسه با ریشهٔ هشتادرقمی و شصت کنترلِ جمعِ جرمِ احتمال، هرکدام یک گروه‌اند. این شمارها نه تعدادِ سرویس‌ها و نه تعدادِ داده‌های مشاهده‌شده‌اند. خطای عددیِ کوچکِ فرمول با اختلافِ مدلِ آماری یا نامناسب‌بودنِ فرضِ استقلال یک مسئله نیست.

معیارهای خطای دسته‌بندیِ عیب نیز نشان می‌دادند یک نسبتِ کلی، همهٔ نوع‌های خطا را توضیح نمی‌دهد. بازهٔ فعلی اطلاعاتِ کلاس، هزینهٔ خطا یا شرایطِ کار را برنمی‌گرداند. برای گزارشِ مهندسی باید تعریفِ رخداد، مرزِ شمارش، تعداد و فرض‌های مدل همراهِ عدد باقی بمانند.

۵. چهار پرسش دربارهٔ اطمینان و وابستگی

فرضِ استقلال را به داده تحمیل نکنیم
تصویر مفهومی: فرضِ استقلال را به داده تحمیل نکنیم؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

پرسش اول: صفر خطا یعنی بازهٔ صفر تا صفر؟ پاسخ: در این روش خیر؛ برای n سی و z دو، کرانِ بالا دو‌هفدهم است. فرمولِ سادهٔ نسبت به‌اضافه‌ومنهای خطای معیارِ نمونه در صفر فرو می‌ریزد، ولی این فروپاشی دلیلِ معلوم‌بودنِ پارامتر نیست.

پرسش دوم: چرا پوششِ دقیق با سطحِ اسمی برابر نیست؟ پاسخ: تعدادِ شکست‌ها گسسته است و Wilson از آزمونِ تقریبی می‌آید. محاسبهٔ کسری، احتمالِ پوششِ همین روش را دقیق می‌سنجد؛ آن را به بازهٔ دقیقِ Clopper–Pearson تبدیل نمی‌کند.

پرسش سوم: می‌توان سی خطای یک قطعی را سی آزمونِ مستقل گرفت؟ پاسخ: بدونِ بررسیِ مدل خیر؛ علتِ مشترک می‌تواند وابستگی بسازد. این تابع آن را تشخیص نمی‌دهد. باید طرحِ مشاهده، واحدِ آزمون و مدلِ مناسبِ وابستگی جداگانه تعیین شوند.

پرسش چهارم: آیا منابع و اجرا هم‌نسخه‌اند؟ پاسخ: اجرای واقعی 3.14.5 و مستنداتِ پایتونِ خوانده‌شده 3.14.8 است. منابع در ۲۶ مهر ۱۴۰۵ خوانده شدند؛ تاریخِ انتشارِ دقیقِ صفحه‌های NIST معلوم نیست و سالِ مقالهٔ Wilson در ۱۹۲۷ را تاریخِ انتشارِ آن صفحه‌ها نمی‌گیریم.

منابع و مطالعهٔ بیشتر

بررسی منابع: ۲۶ مهر ۱۴۰۵. تحلیل‌ها و پیشنهادهای اجرایی، جمع‌بندی نویسنده‌اند.