İçeriğe geç
academia.sh

Ders 04 / 22

Durdurma Ölçütleri

Döngünün nerede duracağının kursun kuralı olarak yazılması ve adım bütçesinin iki, dört, altı, sekiz ve on iki değerlerinde süpürülmesi: 24 kurgu görevde başarım 0,3750'den 1,0000'e çıkıyor, sonra 0,9583'te düzleşiyor; ikinci koşumda 0,4167, 0,8333, 0,9583, 0,9583, 0,9583. Altıncı adımdan sekizinciye düşüş 0,0417'dir ve altıncı adımdaki iki koşum farkı da 0,0417'dir, yani düşüş ölçüm bandının içindedir ve bir bulgu olarak ilan edilemez; mekanizması tek bir görevin izinde gösterilir ve etkisi ölçülmemiş sayılır. Bütçe altıdan on ikiye çıkarıldığında başarım değişmezken belirteç 10884'ten 12214'e çıkıyor. Bütçeyle durmak bir durdurma ölçütü değil emniyet sınırıdır: altıncı adımda üç görev bütçe tükendiği için duruyor.

İçindekiler

Önceki üç dersin hepsi aynı sayıyı sabit tuttu: adım bütçesi sekizdi. Bu bir karardı, gerekçesi yazılmadı ve sonuçların hepsi o karara asılı. Bölünmüş düzende G05 planı tükendikten sonra düzelmek için üç adıma daha ihtiyaç duydu; bütçe altı olsaydı yanlış yanıt verecekti. Tersi de doğrudur: işi biten bir ajan durmayı beceremezse elindeki doğru sonucu bozabilir.

Bu ders o kararı ölçer. Adım bütçesi beş değerde süpürülür ve her değerde başarımın yanına bedeli yazılır. Ders aynı zamanda kursun kuralını kurar: bir ajanın sayısı tek bir yanıtın değil bütün döngünün sayısıdır ve durma koşulu yazılmayan ajan ölçülmemiş sayılır. Taban çizgisi en dar bütçedir — iki adımlık döngü.

  • AM31. Ortam, araç kümesi, görev kümesi ve döngü önceki derslerdeki tanımın aynısıdır ve kurgudur. Tohum 20260218, ikinci koşum 20260219.
  • AM32. Durdurma ölçütü döngünün parçasıdır, dışarıdan konulan bir emniyet değil. Bu benzetici iki ölçüt taşır: iş bitti kararı ve adım bütçesi.
  • AM33. İş bitti kararı belirsizdir. Sırada hedef kalmadığında ajan 0,88 payla durur; kalan payda bir araç daha çağırır.
  • AM34. Dolaşan döngü, hedefi kalmadığı halde adım atmaya devam eden döngüdür. Attığı her adım sayılır.
  • AM35. Adım bütçesi bir durdurma ölçütü değil, sert bir sınırdır. Bütçe tükendiğinde döngü yarıda kesilir ve elindeki değer ne ise yanıt odur.
  • AM36. Süpürülen değerler 2, 4, 6, 8 ve 12’dir; başka her şey sabittir.
  • AM37. Sayılan birimler başarım, adım, araç çağrısı, belirteç, araç hatası, kendi kararıyla biten koşum ve dolaşan adımdır.
  • AM38. Görev kümesi 24 görevdir, yani başarımın en küçük adımı 0,0417’dir. Bundan küçük bir fark bu kümede temsil edilemez.
  • AM39. İki koşum farkının altında kalan fark ölçülmemiş sayılır; bu ders kuralı kendi sonucuna da uygular.
  • AM40. Süre yazılmaz.

Durdurma Ölçütü Nedir

Bir döngünün ne zaman duracağı, ne yapacağı kadar tasarım kararıdır. Ayırt edilmesi gereken iki şey var. İş bitti kararı ajanın kendi kararıdır: sıradaki hedef kalmadı, elde bir sonuç var, dur. Adım bütçesi ise dışarıdan konan sert bir sınırdır ve bir karar değildir; döngüyü nerede olursa olsun keser. İkincisi birincisinin yerine geçemez, çünkü kesilen bir döngü elindeki değeri yanıt diye verir ve o değerin doğruluğuna bakılmamıştır.

Ölçüt sınıfları bundan ibaret değildir: yinelenen adım, belirteç bütçesi ve dış iptal de birer durdurma ölçütüdür. Bu benzetici yalnız ilk ikisini taşır ve bu derste yalnız onların sayısı basılır.

