Ders 18 / 22
Sorguyu Veriye Götürmek
Kurgu ölçüm ağının kaynağında 3.199 satır duruyor ve tek bir soru dört strateji ile cevaplanıyor; dördü de aynı sayıyı veriyor ama çözümleme ortamına taşınan kayıt sayısı 3.199'dan 5'e iniyor. Süzgeç kaynağa itildiğinde 835 satır, sütun seçimi de itildiğinde 1.670 değer, toplulaştırma da itildiğinde 10 değer taşınır ve kazanç 1.919 kata çıkar. Kazancın bedeli görünürlüktür: itilen toplam süzgeçten geçen 835 satırı, kaynaktaki 3.199 satırı ve grup başına satır sayısını getirmez, cevabın yanına kararı yazabilmek için taşınan değer 10'dan 27'ye çıkar ve oran 710 kata iner. Kazanç grup sayısına da bağlıdır: 3 gruplu kırılımda 3.199 kat, 15 gruplu kırılımda 426 kat, 835 gruplu kırılımda 11 kattır ve grup sayısı süzülen satır sayısına eşitlendiğinde sıfırlanır.
İçindekiler
Önceki ders işi birden çok bölüme taşıdı ve dağıtmanın kendi kalemini saydı. Ama bütün o hesap tek bir yönde kuruluydu: veri çözümleme ortamına getiriliyordu. Satırlar okunuyor, bölünüyor, taşınıyor ve sonunda cevap ortaya çıkıyordu. Verinin durduğu yer de hesap yapabiliyorsa bu yön tersine çevrilebilir.
Bu dersin ölçüsü tek bir sayıdır: taşınan satır. Aynı soru için kaynaktan kaç kayıt çıkıyor ve süzgeç ile toplulaştırma kaynağa itildiğinde bu sayı kaça iniyor. Yanında duran ikinci sayı, o kazancın karşılığında görünmez olan kalemdir — itilen bir hesap cevabı getirir, cevabı üreten satırları getirmez.
- AB21. Kaynak kurgudur ve önceki derslerin kümesini tutar: 3.199 satır, altı sütun, 1.329 abone, üç dönem. Aynı tohumla üretilir ve çıktı koşumdan koşuma aynıdır. Modeldir.
- AB22. Kaynak, verinin durduğu yerde hesap yapabilen bir arayüz olarak modellenir: süzgeç, sütun seçimi ve toplulaştırma orada çalıştırılabilir. Modeldir.
- AB23. Ölçülen şey kaynaktan çözümleme ortamına geçen satır ve değer sayısıdır; kaynağın içeride kaç satır taradığı bu ölçünün dışındadır.
- AB24. İki toplamın aynı sayılması için eşik 0,05 m³’tür, çünkü okumalar bir ondalıkla raporlanır ve bundan küçük bir fark yalnızca yuvarlamadan gelebilir.
- AB25. Soru sabittir: 2024-03 döneminde bölge başına toplam okuma. Bu dönemde 835 satır vardır ve doğru cevap 17.307,2 m³’tür.
Kaynak ve Soru
# kaynak.py — verinin durdugu yer bir arayuz olarak modellenir. MODELDIR: # gercek bir uzak depo yerine, istenen isi yapip donen her satiri ve degeri # sayan bir kaynak yazildi. Olcu, cozumleme ortamina tasinan satir ve degerdir. TOHUM = 1246 BOLGE = ("kuzey", "dogu", "merkez", "guney", "bati") DONEM = (("2024-01", 1329), ("2024-02", 1035), ("2024-03", 835)) YOGUNLUK = (0, 1, 2, 2, 2, 3, 4, 2, 2, 1) # merkez agirlikli kurgu olcum agi BASLIK = ("abone_no", "sayac_no", "donem", "bolge", "okuma_m3", "basamak") def uretec(tohum: int): s = tohum & 0xFFFFFFFF def sonraki() -> float: nonlocal s s = (1103515245 * s + 12345) & 0xFFFFFFFF return s / 4294967296 return sonraki def basamak(o: float) -> str: return "0-10" if o <= 10 else "10-25" if o <= 25 else "25-40" def kayitlar() -> list[tuple]: r, k = uretec(TOHUM), [] for donem, adet in DONEM: for i in range(adet): o = round(5 + r() * 32.0, 1) k.append((10000 + i, f"S-{4000 + i}", donem, BOLGE[YOGUNLUK[i % 10]], o, basamak(o))) return k class Kaynak: """Ne istenirse onu doner ve donen her satiri ve degeri sayar. Suzgec, sutun secimi ve toplulastirma kaynakta yapilabilir.""" def __init__(self, k: list): self.k, self.satir, self.deger = k, 0, 0 def _ver(self, satirlar: list, alan: int) -> list: self.satir += len(satirlar) self.deger += len(satirlar) * alan return satirlar def hepsi(self) -> list: return self._ver(list(self.k), len(BASLIK)) def suz(self, kosul, alanlar=None) -> list: s = [x for x in self.k if kosul(x)] if alanlar is None: return self._ver(s, len(BASLIK)) ix = [BASLIK.index(a) for a in alanlar] return self._ver([tuple(x[i] for i in ix) for x in s], len(alanlar)) def say(self, kosul) -> int: return self._ver([sum(1 for x in self.k if kosul(x))], 1)[0] def topla_genis(self, kosul, grup: str, olcu: str) -> list: """Toplamin yanina sayi, en kucuk ve en buyugu de koyar: bes deger.""" gi, oi = BASLIK.index(grup), BASLIK.index(olcu) t = {} for x in self.k: if kosul(x): a = t.setdefault(x[gi], [0.0, 0, x[oi], x[oi]]) a[0], a[1] = a[0] + x[oi], a[1] + 1 a[2], a[3] = min(a[2], x[oi]), max(a[3], x[oi]) return self._ver([(g, *v) for g, v in sorted(t.items())], 5) def topla(self, kosul, grup: str, olcu: str) -> list: gi, oi = BASLIK.index(grup), BASLIK.index(olcu) t = {} for x in self.k: if kosul(x): t[x[gi]] = t.get(x[gi], 0.0) + x[oi] return self._ver(sorted(t.items()), 2) k0 = kayitlar() HEDEF = "2024-03" print(f"tohum {TOHUM}; kaynakta {len(k0)} satir, {len(BASLIK)} sutun, " f"{len(k0) * len(BASLIK)} deger") print(f"soru: {HEDEF} doneminde bolge basina toplam okuma; kaynakta bu donemin " f"{sum(a for d, a in DONEM if d == HEDEF)} satiri var")
tohum 1246; kaynakta 3199 satir, 6 sutun, 19194 deger soru: 2024-03 doneminde bolge basina toplam okuma; kaynakta bu donemin 835 satiri var
Kaynak üç iş yapabiliyor: satır süzmek, sütun seçmek ve grup başına toplam almak. Bunların hepsi çözümleme ortamında da yapılabilir; fark yalnızca nerede yapıldığındadır. Arayüz her dönen satırı ve her dönen değeri sayıyor, çünkü ölçülecek şey hesabın kendisi değil, hesabın sonucunun kaç kayıtla ifade edildiğidir. Kaynağın içeride kaç satır taradığı bu sayının dışındadır ve AB23 bunu ayrı tutar.
Dört İtme Derecesi
# itme.py — ayni soru dort strateji ile cevaplanir. Fark, isin nerede # yapildigidir: hepsi istemcide, suzgec kaynakta, sutun daraltma kaynakta, # toplulastirma da kaynakta. ESIK = 0.05 # okumalar bir ondalikla raporlanir, altindaki fark yuvarlamadandir def istemcide_topla(satirlar, gi: int, oi: int) -> dict: t = {} for x in satirlar: t[x[gi]] = t.get(x[gi], 0.0) + x[oi] return t def s1(kn: Kaynak) -> dict: # hicbir sey itilmez return istemcide_topla([x for x in kn.hepsi() if x[2] == HEDEF], 3, 4) def s2(kn: Kaynak) -> dict: # suzgec itilir return istemcide_topla(kn.suz(lambda x: x[2] == HEDEF), 3, 4) def s3(kn: Kaynak) -> dict: # suzgec ve sutun secimi itilir return istemcide_topla( kn.suz(lambda x: x[2] == HEDEF, ["bolge", "okuma_m3"]), 0, 1) def s4(kn: Kaynak) -> dict: # toplulastirma da itilir return dict(kn.topla(lambda x: x[2] == HEDEF, "bolge", "okuma_m3")) G = (34, 14, 14, 10, 12, 12) y = lambda h: "".join(str(v).rjust(G[j]) if j else str(v).ljust(G[0]) for j, v in enumerate(h)) print(y(["strateji", "tasinan satir", "tasinan deger", "oran", "merkez m3", "toplam m3"])) taban = 0 for ad, f in [("hicbir sey itilmez", s1), ("suzgec itilir", s2), ("suzgec ve sutun secimi itilir", s3), ("toplulastirma da itilir", s4)]: kn = Kaynak(k0) t = f(kn) taban = taban or kn.deger print(y([ad, kn.satir, kn.deger, f"{taban / kn.deger:.0f}x", round(t["merkez"], 1), round(sum(t.values()), 1)])) kn1, kn4 = Kaynak(k0), Kaynak(k0) t1, t4 = s1(kn1), s4(kn4) fark = max(abs(t1[g] - t4[g]) for g in t1) print(f"itilmemis ve itilmis hesabin bolge toplamlari arasindaki en buyuk fark " f"{fark:.1e} m3; esik {ESIK} m3 oldugu icin ayni sayi sayilir. Kayan noktali " f"toplama sirasi degisebildigi icin esitlik == ile degil esikle sinanir")
strateji tasinan satir tasinan deger oran merkez m3 toplam m3 hicbir sey itilmez 3199 19194 1x 8752.6 17307.2 suzgec itilir 835 5010 4x 8752.6 17307.2 suzgec ve sutun secimi itilir 835 1670 11x 8752.6 17307.2 toplulastirma da itilir 5 10 1919x 8752.6 17307.2 itilmemis ve itilmis hesabin bolge toplamlari arasindaki en buyuk fark 0.0e+00 m3; esik 0.05 m3 oldugu icin ayni sayi sayilir. Kayan noktali toplama sirasi degisebildigi icin esitlik == ile degil esikle sinanir
Dört strateji de aynı cevabı veriyor: merkez bölgesinde 8.752,6 m³, toplamda 17.307,2 m³. Taşınan satır 3.199’dan 5’e, taşınan değer 19.194’ten 10’a iniyor — 1.919 kat. Kazanç üç ayrı itme kararının toplamıdır ve her satır bir kararı ekliyor.
Süzgecin itilmesi taşınan satırı 3.199’dan 835’e indiriyor; oran doğrudan seçicilikten geliyor. Sütun seçiminin itilmesi satır sayısını değiştirmiyor ama değer sayısını 5.010’dan 1.670’e düşürüyor, çünkü altı alan yerine iki alan geliyor. Toplulaştırmanın itilmesi ise satır kavramını değiştiriyor: artık taşınan şey kayıt değil, sonuçtur — beş grup, beş satır.
Son satır iki toplamı karşılaştırıyor. İtilmemiş ve itilmiş hesabın bölge toplamları arasındaki en büyük fark sıfırdır, ama karşılaştırma yine de eşikle yapılır. Sebep koşumun sonucu değil, kayan noktalı toplamanın birleşme özelliği taşımamasıdır: aynı sayılar başka bir sırada toplandığında son basamak oynayabilir. Kaynağın grup içini hangi sırada topladığı arayüzün dışındadır ve yazılı değildir; bu yüzden eşitlik doğrudan sınanmaz, eşik yazılır.
Kazancın Karşılığı
# denetim.py — itilen hesap sonucu getirir, sonucu ureten karari getirmez. # Once cevabin yanina karar yazilabilmesi icin kac deger daha gerektigi, # sonra itmenin kazancinin grup sayisiyla nasil eridigi sayilir. TABAN = len(k0) * len(BASLIK) kn = Kaynak(k0) genis = kn.topla_genis(lambda x: x[2] == HEDEF, "bolge", "okuma_m3") suzulen, tumu = kn.say(lambda x: x[2] == HEDEF), kn.say(lambda x: True) G2 = (36, 15, 15, 10) y2 = lambda h: "".join(str(v).rjust(G2[j]) if j else str(v).ljust(G2[0]) for j, v in enumerate(h)) print(y2(["cevabin yanina yazilan", "tasinan satir", "tasinan deger", "oran"])) print(y2(["yalniz toplam", 5, 10, f"{TABAN // 10}x"])) print(y2(["toplam, sayi, en kucuk, en buyuk", len(genis), 5 * len(genis), f"{TABAN // (5 * len(genis))}x"])) print(y2(["ustune suzulen ve toplam satir", kn.satir, kn.deger, f"{TABAN // kn.deger}x"])) for g, toplam, sayi, enk, enb in genis: if g in ("merkez", "bati"): print(f"{g:8s} toplam {toplam:8.1f} m3, {sayi:4d} satir, ortalama " f"{toplam / sayi:5.2f} m3, aralik {enk}-{enb} m3") print(f"suzgecten gecen satir {suzulen}, kaynaktaki toplam satir {tumu}; itilen " f"toplam bu iki sayiyi getirmez ve grup basina satir sayisini da getirmez") # Itmenin kazanci grup sayisina baglidir: sonuc satiri grup sayisi kadardir. print(y2(["gruplama anahtari", "grup sayisi", "tasinan deger", "oran"])) for ad, alan in [("basamak", "basamak"), ("bolge", "bolge"), ("bolge + basamak", None), ("abone_no", "abone_no")]: kn2 = Kaynak(k0) if alan is None: t = {} for x in k0: if x[2] == HEDEF: t[(x[3], x[5])] = t.get((x[3], x[5]), 0.0) + x[4] kn2._ver(sorted(t.items()), 3) else: kn2.topla(lambda x: x[2] == HEDEF, alan, "okuma_m3") print(y2([ad, kn2.satir, kn2.deger, f"{TABAN // kn2.deger}x"])) ham = Kaynak(k0) ham.suz(lambda x: x[2] == HEDEF, ["bolge", "okuma_m3"]) print(f"suzulmus ve daraltilmis ham dilim {ham.deger} deger tasir; abone anahtarli " f"itilen toplulastirma {2 * suzulen} deger tasir") print(f"grup sayisi suzulen satir sayisina esitlendiginde itmenin kazanci sifirlanir: " f"{suzulen} grup, {suzulen} satir")
cevabin yanina yazilan tasinan satir tasinan deger oran yalniz toplam 5 10 1919x toplam, sayi, en kucuk, en buyuk 5 25 767x ustune suzulen ve toplam satir 7 27 710x bati toplam 1789.1 m3, 83 satir, ortalama 21.56 m3, aralik 5.0-37.0 m3 merkez toplam 8752.6 m3, 418 satir, ortalama 20.94 m3, aralik 5.0-37.0 m3 suzgecten gecen satir 835, kaynaktaki toplam satir 3199; itilen toplam bu iki sayiyi getirmez ve grup basina satir sayisini da getirmez gruplama anahtari grup sayisi tasinan deger oran basamak 3 6 3199x bolge 5 10 1919x bolge + basamak 15 45 426x abone_no 835 1670 11x suzulmus ve daraltilmis ham dilim 1670 deger tasir; abone anahtarli itilen toplulastirma 1670 deger tasir grup sayisi suzulen satir sayisina esitlendiginde itmenin kazanci sifirlanir: 835 grup, 835 satir
İlk tablo dersin gizlenen kararıdır. İtilen toplulaştırma on değer getirir ve o on değerin yanında hiçbir karar yazılı değildir. Merkez bölgesinin 8.752,6 m³’ünün 418 satırdan mı yoksa 4 satırdan mı geldiği sonucun içinde yoktur; süzgeçten 835 satır geçtiği de, kaynakta 3.199 satır olduğu da yoktur. Bu kalemleri de istemek taşınan değeri 10’dan 27’ye çıkarır ve kazancı 1.919 kattan 710 kata indirir. Kursun kuralı burada ödenir: kararı yazılmayan sayı ölçülmemiş sayılır, ve o kararı yazmanın bu kaynakta bedeli 17 değerdir.
Sayıların kendisi de karar taşıyor. Merkez bölgesi 418 satırda ortalama 20,94 m³, batı bölgesi 83 satırda ortalama 21,56 m³ veriyor. Toplamlar 8.752,6 ile 1.789,1 m³ ve aralarında beş kat fark var; ortalamalar birbirine yakın. Yalnız toplamı gören bir rapor merkez bölgesini “yüksek tüketimli” diye okur, oysa fark tüketimden değil satır sayısından geliyor. İtilen hesap satır sayısını getirmediği sürece bu ayrım raporda yapılamaz.
İkinci tablo kazancın nereye bağlı olduğunu gösteriyor. İtilen toplulaştırmanın taşıdığı satır grup sayısı kadardır; grup sayısı arttıkça kazanç erir. Üç basamaklı kırılımda oran 3.199 kat, beş bölgeli kırılımda 1.919 kat, bölge ile basamağın çaprazında 426 kat, abone kırılımında 11 kattır. Son satır tam eşitliği veriyor: abone anahtarıyla toplulaştırma 1.670 değer taşır ve süzülmüş, iki sütuna daraltılmış ham dilim de 1.670 değer taşır. Grup sayısı süzülen satır sayısına eşitlendiğinde itmenin kazancı sıfırlanır — 835 grup, 835 satır. Bu noktadan sonra ham dilimi çekmek daha iyidir, çünkü aynı bedelle gelen ham satırlarla başka sorular da cevaplanabilir.
Özet
- Aynı soru dört itme derecesiyle cevaplandı ve dördü de 17.307,2 m³ verdi; taşınan satır 3.199’dan 5’e, taşınan değer 19.194’ten 10’a indi ve kazanç 1.919 kat oldu.
- Kalemler ayrışıyor: süzgecin itilmesi satırı 835’e, sütun seçiminin itilmesi değeri 1.670’e, toplulaştırmanın itilmesi satırı 5’e indirir.
- İtilen toplam süzgeçten geçen 835 satırı, kaynaktaki 3.199 satırı ve grup başına satır sayısını getirmez; bu kalemleri de istemek taşınan değeri 27’ye çıkarır ve oranı 710 kata indirir.
- Merkez bölgesinin 8.752,6 m³’ü 418 satırdan, batının 1.789,1 m³’ü 83 satırdan gelir; ortalamalar 20,94 ve 21,56 m³’tür ve toplam farkı tüketimden değil satır sayısından doğar.
- İtme kazancı grup sayısına bağlıdır: 3 grupta 3.199 kat, 15 grupta 426 kat, 835 grupta 11 kat; grup sayısı süzülen satır sayısına eşitlendiğinde kazanç sıfırlanır.
- İki toplam arasındaki fark sıfır çıksa da eşitlik eşikle sınanır, çünkü kaynağın grup içini hangi sırada topladığı arayüzün dışındadır.
Sonraki Adım
Bu konu beş derste tek bir soruyu izledi: küme belleğe sığmadığında soyutlamanın rahatlığından ne kalıyor. Cevap her derste araç değiştirerek geldi. Tip seçimi sütunu 47,9 kat küçülttü, parçalama bellek tepesini 32 kat düşürdü, sütunlu yerleşim okunan değeri 6,8 kat azalttı, dağıtım büyük kümede 19,7 kata kadar kazandırdı ve hesabı veriye itmek taşınan kaydı 1.919 kat azalttı. Ölçek sorunu her seferinde yerleşimi, bölümlemeyi ya da hesabın yapıldığı yeri değiştirerek çözüldü.
Değişmeyen tek şey dilin kendisiydi. Yirmi derstir aynı ifade biçimi kullanılıyor: döngüler, atamalar, ara değişkenler ve adım adım kurulan hesaplar. Sonraki konu bu varsayımı sorgular ve analizi başka türlü ifade eden ortamlara bakar — aynı analizin kaç adımda anlatıldığını, dönüştürme zincirinin kaç ara değişken tuttuğunu ve bir grafiğin kaç katmanla kurulduğunu sayar. Ölçü yine aynıdır: soyutlamanın kazandırdığı ve gizlediği.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.