Ders 03 / 10
Bileşen ve Yerleşim Diyagramları
Aynı altı sınıf 203 ayrı çalışma zamanı bölüntüsüne düşüyor: beş simgelik bileşen gösterimi 540 sınıf dağılımını 20'ye indiriyor, iç bağ yükünü hiç söylemiyor ve uzak bağ sayısını ancak yerleşim yazıldığında sabitliyor.
İçindekiler
Önceki iki ders sistemi durağan bir bağ kümesi olarak ölçtü ve otuz bir simgeye çıkıldığında belirsizliğin sıfıra indiğini gösterdi. Geri çevrilebilir bir sınıf gösterimi elde edildi — ama o gösterim, altı sınıfın çalışırken kaç ayrı parçada durduğunu hiç söylemiyor. Hepsi tek bir birimde de koşabilir, altısı ayrı ayrı da.
Bu ders o boşluğu ölçüyor. Sınıflar çalışma zamanı birimlerine bölünüyor, birimler düğümlere yerleştiriliyor ve her iki adımda kaç sistemin aynı gösterime düştüğü sayılıyor. Hangi bölüntünün ya da hangi yerleşimin seçilmesi gerektiği bu dersin sorusu değildir; mimari karar Yazılım Mimarlığı ve Dağıtık Sistemler müfredatlarının konusudur. Burada yalnız gösterimlerin neyi ayırt edip neyi ayırt etmediği sayılıyor.
Sınıf Gösterimi Bölünmeyi Söylemez
Bir bileşen, birlikte konuşlandırılan ve birlikte yer değiştiren sınıfların oluşturduğu çalışma zamanı birimidir. Ortak tanımın altı sınıfı için bir bileşen düzeni, sınıfların bir bölüntüsüdür: her sınıf tam olarak bir bileşende bulunur.
- YD14 — Sınıf kümesi ortak tanımın bağlarından çıkar:
IsEmri,Usta,Kalem,Parca,Tezgah,Belge. Bağlar b1 ile b5 arasındaki beş bağdır. - YD15 — Bir bölüntüde bir bağın iki ucu ayrı bileşenlerdeyse o bağ dışarı çıkar ve bileşen gösteriminde görünür; aynı bileşendeyse gösterime hiç çıkmaz.
- YD16 — Ders boyunca tek bir bölüntü izlenir:
Kabul= iş emri ve belge,Atolye= usta ve tezgâh,Stok= kalem ve parça.
"""M01/K06: ortak tanimin bag kumesi calisma zamani birimlerine bolunuyor. Sinif gosterimi bu bolunmeyi hic yazmaz ; alti sinifin butun bolunturleri tam sayimla uretilir.""" SINIFLAR = ["IsEmri", "Usta", "Kalem", "Parca", "Tezgah", "Belge"] BAGLAR = [("IsEmri", "Usta"), ("IsEmri", "Kalem"), ("Kalem", "Parca"), ("Usta", "Tezgah"), ("IsEmri", "Belge")] # ortak tanimin b1..b5 bagi SECILEN = [["IsEmri", "Belge"], ["Usta", "Tezgah"], ["Kalem", "Parca"]] def boluntuler(ogeler): """Bir kumenin butun boluntuleri: her sinif tam bir bilesende.""" if not ogeler: yield [] return ilk, kalan = ogeler[0], ogeler[1:] for b in boluntuler(kalan): for i in range(len(b)): yield b[:i] + [[ilk] + b[i]] + b[i + 1:] yield [[ilk]] + b def dis_bag(boluntu): yer = {s: i for i, g in enumerate(boluntu) for s in g} return sum(1 for k, h in BAGLAR if yer[k] != yer[h]) hepsi = list(boluntuler(SINIFLAR)) print("sinif", len(SINIFLAR), "| bag", len(BAGLAR), "| ayri bilesen boluntusu", len(hepsi)) print("secilen boluntu:", SECILEN, "-> disari cikan bag", dis_bag(SECILEN)) print() dagilim = {} for b in hepsi: a = (len(b), dis_bag(b)) dagilim[a] = dagilim.get(a, 0) + 1 print("bilesen disari cikan bag ayni kaba cizime dusen boluntu") for a in sorted(dagilim): isaret = " <- secilen" if a == (len(SECILEN), dis_bag(SECILEN)) else "" print(f"{a[0]:7d}{a[1]:18d}{dagilim[a]:26d}{isaret}") print("toplam:", sum(dagilim.values())) print() GENIS = SINIFLAR + ["Tedarikci"] print("sinif sayisi ayri boluntu") for n in range(4, len(GENIS) + 1): print(f"{n:12d}{len(list(boluntuler(GENIS[:n]))):14d}")
sinif 6 | bag 5 | ayri bilesen boluntusu 203
secilen boluntu: [['IsEmri', 'Belge'], ['Usta', 'Tezgah'], ['Kalem', 'Parca']] -> disari cikan bag 2
bilesen disari cikan bag ayni kaba cizime dusen boluntu
1 0 1
2 1 5
2 2 10
2 3 10
2 4 5
2 5 1
3 2 10 <- secilen
3 3 30
3 4 35
3 5 15
4 3 10
4 4 30
4 5 25
5 4 5
5 5 10
6 5 1
toplam: 203
sinif sayisi ayri boluntu
4 15
5 52
6 203
7 877
Altı sınıf 203 ayrı bölüntüye düşüyor ve geri çevrilebilir sınıf gösterimi bunların hiçbirini dışarıda bırakmıyor. Bir önceki derste 31 simgeyle belirsizlik sıfıra inmişti; o sıfır yalnız bağ alanları için geçerliydi. Bölünme başka bir eksendir ve o eksende sınıf gösteriminin bilgisi hiç yoktur.
Tablo, en kaba bileşen çiziminin bile bir sayı taşıdığını gösteriyor. Üç kutu çizip aralarına iki bağlantı koyan bir gösterim, 203 bölüntünün 10’uyla uyumlu: kutu sayısı ve dışarı çıkan bağ sayısı yazıldığı anda 203 sistem 10’a iniyor. Aynı tablonun en kalabalık satırı üç bileşen ve dört dış bağdır: 35 bölüntü. Dağılımın uçları ise tekildir — tek bileşenli bölüntü bir tanedir ve dışarı hiç bağ çıkarmaz, altı bileşenli bölüntü de bir tanedir ve beş bağın hepsini dışarı çıkarır.
Son tablo bu eksenin ölçeğini veriyor. Dört sınıfta 15, beşte 52, altıda 203, yedide 877 bölüntü var; sisteme tek bir sınıf eklemek bölüntü sayısını dört katından fazla artırıyor. Sınıf gösterimi bu büyümenin hiçbirini görmez, çünkü yeni sınıf ona yalnız birkaç simge ekler. Önceki derste gösterim doğrusal, bağ belirsizliği üstel büyüyordu; burada bölünme belirsizliği üstelden de hızlı büyüyor. Bir sistem büyüdükçe hakkında söylenmeyen şeyin payı büyür ve bu, gösterimin niteliğinden değil sayının doğasından gelir.
Bileşen Gösterimi Neyi Alıyor
Kaba çizim bileşenleri adlandırmıyor. Adlandırılmış bir gösterimde bileşenlerin kimliği sabit ve ölçülecek olan, hangi sınıfın hangi bileşende olduğu.
- YD17 — Üç adlandırılmış bileşen sabittir ve hiçbiri boş olamaz; bu yüzden sayım altı sınıfın üç bileşene örten atamaları üzerindedir.
"""Adlandirilmis bilesen gosterimi: uc bilesen sabit , sinif dagilimi degisken. Ic baglar gosterime cikmaz ; disari cikan baglar cikar.""" from itertools import product from math import log2 SINIFLAR = ["IsEmri", "Usta", "Kalem", "Parca", "Tezgah", "Belge"] BAGLAR = [("IsEmri", "Usta"), ("IsEmri", "Kalem"), ("Kalem", "Parca"), ("Usta", "Tezgah"), ("IsEmri", "Belge")] BILESEN = ("Kabul", "Atolye", "Stok") SECILEN = {"IsEmri": "Kabul", "Belge": "Kabul", "Usta": "Atolye", "Tezgah": "Atolye", "Kalem": "Stok", "Parca": "Stok"} def dis_yapi(yer): """Gosterime cikan yapi: hangi bilesen cifti arasinda kac bag var.""" d = {} for k, h in BAGLAR: if yer[k] != yer[h]: c = tuple(sorted((yer[k], yer[h]))) d[c] = d.get(c, 0) + 1 return tuple(sorted(d.items())) def ic_yuk(yer): d = dict.fromkeys(BILESEN, 0) for k, h in BAGLAR: if yer[k] == yer[h]: d[yer[k]] += 1 return tuple(d[b] for b in BILESEN) orten = [dict(zip(SINIFLAR, d)) for d in product(BILESEN, repeat=len(SINIFLAR)) if len(set(d)) == len(BILESEN)] hedef = dis_yapi(SECILEN) uyan = [y for y in orten if dis_yapi(y) == hedef] print("orten atama:", len(orten), "| secilen dagilimin disa cikan bagi:", [(f"{a}-{b}", n) for (a, b), n in hedef]) print() print("gosterim duzeyi simge dusen atama bit") for ad, simge, sayi in (("0 kutular ve adlari", 3, len(orten)), ("1 + bilesenler arasi baglanti", 5, len(uyan)), ("2 + her kutunun icerigi", 11, 1)): print(f" {ad:36s}{simge:3d}{sayi:12d}{log2(sayi):8.2f}") print() yuk = {} for y in uyan: yuk[ic_yuk(y)] = yuk.get(ic_yuk(y), 0) + 1 print("ayni bilesen gosterimine dusen", len(uyan), "atamanin ic bag dagilimi") print(" (Kabul , Atolye , Stok) atama") for k in sorted(yuk): print(f" {str(k):24s}{yuk[k]:5d}")
orten atama: 540 | secilen dagilimin disa cikan bagi: [('Atolye-Kabul', 1), ('Kabul-Stok', 1)]
gosterim duzeyi simge dusen atama bit
0 kutular ve adlari 3 540 9.08
1 + bilesenler arasi baglanti 5 20 4.32
2 + her kutunun icerigi 11 1 0.00
ayni bilesen gosterimine dusen 20 atamanin ic bag dagilimi
(Kabul , Atolye , Stok) atama
(0, 0, 3) 2
(0, 3, 0) 2
(1, 1, 1) 2
(2, 0, 1) 4
(2, 1, 0) 4
(3, 0, 0) 6
Üç sayı yan yana. Sistem: altı sınıf, beş bağ, 203 bölüntü ve üç adlandırılmış bileşen için 540 örten atama. Gösterim: beş simge — üç kutu ve iki bağlantı. Bedel: aynı gösterime düşen 20 atama.
Merdivenin adımları önceki dersinkinden farklı davranıyor. Bağlantıları çizen iki simge 9,08 bitten 4,32 bite iniyor: simge başına 2,37 bit. İçeriği yazan altı simge kalan 4,32 biti alıyor: simge başına 0,72 bit. Sınıf gösteriminde her simge tam bir bit alıyordu, çünkü gizli alanlar birbirinden bağımsız ikili seçimlerdi. Burada gizli olgular bağımsız değil — bir sınıfı bir bileşene koymak, ona bağlı sınıfların hangi bileşende olabileceğini de kısıtlar. Bağımlı olguları yazan simgeler eşit bit taşımaz.
Alt tablo bileşen gösteriminin en pahalı sessizliğini gösteriyor. Yirmi atamanın hepsi aynı
gösterimi üretiyor, ama gösterime çıkmayan üç iç bağ bu yirmi atamada altı ayrı biçimde
dağılıyor. Bir uçta bütün iç bağlar tek bileşende toplanıyor — Kabul üç, diğerleri sıfır —
ve bu altı atamada oluyor. Öbür uçta yük eşit bölünüyor: her bileşende bir bağ, iki atamada.
Diyagrama bakan biri üç kutu görüyor ve kutuların içindeki yükün nasıl dağıldığını bilmiyor;
iki atama arasındaki fark, bir bileşenin bütün iç işi taşıması ile hiç taşımaması kadar
büyüktür. Altı dağılımın ağırlıkları da eşit değil: yirmi atamanın altısı, yani tablonun en
kalabalık satırı, üç iç bağın hepsini Kabul bileşenine veriyor.
Buradan çıkan okuma şudur: bileşen gösterimi iç yapıyı gizlemek için vardır ve gizlediği şey yalnız ayrıntı değil, yükün dağılımıdır. Gizlemenin kendisi bir kusur değil; ölçülmemiş olması kusurdur.
Yerleşim ve Uzak Bağ
Bileşenler düğümlere yerleştirildiğinde bağların bir kısmı düğüm sınırını geçer. Sınırı geçen bağ, ortak tanımda uzak bağ olarak sayılır; geçmeyen bağ yereldir.
- YD18 — Yerleşim, bileşen başına bir simgedir: hangi bileşen hangi düğümde. Bileşen gösteriminden okunan iki bileşenler arası bağ ile gösterime çıkmayan üç iç bağ toplam beş bağı verir; iç bağlar tanımı gereği hep yereldir.
"""Yerlesim: bilesenler dugumlere dagitiliyor. Bir bag , iki ucu ayri dugumdeyse UZAK olur. Bilesen gosterimi bunu hic soylemez ; yerlesim gosterimi bilesen basina bir simgeyle soyler.""" from itertools import product BILESEN = ("Kabul", "Atolye", "Stok") BILESEN_BAG = [("Kabul", "Atolye"), ("Kabul", "Stok")] # bilesen gosteriminden okunur IC_BAG = 3 # gosterime cikmaz , hep yerel def uzak(yerlesim): return sum(1 for a, b in BILESEN_BAG if yerlesim[a] != yerlesim[b]) for dugum in (2, 3): dagilim = {} for d in product(range(dugum), repeat=len(BILESEN)): dagilim.setdefault(uzak(dict(zip(BILESEN, d))), []).append(d) print(f"{dugum} dugum -> {dugum ** len(BILESEN)} yerlesim , yerlesim gosterimi" f" {len(BILESEN)} simge") for u in sorted(dagilim): print(f" uzak bag {u}: {len(dagilim[u]):2d} yerlesim" f" | yerel bag {IC_BAG + len(BILESEN_BAG) - u}")
2 dugum -> 8 yerlesim , yerlesim gosterimi 3 simge uzak bag 0: 2 yerlesim | yerel bag 5 uzak bag 1: 4 yerlesim | yerel bag 4 uzak bag 2: 2 yerlesim | yerel bag 3 3 dugum -> 27 yerlesim , yerlesim gosterimi 3 simge uzak bag 0: 3 yerlesim | yerel bag 5 uzak bag 1: 12 yerlesim | yerel bag 4 uzak bag 2: 12 yerlesim | yerel bag 3
Bileşen gösterimi tek başına uzak bağ sayısını söylemiyor. İki düğümlü bir kurulumda sekiz yerleşim var ve bu sekiz yerleşim üç ayrı uzak bağ değeri üretiyor: 0, 1 ya da 2. Üç simgelik yerleşim gösterimi eklendiğinde değer tek bir sayıya iniyor. Bu, bir bileşen gösterimine bakıp “iki bağlantı var, demek ki iki uzak çağrı var” diye okumanın neden yanlış olduğunu veriyor: iki bağlantının ikisi de aynı düğümde kalabilir ve o durumda uzak bağ sıfırdır.
İkinci yapılandırma düğüm sayısını üçe çıkarıyor. Yerleşim gösterimi hâlâ üç simge, ama olası yerleşim sayısı 8’den 27’ye çıkıyor ve dağılım kayıyor: uzak bağı sıfır olan yerleşimlerin payı sekizde ikiden yirmi yedide üçe iniyor, iki uzak bağlı yerleşimlerin payı sekizde ikiden yirmi yedide on ikiye çıkıyor. Aynı sayıda simge, daha çok düğümde daha az şey söylüyor — çünkü simge sayısı bileşen sayısına bağlıdır, belirsizlik ise düğüm sayısına.
Yerleşim gösteriminin ayırt ettiği şeyin sınırı da buradan okunur. Gösterim, bir bağın uzak olup olmadığını söyler; o bağın hangi hızda ya da hangi güvenilirlikte çalıştığını söylemez, çünkü gösterimde böyle bir alan yoktur. Uzak bağın bedeli bu kursta sayılmaz; burada sayılan tek şey, kaç bağın sınırı geçtiği ve gösterimin bunu ne kadar belirlediğidir.
Bir alan daha gösterimde durur ve bu derste sayılmadı: yapı eseri. Yerleşim gösterimi düğümlere bileşenleri değil, bileşenlerin paketlenmiş biçimlerini yerleştirir; bir bileşen birden çok yapı eserine bölünebilir, bir yapı eseri birden çok düğüme kopyalanabilir. Bu iki yönlü esneklik, buradaki üç simgelik yerleşim gösteriminin bileşen başına tek düğüm varsayımına dayandığını söylüyor. Varsayım kaldırıldığında yerleşim sayısı büyür ve gösterim aynı kalır — yani ölçülen 8 ve 27 sayıları, bu varsayımın altındaki alt sınırlardır.
Özet
- Altı sınıf 203 ayrı bileşen bölüntüsüne düşüyor ve geri çevrilebilir sınıf gösterimi bunların hiçbirini eliyor değil: bölünme, bağ alanlarından ayrı bir eksendir.
- Üç kutu ve iki bağlantıdan oluşan en kaba bileşen çizimi 203 bölüntünün 10’uyla uyumlu; aynı tablonun en kalabalık satırı üç bileşen ve dört dış bağdır ve 35 bölüntü taşır.
- Adlandırılmış üç bileşen için 540 örten atama var. Üç simge (kutular ve adları) hiçbirini elemiyor, iki bağlantı simgesi 20’ye indiriyor, altı içerik simgesi tek atamaya indiriyor.
- Bağlantı simgeleri simge başına 2,37 bit, içerik simgeleri 0,72 bit alıyor; sınıf gösterimindeki simge başına tam bir bit sonucu burada geçerli değildir, çünkü gizli olgular birbirinden bağımsız değildir.
- Aynı bileşen gösterimine düşen 20 atama, gösterime çıkmayan üç iç bağı altı ayrı biçimde dağıtıyor; bir uçta tek bileşen üç bağı da taşıyor, öbür uçta yük üçe eşit bölünüyor.
- İki düğümlü kurulumda sekiz yerleşim üç ayrı uzak bağ değeri veriyor (0, 1, 2); üç simgelik yerleşim gösterimi değeri sabitliyor. Düğüm üçe çıkınca simge sayısı değişmiyor, yerleşim sayısı 27’ye çıkıyor.
Sonraki Adım
Bu konudaki üç ders de sistemin durağan yanını ölçtü: hangi tür neye bağlı, kaç tane, hangi birimde, hangi düğümde. Üçünün ortak sınırı da aynıydı — hiçbiri sistemin zaman içinde ne yaptığını söylemiyor. Otuz bir simgelik sınıf gösterimi bağ alanları için geri çevrilebilirdi, ama bir iş emrinin hangi sırayla işlendiği, hangi durumlardan geçtiği ve hangi dizilerin hiç gerçekleşmediği o gösterimde yazmıyor.
Sonraki konu davranış gösterimlerini alıyor ve ölçüyü aynı biçimde kuruyor. İlk ders kullanım senaryosu gösterimini ele alıyor: sistemin üç dış olgusunu gösterip yedi iç olgusunu bilerek atan bir gösterimin, bu bilerek atmayı sayıya dökmedikçe farkında olmadan düşürmekten nasıl ayrılamayacağını ölçüyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.