# BENZETICI -- KURGUDUR. Gercek bir model ucu, arac sunucusu ya da calisma
# zamani cagrilmaz; ortam da araclar da gorevler de kurgudur.
TOHUM, M32 = 20260218, 0xFFFFFFFF


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def belirtecle(m):
    b = []
    for s in str(m).lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


def izno(m):
    h = 2166136261
    for c in str(m):
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


# ---- KURGU ortam: olcum aginin kayitlari
BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
ABONE = {}
for i in range(60):
    r = uretec(TOHUM + 31 * i)
    onceki = 10000 + int(r() * 80000)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "onceki": onceki, "simdiki": onceki + int(r() * 70)}
BASAMAK, USTU = ((10, 4), (25, 7), (40, 11)), 16
ISYERI_KAT = 2
BELGE = {"TR01": "tarife basamaklari 10 25 40 metrekup ve ustu",
         "TR02": "isyeri abonesinde birim ucret iki katidir",
         "SY01": "endeks farki tuketimi verir sayac donusu 100000 eklenir",
         "AR01": "ariza kaydi acildiginda saha ekibi iki gun icinde gider",
         "KS01": "planli kesinti duyurusu bir hafta once yayimlanir"}

CAGRI = [0]                              # arac cagri sayaci


def _bedel(m3, tip):
    kalan, alt, top = m3, 0, 0
    for ust, birim in BASAMAK:
        dilim = min(kalan, ust - alt)
        if dilim <= 0:
            break
        top += dilim * birim
        kalan -= dilim
        alt = ust
    top += kalan * USTU
    return top * (ISYERI_KAT if tip == "isyeri" else 1)


def t_sayac_oku(abone=None, **_):
    a = ABONE.get(abone)
    if a is None:
        return {"hata": "abone yok"}
    return {"onceki": a["onceki"], "simdiki": a["simdiki"], "tip": a["tip"], "bolge": a["bolge"]}


def t_tuketim(onceki=None, simdiki=None, **_):
    if onceki is None or simdiki is None:
        return {"hata": "eksik alan"}
    f = simdiki - onceki
    return {"m3": f + 100000 if f < 0 else f}


def t_tarife(m3=None, tip="mesken", **_):
    if m3 is None:
        return {"hata": "eksik alan"}
    return {"tutar": _bedel(m3, tip)}


def t_belge(anahtar=None, **_):
    if not anahtar:
        return {"hata": "eksik alan"}
    ab = set(belirtecle(anahtar))
    en, kod = -1, None
    for k, m in BELGE.items():
        o = len(ab & set(belirtecle(m)))
        if o > en:
            en, kod = o, k
    return {"kod": kod, "metin": BELGE[kod]} if en > 0 else {"hata": "bulunamadi"}


def t_kayit(abone=None, sutun=None, deger=None, **_):
    if not (abone and sutun and deger is not None):
        return {"hata": "eksik alan"}
    return {"yazildi": True, "abone": abone, "sutun": sutun, "deger": deger}


ARAC = {
    "sayac_oku":  {"islev": t_sayac_oku, "alan": ("abone",), "yan_etki": False},
    "tuketim":    {"islev": t_tuketim, "alan": ("onceki", "simdiki"), "yan_etki": False},
    "tarife":     {"islev": t_tarife, "alan": ("m3", "tip"), "yan_etki": False},
    "belge_ara":  {"islev": t_belge, "alan": ("anahtar",), "yan_etki": False},
    "kayit_yaz":  {"islev": t_kayit, "alan": ("abone", "sutun", "deger"), "yan_etki": True},
}
ARAC_ADI = list(ARAC)


def cagir_arac(ad, durum):
    """Sema disindaki alanlar suzulur; eksik alan aracin kendi hatasidir."""
    CAGRI[0] += 1
    if ad not in ARAC:
        return {"hata": "arac yok"}
    kw = {a: durum[a] for a in ARAC[ad]["alan"] if a in durum}
    return ARAC[ad]["islev"](**kw)


