Ders 13 / 18
Rapor Yeniden Üretilebilirliği
Aynı raporu ikinci kez üretmek için sabitlenmesi gereken kalem sayılır: M26/K03'ün hazırlama defterindeki 39 karar ile M26/K04'ün 9 ortam kaleminin üstüne raporun kendi 11 kalemi eklenir ve toplam 59 olur. On bir kalemin 10'u tek başına serbest bırakıldığında raporu oynatır — okuma oranı 36,042 ile 100,000 arasında herhangi bir yere gider; oynatmayan tek kalem başka bir kalemle birlikte serbest bırakıldığında 87,168'i 94,432'ye taşır. Veri kesme anı ile yenileme düzeni yedi satırlık raporun yedi satırını da değiştirirken sunum kalemleri yalnız birini değiştirir; on bir kalem toplam 26 satır oynatır.
İçindekiler
Önceki ders raporu bir önerme zincirine oturttu ve zincirin halkalarını saydı. O rapor bir kez üretildi. Aynı raporu üç ay sonra, başka bir kişinin, aynı sayıları verecek biçimde yeniden üretmesi hiç sorulmadı. Rapor bir dosya değil bir koşumun ürünüdür ve koşumun her adımında bir karar vardır.
Bu sorunun bir bölümü daha önce kapandı. Veri Toplama ve Hazırlama kursu hazırlama hattını on yedi adım ve otuz dokuz karar olarak yazdı; koşum defteri tutulduğunda otuz dokuz kararın otuz dokuzu koşumdan sonra okunabilir oldu. Python ile Veri Analizi kursu bir adım öteye gitti ve çalışma ortamını dokuz kalemlik bir liste olarak yazdı: kilit dosyasıyla on yedi adımın on biri iki makinede aynı sonucu veriyordu, kalan altısı kilit dosyasında hiç yazmayan beş kaleme bağlıydı. İki hesap da burada tekrarlanmaz, girdi olarak alınır. Bu dersin eklediği şey raporun kendisidir: hat aynı, ortam aynı olsa bile rapor aynı olmayabilir.
- RP25. Küme K03’ten devralınır ve kurgudur: 3.199 satırlık okuma tablosu, 1.329 abone, üç dönem, beş bölge. Tohum koda yazılıdır.
- RP26. Okumaların geliş gecikmeleri de kurgudur ve önceki dersin tohumuyla üretilir.
- RP27. Raporun kalemleri kurgudur: on bir kalem, her birinin bir sabit değeri ve eşit ölçüde savunulabilir bir alternatifi vardır.
- RP28. Eşikler: oran için 0,05 puan (paydadaki tek abone 0,075 puan eder), ortalama için
0,0005 m³ — ikincisi M26/K04’ün kullandığı eşiktir. Kayan noktalı karşılaştırma
==ile yapılmaz. - RP29. M26/K03’ün 39 kararı ve M26/K04’ün 9 ortam kalemi girdi olarak alınır.
- RP30. Rapor yedi satırdır: iki başlık ve beş bölge satırı.
Raporun Kalemleri
# yeniden.py — MODELDIR. K03'un kurgu kumesi ayni tohumla uretilir; uzerine kurgu # gelis gecikmeleri ve raporu ureten kalem listesi kurulur. import math TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF BOLGE = [("kuzey", 0.28, 21), ("guney", 0.22, 17), ("dogu", 0.18, 26), ("bati", 0.14, 14), ("merkez", 0.18, 23)] 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 ABONE, ELENEN = [], [] for i in range(HAM): r = uretec(TOHUM + i) b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])] ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05]) ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17]) (ELENEN if r() < 0.046 else ABONE).append( {"abone_no": 10001 + i, "bolge": b[0], "taban": b[2]}) GECERLI = {k["abone_no"] for k in ABONE} OKUMA = {} for k in ABONE + ELENEN: r = uretec(TOHUM + 7000 + k["abone_no"]) for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])): t = 0.0 if r() < 0.038 else math.floor( k["taban"] * math.exp((r() + r() + r() - 1.5) * 0.62) * (1 - d * 0.05) * 100 + 0.5) / 100 if k["abone_no"] in GECERLI: OKUMA.setdefault(k["abone_no"], {})[d + 1] = t r() # Her okuma kaynaga donem kapanisindan bir sure sonra girer. Gecikme kurgudur ve # ayri bir tohumla cekilir; okumanin degerini degistirmez, yalniz gorunurlugunu. GECIKME = {} for k in ABONE: r = uretec(TOHUM + 120000 + k["abone_no"]) for d in sorted(OKUMA.get(k["abone_no"], {})): GECIKME[(k["abone_no"], d)] = ayrik(r(), [0.58, 0.19, 0.13, 0.07, 0.03]) * 6 def goruntu(gun): """Gecikmesi gun degerini asmayan okumalarin gorundugu kaynak goruntusu.""" g = {} for (a, d), gec in GECIKME.items(): if gec <= gun: g.setdefault(a, {})[d] = OKUMA[a][d] return g # Raporun kendi kalemleri. Her kalemin sabit degeri ve esit olcude savunulabilir # bir alternatifi vardir; alternatif secilirse rapor ayni raporu vermez. KALEM = [("veri kesme ani", "12 gun", "40 gun"), ("yenileme duzeni", "anlik sorgu", "onceden toplanmis model"), ("payda tanimi", "kayitli abone", "okumasi olan abone"), ("sifir okuma", "okuma sayilir", "okuma sayilmaz"), ("gozlem penceresi", "donem 3", "donem 2 ya da 3"), ("abone suzgeci", "tum aboneler", "uc donemi tam olanlar"), ("bolge suzgeci", "bes bolge", "merkez haric"), ("toplulastirma agirligi", "abone agirlikli", "bolge agirliksiz"), ("sunum ondaligi", "uc ondalik", "tam sayi"), ("sunum birimi", "oran", "hedefin yuzdesi"), ("hedef degeri", "65", "60")] SABIT = {a: b for a, b, _ in KALEM} def rapor(k): """Kalem listesinden iki basligi ureten rapor. Her karar bir kalemden okunur.""" kes = 12 if k["veri kesme ani"] == "12 gun" else 40 kes = 0 if k["yenileme duzeni"] != "anlik sorgu" else kes kume = goruntu(kes) sec = [a for a in ABONE if k["bolge suzgeci"] == "bes bolge" or a["bolge"] != "merkez"] if k["abone suzgeci"] != "tum aboneler": sec = [a for a in sec if len(kume.get(a["abone_no"], {})) == 3] don = (2, 3) if k["gozlem penceresi"] != "donem 3" else (3,) pay, deger, bolge = [], [], {} for a in sec: o = kume.get(a["abone_no"], {}) v = [o[d] for d in don if d in o and (k["sifir okuma"] == "okuma sayilir" or o[d] > 0)] bolge.setdefault(a["bolge"], [0, 0]) if v: pay.append(a) deger.extend(v) bolge[a["bolge"]][0] += 1 bolge[a["bolge"]][1] += 1 payda = len(sec) if k["payda tanimi"] == "kayitli abone" else \ len([a for a in sec if kume.get(a["abone_no"])]) oran = (sum(x[0] / x[1] for x in bolge.values()) / len(bolge) * 100 if k["toplulastirma agirligi"] != "abone agirlikli" else len(pay) / payda * 100) if k["sunum birimi"] != "oran": oran = oran / float(k["hedef degeri"]) * 100 ond = 3 if k["sunum ondaligi"] == "uc ondalik" else 0 return round(oran, ond), round(sum(deger) / len(deger), 3) ESIK_ORAN, ESIK_M3 = 0.05, 0.0005 t_oran, t_ort = rapor(SABIT) print(f"kurgu kume (tohum {TOHUM}): {len(ABONE)} abone, {len(GECIKME)} okuma") print(f"raporun kalemleri: {len(KALEM)}") print(f"sabit kalemlerle rapor: okuma orani {t_oran:.3f}, " f"donem 3 ortalamasi {t_ort:.3f} m3") print(f"esikler: oran {ESIK_ORAN} puan, ortalama {ESIK_M3} m3")
kurgu kume (tohum 20260218): 1329 abone, 3199 okuma raporun kalemleri: 11 sabit kalemlerle rapor: okuma orani 56.659, donem 3 ortalamasi 18.128 m3 esikler: oran 0.05 puan, ortalama 0.0005 m3
On bir kalemin hiçbiri bir kod satırında gizli değil; hepsi rapor işlevinin okuduğu bir listede duruyor. Bu, sabitlemenin ilk koşuludur: bir kalem koda gömülüyse serbest mi sabit mi olduğu sorulamaz.
Bir Kalem Serbest Bırakıldığında
# Her kalem tek tek serbest birakilir: alternatif deger secilir, oteki on kalem # sabit kalir ve rapor yeniden uretilir. def oynatan(o, m): return abs(o - t_oran) > ESIK_ORAN or abs(m - t_ort) > ESIK_M3 print(f"{'serbest birakilan kalem':<24}{'alternatif':<24}{'okuma orani':>12}" f"{'ortalama':>10}{'oynatti mi':>12}") oyn = 0 for ad, sab, alt in KALEM: k = dict(SABIT) k[ad] = alt o, m = rapor(k) oyn += 1 if oynatan(o, m) else 0 print(f"{ad:<24}{alt:<24}{o:>12.3f}{m:>10.3f}" f"{('evet' if oynatan(o, m) else 'hayir'):>12}") print(f"\n{len(KALEM)} kalemin {oyn}'i tek basina serbest birakildiginda raporu oynatiyor") ikili = dict(SABIT) ikili["sunum birimi"], ikili["hedef degeri"] = "hedefin yuzdesi", "60" o, m = rapor(ikili) print(f"tek basina oynatmayan 'hedef degeri', 'sunum birimi' ile birlikte serbest " f"birakildiginda: {o:.3f}")
serbest birakilan kalem alternatif okuma orani ortalama oynatti mi veri kesme ani 40 gun 63.055 18.321 evet yenileme duzeni onceden toplanmis model 36.042 18.166 evet payda tanimi okumasi olan abone 60.531 18.128 evet sifir okuma okuma sayilmaz 54.628 18.803 evet gozlem penceresi donem 2 ya da 3 80.512 19.020 evet abone suzgeci uc donemi tam olanlar 100.000 18.160 evet bolge suzgeci merkez haric 55.842 17.476 evet toplulastirma agirligi bolge agirliksiz 56.746 18.128 evet sunum ondaligi tam sayi 57.000 18.128 evet sunum birimi hedefin yuzdesi 87.168 18.128 evet hedef degeri 60 56.659 18.128 hayir 11 kalemin 10'i tek basina serbest birakildiginda raporu oynatiyor tek basina oynatmayan 'hedef degeri', 'sunum birimi' ile birlikte serbest birakildiginda: 94.432
Tek bir kalem serbest kaldığında okuma oranı 36,042 ile 100,000 arasında herhangi bir yere gidiyor. Öteki on kalem sabit; oynatan tek şey serbest bırakılanı.
Altıncı satır ayrıca okunmayı hak ediyor. “Üç dönemi tam olan aboneler” süzgeci makul bir cümledir ve ölçütü tam olarak 100,000 yapar, çünkü süzgeç paydayı da süzer: dönem 3 okuması olmayan abone zaten kümede kalmaz. Ölçüt artık hiçbir şey ölçmüyor ve rapor bunu hiçbir yerde söylemiyor. Bir süzgeç, ölçütün paydasına dokunduğunda ölçütü ölçüt olmaktan çıkarabilir.
Son satır ise sabitleme kararının nasıl verileceğini belirliyor. Hedef değeri tek başına serbest bırakıldığında rapor kımıldamıyor, çünkü sunum birimi “oran” olduğu sürece hedef hiçbir hesaba girmiyor. Sunum birimiyle birlikte serbest bırakıldığında aynı kalem 87,168’i 94,432’ye taşıyor. Bu koşumda oynatmayan kalem, sabitlenmesi gerekmeyen kalem değildir. Kalemler tek tek değil, birlikte oynatır ve bir kalemin etkisiz görünmesi başka bir kalemin sabit olmasına bağlı olabilir.
İkinci Üretim
# Rapor yedi satirdir: iki baslik ve bes bolge satiri. Ikinci uretim ayni kalem # listesiyle kosar; sonra her kalem tek tek serbest birakilip kac satir degistigi sayilir. def satirlar(k): o, m = rapor(k) s = [f"okuma orani {o:.3f}", f"donem 3 ortalamasi {m:.3f} m3"] kes = 12 if k["veri kesme ani"] == "12 gun" else 40 kes = 0 if k["yenileme duzeni"] != "anlik sorgu" else kes kume = goruntu(kes) for b, _, _ in BOLGE: v = [kume[a["abone_no"]][3] for a in ABONE if a["bolge"] == b and 3 in kume.get(a["abone_no"], {})] s.append(f"{b} ortalamasi {sum(v) / len(v):.3f} m3 ({len(v)} okuma)") return s ilk = satirlar(SABIT) print(f"ikinci uretim ayni kalem listesiyle: " f"{sum(1 for a, b in zip(ilk, satirlar(dict(SABIT))) if a == b)}/{len(ilk)} satir ayni") print(f"\n{'serbest birakilan kalem':<24}{'degisen satir':>14} degisenler") toplam = 0 for ad, sab, alt in KALEM: k = dict(SABIT) k[ad] = alt fark = [i for i, (a, b) in enumerate(zip(ilk, satirlar(k))) if a != b] toplam += len(fark) print(f"{ad:<24}{len(fark):>14} {', '.join(str(i + 1) for i in fark) or '-'}") print(f"\n{len(KALEM)} kalemin her biri tek basina serbest birakildiginda toplam " f"{toplam} satir degisiyor ({len(ilk)} satirlik raporda)") DEFTER = [("M26/K03 hazirlama defteri", 39, "hattin 17 adimindaki kararlar"), ("M26/K04 calisma ortami", 9, "kosum ortaminin kalemleri"), ("bu ders — rapor", len(KALEM), "raporun kendi kalemleri")] print(f"\n{'kaynak':<28}{'kalem':>7} ne sabitler") for a, n, s in DEFTER: print(f"{a:<28}{n:>7} {s}") print(f"{'toplam':<28}{sum(n for _, n, _ in DEFTER):>7}")
ikinci uretim ayni kalem listesiyle: 7/7 satir ayni serbest birakilan kalem degisen satir degisenler veri kesme ani 7 1, 2, 3, 4, 5, 6, 7 yenileme duzeni 7 1, 2, 3, 4, 5, 6, 7 payda tanimi 1 1 sifir okuma 2 1, 2 gozlem penceresi 2 1, 2 abone suzgeci 2 1, 2 bolge suzgeci 2 1, 2 toplulastirma agirligi 1 1 sunum ondaligi 1 1 sunum birimi 1 1 hedef degeri 0 - 11 kalemin her biri tek basina serbest birakildiginda toplam 26 satir degisiyor (7 satirlik raporda) kaynak kalem ne sabitler M26/K03 hazirlama defteri 39 hattin 17 adimindaki kararlar M26/K04 calisma ortami 9 kosum ortaminin kalemleri bu ders — rapor 11 raporun kendi kalemleri toplam 59
İkinci üretim yedi satırın yedisinde aynı sonucu veriyor. Bu, kalem listesinin taşınmasının yeterli olduğunu gösteriyor; sabitlenen şey kodun kendisi değil, kodun okuduğu listedir.
Kalemler eşit ağırlıkta değil. Veri kesme anı ile yenileme düzeni yedi satırın yedisini birden değiştiriyor, çünkü ikisi de kaynağın hangi görüntüsünün okunacağını belirliyor ve o görüntü raporun her satırının altında duruyor. Sunum kalemleri yalnız bir satırı değiştiriyor. Aradaki fark bir öncelik listesi verir: raporun yanında taşınacak tek bir kalem seçilecekse o kalem veri kesme anıdır.
Toplam elli dokuz kalem üç ayrı yerden geliyor ve üçü birbirinin yerine geçmiyor. Hazırlama defterinin otuz dokuz kararı hattın adımlarını sabitler ama raporun kesme anını bilmez. Çalışma ortamının dokuz kalemi koşumu sabitler ama raporun süzgecini bilmez. Raporun on bir kalemi ise ötekilerin ikisi de sabit olmadan hiçbir şey garanti etmez: aynı kalem listesiyle koşan iki rapor, altındaki hat ya da ortam değiştiyse yine ayrışır.
Özet
- Bir raporun yeniden üretilmesi üç kaynaktan gelen 59 kalemin sabitlenmesini ister: hazırlama defterinin 39 kararı, çalışma ortamının 9 kalemi ve raporun kendi 11 kalemi.
- On bir kalemin 10’u tek başına serbest bırakıldığında raporu oynatır; okuma oranı 36,042 ile 100,000 arasında herhangi bir yere gider.
- Tek başına oynatmayan kalem sabitlenmesi gerekmeyen kalem değildir: hedef değeri sunum birimiyle birlikte serbest bırakıldığında 87,168’i 94,432’ye taşır.
- Bir süzgeç ölçütün paydasına dokunduğunda ölçütü ölçüt olmaktan çıkarabilir: “üç dönemi tam olan aboneler” süzgeci okuma oranını tanım gereği 100,000 yapar.
- Kalemler eşit ağırlıkta değildir: veri kesme anı ile yenileme düzeni yedi satırın yedisini, sunum kalemleri yalnız birini değiştirir; on bir kalem toplam 26 satır oynatır.
- Kalem listesi taşındığında ikinci üretim yedi satırın yedisinde aynıdır; sabitlenen şey kod değil, kodun okuduğu listedir.
Sonraki Adım
Konu beş derste bir raporu baştan sona kurdu ve her adımda kararı yazdı. Aynı on iki ölçüt üç düzende kodlandığında bir bakışta 1, 2 ve 9 ölçüt geri okundu ve desteklenen karar sayısı 0, 0 ve 3 çıktı. Yüzde 60,948’lik bir ölçüt, ölçüm ağında tek bir okuma değişmeden altı yoldan denendi ve beşi eşiği aştı. Aynı ölçüt üç yenileme düzeninde 56,659, 48,081 ve 36,042 verdi. Bulgudan öneriye giden zincirin on bir yanlış varsayılanından dokuzu öneriyi güçlendirdi. Ve raporun ikinci kez üretilmesi 59 kalem istedi.
Bütün bu işler sessiz bir varsayımla yapıldı: küme tek bir makineye sığıyor. Üç bin yüz doksan dokuz satır her blokta baştan sona okundu, her toplulaştırma tek bir döngüde yapıldı, bir süzgeç denemek saniyeler sürdü. Ölçüm ağı büyüdüğünde bu varsayım düşer ve düştüğü anda raporun kendisi değil hesabın kendisi taşınmak zorunda kalır. Sonraki konu bunu sorar: küme tek makineye sığmadığında raporun hangi kısmı bölünebiliyor, bölünen kısım hangi geçişlerde kaç kayıt taşıyor ve bölünemeyen pay neye mal oluyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.