# ---- KURGU gorevler: her biri bilinen bir arac dizisiyle cozulur
GOREV = []
for i in range(24):
    r = uretec(TOHUM + 9973 * i)
    ab = f"A{1 + int(r() * 60):03d}"
    t = ayrik(r(), [0.30, 0.22, 0.20, 0.28])
    if t == 0:
        GOREV.append({"ad": f"G{i + 1:02d}", "tur": "bedel", "abone": ab,
                      "istek": f"{ab} abonesinin bu donem bedeli nedir",
                      "dizi": ("sayac_oku", "tuketim", "tarife")})
    elif t == 1:
        GOREV.append({"ad": f"G{i + 1:02d}", "tur": "tuketim", "abone": ab,
                      "istek": f"{ab} abonesinin bu donem tuketimi kac metrekup",
                      "dizi": ("sayac_oku", "tuketim")})
    elif t == 2:
        GOREV.append({"ad": f"G{i + 1:02d}", "tur": "belge", "abone": ab,
                      "istek": "sayac donusunde endeks farki nasil hesaplanir",
                      "dizi": ("belge_ara",)})
    else:
        GOREV.append({"ad": f"G{i + 1:02d}", "tur": "kayit", "abone": ab,
                      "istek": f"{ab} abonesinin bedelini hesapla ve kayda yaz",
                      "dizi": ("sayac_oku", "tuketim", "tarife", "kayit_yaz")})


def dogru_yanit(g):
    a = ABONE[g["abone"]]
    f = a["simdiki"] - a["onceki"]
    m3 = f + 100000 if f < 0 else f
    if g["tur"] == "tuketim":
        return m3
    if g["tur"] == "belge":
        return "SY01"
    return _bedel(m3, a["tip"])


# ---- KURGU ajan: her adimda bir arac secer ya da biter
def gorme(d):
    return max(0.34, 0.80 - 0.09 * (d - 1))       # dogru araci secme payi, derinlikle duser


def ajan(g, en_cok_adim=8, tohum=TOHUM, oz_elestiri=False, onay=False):
    """KURGU ajan dongusu. Gercek bir model cagrilmaz; arac secimi
    gorevin dizisine ve derinlige bagli tek bir cekilisten gelir."""
    r = uretec(tohum ^ izno(g["ad"]))
    alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"}
    iz, adim, bel, hata = [], 0, 0, 0
    dizi, k = g["dizi"], 0
    while adim < en_cok_adim:
        adim += 1
        bel += 60 + 22 * len(iz)
        hedef = dizi[k] if k < len(dizi) else None
        if hedef is None:                          # is bitti , ajan durmali
            if r() < 0.88:
                return {"bitti": True, "adim": adim, "iz": iz, "belirtec": bel,
                        "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)}
            sec = ARAC_ADI[int(r() * len(ARAC_ADI))]
        else:
            sec = hedef if r() < gorme(k + 1) else ARAC_ADI[int(r() * len(ARAC_ADI))]
        if ARAC[sec]["yan_etki"] and onay:
            alan["onay"] = alan.get("onay", 0) + 1
        if sec == "kayit_yaz":
            alan["deger"] = alan.get("sonuc")
        s = cagir_arac(sec, alan)
        iz.append((sec, "hata" in s))
        bel += 30
        if "hata" in s:
            hata += 1
            if oz_elestiri:
                bel += 40
            continue
        alan.update({kk: vv for kk, vv in s.items() if kk != "hata"})
        if sec == "tuketim":
            alan["sonuc"] = s["m3"]
        if sec == "tarife":
            alan["sonuc"] = s["tutar"]
        if sec == "belge_ara":
            alan["sonuc"] = s["kod"]
        if sec == hedef:
            k += 1
    return {"bitti": False, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata,
            "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)}


def dolasan(g, s):
    """Is bittikten sonra atilan adim sayisi: hedefi kalmadigi halde yapilan
    arac cagrilari. Durma karari verilmeyen her adim buraya yazilir."""
    k = n = 0
    for sec, hatali in s["iz"]:
        if k >= len(g["dizi"]):
            n += 1
        elif sec == g["dizi"][k] and not hatali:
            k += 1
    return n


def supur(b, tohum=TOHUM):
    CAGRI[0] = 0
    bas = adim = bel = hata = bitti = dol = 0
    for x in GOREV:
        y = ajan(x, en_cok_adim=b, tohum=tohum)
        adim, bel, hata = adim + y["adim"], bel + y["belirtec"], hata + y["hata"]
        bas += y["yanit"] == dogru_yanit(x)
        bitti += y["bitti"]
        dol += dolasan(x, y)
    return bas / len(GOREV), adim, CAGRI[0], bel, hata, bitti, dol


for et, tohum in (("A", TOHUM), ("B", TOHUM + 1)):
    print(f"kosum {et}   butce  basarim   adim  cagri  belirtec  hata  bitti  dolasan")
    for b in (2, 4, 6, 8, 12):
        z = supur(b, tohum)
        print(f"          {b:>6} {z[0]:>8.4f} {z[1]:>6} {z[2]:>6} {z[3]:>9}"
              f" {z[4]:>5} {z[5]:>6} {z[6]:>8}")
kosum A   butce  basarim   adim  cagri  belirtec  hata  bitti  dolasan
               2   0.3750     48     45      4758     8      3        1
               4   0.8750     84     64      9402     8     20        1
               6   1.0000     92     71     10884     8     21        1
               8   0.9583     97     74     11978     8     23        1
              12   0.9583     98     74     12214     8     24        1
kosum B   butce  basarim   adim  cagri  belirtec  hata  bitti  dolasan
               2   0.4167     48     45      4758     7      3        2
               4   0.8333     83     67      9366     7     16        3
               6   0.9583     96     74     11610     7     22        3
               8   0.9583     98     74     11994     7     24        3
              12   0.9583     98     74     11994     7     24        3

İlk üç satır tartışmasızdır. İki adımlık bütçe üç ve dört adımlık dizilere hiç şans tanımıyor; başarım yalnız kısa görevlerden gelebiliyor ve 0,3750 ile 0,4167‘de kalıyor. Dördüncü adımda 0,8750 ve 0,8333, altıncı adımda 1,0000 ve 0,9583 oluyor. İkiden altıya kazanç 0,6250 ve 0,5416’dır; en geniş iki koşum farkı 0,0417 olduğuna göre bu kazanç bandın on katından fazladır ve ölçülmüştür. Dörtten altıya kazanç iki koşumda da 0,1250 ve o da bandın üstündedir.

bitti sütunu bu kazancın niteliğini değiştiriyor. İki adımlık bütçede yirmi dört koşumun yalnız üçü kendi kararıyla duruyor; geri kalan yirmi biri bütçe tükendiği için kesiliyor. Altıncı adımda bile üç koşum kesilerek bitiyor. Kesilen bir koşum yanıt üretmiş sayılmaz, elindeki değeri teslim etmiştir. Bütçe bir durdurma ölçütü değil, ölçütün yokluğunda son çare olan bir sınırdır.

Altıncı Adımdan Sekizinciye: Mekanizma Var, Ölçü Yok

Tablonun dikkat çeken yeri altıncı satırdan sekizinciye geçiştir. Birinci koşumda başarım 1,0000’den 0,9583’e düşüyor. Düşüşün sorumlusu tek bir görevdir ve izi okunabilir.

g = [x for x in GOREV if x["ad"] == "G23"][0]
print(f"{g['ad']} ({g['tur']}) dizi :", " , ".join(g["dizi"]),
      "| dogru yanit", dogru_yanit(g))
for b in (6, 8, 12):
    s = ajan(g, en_cok_adim=b)
    print(f"  butce {b:>2}  adim {s['adim']}  bitti {s['bitti']}  yanit {s['yanit']}")
    print("     iz :", " , ".join(a for a, _ in s["iz"]))
G23 (kayit) dizi : sayac_oku , tuketim , tarife , kayit_yaz | dogru yanit 1132
  butce  6  adim 6  bitti False  yanit 1132
     iz : sayac_oku , tuketim , belge_ara , tuketim , tarife , tarife
  butce  8  adim 8  bitti False  yanit TR01
     iz : sayac_oku , tuketim , belge_ara , tuketim , tarife , tarife , belge_ara , kayit_yaz
  butce 12  adim 9  bitti True  yanit TR01
     iz : sayac_oku , tuketim , belge_ara , tuketim , tarife , tarife , belge_ara , kayit_yaz

Altı adımlık bütçede G23 doğru yanıtı veriyor, ama kendi kararıyla değil: bütçe altıncı adımda tükeniyor ve o an durumda duran değer 1132’dir, yani doğrudur. Sekiz adımlık bütçe iki adım daha tanıyor. Yedinci adımda ajan belge_ara’yı seçiyor; bu seçim yanlıştır ama hata vermez, çünkü aracın istediği alan durumda vardır. Başarıyla dönen çağrı biriken sonucun üzerine bir belge kodu yazıyor. Sekizinci adımda hedef nihayet tutturuluyor ve kayit_yaz o bozuk değeri kayda geçiriyor. On iki adımlık bütçe dokuzuncu adımda durma kararını da veriyor, ama düzeltecek bir şey kalmamıştır.

Mekanizma açıktır ve tek cümleyle yazılabilir: doğru sonuç duruma bir kez yazıldıktan sonra her fazladan adım onu bozma şansıdır. Döngünün ikinci kanalı da aynı yöne bakar — iş bittiğinde ajan 0,12 payla durmayıp bir araç daha çağırır; bu koşumlarda dolaşan adım sayısı 1 ve 3’tür.

Buna karşılık bu düşüş bir bulgu değildir. Altıncı adımda iki koşumun verdiği sayılar 1,0000 ve 0,9583’tür, yani o noktadaki iki koşum farkı 0,0417‘dir. Altıdan sekize düşüş de tam olarak 0,0417’dir ve ikinci koşumda sıfırdır. Fark ölçüm bandının içinde kalıyor: mekanizma gösterilebilir, etkisi ölçülmemiş sayılır.

Bu, ölçeğin dayattığı bir sınırdır. Yirmi dört görevlik bir kümede bir görev 0,0417 eder; band da bir görev genişliğindedir, dolayısıyla bir görevlik etki bu kümede hiçbir zaman bandın üstüne çıkamaz. Etkiyi ölçmek isteyen okurun iki yolu var. Birincisi görev kümesini büyütmektir: küme birkaç katına çıkarsa çözünürlük artar. İkincisi dolaşma payını bir ayar olarak süpürmektir; 0,12 tek bir nokta olmaktan çıkıp eksene dönüşürse başarımın o eksen boyunca nasıl değiştiği tek bir görev farkına bağlı kalmadan okunabilir.

Ölçülen şey ise bedeldir. Bütçe altıdan on ikiye çıkarıldığında birinci koşumda başarım hiç değişmiyor, buna karşılık belirteç 10884’ten 12214’e, adım 92’den 98’e, araç çağrısı 71’den 74’e çıkıyor. Sekizden on ikiye geçiş her iki koşumda da başarımı sabit bırakıyor. Bütçeyi büyütmenin kazancı ölçülemedi, bedeli ölçüldü.

Özet

  • Durdurma ölçütü döngünün parçasıdır; iş bitti kararı ajanın kendi kararı, adım bütçesi ise dışarıdan konan sert bir sınırdır ve birincisinin yerine geçemez.
  • Başarım iki adımda 0,3750 ve 0,4167, altı adımda 1,0000 ve 0,9583; ikiden altıya kazanç en geniş iki koşum farkının on katından fazladır ve ölçülmüştür.
  • İki adımlık bütçede yirmi dört koşumun yalnız üçü kendi kararıyla duruyor; altı adımda bile üç koşum bütçe tükendiği için kesiliyor.
  • Altıdan sekize düşüş 0,0417’dir ve altıncı adımdaki iki koşum farkı da 0,0417’dir; mekanizma tek bir görevin izinde gösterilebilir ama etkisi ölçülmemiş sayılır.
  • Etkiyi ölçmek görev kümesini büyütmeyi ya da dolaşma payını kendi ekseninde süpürmeyi gerektirir.
  • Bütçe altıdan on ikiye çıktığında başarım değişmezken belirteç 10884’ten 12214’e çıkıyor: kazanç ölçülemedi, bedel ölçüldü.

Sonraki Adım

Dört derste döngü kuruldu, içi adım adım açıldı, ikiye bölündü ve nerede duracağı yazıldı. Bütün bu ölçümlerin ortak bir dayanağı vardı ve o dayanak sorgulanmadı: doğru yanıtı biz biliyorduk. Görev kümesi her görevin doğru yanıtını taşıyordu ve başarımı o listeyle karşılaştırarak hesapladık. Ajanın kendisi durduğunda elindeki değere bir kez bile bakmadı; G23 bozuk bir sonucu kayda geçirdi ve bunu bir sorun olarak görmedi. Sonraki ders bu boşluğa girer: ajan kendi çıktısını denetleyen bir tur eklerse ne yakalar, ve o tur kaç adım ile kaç belirtece mal olur.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat