---
title: 'Modelleme ve Gösterim'
source: 'https://academia.sh/tr/kurslar/modelleme-ve-gosterim'
language: tr
updated: '2026-08-17T04:39:37+00:00'
license: 'CC BY-SA 4.0'
lessons: 10
outcomes:
    - 'Bir gösterimin aynı simgeye kaç ayrı sistemi düşürdüğünü sayar'
    - 'Davranış gösterimlerinin kapsadığı ve kapsamadığı yürütmeleri ayırt eder'
    - 'Kavramsal modelden fiziksel şemaya inerken düşen kısıtı ve uydurulan kararı ayrı ayrı sayar'
---

# Modelleme ve Gösterim

Yapı, davranış ve veri gösterimlerinin bir sistemden ne kadarını taşıdığının, neyi ayırt edemediğinin ve düzey değişiminde neyi düşürüp neyi uydurduğunun sayılması.

## Yapısal Diyagramlar

Gösterim ailesinin taşıdığı bilgi ögeleri, sınıf gösteriminde ilişki türü ile çokluğun aldığı belirsizlik ve bileşen ile yerleşim gösterimlerinin ayırt ettiği bölüntüler.

### Gösterim Ailesi ve Kayıp

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/gosterim-ailesi-ve-kayip

Bir gösterim, sistemin bilgi atan bir izdüşümüdür: beş bağlı bir bakım atölyesinin 31 olgusundan 20'sini yazan yapı gösterimi 2048 ayrı sistemi tek diyagrama düşürür ve atılan 11 alan gösterimden geri getirilemez.

İşletim Sistemi Kavramları kursu on beş derste bir makinenin soyutlamalarını saydı: her
soyutlamanın ödettiği adım ölçüldü ve hiçbir olumsuz sonuç saklanmadı. O ölçümlerin ortak yanı
şuydu — hepsi çalıştırılabilir bir metnin çıktısıydı, doğruluğunu koşumun kendisi taşıyordu.
Bir sistemi başkasına anlatmak bu değildir. Anlatmak, sistemi **daha az bilgiyle**
göstermektir; gösterim sistemin tamamı olsaydı anlatı değil kopya olurdu.

Az bilgiyle göstermenin bir bedeli var ve bu kurs onu sayıyor. Bakım atölyesi modelinde beş bağ
ve otuz bir olgu duruyor; bunların yirmisini yazan bir yapı gösterimi, aynı çizimi üreten
**2047 başka sistemden ayırt edilemez** hâle geliyor. Diyagram yanlış değil; eksik ve
eksikliği kendisi üzerinde görünmüyor.

#### Sistem Veridir, Gösterim Onun İzdüşümüdür

Kurs boyunca tek bir kurgu alan kullanılıyor: bir bakım atölyesi. İş emri açılıyor, kalemlere
bölünüyor, kalemler parça istiyor, bir usta atanıyor, usta tezgâh kullanıyor, iş emri belge
üretiyor. Bu alanın kendisi bir diyagram değil, **veridir**: bağlar, akışlar, önkoşullar,
durumlar ve varlıklar birer Python yapısıdır. Gösterim, o verinin bir izdüşümüdür ve her
izdüşüm bilgi atar.

Bu derste ölçülen izdüşüm en dar olanıdır: bağların yalnız kaynağını, hedefini, yönünü ve
çokluğunu yazan bir yapı gösterimi.

- **YD1** — Sistem beş bağdan oluşur ve her bağ yedi alan taşır. Dördü gösterime çıkar
  (kaynak, hedef, yön, **çokluk (multiplicity)**), üçü çıkmaz (yaşam, sıralı, benzersiz).
- **YD2** — Çokluğu bir olan tarafta sıralılık ve benzersizlik tanımsızdır. N:1 bağın tek
  gizli alanı, 1:N ve N:M bağların üç gizli alanı vardır; beş bağda toplam on bir.
- **YD3** — Gizli alanların hepsi ikili değer alır: yaşam bağımsız ya da bağımlı, sıralı ve
  benzersiz doğru ya da yanlış.
- **YD4** — Sayım **tam sayımdır**. Gizli alanların bütün birleşimleri üretilir ve gösterimi
  değişmeyenler sayılır; tahmin, örneklem ya da rastgelelik yoktur.

```python
"""M01/K06 ortak tanim (kesit): sistem VERIDIR , gosterim o verinin bir izdusumudur.
Kurgu alan bir bakim atolyesi. Her bag gosterime CIKAN ve CIKMAYAN alanlar tasir."""
from itertools import product

BAGLAR = [
    {"ad": "b1", "kaynak": "IsEmri", "hedef": "Usta",  "yon": "tek", "cokluk": "N:1",
     "yasam": "bagimsiz", "sirali": False, "benzersiz": True},
    {"ad": "b2", "kaynak": "IsEmri", "hedef": "Kalem", "yon": "tek", "cokluk": "1:N",
     "yasam": "bagimli",  "sirali": True,  "benzersiz": False},
    {"ad": "b3", "kaynak": "Kalem",  "hedef": "Parca", "yon": "tek", "cokluk": "N:1",
     "yasam": "bagimsiz", "sirali": False, "benzersiz": True},
    {"ad": "b4", "kaynak": "Usta",   "hedef": "Tezgah", "yon": "cift", "cokluk": "N:M",
     "yasam": "bagimsiz", "sirali": False, "benzersiz": True},
    {"ad": "b5", "kaynak": "IsEmri", "hedef": "Belge", "yon": "tek", "cokluk": "1:N",
     "yasam": "bagimli",  "sirali": True,  "benzersiz": True},
]


def gizli_alanlar(bag):
    """Cokluk 1 olan tarafta sirililik ve benzersizlik yoktur."""
    alanlar = ["yasam"]
    if bag["cokluk"] in ("1:N", "N:M"):
        alanlar += ["sirali", "benzersiz"]
    return alanlar


def yapi_gosterimi(baglar, ayrinti=0):
    """ayrinti 0: kaynak , hedef , yon , cokluk. 1: + yasam. 2: + sirali ve benzersiz."""
    simge = []
    for b in baglar:
        s = {"kaynak": b["kaynak"], "hedef": b["hedef"], "yon": b["yon"], "cokluk": b["cokluk"]}
        if ayrinti >= 1:
            s["yasam"] = b["yasam"]
        if ayrinti >= 2:
            for a in gizli_alanlar(b):
                s[a] = b[a]
        simge.append(s)
    return simge


def simge_sayisi(gosterim):
    return sum(len(s) for s in gosterim)


def ayni_gosterime_dusen(baglar, ayrinti=0):
    """Ayni gosterimi ureten kac ayri sistem var. Sayim tam sayimdir."""
    secenek = {"yasam": ("bagimsiz", "bagimli"), "sirali": (False, True),
               "benzersiz": (False, True)}
    hedef = yapi_gosterimi(baglar, ayrinti)
    uzaylar = []
    for b in baglar:
        alanlar = gizli_alanlar(b)
        uzaylar.append([dict(zip(alanlar, d)) for d in product(*[secenek[a] for a in alanlar])])
    sayi = 0
    for secim in product(*uzaylar):
        aday = [dict(b, **s) for b, s in zip(baglar, secim)]
        if yapi_gosterimi(aday, ayrinti) == hedef:
            sayi += 1
    return sayi


G = yapi_gosterimi(BAGLAR, 0)
gizli = sum(len(gizli_alanlar(b)) for b in BAGLAR)
print("sistem  : bag", len(BAGLAR), "| gorunur alan", simge_sayisi(G),
      "| gizli alan", gizli, "| toplam olgu", simge_sayisi(G) + gizli)
print("gosterim:", simge_sayisi(G), "simge")
print("bedel   :", ayni_gosterime_dusen(BAGLAR, 0), "sistem ayni gosterime dusuyor")
print()
print("yazilan satirlar:")
for s in G:
    print("  ", s["kaynak"], s["yon"], s["hedef"], s["cokluk"])
print()
print("b2 (IsEmri -> Kalem) icin yazilmayan alanlarin butun secenekleri:")
for yasam in ("bagimsiz", "bagimli"):
    for sirali in (False, True):
        for benzersiz in (False, True):
            aday = [dict(b) for b in BAGLAR]
            aday[1].update(yasam=yasam, sirali=sirali, benzersiz=benzersiz)
            print(f"   yasam={yasam:9s} sirali={str(sirali):5s} benzersiz={str(benzersiz):5s}"
                  f"  ayni gosterim: {yapi_gosterimi(aday, 0) == G}")
```

```
sistem  : bag 5 | gorunur alan 20 | gizli alan 11 | toplam olgu 31
gosterim: 20 simge
bedel   : 2048 sistem ayni gosterime dusuyor

yazilan satirlar:
   IsEmri tek Usta N:1
   IsEmri tek Kalem 1:N
   Kalem tek Parca N:1
   Usta cift Tezgah N:M
   IsEmri tek Belge 1:N

b2 (IsEmri -> Kalem) icin yazilmayan alanlarin butun secenekleri:
   yasam=bagimsiz  sirali=False benzersiz=False  ayni gosterim: True
   yasam=bagimsiz  sirali=False benzersiz=True   ayni gosterim: True
   yasam=bagimsiz  sirali=True  benzersiz=False  ayni gosterim: True
   yasam=bagimsiz  sirali=True  benzersiz=True   ayni gosterim: True
   yasam=bagimli   sirali=False benzersiz=False  ayni gosterim: True
   yasam=bagimli   sirali=False benzersiz=True   ayni gosterim: True
   yasam=bagimli   sirali=True  benzersiz=False  ayni gosterim: True
   yasam=bagimli   sirali=True  benzersiz=True   ayni gosterim: True
```

Üç sayı yan yana duruyor ve bundan sonraki her derste duracak. **Sistem:** beş bağ, otuz bir
olgu. **Gösterim:** yirmi simge. **Bedel:** aynı gösterime düşen 2048 sistem — yani yazılan
diyagram, birbirinden gerçekten farklı 2048 sistemin ortak resmidir.

#### Yazılmayan Alan Geri Getirilemez

Çıktının son bloğu bedeli tek bir bağ üzerinde gösteriyor. `b2` bağı, bir iş emrinin
kalemlerini taşıyor ve gösterimde tek satır olarak duruyor: iş emrinden kaleme tek yönlü,
çokluk 1:N. Bu satırın **söylemediği** üç şey var. Kalemler iş emriyle birlikte mi yaşıyor,
yoksa iş emri kapandıktan sonra da duruyor mu. Kalemlerin bir sırası var mı, yoksa küme mi.
Aynı kalem iki kez geçebilir mi.

Üç ikili soru sekiz seçenek yapıyor ve sekizinin de gösterimi **birebir aynı**. Diyagrama bakan
biri bu üç soruyu yanıtlayamaz; sorabileceği tek yer sistemin kendisidir. Beş bağın on bir
gizli alanı birlikte alındığında sayı $2^{11} = 2048$ oluyor.

Asıl nokta sayının büyüklüğü değil, yönü. İzdüşüm tek yönlüdür: sistemden gösterime giden yol
tektir, gösterimden sisteme dönen yol 2048 tanedir. Diyagramı okuyan kişi bu 2048 sistemden
birini seçmek zorundadır ve **hangisini seçtiğini fark etmez**, çünkü diyagram bir seçim
yapıldığını söylemez. Kaybın en pahalı yanı budur: kaybın kendisi gösterimde görünmez.

#### Gösterim Ailesi: Yapı, Davranış, Veri

Bu derslerde kullanılan gösterim ailesi bir belirtimde tanımlıdır ve adı **UML (Unified
Modeling Language)**'dir. Belirtim bir aracın değil bir **gösterimin** tanımıdır: hangi ögenin
hangi anlamı taşıdığını sabitler. Kursun konusu belirtimin kendisi değil, **izin verdiği
izdüşümlerin ne kadar bilgi attığıdır**.

Kurs aileyi üç öbekte topluyor; belirtimin kendi ayrımı ise ikilidir — **yapı** ve
**davranış**. Üçüncü öbek olan veri gösterimleri UML'in içinde değil, varlık–ilişki
geleneğinden gelir ve ayrı bir gösterim ailesidir. Üçü de aynı sistemin üç ayrı
izdüşümüdür. **Yapı gösterimleri**
sistemin durağan bağlarını taşır: hangi tür neyle ilişkilidir, kaç tanedir, hangi çalışma
zamanı birimindedir. **Davranış gösterimleri** sistemin zaman içindeki işleyişini taşır:
iletiler, sıralar, durumlar, geçişler. **Veri gösterimleri** saklanan olguyu taşır: varlıklar,
öznitelikler, ilişkiler, kısıtlar.

Aşağıdaki tablo üç öbeğin kaybını yan yana koyuyor. Yapı satırı bu derste ölçüldü; diğer iki
satır ortak tanımın doğrulanmış okumalarındandır ve ilgili konularda ayrıntısıyla ölçülecektir.

| Aile | Sistemdeki olgu | Gösterimin taşıdığı | Geri getirilemeyen |
|---|---|---|---|
| Yapı | 5 bağ, 31 alan | 20 simge | 11 alan; 2048 sistem tek diyagrama düşüyor |
| Davranış | 24 iz | bir sıra gösterimi 1 iz | 23 iz; kapsam 0,0417 |
| Veri | 26 olgu (5 varlık, 12 öznitelik, 4 ilişki, 5 kısıt) | ilişkisel yapıya taşınan 3 kısıt | 2 kısıt düşüyor, 114 karar modelde yazmıyor |

Üç satırın hiçbiri diğerini kapsamıyor ve üçü birleştirildiğinde de sistem geri gelmiyor.
Aile bir bütünün parçaları değil, **aynı bütünün üç ayrı kaybıdır**.

Yazılım Mimarlığı müfredatındaki Mimari Dokümantasyon kursu bu türleri başka bir eksende ölçtü:
on sekiz soruyu dört türe eşledi, yanlış türün bıraktığı eksik bilgi ögesini ve her türün
bakım maliyetini saydı. O kursun sorusu **hangi türün seçileceğiydi**. Bu kursun sorusu
başkadır ve tür seçildikten sonra başlar: seçilen tür, kaç sistemi birbirinden ayırt edemiyor.
Soru–tür eşlemesi burada yeniden kurulmaz.

#### Gösterim Doğrusal, Belirsizlik Üstel Büyür

Ortak tanımın çözünürlük kuralı gereği her ders sayısını **ikinci bir yapılandırmayla** sınar.
Buradaki sınama şudur: sisteme altıncı bir bağ eklendiğinde gösterim ile belirsizlik aynı
hızda mı büyüyor.

- **YD5** — Eklenen bağ gösterime dört simge ekler; bu, çokluğundan bağımsızdır.
- **YD6** — Eklenen bağın gizli alan sayısı çokluğuna bağlıdır: N:1 ise bir, 1:N ya da N:M ise
  üç.

```python
"""Ikinci yapilandirma: bir bag eklenince gosterim ile belirsizlik ayni hizda buyumuyor.
Gizli alan kurali ortak tanimdandir: cokluk 1:N ya da N:M ise yasam , sirali ve benzersiz ,
degilse yalniz yasam. Gorunur alanlar sabit oldugu icin ayni gosterime dusen sistem sayisi ,
gizli alan seceneklerinin tam sayimidir."""
from itertools import product


def gizli_alanlar(cokluk):
    return ["yasam", "sirali", "benzersiz"] if cokluk in ("1:N", "N:M") else ["yasam"]


def tam_sayim(cokluklar):
    uzaylar = [list(product(*[(False, True)] * len(gizli_alanlar(c)))) for c in cokluklar]
    return sum(1 for _ in product(*uzaylar))


TEMEL = ["N:1", "1:N", "N:1", "N:M", "1:N"]
DURUM = [("bes bag  (ortak tanim)", TEMEL),
         ("+ Usta-Belge     N:1", TEMEL + ["N:1"]),
         ("+ Tezgah-Parca   1:N", TEMEL + ["1:N"]),
         ("+ Kalem-Tezgah   N:M", TEMEL + ["N:M"])]

print("yapilandirma            bag  simge  gizli alan  ayni gosterime dusen")
for ad, c in DURUM:
    print(f"{ad:24s}{len(c):4d}{4 * len(c):7d}"
          f"{sum(len(gizli_alanlar(x)) for x in c):12d}{tam_sayim(c):22d}")
print()
temel = tam_sayim(TEMEL)
for ad, c in DURUM[1:]:
    print(f"{ad:24s} simge x{4 * len(c) / 20:.2f}   belirsizlik x{tam_sayim(c) // temel}")
```

```
yapilandirma            bag  simge  gizli alan  ayni gosterime dusen
bes bag  (ortak tanim)     5     20          11                  2048
+ Usta-Belge     N:1       6     24          12                  4096
+ Tezgah-Parca   1:N       6     24          14                 16384
+ Kalem-Tezgah   N:M       6     24          14                 16384

+ Usta-Belge     N:1     simge x1.20   belirsizlik x2
+ Tezgah-Parca   1:N     simge x1.20   belirsizlik x8
+ Kalem-Tezgah   N:M     simge x1.20   belirsizlik x8
```

Üç eklemenin üçü de gösterime **aynı sayıda** simge koyuyor: dört. Diyagram her durumda yüzde
yirmi büyüyor. Belirsizlik ise ikiye, sekize ve sekize katlanıyor. Aynı çizim emeği, hangi
bağın eklendiğine göre 2048'i 4096 ya da 16384 yapıyor.

Farkın kaynağı çokluk. Bir N:1 bağın karşı tarafında tek nesne durur; orada sıralılık ve
benzersizlik sorulamaz, dolayısıyla saklanan tek şey yaşam alanıdır. Bir 1:N ya da N:M bağın
karşı tarafında bir topluluk durur ve topluluğun sırası ile tekrar kabul edip etmediği ayrı
iki olgudur. Çokluk simgesi bu yüzden diyagramın en yüklü simgesidir: kendisi bir olgu
söylerken **iki olgunun daha var olduğunu** da haber verir ve o iki olguyu yazmaz.

Gösterim bağ başına sabit sayıda simgeyle, yani **doğrusal** büyür; belirsizlik gizli alan
sayısının **üssü** kadar. Sistem büyüdükçe diyagramın anlattığı payın küçülmesi bir
dikkatsizlik değil, iki büyüme hızı arasındaki farkın sonucudur.

#### Simge Çıkarmanın Bedeli

Aynı ölçü ters yönde de işler. Yirmi simgelik gösterim, çokluk yazmayan on beş simgelik bir
gösterime indirilebilir; bağların kim kime bağlı olduğu durur, kaç tane olduğu düşer.

- **YD7** — Çokluk yazılmadığında bir bağın çokluğu dört seçenekten biri olabilir: 1:1, N:1,
  1:N ya da N:M. Çokluk bilinmediği için ona bağlı gizli alanların **kaç tane olduğu** da
  bilinmez.

```python
"""Daha dar bir gosterim: cokluk simgesi hic yazilmazsa ne oluyor. Cokluk yazilmayinca
hem coklugun kendisi hem de ona bagli gizli alanlar bilinmez olur ; bir bag icin gecerli
sistem sayisi , dort coklugun her birinin gizli alan seceneklerinin toplamidir."""
from itertools import product

COKLUKLAR = ("1:1", "N:1", "1:N", "N:M")


def gizli_alanlar(cokluk):
    return ["yasam", "sirali", "benzersiz"] if cokluk in ("1:N", "N:M") else ["yasam"]


def bag_secenegi(cokluk_yazili, cokluk):
    """Bir bag icin gosterimi degistirmeyen sistem sayisi , tam sayim."""
    sayi = 0
    for c in ([cokluk] if cokluk_yazili else list(COKLUKLAR)):
        for _ in product(*[(False, True)] * len(gizli_alanlar(c))):
            sayi += 1
    return sayi


TEMEL = ["N:1", "1:N", "N:1", "N:M", "1:N"]
sonuc = {}
for yazili, bag_simge in ((True, 4), (False, 3)):
    toplam = 1
    for c in TEMEL:
        toplam *= bag_secenegi(yazili, c)
    sonuc[yazili] = toplam
    print(f"cokluk yazili {str(yazili):5s} | simge {bag_simge * len(TEMEL):3d}"
          f" | ayni gosterime dusen {toplam:9d}")
print("5 simge cikarmanin bedeli: x", sonuc[False] / sonuc[True], sep="")
```

```
cokluk yazili True  | simge  20 | ayni gosterime dusen      2048
cokluk yazili False | simge  15 | ayni gosterime dusen   3200000
5 simge cikarmanin bedeli: x1562.5
```

Beş simge eksiliyor, belirsizlik 1562,5 katına çıkıyor. Oran, çıkarılan simge başına ikiden
fazla bit demektir; oysa gizli alanların her biri ikili olduğu için simge başına en çok bir bit
beklenirdi. Fark çokluğun **ikili olmamasından** geliyor: dört değer alabilen bir alanın
yazılmaması iki bit götürür, üstüne o alan başka alanların var olup olmadığını belirlediği için
bir de yapıyı belirsizleştirir.

Bir gösterimden simge çıkarmak onu okunaklı yapabilir, ama okunaklılık ölçülmüş bir kazanç
değildir; **1562,5 ise ölçülmüş bir bedeldir**. İkisi aynı tabloya yazılmadıkça sadeleştirme
bir iyileştirme sayılamaz.

#### Kursun Kuralı

Bu ders kursun ölçüsünü kuruyor: **bir gösterimin sayısı taşıdığı simge değil, aynı gösterime
düşen sistem sayısıdır.** Kaç sistemi birbirinden ayıramadığı yazılmayan bir gösterim
ölçülmemiş sayılır. Yirmi simge bir diyagramın büyüklüğüdür; 2048 onun bedelidir ve ikisi
birlikte yazılmadıkça diyagram hakkında hiçbir şey söylenmiş olmaz.

Ölçünün çözünürlüğü de burada belirlenir. Sayım tamdır, örneklem değildir: 2048'in etrafında
bir ölçüm bandı yoktur ve iki gösterim karşılaştırılırken **bir sistemlik fark bile
anlamlıdır**.

#### Özet

- Gösterim, sistemin bilgi atan bir izdüşümüdür; sistemden gösterime giden yol tek, gösterimden
  sisteme dönen yol çoktur ve kaybın kendisi gösterim üzerinde görünmez.
- Bakım atölyesinin beş bağı 31 olgu taşıyor. Yirmi simgelik ayrıntısız yapı gösterimi bunun
  20'sini yazıyor, 11'ini atıyor ve $2^{11} = 2048$ ayrı sistemi tek diyagrama düşürüyor.
- Tek bir bağın yazılmayan üç alanı sekiz seçenek üretiyor ve sekizinin gösterimi birebir aynı;
  diyagramı okuyan kişi seçim yapmak zorundadır ve seçim yaptığını fark etmez.
- Gösterim ailesinin üç öbeği aynı sistemin üç ayrı kaybıdır: yapı 11 alanı, davranış 24 izin
  23'ünü, veri düzeyi 5 kısıttan 2'sini atıyor ve üçü birleştirildiğinde de sistem geri gelmiyor.
- Altıncı bir bağ eklemek gösterimi her durumda 4 simge büyütüyor, belirsizliği ise çokluğa
  göre 2 ya da 8 katına çıkarıyor: gösterim doğrusal, belirsizlik üstel büyür.
- Çokluk hiç yazılmazsa gösterim 20 simgeden 15'e iner ve aynı gösterime düşen sistem 2048'den
  3.200.000'e çıkar: 1562,5 kat. Sadeleştirmenin kazancı ölçülmemiş, bedeli ölçülmüştür.

#### Sonraki Adım

Bu derste yalnız en dar izdüşüm ölçüldü ve 2048 sayısı tek başına duruyor. Diyagrama simge
eklemek bu sayıyı düşürür — ama ne kadar düşürdüğü ölçülmedi. Bir simge belirsizliği yarıya mı
indiriyor, daha fazlasını mı alıyor, yoksa hiç almayan simgeler de var mı.

Sonraki ders sınıf gösterimini alıp bunu simge simge sayar: yaşam döngüsü simgesi eklendiğinde
20 simge 25'e çıkarken 2048 kaça iner, sıralılık ve benzersizlik notları da yazıldığında geriye
kaç sistem kalır. Aynı derste sıkı ve gevşek bileşim ayrımının hangi olguyu taşıdığı
ölçülecek: bir iş emri silindiğinde kaç nesnenin gittiğini belirleyen şey, diyagramda tek bir
simgedir.

### Sınıf Diyagramları

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/sinif-diyagramlari

İlişki türü ve çokluk simgelerinin belirsizlikten aldığı pay: 20 simge 2048, 25 simge 64, 31 simge 1 sistem bırakıyor; ikili bir alanın simgesi tam bir bit alırken üç değerli bir alanınki 1,58 bit alıyor.

Önceki ders tek bir sayı bıraktı: yirmi simgelik yapı gösterimi 2048 sistemi tek diyagrama
düşürüyor. Sayı tek başına az şey söylüyor. Diyagrama simge eklemek onu düşürür, ama ne kadar
düşürdüğü ölçülmedi — bir simge belirsizliği yarıya mı indiriyor, daha çoğunu mu alıyor, hiç
almayanı var mı.

Sınıf gösterimi bu soruyu yanıtlamak için elverişli, çünkü ilişki simgelerinin her biri belirli
bir olguyu yazıyor ve yazılmadığında o olgu düşüyor. Sınıfın, kalıtımın ve arayüzün ne olduğu
Programlama Temelleri kursunda kuruldu; bu ders onları tanımlamıyor. Ölçtüğü tek şey şu:
**ilişki türü** ve **çokluk** simgeleri, aynı gösterime düşen sistem sayısını kaç kat
düşürüyor.

#### Simge Başına Bir Bit

Ortak tanım üç ayrıntı düzeyi tanımlıyor. Sıfırıncı düzeyde her bağın yalnız kaynağı, hedefi,
yönü ve çokluğu yazılıyor. Birinci düzeyde **yaşam** alanı da yazılıyor: bağın bir yaşam
döngüsü sahipliği taşıyıp taşımadığı. İkinci düzeyde topluluk taşıyan bağların **sıralı** ve
**benzersiz** alanları da köşeli notlar olarak ekleniyor.

- **YD8** — Üç düzey aynı sistem üzerinde ölçülür; değişen tek şey yazılan alan kümesidir.
- **YD9** — Belirsizliğin bit karşılığı, aynı gösterime düşen sistem sayısının ikili
  logaritmasıdır. Tek sistem kalırsa bit sıfırdır ve gösterim geri çevrilebilir olmuştur.

```python
"""M01/K06 ortak tanim (kesit): yapi gosterimi uc ayrinti duzeyinde ve her duzeyin
ayni gosterime dusurdugu sistem sayisi. Sayim tam sayimdir."""
from itertools import product
from math import log2

BAGLAR = [
    {"ad": "b1", "kaynak": "IsEmri", "hedef": "Usta",  "yon": "tek", "cokluk": "N:1",
     "yasam": "bagimsiz", "sirali": False, "benzersiz": True},
    {"ad": "b2", "kaynak": "IsEmri", "hedef": "Kalem", "yon": "tek", "cokluk": "1:N",
     "yasam": "bagimli",  "sirali": True,  "benzersiz": False},
    {"ad": "b3", "kaynak": "Kalem",  "hedef": "Parca", "yon": "tek", "cokluk": "N:1",
     "yasam": "bagimsiz", "sirali": False, "benzersiz": True},
    {"ad": "b4", "kaynak": "Usta",   "hedef": "Tezgah", "yon": "cift", "cokluk": "N:M",
     "yasam": "bagimsiz", "sirali": False, "benzersiz": True},
    {"ad": "b5", "kaynak": "IsEmri", "hedef": "Belge", "yon": "tek", "cokluk": "1:N",
     "yasam": "bagimli",  "sirali": True,  "benzersiz": True},
]


def gizli_alanlar(bag):
    alanlar = ["yasam"]
    if bag["cokluk"] in ("1:N", "N:M"):
        alanlar += ["sirali", "benzersiz"]
    return alanlar


def yapi_gosterimi(baglar, ayrinti=0):
    simge = []
    for b in baglar:
        s = {"kaynak": b["kaynak"], "hedef": b["hedef"], "yon": b["yon"], "cokluk": b["cokluk"]}
        if ayrinti >= 1:
            s["yasam"] = b["yasam"]
        if ayrinti >= 2:
            for a in gizli_alanlar(b):
                s[a] = b[a]
        simge.append(s)
    return simge


def simge_sayisi(gosterim):
    return sum(len(s) for s in gosterim)


def ayni_gosterime_dusen(baglar, ayrinti=0):
    secenek = {"yasam": ("bagimsiz", "bagimli"), "sirali": (False, True),
               "benzersiz": (False, True)}
    hedef = yapi_gosterimi(baglar, ayrinti)
    uzaylar = []
    for b in baglar:
        alanlar = gizli_alanlar(b)
        uzaylar.append([dict(zip(alanlar, d)) for d in product(*[secenek[a] for a in alanlar])])
    sayi = 0
    for secim in product(*uzaylar):
        aday = [dict(b, **s) for b, s in zip(baglar, secim)]
        if yapi_gosterimi(aday, ayrinti) == hedef:
            sayi += 1
    return sayi


YAZILAN = {0: "kaynak/hedef/yon/cokluk", 1: "+ yasam", 2: "+ sirali , benzersiz"}
olcum = []
print("ayrinti  yazilan alan             simge  dusen sistem   bit")
for a in (0, 1, 2):
    g = yapi_gosterimi(BAGLAR, a)
    s, d = simge_sayisi(g), ayni_gosterime_dusen(BAGLAR, a)
    olcum.append((s, d))
    print(f"  {a:5d}  {YAZILAN[a]:23s}{s:6d}{d:14d}{log2(d):7.2f}")
print()
print("gecis            eklenen simge  alinan bit  simge basina bit")
for (s0, d0), (s1, d1) in zip(olcum, olcum[1:]):
    print(f"  {s0:2d} -> {s1:2d} simge{s1 - s0:12d}{log2(d0) - log2(d1):12.2f}"
          f"{(log2(d0) - log2(d1)) / (s1 - s0):18.2f}")
```

```
ayrinti  yazilan alan             simge  dusen sistem   bit
      0  kaynak/hedef/yon/cokluk    20          2048  11.00
      1  + yasam                    25            64   6.00
      2  + sirali , benzersiz       31             1   0.00

gecis            eklenen simge  alinan bit  simge basina bit
  20 -> 25 simge           5        5.00              1.00
  25 -> 31 simge           6        6.00              1.00
```

Üç sayı yan yana. **Sistem:** beş bağ, 31 olgu. **Gösterim:** 20, 25 ya da 31 simge.
**Bedel:** sırasıyla 2048, 64 ve 1 sistem.

Alt tablo dersin ana sonucunu veriyor: **eklenen her simge tam olarak bir bit alıyor.** Beş
yaşam simgesi beş bit, altı sıralılık ve benzersizlik notu altı bit götürüyor; ne daha az ne
daha çok. Son satırda belirsizlik sıfır bite iniyor, yani 31 simgelik gösterim geri
çevrilebilir hâle geliyor — o gösterimi üreten tek bir sistem var ve okuyucu seçim yapmak
zorunda kalmıyor.

Bu tam örtüşme bir rastlantı değil. Gizli alanların hepsi ikili: yaşam iki değer, sıralı iki
değer, benzersiz iki değer. Bir ikili alanı yazmak seçenek uzayını tam yarıya indirir ve yarıya
inen bir uzay tam bir bit kaybeder. Bir sonraki bölüm bu koşulun kalktığı durumu ölçecek.

Ölçünün kapsamı da burada sınırlanıyor. Model yalnız bağ satırlarını sayıyor; sınıf adları,
öznitelikler ve işlemler modelin dışında ve dolayısıyla 2048 sayısı **yalnız ilişki
belirsizliğidir**. Gerçek bir sınıf gösterimi bunlardan fazlasını taşır ve taşıdığı her yeni
alan kendi gizli alanlarını da getirir; buradaki sayı bir alt sınırdır, bir toplam değildir.

#### Yaşam Döngüsü Sahipliği

Yaşam simgesinin aldığı bit, gösterimde iki ilişki türünü ayırıyor. **Sıkı bileşim
(composition)** bir yaşam döngüsü sahipliği bildirir: sahip nesne silindiğinde parça nesne de
silinir, çünkü parçanın sahibinden bağımsız bir varlığı yoktur. **Gevşek bileşim
(aggregation)** sahiplik iddia etmez; parça, bütün silindikten sonra da durur. Bileşim
kavramının kendisi Programlama Temelleri kursunda kuruldu; buradaki ek, iki türün ayrımının
**hangi olguyu** taşıdığıdır.

Ayrım, gösterimde tek simge; örnek düzeyinde ise silinen nesne sayısı.

- **YD10** — Örnek durum: bir iş emri, üç kalem, iki belge, bir usta, iki tezgâh, üç parça —
  toplam on iki nesne.
- **YD11** — Silme kökten başlar ve yalnız bağımlı bağlar üzerinden **geçişli** yayılır. Bir
  bağın hedefi silinmediyse ve kaynağı silindiyse, hedef **bağsız** kalır.
- **YD12** — Bir topluluğun geçerli içerik sayısı için dört parçalık bir katalog ve üç
  kalemlik bir iş emri alınır.

```python
"""Yazilmayan alanlarin ornek duzeyindeki karsiligi. Yasam alani silme yayilimini ,
sirali ve benzersiz alanlari bir toplulugun gecerli icerik sayisini belirler.
Ornek durum: 1 is emri , 3 kalem , 2 belge , 1 usta , 2 tezgah , 3 parca."""
from itertools import product

NESNE = {"IsEmri": 1, "Kalem": 3, "Parca": 3, "Usta": 1, "Tezgah": 2, "Belge": 2}
BAG = [("IsEmri", "Usta"), ("IsEmri", "Kalem"), ("Kalem", "Parca"),
       ("Usta", "Tezgah"), ("IsEmri", "Belge")]          # ortak tanimin b1..b5 sirasi
GERCEK = ("bagimsiz", "bagimli", "bagimsiz", "bagimsiz", "bagimli")


def silme(yasamlar, kok="IsEmri"):
    """Siki bilesim yasam dongusu sahipligidir: sahip silinince parca da silinir."""
    silinen, degisti = {kok}, True
    while degisti:
        degisti = False
        for (k, h), y in zip(BAG, yasamlar):
            if y == "bagimli" and k in silinen and h not in silinen:
                silinen.add(h)
                degisti = True
    bagsiz = {h for (k, h), y in zip(BAG, yasamlar)
              if y == "bagimsiz" and k in silinen and h not in silinen}
    return sum(NESNE[t] for t in silinen), sum(NESNE[t] for t in bagsiz), sorted(silinen)


dagilim = {}
for y in product(("bagimsiz", "bagimli"), repeat=5):
    n = silme(y)[0]
    dagilim[n] = dagilim.get(n, 0) + 1
print("toplam nesne:", sum(NESNE.values()), "| yasam secimi:", 2 ** 5,
      "| ayri silinen-nesne degeri:", len(dagilim))
print("  silinen nesne:", sorted(dagilim), "-> en az", min(dagilim), ", en cok", max(dagilim))
n, b, kume = silme(GERCEK)
print("yasam yazildiginda tek deger:", n, "nesne siliniyor", kume,
      "|", b, "nesne bagsiz kaliyor")
print()
print("b2 (IsEmri -> Kalem , 1:N): 4 parcali katalog , 3 kalemlik is emri")
print("  sirali  benzersiz  gecerli icerik sayisi")
for sirali in (False, True):
    for benzersiz in (False, True):
        icerik = set()
        for d in product(range(4), repeat=3):
            if benzersiz and len(set(d)) != len(d):
                continue
            icerik.add(d if sirali else tuple(sorted(d)))
        print(f"  {str(sirali):8s}{str(benzersiz):11s}{len(icerik):10d}")
```

```
toplam nesne: 12 | yasam secimi: 32 | ayri silinen-nesne degeri: 11
  silinen nesne: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12] -> en az 1 , en cok 12
yasam yazildiginda tek deger: 6 nesne siliniyor ['Belge', 'IsEmri', 'Kalem'] | 4 nesne bagsiz kaliyor

b2 (IsEmri -> Kalem , 1:N): 4 parcali katalog , 3 kalemlik is emri
  sirali  benzersiz  gecerli icerik sayisi
  False   False              20
  False   True                4
  True    False              64
  True    True               24
```

Yirmi simgelik gösterime bakan biri, bir iş emri silindiğinde kaç nesnenin gideceğini
bilemiyor. Otuz iki yaşam seçimi **on bir ayrı** silinen-nesne değeri üretiyor ve aralık
1 ile 12 arasında: bütün bağlar bağımsızsa yalnız iş emri siliniyor, hepsi bağımlıysa
sistemdeki her nesne gidiyor. Diyagram bu on bir sonucun hepsiyle uyumlu.

Aralıkta bir boşluk var ve nedeni öğreticidir: on iki değerden yalnız **11 çıkmıyor**. Nesneler
tek tek değil kümeler hâlinde gidiyor — üç kalem birlikte, üç parça birlikte, iki belge
birlikte — ve bu kümelerin hiçbir birleşimi tam on bir nesne etmiyor. Silme davranışı sürekli
bir aralık değil, bağ yapısının izin verdiği ayrık bir değer kümesidir.

Yaşam simgeleri yazıldığında sonuç tek bir değere iniyor: **6 nesne** siliniyor — iş emri, üç
kalem, iki belge — ve **4 nesne bağsız kalıyor**: kalemlerin işaret ettiği üç parça ile atanmış
usta. Beş simgenin aldığı beş bit, örnek düzeyinde bir aralığı tek bir sayıya indiriyor. Bunun
karşılığı somuttur: silme yordamını yazan kişi, gösterimde o simge yoksa kararı kendisi verir
ve verdiği karar diyagramda yazmaz.

Bağsız kalan dört nesne ayrı bir kalemdir ve gevşek bileşimin bedelini gösterir. Parçalar
silinmiyor, ama artık onlara işaret eden bir kalem yok; sistemde ulaşılamaz durur. Sıkı bileşim
bu durumu ortadan kaldırır ve yerine başka bir şey koyar: sahibi silinen her nesne, başka bir
yerden kullanılıyor olsa bile gider.

Çokluk simgesi de aynı biçimde eksik. Gösterim `IsEmri` ile `Kalem` arasında 1:N yazıyor ve
bunun anlamı "bir iş emrinin birden çok kalemi var" cümlesiyle sınırlı. Dört parçalık bir
katalogda üç kalemlik bir iş emrinin kaç ayrı geçerli içeriği olduğu ise yazılmayan iki alana
bağlı: sıralı ve tekrar kabul eden bir listede **64**, sırasız ve benzersiz bir kümede **4**.
Aradaki on altı katlık aralık gösterimde tek bir `1:N` olarak duruyor.

#### Simge Her Zaman Bir Bit Almaz

Simge başına tam bir bit sonucu, gizli alanların ikili olmasından geliyordu. Ortak tanımın
çözünürlük kuralı gereği bu koşul ikinci bir yapılandırmayla sınanır: yaşam alanı **üç** değer
alsaydı ne olurdu.

- **YD13** — Üç değerli yaşam alanı şunları ayırır: sahiplik iddia etmeyen düz **bağ
  (association)**, parçayı paylaşan **gevşek bileşim**, parçayı yaşam döngüsüyle birlikte
  taşıyan **sıkı bileşim**. Yazılan simge sayısı değişmez; yalnız simgenin ayırabildiği değer
  sayısı artar.

```python
"""Ikinci yapilandirma: yasam alani ikili degil uc degerli olsaydi. Uc deger: duz bag ,
gevsek bilesim , siki bilesim. Yazilan simge sayisi degismez ; degisen , bir simgenin
aldigi bit sayisidir. Sayim yine tam sayimdir."""
from itertools import product
from math import log2

COKLUKLAR = ["N:1", "1:N", "N:1", "N:M", "1:N"]          # ortak tanimin bes bagi


def gizli_alanlar(cokluk):
    return ["yasam", "sirali", "benzersiz"] if cokluk in ("1:N", "N:M") else ["yasam"]


def tam_sayim(yasam_degeri, yasam_yazili):
    uzaylar = []
    for c in COKLUKLAR:
        secenek = [range(1 if yasam_yazili else yasam_degeri) if a == "yasam" else range(2)
                   for a in gizli_alanlar(c)]
        uzaylar.append(list(product(*secenek)))
    return sum(1 for _ in product(*uzaylar))


print("yasam degeri  yasam yazili  simge  dusen sistem     bit")
for d in (2, 3):
    for yazili, simge in ((False, 20), (True, 25)):
        s = tam_sayim(d, yazili)
        print(f"{d:12d}  {str(yazili):12s}{simge:7d}{s:14d}{log2(s):8.2f}")
print()
for d in (2, 3):
    alinan = log2(tam_sayim(d, False)) - log2(tam_sayim(d, True))
    print(f"{d} degerli yasam alani: 5 simge {alinan:.2f} bit aliyor"
          f" , simge basina {alinan / 5:.2f}")
```

```
yasam degeri  yasam yazili  simge  dusen sistem     bit
           2  False            20          2048   11.00
           2  True             25            64    6.00
           3  False            20         15552   13.92
           3  True             25            64    6.00

2 degerli yasam alani: 5 simge 5.00 bit aliyor , simge basina 1.00
3 degerli yasam alani: 5 simge 7.92 bit aliyor , simge basina 1.58
```

Gösterim iki durumda da aynı: 20 simgeden 25 simgeye. Alınan bit ise 5,00'ten 7,92'ye çıkıyor,
simge başına 1,58. Kural şu biçimde düzeltiliyor: **bir simge, ayırdığı değer sayısının ikili
logaritması kadar bit alır.** İkili bir alanda bu tam bir bittir; üç değerli bir alanda 1,58,
dört değerli bir alanda iki bit olur.

Sonucun ters okuması daha kullanışlı. Yaşam simgesi yazılmadığında kaybedilen bilgi, o
simgenin **kaç şeyi ayırabildiğine** bağlıdır. Bağ ile gevşek bileşimi ayırmayan bir gösterimde
yazılmayan simge 1,00 bit götürür; ikisini ayıran bir gösterimde aynı yazılmayan simge 1,58
bit götürür. Gösterimi zenginleştirmek, o gösterimin **eksik bırakılmasını da pahalılaştırır**
— ve bu iki etki aynı tabloda görünmedikçe zenginleştirme bir kazanç sayılamaz.

#### Özet

- Ayrıntısız yapı gösterimi 20 simge ve 2048 sistem; yaşam simgeleri eklenince 25 simge ve 64
  sistem; sıralılık ile benzersizlik notları da eklenince 31 simge ve tek sistem kalıyor.
- Bit cinsinden ölçüldüğünde eklenen her simge **tam olarak bir bit** alıyor: 5 simge 5,00 bit,
  6 simge 6,00 bit. Otuz bir simgelik gösterimde belirsizlik sıfır bittir, yani gösterim geri
  çevrilebilir olmuştur.
- Sıkı bileşim yaşam döngüsü sahipliği bildirir, gevşek bileşim bildirmez. Yaşam simgeleri
  yazılmadığında bir iş emrinin silinmesi 12 nesnelik sistemde 11 ayrı sonuçla uyumludur
  (1 ile 12 arası); yazıldığında sonuç tek değere iner: 6 silinen, 4 bağsız kalan nesne.
- Çokluk simgesi topluluğun varlığını söyler, içeriğini söylemez: dört parçalık katalogda üç
  kalemlik bir iş emrinin geçerli içerik sayısı sıralı ve tekrarlıysa 64, sırasız ve
  benzersizse 4 — on altı katlık aralık gösterimde tek bir `1:N` olarak durur.
- Simge başına bir bit yalnız ikili alanlar için geçerlidir. Yaşam alanı üç değerli olsaydı 20
  simgelik gösterime düşen sistem 15552 olurdu ve aynı beş simge 7,92 bit, yani simge başına
  1,58 bit alırdı.

#### Sonraki Adım

Bu derste sayılan her şey durağandı: hangi tür neye bağlı, kaç tane, kim kimin yaşam döngüsünü
taşıyor. Sistemin çalışırken kaç ayrı parçaya bölündüğü hiç sorulmadı — beş bağın altı sınıfı
tek bir birimde de koşabilir, altı ayrı birimde de ve otuz bir simgelik gösterim bunların
hiçbirini ayırt etmiyor.

Sonraki ders aynı sınıf kümesini çalışma zamanı birimlerine bölüyor ve bölüntüyü sayıyor: altı
sınıf kaç ayrı bileşen bölüntüsüne düşüyor, bir bileşen gösterimi bunların kaçını aynı çizime
indiriyor ve bileşenler düğümlere yerleştirildiğinde hangi bağlar uzak bağ hâline geliyor.

### Bileşen ve Yerleşim Diyagramları

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/bilesen-ve-yerlesim-diyagramlari

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.

Ö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.

```python
"""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.

```python
"""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.

```python
"""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.

## Davranışsal Diyagramlar

Kullanım senaryosunun bilerek attığı olgular, sıra gösteriminin kapsadığı iz oranı, kısmi sıranın kabul ettiği tam sıra sayısı ve durum makinesinin fazla ile eksik kabulü.

### Kullanım Senaryosu Diyagramları

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/kullanim-senaryosu-diyagramlari

Aktör, senaryo ve sistem sınırı gösteriminin taşıdığı olgu ile attığı olgunun ayrı ayrı sayılması: bilerek atılan yedi iç adım, farkında olmadan düşen iki bağ ve aynı diyagrama düşen 512 sistem.

Önceki konu bir sistemin durağan yanını ölçtü: hangi sınıf hangisine bağlı, bağ hangi yöne
gidiyor, aynı sınıf kümesi kaç ayrı bileşen bölüntüsüne düşüyor. Sorulan her soru sistemin
çalışmadığı andaki hâline bakıyordu.

Bu konu sistemin çalıştığı ana bakıyor: kim neyi başlatıyor, iletiler hangi sırayla gidiyor, işler
hangi sırayla yapılabiliyor, bir nesne hangi durumlardan geçiyor. Dört davranış gösteriminin
ilki, dördünün içinde **en az bilgi taşıyanıdır** — ve bu bir kusur değildir. Kullanım senaryosu
gösterimi sistemin içini bilerek boşaltır. Bu dersin işi o boşluğu saymaktır, çünkü sayılmadıkça
bir boşluğun **bilerek mi bırakıldığı** yoksa **gözden mi kaçtığı** bilinemez.

Dersin sorusu, diyagram türünün hangi soruya uyduğu değildir; o ölçüm Yazılım Mimarlığı
müfredatının Mimari Dokümantasyon kursunda on sekiz soruluk bir küme üzerinde yapıldı ve burada
tekrarlanmıyor. Buradaki soru tür **seçildikten sonra** başlar: seçilen tür kaç ayrı sistemi
birbirinden ayırt edemiyor.

#### Gösterimin Taşıdığı Dört Alan

Kullanım senaryosu gösterimi dört tür bilgi taşır: **aktör**, **senaryo**, aktörü senaryoya
bağlayan **bağ** ve neyin sistemin işi neyin komşusunun işi olduğunu söyleyen **sistem sınırı**.
Bu ölçümün saydığı alanlar bunlardır. Gösterim ayrıca senaryolar arasında içerme,
genişletme ve genelleme ilişkileri tanımlar — ileride bunlardan içerme kullanılacak — ama
hiçbiri sıra, koşul, iç adım ya da veri taşımaz.

Bakım atölyesinde bu dört alanın karşılığı şudur. İki aktör var: müşteri ve kabul görevlisi. Üç
dış olgu var: iş emri açma, durum sorma, teslim alma. Üçü de sistemin dışından başlatılır ve üçü
de atölyenin kendi işidir — sınırın söylediği şey budur ve bu üç sahiplik kararı üç ayrı olgudur.
Buna karşılık sistemin içinde yedi iç adım dönüyor — stok ayırma, usta atama, tezgâh ayırma, kalem
işleme, belge üretme, maliyet hesabı, kayıt tutma — ve bunların hiçbirini bir aktör başlatmaz.

Toplam **20 olgu**: 2 aktör, 3 senaryo, 5 aktör–senaryo bağı, 3 sahiplik, 7 iç adım.

#### Diyagramın Kurulması ve Sayılması

Aşağıdaki model diyagramı çizmez; diyagramın **taşıdığı alanların listesini** kurar ve o listeyi
üreten kaç ayrı sistem olduğunu tam sayımla bulur. Gerçek bağ kümesi beş bağdır (**DD1**);
çizilmiş diyagram bunların üçünü yazıyor (**DD2**).

```python
"""Kullanim senaryosu gosterimi: bilerek atilan olgu ile farkinda olmadan
dusen olgu ayri ayri sayilir. Sayim tam sayimdir , tahmin degildir."""
from itertools import product

IC_OLGULAR = ["stok ayirma", "usta atama", "tezgah ayirma", "kalem isleme",
              "belge uretme", "maliyet hesabi", "kayit tutma"]
DIS_OLGULAR = ["is emri acma", "durum sorma", "teslim alma"]

# DD1: atolyenin gercek aktor-senaryo baglari ve her senaryonun sahibi
AKTORLER = ["Musteri", "KabulGorevlisi"]
GERCEK_BAGLAR = [("Musteri", "is emri acma"), ("Musteri", "durum sorma"),
                 ("Musteri", "teslim alma"), ("KabulGorevlisi", "is emri acma"),
                 ("KabulGorevlisi", "teslim alma")]
GERCEK_SAHIP = {s: "sistem" for s in DIS_OLGULAR}   # ucu de atolyenin isi
# DD2: cizilmis diyagram bes bagin ucunu yaziyor
CIZILEN = [("Musteri", "is emri acma"), ("Musteri", "durum sorma"),
           ("Musteri", "teslim alma")]


def gosterim(baglar, ic, sahip, cizilen_bag, cizilen_ic=(), sinir=True):
    """Gosterim yalnizca sunu tasir: aktor , senaryo , aktor-senaryo bagi ,
    sistem siniri. Cizilmemis bag ve ic adim gosterime hic cikmaz; sinir
    cizilmezse senaryonun sistemin isi mi komsunun isi mi oldugu yazilmaz."""
    return (tuple(AKTORLER),
            tuple(DIS_OLGULAR) + tuple(sorted(i for i in ic if i in cizilen_ic)),
            tuple(sorted(b for b in baglar if b in cizilen_bag)),
            tuple(sahip[s] for s in DIS_OLGULAR) if sinir else None)


def simge(cizilen_bag, cizilen_ic=(), sinir=True):
    return (len(AKTORLER) + len(DIS_OLGULAR) + len(cizilen_bag) + (1 if sinir else 0)
            + 2 * len(cizilen_ic))


def ayni_gosterime_dusen(cizilen_bag, cizilen_ic=(), sinir=True):
    """Ayni diyagrami ureten kac ayri sistem var: tam sayim."""
    hedef = gosterim(GERCEK_BAGLAR, IC_OLGULAR, GERCEK_SAHIP, cizilen_bag,
                     cizilen_ic, sinir)
    sayi = 0
    for bm in product((0, 1), repeat=len(GERCEK_BAGLAR)):
        baglar = [b for b, m in zip(GERCEK_BAGLAR, bm) if m]
        for im in product((0, 1), repeat=len(IC_OLGULAR)):
            ic = [i for i, m in zip(IC_OLGULAR, im) if m]
            for sm in product(("sistem", "komsu"), repeat=len(DIS_OLGULAR)):
                sahip = dict(zip(DIS_OLGULAR, sm))
                if gosterim(baglar, ic, sahip, cizilen_bag, cizilen_ic, sinir) == hedef:
                    sayi += 1
    return sayi


olgu = (len(AKTORLER) + len(DIS_OLGULAR) + len(GERCEK_BAGLAR) + len(DIS_OLGULAR)
        + len(IC_OLGULAR))
print("SISTEM  :", olgu, "olgu =", len(AKTORLER), "aktor +", len(DIS_OLGULAR),
      "senaryo +", len(GERCEK_BAGLAR), "bag +", len(DIS_OLGULAR), "sahiplik +",
      len(IC_OLGULAR), "ic adim")
print("GOSTERIM:", simge(CIZILEN), "simge")
print("BEDEL   :", ayni_gosterime_dusen(CIZILEN), "sistem ayni diyagrama dusuyor")
print()
print("  bilerek atilan (gosterim tasiyamaz)   :", len(IC_OLGULAR), "ic adim")
print("  farkinda olmadan dusen (tasinabilirdi):",
      len([b for b in GERCEK_BAGLAR if b not in CIZILEN]), "bag")
for b in GERCEK_BAGLAR:
    if b not in CIZILEN:
        print("     yazilmamis:", b[0], "->", b[1])
print("  cizilen diyagram       : simge", simge(CIZILEN),
      "| dusen", ayni_gosterime_dusen(CIZILEN))
print("  bes bagin besi yazilsa : simge", simge(GERCEK_BAGLAR),
      "| dusen", ayni_gosterime_dusen(GERCEK_BAGLAR), "<- gosterimin TABANI")
print()
print("alan dusurulunce taban ne oluyor")
print("alan kumesi                 simge  dusen  tasidigi bit")
TABAN = ayni_gosterime_dusen(GERCEK_BAGLAR)
for ad, bag, sinir in (("aktor+senaryo+bag+sinir", GERCEK_BAGLAR, True),
                       ("bag dusurulur", [], True),
                       ("sinir dusurulur", GERCEK_BAGLAR, False),
                       ("ikisi de dusurulur", [], False)):
    d = ayni_gosterime_dusen(bag, (), sinir)
    print(f"{ad:26s} {simge(bag, (), sinir):5d} {d:6d} {(d // TABAN).bit_length() - 1:12d}")
print()
# DD3: ikinci yapilandirma. Iki ic adim "dahil edilen senaryo" olarak cizilir.
EK = ("belge uretme", "maliyet hesabi")
print("iki ic adim dahil edilen senaryo olarak cizilirse:")
print("  simge", simge(GERCEK_BAGLAR), "->", simge(GERCEK_BAGLAR, EK),
      "| dusen", TABAN, "->", ayni_gosterime_dusen(GERCEK_BAGLAR, EK))
print("  bedel: aktoru olmayan senaryo sayisi 0 ->", len(EK),
      "| dis olgu orani", f"{len(DIS_OLGULAR)}/{len(DIS_OLGULAR)}",
      "->", f"{len(DIS_OLGULAR)}/{len(DIS_OLGULAR) + len(EK)}")

# DD4: iki aktor tek bir rolde birlestirilirse
OLASI = [(a, s) for a in AKTORLER for s in DIS_OLGULAR]


def birlesik(baglar, ic, sahip):
    """Tek aktorlu diyagram: senaryo basina yalnizca 'bagli bir aktor var mi'."""
    return (("Kullanici",), tuple(DIS_OLGULAR),
            tuple(any(b[1] == s for b in baglar) for s in DIS_OLGULAR),
            tuple(sahip[s] for s in DIS_OLGULAR))


hedef = birlesik(GERCEK_BAGLAR, IC_OLGULAR, GERCEK_SAHIP)
sayi = 0
for bm in product((0, 1), repeat=len(OLASI)):
    baglar = [b for b, m in zip(OLASI, bm) if m]
    for im in product((0, 1), repeat=len(IC_OLGULAR)):
        ic = [i for i, m in zip(IC_OLGULAR, im) if m]
        if birlesik(baglar, ic, GERCEK_SAHIP) == hedef:
            sayi += 1
print()
print("iki aktor tek rolde birlestirilirse:")
print("  simge", simge(GERCEK_BAGLAR), "-> 8 | dusen", TABAN, "->", sayi,
      "| oran", sayi // TABAN, "kat")
```

```
SISTEM  : 20 olgu = 2 aktor + 3 senaryo + 5 bag + 3 sahiplik + 7 ic adim
GOSTERIM: 9 simge
BEDEL   : 512 sistem ayni diyagrama dusuyor

  bilerek atilan (gosterim tasiyamaz)   : 7 ic adim
  farkinda olmadan dusen (tasinabilirdi): 2 bag
     yazilmamis: KabulGorevlisi -> is emri acma
     yazilmamis: KabulGorevlisi -> teslim alma
  cizilen diyagram       : simge 9 | dusen 512
  bes bagin besi yazilsa : simge 11 | dusen 128 <- gosterimin TABANI

alan dusurulunce taban ne oluyor
alan kumesi                 simge  dusen  tasidigi bit
aktor+senaryo+bag+sinir       11    128            0
bag dusurulur                  6   4096            5
sinir dusurulur               10   1024            3
ikisi de dusurulur             5  32768            8

iki ic adim dahil edilen senaryo olarak cizilirse:
  simge 11 -> 15 | dusen 128 -> 32
  bedel: aktoru olmayan senaryo sayisi 0 -> 2 | dis olgu orani 3/3 -> 3/5

iki aktor tek rolde birlestirilirse:
  simge 11 -> 8 | dusen 128 -> 3456 | oran 27 kat
```

Üç sayı yan yana duruyor: sistem **20 olgu**, gösterim **9 simge**, bedel **512 sistem**. Beş yüz
on iki ayrı bakım atölyesi bu diyagramla aynı görünüyor; diyagrama bakan biri hangisine baktığını
bilemez.

#### İki Ayrı Kayıp

Beş yüz on iki sayısı iki farklı kaynaktan geliyor ve ayrılmadıkları sürece hiçbir işe yaramazlar.

**Bilerek atılan olgu.** Yedi iç adımın hiçbiri gösterimin bilgi kümesinde yer bulmuyor. Kullanım
senaryosu gösteriminde iç adımı yazacak bir alan yoktur; olsaydı da yazılmazdı, çünkü bu
gösterimin varlık nedeni sistemin içini kapatıp dışını göstermektir. Bu kayıp **çizeni değil türü
bağlar**: her kullanım senaryosu diyagramı bu yedi olguyu atar, ne kadar dikkatli çizilirse
çizilsin.

**Farkında olmadan düşen olgu.** Kabul görevlisinin iki bağı gösterimin taşıyabileceği türdendi —
aktör–senaryo bağı, listenin üçüncü kalemi. Yazılmadılar. Bu kayıp **türü değil çizeni bağlar** ve
başka bir diyagram çizmeye gerek kalmadan düzeltilebilir.

İkisi arasındaki fark, diyagrama bakarak görülemez. Okur her iki durumda da aynı şeyi görür:
orada olmayan bir bilgi. Bir bilginin **kasıtla mı yoksa dikkatsizlikle mi** yok olduğu, ancak
sistemin kendisi elde tutulup gösterimle karşılaştırıldığında ortaya çıkar. Bu yüzden kayıp
sayılmadıkça amaç olduğu bilinemez; sayılmamış bir boşluk savunulmuş bir boşluk değildir, yalnız
görülmemiş bir boşluktur.

#### Taban Belirsizlik Türle Gelir

İki bağ yazıldığında belirsizlik 512'den **128**'e iniyor: dört kat. Bu düşüşün tamamı çizenin
hesabına yazılır, çünkü ödenen bedel yalnız iki simgedir — 9 simge 11 oluyor.

Yüz yirmi sekiz sayısı ise oradan aşağı inmiyor. Bu, kullanım senaryosu gösteriminin **taban
belirsizliğidir**: yedi iç adımın her biri sistemde ya vardır ya yoktur, gösterim hiçbirini yazmaz,
dolayısıyla $2^7 = 128$ ayrı sistem aynı diyagrama düşer. Taban çizim ustalığıyla değişmeyen bir
sayıdır; **türle birlikte gelir**.

Bir gösterim değerlendirilirken bakılacak iki sayı budur. Taban, seçilen türün ne kadarını
göstermeyi baştan reddettiğini söyler. Taban ile gerçek belirsizlik arasındaki fark, çizenin ne
kadarını gereksiz yere kaybettiğini söyler. İlki bir tasarım kararıdır, ikincisi bir kusurdur ve
tek bir sayıyla anıldıklarında ayırt edilemezler.

#### Bir Simge Her Zaman Bir Bit Değildir

Orta tablo alanları teker teker düşürüp tabanın nereye çıktığını ölçüyor. Beş bağ simgesi
düşürülünce taban 128'den 4096'ya çıkıyor: beş simge **5 bit** taşıyormuş. Bağ başına tam bir bit,
çünkü her bağ sistemde ya vardır ya yoktur.

Sınır ise böyle davranmıyor. Tek bir sınır simgesi düşürüldüğünde taban 128'den **1024**'e
çıkıyor — bir simge **3 bit** taşıyor. Nedeni şu: sınır tek bir olguyu değil, üç senaryonun
üçünün birden sahipliğini söylüyor. Sınır çizilmemiş bir diyagramda okur, iş emri açmanın
atölyenin işi mi yoksa komşu bir sistemin işi mi olduğunu bilemez; üç senaryo için üç ayrı
bilinmeyen kalır.

Bu, yapı gösteriminde ölçülen orandan farklıdır: orada eklenen her simge tam olarak bir bit
belirsizlik alıyordu, çünkü her simge tek bir ikili alanı yazıyordu. Kullanım senaryosu
gösteriminde bir simgenin taşıdığı bit sayısı, o simgenin kaç olguyu birden sabitlediğine bağlıdır.
İkisi düşürüldüğünde taban 32768'e çıkıyor ve gösterim 5 simgeye iniyor: kalan diyagram iki aktör
ve üç senaryo adından ibarettir ve **8 bit** bilgi kaybetmiştir. Buradan çıkan kural, simge saymanın
tek başına bir ölçü olmadığıdır; sayılacak şey simge değil, **simgenin sabitlediği olgudur**.

#### Rolleri Birleştirmenin Sayısı

Aynı ölçü ters yönde de işler. Müşteri ile kabul görevlisi tek bir kullanıcı rolünde
birleştirilirse (**DD4**) diyagram sadeleşir: 11 simge 8'e iner, bağ sayısı beşten üçe düşer,
çizim küçülür. Belirsizlik ise 128'den **3456**'ya çıkıyor — **27 kat**.

Yirmi yedi sayısı doğrudan okunabilir. Tek aktörlü diyagram her senaryo için yalnız "bir kullanıcı
buna bağlıdır" diyor; hangi rolün bağlı olduğunu söylemiyor. Üç senaryonun her biri için iki rolden
en az birinin bağlı olması gerekiyor, bu da senaryo başına $2^2 - 1 = 3$ olasılık, üç senaryo için
$3^3 = 27$ demektir. Yedi iç adımın 128'i ile çarpılınca 3456 çıkıyor.

Burada rolleri ayrı tutmanın gerekçesi bir üslup tercihi değil, ölçülmüş bir bilgi miktarıdır. Üç
simge tasarruf edildi ve karşılığında yaklaşık 4,75 bit bilgi verildi. Bir gösterim sadeleştirilirken
sorulacak soru, çizimin daha temiz görünüp görünmediği değil, hangi olguların ayırt edilemez hâle
geldiğidir.

#### İç Adımı Gösterime Sokmak

Belirsizliği tabanın altına indirmenin tek bir yolu var: taşınmayan olguyu taşınır kılmak. Belge
üretme ile maliyet hesabı, senaryonun içine dâhil edilen ikinci düzey senaryolar olarak çizilebilir
(**DD3**). Sayı hemen düşüyor: taban **128'den 32'ye** iniyor, iki bit kazanılıyor, gösterim 11
simgeden 15'e çıkıyor.

Bedel simge sayısı değil. Yeni çizilen iki senaryonun **hiçbir aktör bağı yok** — hiçbir aktör
onları başlatmıyor, çünkü ikisi de sistemin kendi işidir. Aktörü olmayan senaryo sayısı 0'dan 2'ye
çıkıyor. Diyagramdaki dış olgu oranı 3/3'ten 3/5'e düşüyor: gösterimin beş senaryosundan yalnız
üçü sistemin dışından başlatılıyor.

Bunun anlamı şudur: sistem sınırı artık bir şey ayırmıyor. Sınırın taşıdığı bilgi, "içerisi
kapalıdır, dışarısı bu üç kapıdan girer" bilgisiydi; iç adımlar kapının aynı tarafına taşınınca o
bilgi geçersizleşiyor. Belirsizlik dört kat azaldı, ama gösterimin **söylediği şey değişti** —
artık dışarıdan görünen yüzü değil, işin bir kısmını anlatıyor. Kazanç 2 bittir ve sayılabilir;
kayıp bir alanın anlamıdır ve ancak fark edildiğinde sayılabilir.

#### Özet

- Kullanım senaryosu gösterimi dört alan taşır: aktör, senaryo, aktör–senaryo bağı, sistem sınırı.
  Sıra, koşul, iç adım ve veri bu listede yoktur.
- Atölyenin 20 olgusundan (2 aktör, 3 senaryo, 5 bağ, 3 sahiplik, 7 iç adım) çizilen diyagram 9
  simge yazıyor ve **512 ayrı sistem** aynı diyagrama düşüyor.
- Beş yüz on iki iki kaynaktan gelir: gösterimin taşıyamadığı **7 iç adım** ve gösterimin
  taşıyabileceği hâlde yazılmamış **2 bağ**. İkisi diyagrama bakarak ayırt edilemez.
- Eksik iki bağ yazılınca belirsizlik 128'e iner; 128 gösterimin **taban belirsizliğidir**, türle
  birlikte gelir ve çizim ustalığıyla değişmez.
- Beş bağ simgesi 5 bit, tek sınır simgesi 3 bit taşıyor: bir simgenin taşıdığı bit, o simgenin
  kaç olguyu birden sabitlediğine bağlıdır.
- İki aktörü tek rolde birleştirmek 11 simgeyi 8'e indiriyor ama belirsizliği 128'den 3456'ya
  çıkarıyor: 27 kat. İki iç adımı dâhil edilen senaryo olarak çizmek tabanı 32'ye indiriyor ama
  aktörü olmayan senaryo sayısını 0'dan 2'ye çıkarıyor ve dış olgu oranını 3/3'ten 3/5'e düşürüyor.

#### Sonraki Adım

Kullanım senaryosu gösterimi sistemin içini bilerek kapattı ve bunun bedeli sayıldı. Sonraki
gösterim tam tersini yapıyor: kapağı kaldırıp içeriyi, iletileri zaman eksenine dizerek gösteriyor.
İlk bakışta bu, kaybı sıfırlayan bir seçim gibi görünür — her ileti, her katılımcı, her sıra
numarası yazılıdır.

Sonraki ders bunun neden yanlış bir okuma olduğunu ölçer. Atölyenin akışı, ayırmanın iki dalı,
usta bulunmasının iki dalı, değişken kalem sayısı ve isteğe bağlı belge üretimi yüzünden **24 ayrı
iz** üretiyor. Bir sıra diyagramı tanımı gereği **tek bir izdir**; kapsamı 1/24, yani 0,0417. Dört
diyagram 0,1667 yapar. Ders koşullu dal ve döngü gösterimlerinin bu oranı nereye taşıdığını ve
oranı 1,0'a çıkarmanın hangi bedelle geldiğini sayar.

### Sıra Diyagramları

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/sira-diyagramlari

Zaman ekseninde ileti alışverişini gösteren diyagramın kapsadığı iz oranının ölçülmesi: 24 izin biri için 0,0417, dördü için 0,1667, koşullu dal ve döngü parçalarıyla 1,0 — ve döngü sınırı yazılmazsa 24 fazla kabul.

Önceki ders sistemin içini bilerek kapatan bir gösterimi ölçtü: yedi iç adım gösterime hiç
çıkmadı ve 128 ayrı sistem aynı diyagrama düştü. Bu ders içeriyi açıyor. Sıra gösterimi
katılımcıları yan yana dizer, iletileri aralarındaki oklarla yazar ve okları yukarıdan aşağıya
sıralar. Her ileti, gönderen ve alanıyla birlikte yazılıdır; sırayı taşıyan şey okun dikey
konumudur, sıra numarası isteğe bağlı bir ektir.

İlk bakışta bu, kaybın kapandığı yerdir. Değildir. Sıra gösterimi bir kaybı başka bir kaybın
karşılığında kapatır: sistemin **bir koşumunu** eksiksiz gösterirken, sistemin **öteki bütün
koşumlarını** hiç göstermez. Bu dersin ölçüsü o "öteki"nin sayısıdır.

#### Sistemin Ürettiği İzler

Bakım atölyesinin akışı dört yerde çatallanıyor. Stok ayırma başarılı olabilir ya da olmayıp
işi bekletip yeniden denetebilir. Uygun usta bulunabilir ya da bulunmayıp iş kuyruğa alınabilir.
İş emri bir, iki ya da üç kalem taşıyabilir. Belge üretimi istenebilir ya da istenmeyebilir.

Bu dört boyut bağımsız olduğu için sistem $2 \times 2 \times 3 \times 2 = 24$ ayrı **iz** üretiyor.
İz, baştan sona bir koşumun ileti dizisidir; uzunlukları altı ile on iki arasında değişiyor. Bir
sıra diyagramı tanımı gereği bu 24 dizinin **birini** çizer.

#### Kapsamın Ölçülmesi

Aşağıdaki model ortak tanımın akış ve iz tanımlarını aynen kurar, üstüne **parçalı diyagram**
kavramını ekler (**DD5**): bir boyut "açık" bırakılırsa diyagram o boyutu tek bir değere
sabitlemek yerine bir koşullu dal ya da döngü parçasıyla çizer ve o boyutun bütün değerlerini
kapsar. Simge sayımı katılımcı, ileti, parça ve koruma koşulu toplamıdır.

```python
"""Sira gosterimi: bir diyagram kac izi kapsiyor , kac izi disarida birakiyor.
Ortak tanimin AKIS ve izler() tanimlari aynen kurulur."""
from itertools import product

AKIS = {
    "baslat": [("Kabul", "IsEmri", "olustur"), ("IsEmri", "Stok", "ayir")],
    "ayirma_basarili": [("IsEmri", "Atolye", "planla")],
    "ayirma_basarisiz": [("IsEmri", "Kabul", "beklet"), ("IsEmri", "Stok", "ayir")],
    "usta_bulundu": [("Atolye", "Usta", "ata")],
    "usta_yok": [("Atolye", "Kabul", "kuyruga_al"), ("Atolye", "Usta", "ata")],
    "her_kalem": [("Usta", "Kalem", "isle")],
    "belge": [("IsEmri", "Belge", "uret")],
    "bitir": [("IsEmri", "Kabul", "kapat")],
}
KALEM_ARALIGI = (1, 2, 3)


def iz_kur(ayirma, usta, k, belge):
    iz = list(AKIS["baslat"])
    if ayirma == "basarisiz":
        iz += AKIS["ayirma_basarisiz"]
    iz += AKIS["ayirma_basarili"]
    iz += AKIS["usta_bulundu"] if usta == "bulundu" else AKIS["usta_yok"]
    iz += AKIS["her_kalem"] * k
    if belge:
        iz += AKIS["belge"]
    iz += AKIS["bitir"]
    return tuple(iz)


def izler(kalem_araligi=KALEM_ARALIGI):
    return [iz_kur(a, u, k, b)
            for a in ("basarili", "basarisiz") for u in ("bulundu", "yok")
            for k in kalem_araligi for b in (True, False)]


def kapsam(gosterimler, tum_izler):
    kapsanan = {g for g in gosterimler if g in tum_izler}
    return {"gosterim": len(gosterimler), "kapsanan": len(kapsanan),
            "toplam": len(tum_izler), "oran": round(len(kapsanan) / len(tum_izler), 4)}


# ---- DD5: parcali diyagram. Acik boyut bir parca simgesiyle cizilir , kapali
# boyut tek bir degere sabitlenir. Simge sayimi: katilimci + ileti + parca + koruma.
KATILIMCI = 7   # Kabul , IsEmri , Stok , Atolye , Usta , Kalem , Belge


def parcali(acik, sabit=("basarili", "bulundu", 3, True), kalem_ust=3):
    ayirma, usta, k, belge = sabit
    ileti = len(AKIS["baslat"]) + len(AKIS["ayirma_basarili"]) + len(AKIS["bitir"])
    parca = koruma = 0
    if "ayirma" in acik:
        ileti += len(AKIS["ayirma_basarisiz"]); parca += 1; koruma += 2
    elif ayirma == "basarisiz":
        ileti += len(AKIS["ayirma_basarisiz"])
    if "usta" in acik:
        ileti += len(AKIS["usta_bulundu"]) + len(AKIS["usta_yok"]); parca += 1; koruma += 2
    else:
        ileti += len(AKIS["usta_bulundu"] if usta == "bulundu" else AKIS["usta_yok"])
    if "kalem" in acik:
        ileti += 1; parca += 1; koruma += 1
    else:
        ileti += k
    if "belge" in acik:
        ileti += 1; parca += 1; koruma += 1
    elif belge:
        ileti += 1
    kabul = [iz_kur(a, u, kk, b)
             for a in (("basarili", "basarisiz") if "ayirma" in acik else (ayirma,))
             for u in (("bulundu", "yok") if "usta" in acik else (usta,))
             for kk in (range(1, kalem_ust + 1) if "kalem" in acik else (k,))
             for b in ((True, False) if "belge" in acik else (belge,))]
    return {"simge": KATILIMCI + ileti + parca + koruma, "ileti": ileti,
            "parca": parca, "kabul": kabul}


def duz_simge(iz):
    """Parcasiz bir sira diyagraminin simgesi: katilimci + cizilen ileti."""
    return KATILIMCI + len(iz)


IZ = izler()
print("SISTEM  :", len(IZ), "iz | uzunluklar:", sorted({len(i) for i in IZ}))
print("GOSTERIM:", parcali(())["simge"], "simge (parcasiz tek iz)")
print("BEDEL   :", len(IZ) - 1, "iz gosterime hic girmiyor")
print()
for n in (1, 2, 3, 4):
    k = kapsam([tuple(i) for i in IZ[:n]], IZ)
    print(f"  {n} parcasiz diyagram -> kapsam {k['kapsanan']}/{k['toplam']}"
          f" = {k['oran']} | simge {sum(duz_simge(i) for i in IZ[:n])}")
print()
print("parca eklendikce")
print("acik boyut                     simge  kapsanan  kapsam  simge/iz")
birikim = ()
for ek in ("kalem", "belge", "ayirma", "usta"):
    birikim += (ek,)
    p = parcali(birikim)
    kap = kapsam(p["kabul"], IZ)
    print(f"{'+'.join(birikim):30s} {p['simge']:5d} {kap['kapsanan']:9d}"
          f"  {kap['oran']:6} {p['simge'] / kap['kapsanan']:9.2f}")
print()
print("24 izin hepsini parcasiz kapsamak:", sum(duz_simge(i) for i in IZ),
      "simge | parcali kapsamak:",
      parcali(("kalem", "belge", "ayirma", "usta"))["simge"], "simge")
print()
# DD6: dongu siniri [1..*] yazilirsa. Karsilastirma penceresi kalem <= 6.
acik = ("kalem", "belge", "ayirma", "usta")
for ust, ad in ((3, "dongu siniri [1..3]"), (6, "dongu siniri [1..*]")):
    p = parcali(acik, kalem_ust=ust)
    kap = kapsam(p["kabul"], IZ)
    fazla = [i for i in p["kabul"] if i not in IZ]
    print(f"{ad:22s} kabul {len(p['kabul']):3d} | kapsam"
          f" {kap['kapsanan']}/{kap['toplam']} = {kap['oran']} | fazla kabul {len(fazla)}")
print()
# DD7: sistem degismeden IZ KUMESI buyurse. Kalem araligi 1..6 olan atolye.
IZ6 = izler((1, 2, 3, 4, 5, 6))
tek = [iz_kur("basarili", "bulundu", 3, True)]
p3 = parcali(acik, kalem_ust=3)
print("ayni iki diyagram , iz kumesi", len(IZ), "yerine", len(IZ6), "olsaydi")
for ad, g in (("parcasiz tek iz", tek), ("dort parcali diyagram", p3["kabul"])):
    a, b = kapsam(g, IZ), kapsam(g, IZ6)
    print(f"  {ad:22s} kapsam {a['kapsanan']}/{a['toplam']} = {a['oran']}"
          f"  ->  {b['kapsanan']}/{b['toplam']} = {b['oran']}")
print()
# DD8: her ileti turu senkron ya da eszamansiz. Gosterim yazmazsa kac sistem duser.
ILETI_TURU = sorted({m[2] for a in AKIS.values() for m in a})
GERCEK_KIP = {x: ("eszamansiz" if x in ("uret", "kuyruga_al") else "senkron")
              for x in ILETI_TURU}


def kip_gosterimi(kip, yazilan):
    return tuple(kip[x] if x in yazilan else None for x in ILETI_TURU)


def kip_dusen(yazilan):
    hedef = kip_gosterimi(GERCEK_KIP, yazilan)
    return sum(1 for s in product(("senkron", "eszamansiz"), repeat=len(ILETI_TURU))
               if kip_gosterimi(dict(zip(ILETI_TURU, s)), yazilan) == hedef)


tam = parcali(acik, kalem_ust=3)["simge"]
print("kapsami 1.0 olan diyagramda", len(ILETI_TURU), "ileti turu var")
for ad, yazilan in (("kip hic yazilmaz", ()),
                    ("yalniz iki eszamansiz kip yazilir", ("uret", "kuyruga_al")),
                    ("dokuz kipin dokuzu yazilir", tuple(ILETI_TURU))):
    print(f"  {ad:34s} simge {tam + len(yazilan):3d}"
          f" | ayni gosterime dusen {kip_dusen(yazilan):4d}")
```

```
SISTEM  : 24 iz | uzunluklar: [6, 7, 8, 9, 10, 11, 12]
GOSTERIM: 16 simge (parcasiz tek iz)
BEDEL   : 23 iz gosterime hic girmiyor

  1 parcasiz diyagram -> kapsam 1/24 = 0.0417 | simge 14
  2 parcasiz diyagram -> kapsam 2/24 = 0.0833 | simge 27
  3 parcasiz diyagram -> kapsam 3/24 = 0.125 | simge 42
  4 parcasiz diyagram -> kapsam 4/24 = 0.1667 | simge 56

parca eklendikce
acik boyut                     simge  kapsanan  kapsam  simge/iz
kalem                             16         3   0.125      5.33
kalem+belge                       18         6    0.25      3.00
kalem+belge+ayirma                23        12     0.5      1.92
kalem+belge+ayirma+usta           28        24     1.0      1.17

24 izin hepsini parcasiz kapsamak: 384 simge | parcali kapsamak: 28 simge

dongu siniri [1..3]    kabul  24 | kapsam 24/24 = 1.0 | fazla kabul 0
dongu siniri [1..*]    kabul  48 | kapsam 24/24 = 1.0 | fazla kabul 24

ayni iki diyagram , iz kumesi 24 yerine 48 olsaydi
  parcasiz tek iz        kapsam 1/24 = 0.0417  ->  1/48 = 0.0208
  dort parcali diyagram  kapsam 24/24 = 1.0  ->  24/48 = 0.5

kapsami 1.0 olan diyagramda 9 ileti turu var
  kip hic yazilmaz                   simge  28 | ayni gosterime dusen  512
  yalniz iki eszamansiz kip yazilir  simge  30 | ayni gosterime dusen  128
  dokuz kipin dokuzu yazilir         simge  37 | ayni gosterime dusen    1
```

Üç sayı: sistem **24 iz**, gösterim **16 simge**, bedel **23 iz** gösterime hiç girmiyor. Kapsam
1/24, yani 0,0417.

#### Dört Diyagram Yetmez

Kapsam doğrusal artıyor. İki diyagram 2/24 = 0,0833, üç diyagram 3/24 = 0,125, dört diyagram
4/24 = 0,1667. Her yeni diyagram tam olarak bir iz ekliyor, çünkü her biri tek bir koşumdur ve
koşumlar birbirinin yerini tutmaz.

Yirmi dört izin hepsini parçasız diyagramlarla kapsamak **384 simge** gerektiriyor. Bu, ileti
sayısı toplamına katılımcı listelerinin yirmi dört kez tekrar edilmesinin eklenmesidir. Böyle bir
belge kimse tarafından okunmaz; sıra diyagramlarının pratikte üç beş taneyle sınırlı kalmasının
nedeni budur ve o üç beş tane 0,125 civarında bir kapsam demektir.

Buradan çıkan cümle şudur: **bir sıra diyagramı kümesi sistemi göstermez, sistemden birkaç örnek
gösterir.** Örneklerin hangileri olduğu bir seçimdir ve o seçim gösterimde yazmaz — okur, elindeki
dört izin 24'ün hangi dördü olduğunu diyagramdan okuyamaz.

#### Parça Simgeleri Kapsamı Simge Başına Büyütür

Orta tablo başka bir yol ölçüyor. Döngü parçası açıldığında kalem boyutu tek bir değere
sabitlenmiyor: üç ileti yerine bir ileti ve bir döngü parçası çiziliyor. Simge sayısı 16'da
kalıyor — parçasız diyagramla **aynı** — ama kapsanan iz 1'den 3'e çıkıyor.

Sıradaki üç satır aynı biçimde ilerliyor. İsteğe bağlı belge üretimi bir parçaya alınınca 18
simge 6 iz kapsıyor. Ayırmanın iki dalı koşullu dala alınınca 23 simge 12 iz. Usta bulunmasının
iki dalı da alınınca 28 simge 24 izin hepsini kapsıyor. İz başına simge 5,33'ten **1,17**'ye
iniyor; aynı kapsamı parçasız elde etmek 384 simge isterken parçalı gösterim **28 simge** ile
bitiriyor, yaklaşık on dört kat az.

Bu, parçalı gösterimin bedava olduğu anlamına gelmez. Parçasız bir diyagram tek bir yukarıdan
aşağıya okumadır; parçalı diyagram, dört parçanın her birinde okuyucudan bir seçim yapmasını
ister ve okuma sayısı 24'e çıkar. Kapsam kazanıldı, **tek okunurluk** verildi. Gösterimin
söylediği şey de değişti: parçasız diyagram "böyle bir koşum olmuştur" der, parçalı diyagram
"şu koşumlar olabilir" der. Birincisi bir gözlem, ikincisi bir iddiadır ve iddia yanlış olabilir.

#### Kapsam Bir Kalite Ölçüsü Değildir

Alt iki blok bunun iki ayrı kanıtını veriyor.

Birincisi: döngü parçasına üst sınır yazılmazsa (**DD6**), yani "bir ya da daha çok kalem" denip
üst sınır verilmezse, kapsam yine 24/24 = 1,0 kalıyor ama diyagramın kabul ettiği dizi sayısı
24'ten 48'e çıkıyor. Yirmi dörtü gerçek, yirmi dördü sistemde olmayan dizilerdir: dört, beş, altı
kalemli iş emirleri. **Fazla kabul 0'dan 24'e çıktı ve kapsam hiç değişmedi.** Kapsam yalnız
"gerçek izlerin kaçı gösterildi" sorusunu yanıtlar; "gösterilenlerin kaçı gerçek" sorusunu
yanıtlamaz ve ikinci soru sorulmadıkça bir gösterim ölçülmüş sayılmaz.

İkincisi: iz kümesi büyüyünce oran, gösterim hiç değişmeden düşüyor. Kalem aralığı üç yerine altı
olan bir atölyede (**DD7**) aynı sistem 48 iz üretiyor. Parçasız tek diyagramın kapsamı
0,0417'den **0,0208**'e, dört parçalı diyagramın kapsamı 1,0'dan **0,5**'e iniyor. Diyagramlara
tek bir simge eklenmedi, tek bir simge silinmedi.

Bu yüzden kapsam oranı hiçbir yerde yalnız yazılmaz. "Kapsam 0,5" bir bilgi taşımaz; "48 izin
24'ü" taşır. Oran, paydanın büyüklüğüne bağlı bir sayıdır ve payda yazılmadığında karşılaştırma
yapılamaz.

#### Kapsanan İz de Eksik Yazılabilir

Kapsam bir izin **çizilip çizilmediğini** ölçüyor, **nasıl çizildiğini** ölçmüyor. Son blok bu
ikinci ekseni sayıyor. Sıra gösterimi her iletiyi bir kip ile yazabilir: çağıran, yanıt gelene
kadar bekliyorsa senkron, beklemiyorsa eşzamansız. Akıştaki dokuz ayrı ileti türünün her biri
için bu bir ikili karardır ve atölyede ikisi eşzamansızdır — belge üretimi ile kuyruğa alma
(**DD8**).

Kapsamı 1,0 olan 28 simgelik diyagram bu dokuz kararın hiçbirini yazmıyor. Sonuç: **512 ayrı
sistem** aynı diyagrama düşüyor. Diyagram bütün izleri kapsıyor ve gene de hangi sistemi
gösterdiğini söylemiyor. İki eşzamansız kip yazıldığında sayı 128'e, dokuzunun dokuzu
yazıldığında **1**'e iniyor; bedel 28 simgeden 37'ye çıkmaktır.

İki eksen birbirinden bağımsızdır ve ikisi de ayrı ayrı yazılmadıkça gösterim ölçülmüş sayılmaz.
Birincisi **hangi izler** sorusudur ve yanıtı kapsamdır. İkincisi **her izin ne kadarı** sorusudur
ve yanıtı aynı gösterime düşen sistem sayısıdır. Bir gösterim ilkinde tam not alıp ikincisinde
512'de kalabilir; tersi de olur, tek bir izi bütün alanlarıyla yazan bir diyagram ikinci eksende
1'dir ve birincide 0,0417.

#### Özet

- Bakım atölyesinin akışı dört bağımsız çatallanmayla **24 iz** üretiyor; bir sıra diyagramı
  tanımı gereği bu izlerin **birini** çizer, kapsamı 1/24 = 0,0417 ve 23 iz dışarıda kalır.
- Kapsam parçasız diyagram sayısıyla doğrusal artar: dört diyagram 4/24 = 0,1667 ve 56 simge.
  Yirmi dört izin hepsini parçasız kapsamak **384 simge** ister.
- Döngü ve koşullu dal parçaları kapsamı simge başına büyütür: 16 simge 3 iz, 18 simge 6 iz,
  23 simge 12 iz, 28 simge 24 iz. İz başına simge 5,33'ten 1,17'ye iner.
- Parçalı gösterim tek okunurluğu verir: dört parça okuyucudan dört seçim ister ve olası okuma
  sayısı 24'e çıkar. Gösterim bir gözlem olmaktan çıkıp bir iddiaya dönüşür.
- Kapsam 1,0 bir başarı ölçüsü değildir: döngü sınırı yazılmayınca kapsam 1,0 kalırken fazla kabul
  0'dan **24'e** çıkıyor; iz kümesi 24'ten 48'e büyüyünce aynı diyagramların kapsamı 0,0417'den
  0,0208'e ve 1,0'dan 0,5'e iniyor.
- Kapsam ile belirsizlik ayrı eksenlerdir: kapsamı 1,0 olan 28 simgelik diyagram dokuz iletinin
  kipini yazmadığı için **512 sistemi** ayırt edemiyor; dokuzu da yazılınca 37 simgeyle 1'e iner.

#### Sonraki Adım

Sıra gösterimi bir soruyu hiç sormadı: bu iletiler **başka bir sırayla** gidebilir miydi. Her
diyagram tek bir sıra yazıyor ve o sırayı zorunluymuş gibi gösteriyor. Oysa atölyedeki işlerin
çoğu birbirini beklemiyor; müşteriyi bilgilendirmekle maliyet hesaplamak arasında hiçbir öncelik
yok ve ikisi herhangi bir sırada yapılabilir.

Sonraki gösterim tam olarak bunu yazar: işler arasındaki **önkoşulları** yazar, sırayı yazmaz.
On iş ve on üç önkoşul, hangi sıraların geçerli olduğunu belirler ve bu sıraların sayısı Veri
Yapıları kursundaki topolojik sıralamanın kaç ayrı çıktı verebildiğidir. Sayı **168**'dir. Bir
etkinlik diyagramı, tek bir yürütme sırası değil, 168 yürütme sırasının tamamını birden kabul
eder — ve gevşekliğin sayısı yazılmadıkça okur onu kesinlik sanar.

### Etkinlik Diyagramları

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/etkinlik-diyagramlari

İş akışını önkoşullarla gösteren diyagramın kabul ettiği tam sıralama sayısının topolojik sıralamayla sayılması: on iş, on üç önkoşul, 168 tam sıralama, altı katmanlık kritik yol ve bir önkoşul eklemenin 168'i nereye indirdiği.

Önceki ders sıra gösteriminin bir koşumu eksiksiz, öteki 23 koşumu hiç göstermediğini saydı. O
gösterimin yazdığı her ileti belirli bir sırada duruyordu ve o sıra zorunluymuş gibi
görünüyordu. Oysa atölyedeki işlerin çoğu birbirini beklemiyor: müşteriyi bilgilendirmekle maliyeti
hesaplamak arasında hiçbir öncelik yok ve ikisi herhangi bir sırada yapılabilir.

Etkinlik gösterimi bunu düzeltir. Sıra yazmaz, **önkoşul** yazar: hangi işin hangi işlerden sonra
başlayabileceğini söyler, hangisinin önce yapılacağını söylemez. Böylece gösterim bir yalan
söylemekten kurtulur. Karşılığında başka bir şey yapar: **tek bir yürütmeyi değil, bir yürütme
kümesini** birden anlatır. Bu dersin ölçüsü o kümenin büyüklüğüdür.

#### Kısmi Sıra Bir Küme Anlatır

Atölyenin iş akışı on iş içeriyor: kabul, stok ayırma, usta atama, tezgâh ayırma, müşteri
bilgilendirme, maliyet hesabı, işleme, belgeleme, fatura kesme, kapatma. Aralarında on üç önkoşul
var. Bu on üç önkoşul bir **kısmi sıralama** kurar: bazı iş çiftlerinin sırasını belirler, bazılarını
serbest bırakır.

Sistemin gerçekte yaptığı şey ise bir **tam sıralamadır**. Bir iş emri koşarken işler tek tek olur ve
belirli bir sıraya girer; o koşumun bir tek sırası vardır. Gösterim ise bu sıraların tamamını
birden kabul eder. Kabul edilen sıra sayısı, gösterimin bıraktığı gevşekliğin ölçüsüdür.

Bu sayı, Veri Yapıları kursundaki **topolojik sıralamanın** kaç ayrı çıktı verebildiğidir. O ders
giriş dereceli yordamı kurdu ve sıralamanın tek olmadığını, kuyrukta birden çok düğüm varken
algoritmanın bir seçim yaptığını gösterdi — ama seçimlerin **kaç ayrı sonuç** verdiğini saymadı.
Bu ders o sayımı yapıyor. Yordam tekrarlanmıyor, aynen çağrılıyor.

#### Sayının Kendisi

```python
"""Etkinlik gosterimi: kismi siralama kac tam siralamayi birden kabul ediyor.
Ortak tanimin ETKINLIK ve tam_siralamalar tanimlari aynen kurulur; topolojik
siralama Veri Yapilari kursundaki giris dereceli yordamdir."""
from collections import deque
from itertools import combinations

ETKINLIK = {                      # is -> onkosul isler
    "kabul": [],
    "stok_ayir": ["kabul"],
    "usta_ata": ["kabul"],
    "tezgah_ayir": ["usta_ata"],
    "musteri_bilgilendir": ["kabul"],
    "maliyet_hesapla": ["stok_ayir"],
    "isle": ["stok_ayir", "tezgah_ayir"],
    "belgele": ["isle"],
    "fatura_kes": ["maliyet_hesapla", "isle"],
    "kapat": ["belgele", "fatura_kes", "musteri_bilgilendir"],
}


def tam_siralamalar(onkosul):
    isler = list(onkosul)
    sonuc = []

    def gez(kalan, dizi):
        if not kalan:
            sonuc.append(tuple(dizi))
            return
        for i in kalan:
            if all(o in dizi for o in onkosul[i]):
                dizi.append(i)
                gez([x for x in kalan if x != i], dizi)
                dizi.pop()
    gez(isler, [])
    return sonuc


def komsuluk(onkosul):
    """Onkosul esleme -> yonlu cizge: onkosul isten bagimli ise kenar."""
    k = {i: [] for i in onkosul}
    for i, oncekiler in onkosul.items():
        for o in oncekiler:
            k[o].append(i)
    return k


def topolojik_sirala(k):
    """Veri Yapilari kursundaki giris dereceli yordam , aynen."""
    giris = {d: 0 for d in k}
    for d in k:
        for h in k[d]:
            giris[h] += 1
    kuyruk = deque(sorted(d for d in giris if giris[d] == 0))
    sonuc = []
    while kuyruk:
        d = kuyruk.popleft()
        sonuc.append(d)
        for h in k[d]:
            giris[h] -= 1
            if giris[h] == 0:
                kuyruk.append(h)
    return sonuc if len(sonuc) == len(k) else None


def katmanlar(k):
    giris = {d: 0 for d in k}
    for d in k:
        for h in k[d]:
            giris[h] += 1
    hazir = sorted(d for d in giris if giris[d] == 0)
    sonuc, islenen = [], 0
    while hazir:
        sonuc.append(hazir)
        islenen += len(hazir)
        sonraki = []
        for d in hazir:
            for h in k[d]:
                giris[h] -= 1
                if giris[h] == 0:
                    sonraki.append(h)
        hazir = sorted(sonraki)
    return sonuc if islenen == len(k) else None


def once_gelenler(onkosul):
    """Gecisli kapanis: her isin kendisinden once gelmesi zorunlu isler."""
    kapanis = {i: set(onkosul[i]) for i in onkosul}
    degisti = True
    while degisti:
        degisti = False
        for i in kapanis:
            yeni = set(kapanis[i])
            for o in kapanis[i]:
                yeni |= kapanis[o]
            if yeni != kapanis[i]:
                kapanis[i] = yeni
                degisti = True
    return kapanis


def karsilastirilamaz(onkosul):
    kap = once_gelenler(onkosul)
    return [(a, b) for a, b in combinations(sorted(onkosul), 2)
            if b not in kap[a] and a not in kap[b]]


def carpan(n):
    s = 1
    for i in range(2, n + 1):
        s *= i
    return s


IS = len(ETKINLIK)
ONKOSUL = sum(len(v) for v in ETKINLIK.values())
TS = tam_siralamalar(ETKINLIK)
print("SISTEM  : her kosumda TEK bir yurutme sirasi gerceklesir")
print("GOSTERIM:", IS + ONKOSUL, "simge =", IS, "is +", ONKOSUL, "onkosul")
print("BEDEL   :", len(TS), "tam siralama kabul ediliyor | tek siralamayi cizmek kapsam",
      round(1 / len(TS), 4))
print()
K = komsuluk(ETKINLIK)
print("topolojik siralama tek bir cikti veriyor:")
print(" ", topolojik_sirala(K))
print("ayni cizgenin gecerli cikti sayisi:", len(TS))
KAT = katmanlar(K)
print("katmanlar (esazamanli baslatilabilir isler):")
for i, kat in enumerate(KAT, 1):
    print(f"  {i}. {kat}")
print("kritik yol uzunlugu:", len(KAT), "adim | sirali yurutme", IS, "adim")
print()
KI = karsilastirilamaz(ETKINLIK)
CIFT = carpan(IS) // (carpan(2) * carpan(IS - 2))
print("is cifti:", CIFT, "| onkosulun sirasini belirledigi cift:", CIFT - len(KI),
      "| serbest cift:", len(KI))
print("onkosulsuz kabul:", carpan(IS), "-> onkosullu kabul:", len(TS),
      "| daralma", carpan(IS) // len(TS), "kat")
print()
print("bir onkosul eklenirse 168 nereye iner")
sonuc = []
for a, b in KI:
    for x, y in ((a, b), (b, a)):
        yeni = {i: list(v) for i, v in ETKINLIK.items()}
        yeni[y].append(x)
        if topolojik_sirala(komsuluk(yeni)) is None:
            continue
        sonuc.append((len(tam_siralamalar(yeni)), f"{x} -> {y}"))
sonuc.sort()
print("  eklenebilir onkosul sayisi:", len(sonuc))
print("  en cok daraltan uc secim:")
for n, ad in sonuc[:3]:
    print(f"    {ad:38s} {len(TS)} -> {n}")
print("  en az daraltan uc secim:")
for n, ad in sonuc[-3:]:
    print(f"    {ad:38s} {len(TS)} -> {n}")
print("  hepsinin ortalamasi:", round(sum(n for n, _ in sonuc) / len(sonuc), 1))
print("  atolyede anlami olan iki secim (DD9):")
for x, y in (("musteri_bilgilendir", "isle"), ("belgele", "fatura_kes")):
    yeni = {i: list(v) for i, v in ETKINLIK.items()}
    yeni[y].append(x)
    print(f"    {x + ' -> ' + y:38s} {len(TS)} -> {len(tam_siralamalar(yeni))}")
print()
# DD10: karar dugumu. Yeniden isleme dali istege bagli bir is ekliyor.
DAL = {i: list(v) for i, v in ETKINLIK.items()}
DAL["yeniden_isle"] = ["isle"]
DAL["belgele"] = ["yeniden_isle"]
TS2 = tam_siralamalar(DAL)
print("karar dugumu eklenirse (yeniden isleme dali):")
print("  simge", IS + ONKOSUL, "->",
      len(DAL) + sum(len(v) for v in DAL.values()) + 1, "(karar dugumu dahil)")
print("  dal A", len(TS), "tam siralama | dal B", len(TS2), "tam siralama | toplam kabul",
      len(TS) + len(TS2))
```

```
SISTEM  : her kosumda TEK bir yurutme sirasi gerceklesir
GOSTERIM: 23 simge = 10 is + 13 onkosul
BEDEL   : 168 tam siralama kabul ediliyor | tek siralamayi cizmek kapsam 0.006

topolojik siralama tek bir cikti veriyor:
  ['kabul', 'stok_ayir', 'usta_ata', 'musteri_bilgilendir', 'maliyet_hesapla', 'tezgah_ayir', 'isle', 'belgele', 'fatura_kes', 'kapat']
ayni cizgenin gecerli cikti sayisi: 168
katmanlar (esazamanli baslatilabilir isler):
  1. ['kabul']
  2. ['musteri_bilgilendir', 'stok_ayir', 'usta_ata']
  3. ['maliyet_hesapla', 'tezgah_ayir']
  4. ['isle']
  5. ['belgele', 'fatura_kes']
  6. ['kapat']
kritik yol uzunlugu: 6 adim | sirali yurutme 10 adim

is cifti: 45 | onkosulun sirasini belirledigi cift: 31 | serbest cift: 14
onkosulsuz kabul: 3628800 -> onkosullu kabul: 168 | daralma 21600 kat

bir onkosul eklenirse 168 nereye iner
  eklenebilir onkosul sayisi: 28
  en cok daraltan uc secim:
    maliyet_hesapla -> usta_ata            168 -> 16
    belgele -> maliyet_hesapla             168 -> 24
    fatura_kes -> musteri_bilgilendir      168 -> 30
  en az daraltan uc secim:
    musteri_bilgilendir -> fatura_kes      168 -> 138
    maliyet_hesapla -> belgele             168 -> 144
    usta_ata -> maliyet_hesapla            168 -> 152
  hepsinin ortalamasi: 84.0
  atolyede anlami olan iki secim (DD9):
    musteri_bilgilendir -> isle            168 -> 96
    belgele -> fatura_kes                  168 -> 96

karar dugumu eklenirse (yeniden isleme dali):
  simge 23 -> 26 (karar dugumu dahil)
  dal A 168 tam siralama | dal B 324 tam siralama | toplam kabul 492
```

Üç sayı: sistem her koşumda **tek bir sıra** gerçekleştiriyor, gösterim **23 simge** yazıyor, bedel
**168 tam sıralama** kabul etmek. Tek bir sırayı çizmek kapsamı 1/168, yani 0,006 yapar.

#### Bir Çıktı ile Yüz Altmış Sekiz Çıktı

Giriş dereceli yordam bir sıralama döndürüyor ve o sıralama geçerlidir. Ama tek geçerli sıralama
değildir; yordam kuyrukta birden çok iş varken alfabetik sırayla seçim yaptığı için hep aynı
çıktıyı veriyor. Bu, gösterimin bir özelliği değil, **yordamın belirliliğini sağlamak için konmuş
bir ölçüttür**. Başka bir ölçüt başka bir sıra verirdi ve o sıra da geçerli olurdu.

Kaç tanesi geçerli olurdu sorusunun yanıtı 168'dir. Kırk beş iş çiftinin 31'inin sırası
önkoşullarla belirlenmiş, **14'ü serbest** bırakılmıştır. Serbest çiftler birbirinden bağımsız
değildir — biri sabitlenince başkaları da kısıtlanır — bu yüzden sayı iki üzeri on dört değil,
tam sayımla bulunan 168'dir.

Buradaki asıl sonuç, gösterimin ne kadar iş yaptığıdır. Hiçbir önkoşul yazılmasaydı on iş, ondan
bire inen çarpımın verdiği **3.628.800** ayrı sırada yapılabilirdi. On üç önkoşul bu sayıyı 168'e
indiriyor: **21600 kat daralma**. Gösterim ciddi bir bilgi taşıyor. Yine de 168 kalıyor ve 168
sıfır değildir.

#### Eşzamanlı Dallar ve Katmanlar

Katman listesi aynı yordamın ikinci çıktısıdır: her turda kuyruğa giren işler kümesi. Atölyenin
işleri altı katmana ayrılıyor. İkinci katmanda üç iş birden hazır oluyor — müşteri bilgilendirme,
stok ayırma, usta atama — ve üçü de birbirini beklemiyor.

Katman sayısı **kritik yol uzunluğudur**: sınırsız paralellikle bütün işlerin bitebileceği en kısa
adım sayısı. Altı adım, sıralı yürütmenin 10 adımına karşılık geliyor. Eşzamanlı dal gösterimi bu
farkı yazan şeydir; dalları çizmeyen bir gösterim on adımlık bir zincir gibi okunur ve dört adımlık
kazanç görünmez olur.

Katman yapısının 168 ile ilişkisi doğrudandır: gevşeklik tam olarak katman içindeki işlerin
birbirine göre serbest olmasından doğuyor. Eşzamanlılık ile belirsizlik burada aynı olgunun iki
adıdır — **gösterim paralelliği ancak sırayı serbest bırakarak söyleyebilir.**

#### Bir Önkoşul Eklemenin Sayısı

Yirmi sekiz ayrı önkoşul, döngü yaratmadan eklenebiliyor. Her biri 168'i başka bir yere indiriyor
ve aralık geniş: en dar sonuç **16**, en geniş sonuç **152**, ortalama 84.

Aradaki fark yazılan cümlenin uzunluğundan gelmiyor. Her seçim tek bir önkoşuldur ve gösterime tek
bir simge ekler; ama bir simge 168'i 16'ya indirirken bir başkası onu 152'de bırakıyor, yani
neredeyse hiçbir şey söylemiyor. **Bir simgenin belirsizlikten aldığı pay, o simgenin nereye
konduğuyla belirlenir** ve bu pay dokuz kattan fazla değişebiliyor.

En çok daraltan seçim, atölyede en anlamlı seçim de değil. Maliyet hesabını usta atamasından önce
zorlamak 168'i 16'ya indiriyor, ama böyle bir kural atölyenin işleyişinde karşılığı olmayan bir
kuraldır. Atölyede gerçekten savunulabilecek iki kural — müşteri işleme başlamadan bilgilendirilir,
belge fatura kesilmeden hazırlanır (**DD9**) — 168'i **96**'ya indiriyor. Doğru sayı en küçük sayı
değildir; doğru sayı, gerçekten var olan kısıtların bıraktığı sayıdır. Bir gösterimi daraltmak için
olmayan bir kısıt yazmak, belirsizliği yalanla değiştirmektir.

Bunun bir yan sonucu, kullanım senaryosu dersinde ayrılan iki kaybın burada da karşımıza
çıkmasıdır. Serbest bırakılmış 14 çiftin bir kısmı **gerçekten serbesttir** — atölye o iki işi
istediği sırada yapabilir. Bir kısmı ise yalnızca **yazılmamıştır**: sıra gerçekte bellidir ama
önkoşul kâğıda geçmemiştir. Gösterim ikisini aynı biçimde yazar, çünkü kısmi sıralamanın "serbest" ile
"bilinmiyor" için ayrı bir simgesi yoktur. On dört çiftin kaçının hangi türden olduğu diyagramdan
okunamaz; ancak akış sahibine tek tek sorularak ayrılabilir. Bu ayrım yapılmadığı sürece 168 sayısı
gevşekliğin **üst sınırıdır**, ölçüsü değildir.

#### Karar Düğümü Belirsizliği Çoğaltır

Etkinlik gösteriminin üçüncü ögesi karardır: akış bir noktada koşula göre iki dala ayrılır. Atölyede
böyle bir dal var — işleme sonrası denetim başarısız olursa iş yeniden işlenir (**DD10**).

Karar düğümü eklendiğinde gösterim 23 simgeden 26'ya çıkıyor. Kabul edilen tam sıralama sayısı ise 168
değil, iki dalın toplamı oluyor: dal A 168, dal B **324**, toplam **492**. Bir düğüm ve iki kenar
eklemek kabul edilen yürütme sayısını yaklaşık üç katına çıkardı.

Nedeni şudur: gösterim dalın **hangi koşulda** seçildiğini bir metin olarak yazar, ama o metni
sınayan bir yapı taşımaz. Diyagrama bakan biri için iki dal da her zaman açıktır. Karar, akışı
ayıran bir şey gibi görünür; ölçüldüğünde **birleştiren** bir şey olduğu çıkar — iki ayrı yürütme
kümesini tek gösterimin altında toplar.

#### Özet

- Etkinlik gösterimi sıra yazmaz, önkoşul yazar; on iş ve on üç önkoşul **23 simge** ile bir kısmi
  sıra kurar ve o kısmi sıralama **168 tam sıralamayı** birden kabul eder. Tek bir sırayı çizmek kapsamı
  0,006 yapar.
- Topolojik sıralama tek bir çıktı verir çünkü kuyruktan seçim için bir ölçüt kullanır; geçerli
  çıktı sayısı 168'dir. Kırk beş iş çiftinin 31'i belirli, 14'ü serbesttir ve serbest çiftler
  bağımsız olmadığı için sayı tam sayımla bulunur.
- Önkoşulsuz on iş 3.628.800 sırada yapılabilirdi; on üç önkoşul bunu **21600 kat** daraltıyor.
  Gevşeklik yazılmadıkça okur 168'i 1 sanır.
- İşler altı katmana ayrılıyor: kritik yol 6 adım, sıralı yürütme 10 adım. Paralellik ile
  belirsizlik aynı olgunun iki adıdır; gösterim paralelliği ancak sırayı serbest bırakarak söyler.
- Döngü yaratmadan eklenebilecek 28 önkoşuldan biri 168'i 16'ya indirirken bir başkası 152'de
  bırakıyor; atölyede gerçekten savunulabilir iki kural 96 veriyor. En çok daraltan kısıt en doğru
  kısıt değildir.
- Karar düğümü 23 simgeyi 26'ya çıkarırken kabul edilen tam sıralamayı 168'den **492**'ye taşıyor:
  karar akışı ayırmaz, iki yürütme kümesini tek gösterimde birleştirir.

#### Sonraki Adım

Bu ders gösterimin **fazla kabul ettiği** yürütmeleri saydı: 168 sıranın hepsi geçerlidir, ama
sistem her koşumda yalnız birini yapar. Kabul fazlaydı ve fazlalığın tamamı bilinçliydi — kısmi
sıra zaten gevşek olmak için yazılır.

Sonraki gösterim aynı fazlalığı bilinçsizce üretir ve üstüne bir de tersini yapar. Durum makinesi
bir nesnenin geçebileceği durumları ve geçişleri yazar; atölyede iş emrinin dört durumu ve altı
geçişi var. Bu makine gerçekte olan altı diziden **ikisini reddediyor** ve sistemde olmayan **iki
diziyi kabul ediyor**. Reddedilenleri kurtarmak için iki geçiş eklendiğinde reddedilen sıfıra
iniyor, ama fazla kabul 2'den **26'ya** çıkıyor. Ders bunu bir kural olarak yazar: eksik kabulü
kapatmanın bedeli fazla kabuldür.

### Durum Makinesi Diyagramları

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/durum-makinesi-diyagramlari

Durum, geçiş ve koruma koşulu gösteriminin eksik kabulü ile fazla kabulünün ayrı ayrı sayılması: dört durumlu makine iki gerçek diziyi reddediyor, iki geçiş eklemek reddedileni sıfırlarken fazla kabulü 2'den 26'ya çıkarıyor.

Önceki ders bir gevşekliği ölçtü: etkinlik gösterimi 168 tam sıralamayı birden kabul ediyordu ve bu
fazlalık bilinçliydi. Kısmi sıra zaten gevşek olmak için yazılır; sayılması gereken şey
gevşekliğin büyüklüğüydü.

Durum makinesi gevşek olmak için yazılmaz. Tam tersini iddia eder: bir nesnenin geçebileceği
durumları ve o durumlar arasında **izin verilen** geçişleri sayar, geri kalan her şeyi reddeder.
Bir kesinlik iddiasıdır. Bu ders o iddiayı iki yönden sınıyor: makine sistemde **gerçekten olan**
bir diziyi reddediyor mu ve sistemde **hiç olmayan** bir diziyi kabul ediyor mu. İki hata ayrı
şeylerdir, ayrı sayılırlar ve birini düzeltmek ötekini büyütür.

#### İki Yönlü Karşılaştırma

Atölyede bir iş emrinin dört durumu var: açık, ayrıldı, planlı, kapalı. Altı geçiş yazılı. Bu
makinenin **dili**, başlangıç durumundan başlayıp kapalı durumda biten bütün olay dizileridir; en
çok altı olaya kadar bakıldığında bu dilde altı dizi var.

Sistemin gerçekten ürettiği dizi sayısı da altı. İki sayı eşit olduğu için makinenin doğru olduğu
sanılabilir. Değildir — kümeler eşit değil, yalnız büyüklükleri eşit. Ölçülmesi gereken iki şey
var:

- **Eksik kabul.** Sistemde olan ama makinenin reddettiği dizi. Makine gerçeği dar tutuyor
  demektir; böyle bir makineye dayanarak yazılan bir denetim, gerçek bir iş emrini hatalı sayar.
- **Fazla kabul.** Makinenin kabul ettiği ama sistemde hiç olmayan dizi. Makine gerçeği geniş
  tutuyor demektir; böyle bir makine, olmayacak bir yolu varmış gibi gösterir ve o yol için kod
  yazılmasına yol açar.

```python
"""Durum makinesi gosterimi: eksik kabul ile fazla kabul ayri ayri sayilir.
Ortak tanimin DURUM_MAKINESI , GERCEK_DIZILER ve makine_dili tanimlari aynen kurulur."""
from itertools import product

DURUM_MAKINESI = {
    "acik":     {"ayir": "ayrildi", "iptal": "kapali"},
    "ayrildi":  {"planla": "planli", "iptal": "kapali"},
    "planli":   {"isle": "planli", "bitir": "kapali"},
    "kapali":   {},
}
BASLANGIC = "acik"
OLAYLAR = ("ayir", "planla", "isle", "bitir", "iptal")

GERCEK_DIZILER = [
    ("ayir", "planla", "isle", "bitir"),
    ("ayir", "planla", "isle", "isle", "bitir"),
    ("ayir", "planla", "isle", "isle", "isle", "bitir"),
    ("ayir", "planla", "isle", "planla", "isle", "bitir"),   # yeniden planlama
    ("ayir", "planla", "iptal"),                             # islemeden once iptal
    ("iptal",),
]


def makine_kabul(makine, dizi, baslangic=BASLANGIC):
    d = baslangic
    for olay in dizi:
        if olay not in makine[d]:
            return False
        d = makine[d][olay]
    return True


def makine_dili(makine, olaylar, uzunluk, baslangic=BASLANGIC):
    kabul = []
    for n in range(1, uzunluk + 1):
        for dizi in product(olaylar, repeat=n):
            d = baslangic
            gecerli = True
            for olay in dizi:
                if olay not in makine[d]:
                    gecerli = False
                    break
                d = makine[d][olay]
            if gecerli and not makine[d]:
                kabul.append(dizi)
    return kabul


# ---- onarilmis makine: iki gecis eklenir
ONARILMIS = {d: dict(g) for d, g in DURUM_MAKINESI.items()}
ONARILMIS["planli"]["planla"] = "planli"
ONARILMIS["planli"]["iptal"] = "kapali"


# ---- DD11: korumali makine. Ayni iki gecis , ustune koruma kosulu.
def son_planladan_sonra_isle(g):
    """planli durumuna en son girildiginden beri en az bir isle oldu mu."""
    yer = max((i for i, e in enumerate(g) if e == "planla"), default=None)
    return yer is not None and "isle" in g[yer + 1:]


KORUMA = {
    ("planli", "planla"): son_planladan_sonra_isle,
    ("planli", "iptal"): lambda g: "isle" not in g,
}


def korumali_kabul(dizi, baslangic=BASLANGIC):
    d, gecmis = baslangic, []
    for olay in dizi:
        if olay not in ONARILMIS[d]:
            return False
        kosul = KORUMA.get((d, olay))
        if kosul and not kosul(tuple(gecmis)):
            return False
        gecmis.append(olay)
        d = ONARILMIS[d][olay]
    return True


def korumali_dil(olaylar, uzunluk, baslangic=BASLANGIC):
    kabul = []
    for n in range(1, uzunluk + 1):
        for dizi in product(olaylar, repeat=n):
            if not korumali_kabul(dizi, baslangic):
                continue
            d = baslangic
            for olay in dizi:
                d = ONARILMIS[d][olay]
            if not ONARILMIS[d]:
                kabul.append(dizi)
    return kabul


# ---- DD12: gecmisi metne degil DURUMA yazmak. planli ikiye bolunur.
BOLUNMUS = {
    "acik":     {"ayir": "ayrildi", "iptal": "kapali"},
    "ayrildi":  {"planla": "planli", "iptal": "kapali"},
    "planli":   {"isle": "islenmis", "iptal": "kapali"},
    "islenmis": {"isle": "islenmis", "planla": "planli", "bitir": "kapali"},
    "kapali":   {},
}


def simge(makine, koruma=0):
    return len(makine) + sum(len(g) for g in makine.values()) + koruma


def olc(ad, dil, kabul_eden):
    fazla = [d for d in dil if d not in GERCEK_DIZILER]
    eksik = [d for d in GERCEK_DIZILER if not kabul_eden(d)]
    return {"ad": ad, "dil": len(dil), "fazla": len(fazla), "eksik": len(eksik),
            "eksik_liste": eksik, "fazla_liste": fazla}


D1 = makine_dili(DURUM_MAKINESI, OLAYLAR, 6)
O1 = olc("dort durum , alti gecis", D1, lambda d: makine_kabul(DURUM_MAKINESI, d))
print("SISTEM  :", len(GERCEK_DIZILER), "gercek gecis dizisi")
print("GOSTERIM:", simge(DURUM_MAKINESI), "simge =", len(DURUM_MAKINESI), "durum +",
      sum(len(g) for g in DURUM_MAKINESI.values()), "gecis")
print("BEDEL   : eksik kabul", O1["eksik"], "| fazla kabul", O1["fazla"])
print()
for d in O1["eksik_liste"]:
    print("  REDDEDILEN:", " ".join(d))
for d in O1["fazla_liste"]:
    print("  FAZLA KABUL:", " ".join(d))
print()
D2 = makine_dili(ONARILMIS, OLAYLAR, 6)
O2 = olc("iki gecis eklenmis", D2, lambda d: makine_kabul(ONARILMIS, d))
D3 = korumali_dil(OLAYLAR, 6)
O3 = olc("iki gecis + iki koruma kosulu", D3, korumali_kabul)
D4 = makine_dili(BOLUNMUS, OLAYLAR, 6)
O4 = olc("bes durum , dokuz gecis", D4, lambda d: makine_kabul(BOLUNMUS, d))
print("makine                          simge  kabul  eksik  fazla")
for o, s in ((O1, simge(DURUM_MAKINESI)), (O2, simge(ONARILMIS)),
             (O3, simge(ONARILMIS, 2)), (O4, simge(BOLUNMUS))):
    print(f"{o['ad']:31s} {s:5d} {o['dil']:6d} {o['eksik']:6d} {o['fazla']:6d}")
print()
print("fazla kabul uzunluk penceresine bagli")
print("pencere  alti gecis  sekiz gecis  koruma kosullu  bolunmus durum")
for u in (4, 5, 6, 7, 8):
    a = len([d for d in makine_dili(DURUM_MAKINESI, OLAYLAR, u)
             if d not in GERCEK_DIZILER])
    b = len([d for d in makine_dili(ONARILMIS, OLAYLAR, u) if d not in GERCEK_DIZILER])
    c = len([d for d in korumali_dil(OLAYLAR, u) if d not in GERCEK_DIZILER])
    e = len([d for d in makine_dili(BOLUNMUS, OLAYLAR, u) if d not in GERCEK_DIZILER])
    print(f"{u:7d} {a:11d} {b:12d} {c:15d} {e:15d}")
print()
print("koruma kosullu makinenin fazla kabulu:", [" ".join(d) for d in O3["fazla_liste"]])
print("bolunmus makinenin fazla kabulu      :", [" ".join(d) for d in O4["fazla_liste"]])
```

```
SISTEM  : 6 gercek gecis dizisi
GOSTERIM: 10 simge = 4 durum + 6 gecis
BEDEL   : eksik kabul 2 | fazla kabul 2

  REDDEDILEN: ayir planla isle planla isle bitir
  REDDEDILEN: ayir planla iptal
  FAZLA KABUL: ayir iptal
  FAZLA KABUL: ayir planla bitir

makine                          simge  kabul  eksik  fazla
dort durum , alti gecis            10      6      2      2
iki gecis eklenmis                 12     32      0     26
iki gecis + iki koruma kosulu      14     10      0      4
bes durum , dokuz gecis            14      9      0      3

fazla kabul uzunluk penceresine bagli
pencere  alti gecis  sekiz gecis  koruma kosullu  bolunmus durum
      4           2            5               2               1
      5           2           12               3               2
      6           2           26               4               3
      7           3           58               9               8
      8           4          122              17              16

koruma kosullu makinenin fazla kabulu: ['ayir iptal', 'ayir planla bitir', 'ayir planla isle planla bitir', 'ayir planla isle isle planla bitir']
bolunmus makinenin fazla kabulu      : ['ayir iptal', 'ayir planla isle planla iptal', 'ayir planla isle isle planla iptal']
```

Üç sayı: sistem **6 gerçek dizi**, gösterim **10 simge**, bedel **2 eksik kabul ve 2 fazla kabul**.

#### Reddedilen İki Dizi

Makinenin reddettiği iki dizi atölyede gerçekten oluyor. Birincisi yeniden planlamadır: iş
işlendikten sonra bir aksaklık çıkıyor, iş yeniden planlanıyor ve yeniden işleniyor. Makinede
planlı durumundan planlı durumuna dönen bir geçiş yok, bu yüzden ikinci `planla` olayı reddediliyor.

İkincisi işleme başlamadan yapılan iptaldir. Makine iptali yalnız açık ve ayrıldı durumlarında
kabul ediyor; planlı durumundan iptal yolu yok. Oysa planlanmış ama henüz işlenmemiş bir iş emri
iptal edilebiliyor.

İki eksik kabulün ortak yanı, ikisinin de **görünmez** olmasıdır. Makine yanlış olduğunu
söylemiyor; yalnızca o dizileri kabul etmiyor. Diyagrama bakan biri eksikliği fark edemez, çünkü
eksik olan şey diyagramda çizili değildir. Ancak gerçek dizilerin listesi elde tutulup makineye tek
tek sınatıldığında ortaya çıkar — bu dersin yaptığı da tam olarak budur.

Fazla kabul edilen iki dizi de aynı biçimde çizilidir ama gerçekte yoktur. Stok ayrıldıktan sonra
doğrudan iptal etmek ve planlamadan sonra hiç işlemeden bitirmek makinenin izin verdiği
yollardır; atölyede ikisi de olmuyor.

#### Onarmanın Bedeli

Reddedilen iki diziyi kurtarmanın yolu açık: planlı durumuna iki geçiş eklemek. Biri planlı
durumundan planlı durumuna `planla`, öteki planlı durumundan kapalı durumuna `iptal`. Gösterim 10
simgeden 12'ye çıkıyor. Eksik kabul **0**'a iniyor — iki gerçek dizi de artık kabul ediliyor.

Fazla kabul ise 2'den **26**'ya çıkıyor. On üç kat. Makinenin dili altı diziden 32'ye büyüyor ve
büyümenin tamamı sistemde karşılığı olmayan dizilerden geliyor.

Nedeni yapısaldır. Planlı durumuna kendine dönen bir `planla` geçişi eklemek, "işlendikten sonra
yeniden planlanabilir" demez; **"planlı durumundayken her an, kaç kez olursa olsun yeniden
planlanabilir"** der. Durum makinesi geçmişi tutmaz; tuttuğu tek şey içinde bulunduğu durumdur. Bir
geçiş eklendiğinde o geçiş, durumun ulaşılabildiği **bütün** yollardan sonra açık hâle gelir.
Amaçlanan tek bir yol için eklenir, elde edilen bütün yollar için açılır.

Buradan çıkan kural şudur: **eksik kabulü kapatmanın bedeli fazla kabuldür.** İki hata birbirinin
tersi yönde durur ve bir gösterim ikisini birden sıfıra indiremez — indirebilseydi gösterim
sistemin kendisi olurdu, izdüşümü değil. Bir durum makinesi değerlendirilirken bu yüzden tek bir
sayı yetmez; iki sayı yan yana yazılır.

#### Koruma Koşulu Bedeli Kısar

Gösterimin bu duruma karşı bir aracı var: **koruma koşulu**. Bir geçişe, ancak sağlandığında
alınabileceği bir koşul yazılır. İki yeni geçişe iki koruma koşulu ekleyelim (**DD11**): yeniden
planlama ancak planlı durumuna girildiğinden beri en az bir işleme olduysa, iptal ancak hiç işleme
yapılmadıysa alınabilsin.

Sonuç tabloda: 14 simge, eksik kabul yine **0**, fazla kabul 26'dan **4**'e iniyor. İki simge
karşılığında yirmi iki yanlış dizi kapandı.

Kalan dördün ikisi zaten baştan vardı — stok ayrılınca doğrudan iptal ve planlamadan sonra hiç
işlemeden bitirme. Yani iki geçiş ve iki koruma koşulunun getirdiği net fazla kabul **2**'dir ve
bu ikisi de yeniden planladıktan sonra hiç işlemeden bitirme durumudur. Koruma koşulu bedeli
sıfırlamıyor, kısıyor.

Kısmanın kendi bedeli de var. Koruma koşulu bir metindir; durum çizgesinin yapısında değil, geçişin
üzerinde bir cümle olarak durur. Makinenin yapısı onu sınamaz — sınayan şey, koşulu okuyup
gerçekleştiren koddur. Gösterim iki simge daha yazdı ama sınanabilirliği çizgeden metne taşıdı ve
metin olarak yazılan bir kısıt yanlış olabilir. Nitekim burada da öyle: yazılan koşul yeniden
planlamadan sonra doğrudan bitirmeyi engellemiyor.

#### Geçmişi Metne Değil Duruma Yazmak

Koruma koşulunun yaptığı iş aslında **geçmişi hatırlamaktır**: "planlı durumuna girdiğimden beri
işleme oldu mu" sorusu, durumun taşımadığı bir bilgiyi soruyor. Bu bilgiyi taşımanın ikinci bir
yolu var — onu bir duruma çevirmek.

Planlı durumu ikiye bölünüyor (**DD12**): planlanmış ama henüz işlenmemiş iş için **planlı**,
işleme başlanmış iş için **işlenmiş**. İptal yalnız planlı durumundan, bitirme yalnız işlenmiş
durumundan alınabiliyor; yeniden planlama işlenmiş durumundan planlı durumuna dönüyor. Sonuç beş
durum ve dokuz geçiş, yani **14 simge** — koruma koşullu makineyle tam olarak aynı sayı.

Ölçüm iki yerde ondan iyi çıkıyor. Eksik kabul yine 0, fazla kabul **4 yerine 3**. Üstelik kalan
üçün biri zaten baştan vardı ve koruma koşullu makinenin kapatamadığı iki dizi — yeniden planlayıp
hiç işlemeden bitirmek — burada yapısal olarak kapalı: planlı durumunda `bitir` geçişi yoktur.
Buna karşılık bölünmüş makine yeniden planladıktan sonra iptali kabul ediyor ve bu iki dizi
atölyede olmuyor.

Asıl fark sayıda değil, kısıtın nerede durduğundadır. Bölünmüş makinede kural **çizgenin
kendisindedir**: bir geçişin olup olmadığı bakılarak görülür. Koruma koşullu makinede kural bir
cümledir ve cümlenin doğru okunup doğru gerçekleştirildiği çizgeye bakarak anlaşılamaz. Aynı 14
simge, iki farklı yerde duruyor; biri gösterimin sınanabilir kısmında, öteki sınanamaz kısmında.

#### Sayı Pencereye Bağlıdır

Orta alttaki tablo bir uyarı taşıyor. Bir makinenin dili çoğunlukla sonsuzdur — planlı durumundaki
`isle` döngüsü her uzunlukta dizi üretir. Bu yüzden "fazla kabul 26" mutlak bir sayı değil, **en
çok altı olaylık diziler** penceresinde sayılmış bir değerdir.

Pencere büyüdükçe dört makinenin dördü de büyüyor, ama farklı hızlarda. Altı geçişli taban makine
4'ten 8'e giden pencerede 2, 2, 2, 3, 4 veriyor; sekiz geçişli makine 5, 12, 26, 58, **122**;
koruma koşullu makine 2, 3, 4, 9, 17; bölünmüş durumlu makine 1, 2, 3, 8, 16. Taban makine dar
kaldığı için yavaş büyüyor, onarılmış makine her uzunlukta yeni yollar açtığı için hızlı.

Bunun karşılaştırma için anlamı şudur: iki makinenin fazla kabulü ancak **aynı pencerede**
karşılaştırılabilir ve pencere yazılmadan verilen bir fazla kabul sayısı okunamaz. Kapsam oranının
paydası neyse, fazla kabulün penceresi odur.

#### Özet

- Durum makinesi iki yönde birden yanılabilir: **eksik kabul** sistemde olanı reddetmek, **fazla
  kabul** sistemde olmayanı kabul etmektir. İki sayı ayrı ayrı yazılır; dil ile gerçek dizi
  sayısının eşit olması makinenin doğru olduğunu göstermez.
- Dört durumlu, altı geçişli makine **10 simge** ile atölyenin 6 gerçek dizisinden **2'sini
  reddediyor** (yeniden planlama ve işlemeden önce iptal) ve sistemde olmayan **2 diziyi kabul
  ediyor**.
- İki geçiş eklemek eksik kabulü **0**'a indiriyor ama fazla kabulü 2'den **26**'ya çıkarıyor:
  on üç kat. Durum makinesi geçmişi tutmadığı için eklenen geçiş, durumun ulaşıldığı bütün
  yollardan sonra açılır.
- **Eksik kabulü kapatmanın bedeli fazla kabuldür.** Bir gösterim iki hatayı birden sıfırlayamaz;
  sıfırlayabilseydi izdüşüm değil sistemin kendisi olurdu.
- İki koruma koşulu 14 simgeyle fazla kabulü 26'dan **4**'e indiriyor; planlı durumunu ikiye bölmek
  aynı 14 simgeyle **3**'e indiriyor. Fark sayıda değil, kısıtın çizgede mi metinde mi durduğundadır.
- Fazla kabul sayısı uzunluk penceresine bağlıdır: pencere 4'ten 8'e çıkınca taban makine 2'den
  4'e, onarılmış makine 5'ten **122**'ye, koruma koşullu makine 2'den 17'ye, bölünmüş makine 1'den
  16'ya gidiyor. Pencere yazılmadan verilen fazla kabul sayısı okunamaz.

#### Sonraki Adım

Bu konu davranışın dört gösterimini saydı. Kullanım senaryosu iç adımları bilerek attı ve 128
sistemi ayırt edemedi; sıra gösterimi 24 izin birini gösterdi; etkinlik gösterimi 168 tam sıralamayı
birden kabul etti; durum makinesi iki yönde birden yanıldı. Dördünün ortak yanı, her birinin
sistemin **zaman içindeki** yanını göstermeye çalışmasıdır.

Sonraki konu zamanı hiç konuşmuyor. Bir sistemin **neyi sakladığını** soruyor: hangi varlıklar var,
hangi öznitelikleri taşıyorlar, aralarında hangi ilişkiler kurulu. Kavramsal model bakım atölyesi
için **26 olgu** söylüyor: 5 varlık, 12 öznitelik, 4 ilişki, 5 kısıt. Bu 26 olgunun bir şemaya
inerken nasıl davrandığı, davranış gösterimlerinden farklı bir kayıp türü ortaya çıkarır — model
yalnız unutmuyor, aynı zamanda **uyduruyor** ve ikisi ayrı ayrı sayılıyor.

## Veri Modelleme

Varlık–ilişki modelinin söylediği olgular, üç soyutlama düzeyi arasındaki geçişte düşen kısıtlar ve fiziksel şemanın modelde hiç yazmayan kararları.

### Varlık–İlişki Modeli

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/varlik-iliski-modeli

Bakım atölyesinin kavramsal modeli 26 olgu söylüyor: 5 varlık, 12 öznitelik, 4 ilişki, 5 kısıt. Kardinalite yazılıp katılım yazılmadığında aynı gösterime 1.048.576 sistem düşüyor.

Önceki ders bir iş emrinin zaman içindeki davranışını dört durum ve altı geçişle gösterdi.
Ölçü, makinenin kabul ettiği dil ile sistemin gerçek izleri arasındaki farktı: iki dizi
reddediliyordu, sistemde olmayan iki dizi kabul ediliyordu ve iki geçiş eklenince
reddedilen sıfıra inerken fazla kabul 2'den 26'ya çıkıyordu. O gösterim sistemin **ne
yaptığını** anlatıyordu.

Bu konu sistemin **ne tuttuğunu** anlatan gösterimi ele alır. Sorusu aynı biçimdedir:
alanın veri yapısını varlık, öznitelik ve ilişki cinsinden yazmak kaç olgu söyler ve kaç
olguyu söylemeden bırakır. İlişkisel model, anahtar çeşitleri, bütünlük kısıtları ve
normalleştirme burada öğretilmez; bunlar Veritabanları müfredatının İlişkisel Kuram
kursunda kuruldu ve tekrarlanmaz. Buradaki tek iş, **düzey değişiminde düşen ve uydurulan
olguyu saymaktır.**

#### Varlık, Öznitelik, İlişki

**Varlık** (entity), alanın kendi başına kimliği olan bir kavramıdır: bir iş emri, bir
usta, bir parça. **Öznitelik** (attribute), bir varlığın taşıdığı tek değerlik bir
olgudur: iş emrinin açılış tarihi, ustanın uzmanlığı. **İlişki** (relationship), iki
varlık arasındaki bağdır ve bir **kardinalite** taşır — hangi tarafın bir, hangi tarafın
çok olduğunu söyleyen etiket.

Varlık terimi burada bir kimlik taşıyıcısını adlandırır; Veritabanları müfredatında geçen
**varlık nesnesi** ise alan katmanındaki bir programlama nesnesidir ve ayrı bir kavramdır.

- **VM1** — Modellenen alan bir bakım atölyesidir ve sistem veridir. Hiçbir modelleme
  aracı, çizim ürünü ya da veri saklama ürünü çağrılmaz; ölçülen şey verinin kendisidir.
- **VM2** — Kavramsal modelin **olgu sayısı**, varlık, öznitelik, ilişki ve kısıt
  sayılarının toplamıdır. Her olgu bir kez sayılır.

```python
"""M01/K06 ortak tanim (kesit): kavramsal varlik-iliski modeli ve olgu sayimi."""
KISITLAR = [
    {"metin": "her is emrinin tek ustasi var",      "arac": "yabanci anahtar"},
    {"metin": "parca kodu benzersiz",               "arac": "benzersizlik"},
    {"metin": "belge yalnizca kendi is emrine ait", "arac": "yabanci anahtar"},
    {"metin": "bir is emri en az bir parca ister",  "arac": None},
    {"metin": "bir usta ayni anda tek tezgahta",    "arac": None},
]
KAVRAMSAL = {
    "varliklar": ["IsEmri", "Usta", "Parca", "Tezgah", "Belge"],
    "oznitelikler": {"IsEmri": ["no", "acilis", "durum"], "Usta": ["ad", "uzmanlik"],
                     "Parca": ["kod", "ad", "birim"], "Tezgah": ["kod", "tur"],
                     "Belge": ["tur", "tarih"]},
    "iliskiler": [("IsEmri", "Usta", "N:1"), ("IsEmri", "Parca", "N:M"),
                  ("Usta", "Tezgah", "N:M"), ("IsEmri", "Belge", "1:N")],
    "kisitlar": KISITLAR,
}


def olgular(model):
    v = len(model["varliklar"])
    o = sum(len(a) for a in model["oznitelikler"].values())
    i = len(model["iliskiler"])
    k = len(model["kisitlar"])
    return {"varlik": v, "oznitelik": o, "iliski": i, "kisit": k, "toplam": v + o + i + k}


print("kavramsal model:", olgular(KAVRAMSAL))
print()
print("varlik    oznitelik  girdigi iliskiler")
for ad in KAVRAMSAL["varliklar"]:
    bag = [f"{a}-{b} {c}" for a, b, c in KAVRAMSAL["iliskiler"] if ad in (a, b)]
    print(f"{ad:8s}  {len(KAVRAMSAL['oznitelikler'][ad]):9d}  {', '.join(bag)}")
```

```
kavramsal model: {'varlik': 5, 'oznitelik': 12, 'iliski': 4, 'kisit': 5, 'toplam': 26}

varlik    oznitelik  girdigi iliskiler
IsEmri            3  IsEmri-Usta N:1, IsEmri-Parca N:M, IsEmri-Belge 1:N
Usta              2  IsEmri-Usta N:1, Usta-Tezgah N:M
Parca             3  IsEmri-Parca N:M
Tezgah            2  Usta-Tezgah N:M
Belge             2  IsEmri-Belge 1:N
```

**Sistem:** bakım atölyesinin kavramsal modeli **26 olgu** söylüyor. **Gösterim:** aynı 26
öge diyagrama yazılıyor — beş varlık kutusu, on iki öznitelik, dört ilişki çizgisi ve beş
kısıt notu. Bire bir bir eşleşme gibi görünüyor. **Bedel** ise bu eşleşmenin dışında kalan
şeydir ve bir sonraki bölümde sayılacak.

#### Kardinalite Ne Söyler, Çokluk Ne Ekler

Bu kursta iki ayrı terim, iki ayrı bilgiyi taşır ve karıştırılmaları ölçümü bozar.
**Kardinalite** (cardinality) varlık–ilişki gösteriminin etiketidir ve ilişkinin
**bütününe** yazılır: `N:1`, `1:N`, `N:M`. Söylediği şey her iki uçtaki **üst sınırdır** —
hangi tarafta en çok bir tane, hangi tarafta sınırsız sayıda olabileceği. **Çokluk**
(multiplicity) ise yapı gösteriminin etiketidir ve ilişkinin **her ucuna ayrı ayrı**
yazılır; biçimi `alt..üst` aralığıdır.

Aradaki fark tam olarak şudur: kardinalite üst sınırları söyler, çokluk üst sınırların
yanına **alt sınırı** da koyar. Alt sınır o ucun **katılımının** zorunlu mu isteğe bağlı mı
olduğudur. `N:1` etiketi bir iş emrinin en çok bir ustası olduğunu söyler; bir iş emrinin
**ustasız açılıp açılamayacağını** söylemez.

- **VM3** — Her ilişkinin iki ucu vardır ve her uç bağımsız olarak zorunlu ya da isteğe
  bağlı katılır. Kardinalite yalnız üst sınırları taşır.
- **VM4** — Her öznitelik bağımsız olarak zorunlu ya da isteğe bağlıdır. Katılım uzayı ile
  zorunluluk uzayı birbirinden bağımsızdır; toplam sayı ikisinin çarpımıdır.
- **VM5** — Sayım tamdır, örneklem değildir; aradaki bir sistemlik fark bile anlamlıdır.

```python
"""Kardinalite ne yaziyor , cokluk ne ekliyor: ayni gosterime kac sistem dusuyor."""
from itertools import product

ILISKILER = [("IsEmri", "Usta", "N:1"), ("IsEmri", "Parca", "N:M"),
             ("Usta", "Tezgah", "N:M"), ("IsEmri", "Belge", "1:N")]
UST = {"N:1": ("*", "1"), "1:N": ("1", "*"), "N:M": ("*", "*"), "1:1": ("1", "1")}
OZNITELIK = 12          # kavramsal modelin 12 ozniteligi


def er_gosterimi(sistem, cokluk=False):
    """sistem: (kaynak , hedef , kardinalite , alt_kaynak , alt_hedef) listesi."""
    yazi = []
    for kaynak, hedef, kard, alt_k, alt_h in sistem:
        s = {"kaynak": kaynak, "hedef": hedef, "kardinalite": kard}
        if cokluk:
            ust_k, ust_h = UST[kard]
            s["cokluk_kaynak"] = f"{alt_k}..{ust_k}"
            s["cokluk_hedef"] = f"{alt_h}..{ust_h}"
        yazi.append(s)
    return yazi


def ayni_gosterime_dusen(sistem, cokluk=False):
    """Tam sayim: kac ayri katilim secimi ayni gosterimi uretiyor."""
    hedef = er_gosterimi(sistem, cokluk)
    sayi = 0
    for secim in product((0, 1), repeat=2 * len(sistem)):
        aday = [(k, h, kd, secim[2 * i], secim[2 * i + 1])
                for i, (k, h, kd, _, _) in enumerate(sistem)]
        if er_gosterimi(aday, cokluk) == hedef:
            sayi += 1
    return sayi


SISTEM = [(k, h, kd, 1, 1) for k, h, kd in ILISKILER]
print("iliski ucu:", 2 * len(SISTEM), "| yazilmayan katilim biti:", 2 * len(SISTEM))
print("kardinalite yazili , cokluk yazili degil ->",
      ayni_gosterime_dusen(SISTEM, cokluk=False), "sistem")
print("cokluk yazili                            ->",
      ayni_gosterime_dusen(SISTEM, cokluk=True), "sistem")
print()
oznitelik_uzayi = sum(1 for _ in product((0, 1), repeat=OZNITELIK))
print("oznitelik zorunlulugu yazili degil ->", oznitelik_uzayi, "sistem")
print("iki uzay bagimsiz , carpim          ->",
      ayni_gosterime_dusen(SISTEM) * oznitelik_uzayi, "sistem")
print()
print("yazili oge  ne eklendi                      ayni gosterime dusen")
print(f"        26  varlik+oznitelik+iliski+kisit  "
      f"{ayni_gosterime_dusen(SISTEM) * oznitelik_uzayi:20d}")
print(f"        34  + 8 katilim isareti            "
      f"{ayni_gosterime_dusen(SISTEM, True) * oznitelik_uzayi:20d}")
print(f"        46  + 12 zorunluluk isareti        {1:20d}")
```

```
iliski ucu: 8 | yazilmayan katilim biti: 8
kardinalite yazili , cokluk yazili degil -> 256 sistem
cokluk yazili                            -> 1 sistem

oznitelik zorunlulugu yazili degil -> 4096 sistem
iki uzay bagimsiz , carpim          -> 1048576 sistem

yazili oge  ne eklendi                      ayni gosterime dusen
        26  varlik+oznitelik+iliski+kisit               1048576
        34  + 8 katilim isareti                            4096
        46  + 12 zorunluluk isareti                           1
```

**Bedel budur.** Yirmi altı olguyla yazılmış kavramsal model, kendisine benzeyen
**1.048.576 ayrı sistemden ayırt edilemiyor**. Bu sayı iki bağımsız kaynaktan geliyor:
dört ilişkinin sekiz ucundaki katılım bilgisi (256) ve on iki özniteliğin zorunluluk
bilgisi (4096). İkisi de gösterimde yazılı değil, ama ikisi de sistemde belirli.

Yapısal Diyagramlar konusunda ölçülen "her simge bir bit" ilişkisi burada da işliyor;
tekrarlanmaz. Bu dersin eklediği şey **hangi bitlerin** düştüğüdür ve bu seçim rastgele
değildir: varlık–ilişki gösterimi tarihsel olarak kardinaliteyi taşımak için tasarlandı,
katılımı taşımak için değil. Düşen yirmi bit yok olmuyor — birazdan görüleceği gibi
mantıksal ve fiziksel düzeylerde **başka birinin vereceği karara** dönüşüyor. Özniteliğin
zorunlu olup olmadığı, fiziksel şemada "boş geçilebilirlik" adıyla yeniden karşımıza
çıkacak ve o düzeyde bir yanıt vermek **zorunlu** olacak.

#### Varlık mı, Öznitelik mi

Modelin en sık verilen kararı, bir olgunun kendi varlığı mı yoksa başka bir varlığın
özniteliği mi olacağıdır. Bu karar bir üslup tercihi değildir; **modelin söyleyebildiği
olgu sayısını ve gösterebildiği durum sayısını birlikte değiştirir.**

- **VM6** — Bir iş emrine bağlanabilecek belge havuzu dört adaydır. Varlık biçimi bu
  havuzun herhangi bir alt kümesini gösterebilir; öznitelik biçimi tek değer taşır, yani
  en çok bir öge.
- **VM7** — `birim` özniteliği kendi varlığına yükseltildiğinde değer kümesi kapanır ve
  "birim yalnızca tanımlı kümeden" kısıtı söylenebilir hâle gelir.

```python
"""Ayni alan , iki ayri varlik-oznitelik karari: kac olgu degisiyor , kac durum kayboluyor."""
from itertools import combinations

KAVRAMSAL = {
    "varliklar": ["IsEmri", "Usta", "Parca", "Tezgah", "Belge"],
    "oznitelikler": {"IsEmri": ["no", "acilis", "durum"], "Usta": ["ad", "uzmanlik"],
                     "Parca": ["kod", "ad", "birim"], "Tezgah": ["kod", "tur"],
                     "Belge": ["tur", "tarih"]},
    "iliskiler": [("IsEmri", "Usta", "N:1"), ("IsEmri", "Parca", "N:M"),
                  ("Usta", "Tezgah", "N:M"), ("IsEmri", "Belge", "1:N")],
    "kisit": 5,
}
INDIRGENMIS = {                      # Belge varlik olmaktan cikip oznitelige iniyor
    "varliklar": ["IsEmri", "Usta", "Parca", "Tezgah"],
    "oznitelikler": {"IsEmri": ["no", "acilis", "durum", "belge"], "Usta": ["ad", "uzmanlik"],
                     "Parca": ["kod", "ad", "birim"], "Tezgah": ["kod", "tur"]},
    "iliskiler": [("IsEmri", "Usta", "N:1"), ("IsEmri", "Parca", "N:M"),
                  ("Usta", "Tezgah", "N:M")],
    "kisit": 4,                      # "belge yalnizca kendi is emrine ait" soylenemiyor
}
YUKSELTILMIS = {                     # birim oznitelik olmaktan cikip varliga yukseliyor
    "varliklar": ["IsEmri", "Usta", "Parca", "Tezgah", "Belge", "Birim"],
    "oznitelikler": {"IsEmri": ["no", "acilis", "durum"], "Usta": ["ad", "uzmanlik"],
                     "Parca": ["kod", "ad"], "Tezgah": ["kod", "tur"],
                     "Belge": ["tur", "tarih"], "Birim": ["ad"]},
    "iliskiler": [("IsEmri", "Usta", "N:1"), ("IsEmri", "Parca", "N:M"),
                  ("Usta", "Tezgah", "N:M"), ("IsEmri", "Belge", "1:N"),
                  ("Parca", "Birim", "N:1")],
    "kisit": 6,                      # "birim yalnizca tanimli kumeden" soylenebiliyor
}


def olgu(model):
    return (len(model["varliklar"]) + sum(len(a) for a in model["oznitelikler"].values())
            + len(model["iliskiler"]) + model["kisit"])


print("karar               varlik  oznitelik  iliski  kisit  olgu")
for ad, m in (("ortak tanim", KAVRAMSAL), ("Belge oznitelige", INDIRGENMIS),
              ("birim varliga", YUKSELTILMIS)):
    print(f"{ad:18s}  {len(m['varliklar']):6d}  "
          f"{sum(len(a) for a in m['oznitelikler'].values()):9d}  "
          f"{len(m['iliskiler']):6d}  {m['kisit']:5d}  {olgu(m):4d}")
print()
ADAY = ("kabul formu", "ariza raporu", "test kaydi", "teslim tutanagi")
tum_durum = [k for n in range(len(ADAY) + 1) for k in combinations(ADAY, n)]
tek_degerli = [d for d in tum_durum if len(d) <= 1]
print("bir is emrinin belge durumu -> toplam", len(tum_durum),
      "| varlik bicimi gosteriyor:", len(tum_durum),
      "| oznitelik bicimi:", len(tek_degerli))
print("gosterilemez hale gelen durum:", len(tum_durum) - len(tek_degerli))
```

```
karar               varlik  oznitelik  iliski  kisit  olgu
ortak tanim              5         12       4      5    26
Belge oznitelige         4         11       3      4    22
birim varliga            6         12       5      6    29

bir is emrinin belge durumu -> toplam 16 | varlik bicimi gosteriyor: 16 | oznitelik bicimi: 5
gosterilemez hale gelen durum: 11
```

Belgeyi özniteliğe indirmek modeli **26 olgudan 22 olguya** düşürüyor: bir varlık, bir
öznitelik, bir ilişki ve bir kısıt kayboluyor. Kaybolan kısıt "belge yalnızca kendi iş
emrine ait" kısıtıdır ve bunun sebebi yapısaldır — belge artık ayrı bir şey olmadığı için
kime ait olduğu sorusu sorulamaz hâle gelmiştir. Daha ağır olan sonuç ikinci satırdadır:
bir iş emrinin belge durumu için **16 olası durumun 11'i** artık gösterilemiyor, çünkü tek
değerlik bir öznitelik ancak boş kalabilir ya da tek bir belge taşıyabilir.

Ters yön de ücretsiz değildir. `birim` özniteliğini kendi varlığına yükseltmek olgu
sayısını **26'dan 29'a** çıkarıyor: bir varlık, bir ilişki ve bir kısıt ekleniyor. Karşılığı
somuttur — birim değerlerinin kümesi kapanır, yani modelde tanımlı olmayan bir birim
yazılamaz. Yükseltmenin bedeli üç olguluk ek bakım yüküdür; indirgemenin bedeli dört
olguluk kayıp ve on bir gösterilemez durumdur. **İkisi de bedelsiz değildir ve ikisi de
sayılabilir.**

Buradan bir karar ölçütü çıkar ve ölçüt bir zevk meselesi değil, üç soruya verilen
yanıttır. Bir olgunun kendi varlığı olmayı hak edip etmediği şuradan bakılarak anlaşılır:
kendi öznitelikleri var mı, kendi başına başvurulması gerekiyor mu ve bir üst varlığa
**birden çok** kez bağlanabiliyor mu. Belge üçünde de olumlu yanıt veriyor — türü ve
tarihi var, ait olduğu iş emri sorulabiliyor ve bir iş emri birden çok belge taşıyor.
`birim` ise yalnız üçüncüde olumsuz: bir parçanın tek birimi vardır. Bu yüzden birimi
yükseltmek gösterilebilen durum sayısını hiç değiştirmiyor, yalnız bir kısıt kazandırıyor
ve üç olgu ekliyor. **Karar, kazanılan kısıt ile eklenen olgunun karşılaştırılmasıdır.**

#### Kısıtlar da Birer Olgudur

Yirmi altı olgunun beşi kısıttır ve bunlar diyagramın çizgilerinde değil, yanına yazılan
notlarda durur. Bu ayrım gösterimin en zayıf yeridir: kutu ile ok bir biçim dilinin
parçasıdır ve mekanik olarak işlenir, not ise serbest metindir. Beş kısıtın üçü ilişkisel
yapının araçlarıyla yazılabilir, ikisi yazılamaz — hangisinin hangisi olduğu ve
yazılamamanın **yapısal sebebi** sonraki dersin konusudur.

İki kısıtın biçimine şimdiden bakmak, farkın nereden geldiğini sezdirir. "Parça kodu
benzersiz" tek bir sütuna bakar ve iki satırı karşılaştırır. "Bir iş emri en az bir parça
ister" ise tek bir satıra bakarak yanıtlanamaz; bir iş emrine bağlı **satırların
sayısını** sorar. Üçüncüsü daha da uzaktır: "bir usta aynı anda tek tezgahta" iki satırın
zaman aralıklarının **kesişip kesişmediğini** sorar ve kavramsal modelde zaman diye bir
öznitelik yoktur. Üç kısıt üç ayrı türden yüklemdir; birinin yazılabilmesi ötekinin de
yazılabileceği anlamına gelmez.

Şimdilik kaydedilmesi gereken şudur: bir kısıt, gösterimde bir not olduğu sürece
**modelin bir olgusudur**; ama gösterimden şemaya inerken not taşınabilir bir yapıya
çevrilemezse, kimse onu silmeden ortadan kalkar.

#### Özet

- Kavramsal model bakım atölyesi için 26 olgu söylüyor: 5 varlık, 12 öznitelik, 4 ilişki,
  5 kısıt. Olgu sayımı bu konunun ölçü birimidir.
- Kardinalite ilişkinin bütününe yazılır ve yalnız üst sınırları söyler; çokluk her uca
  ayrı yazılır ve alt sınırı, yani katılımı da taşır. Aradaki fark ilişki başına iki bittir.
- Kardinalite yazılıp katılım ve öznitelik zorunluluğu yazılmadığında aynı gösterime
  1.048.576 sistem düşüyor: 256 katılım seçiminin 4096 zorunluluk seçimiyle çarpımı.
  Sekiz katılım işareti eklendiğinde 4096, on iki zorunluluk işareti de eklendiğinde 1 kalıyor.
- Bir olguyu varlık yerine öznitelik kurmak modeli 26 olgudan 22'ye indiriyor ve bir iş
  emrinin 16 belge durumundan 11'ini gösterilemez yapıyor; ters yönde yükseltmek olguyu
  29'a çıkarıp bir kısıtı söylenebilir hâle getiriyor.
- Kısıtlar da modelin olgusudur, ama diyagramda not olarak durdukları için taşınmaları
  biçim diline değil, sonraki düzeyin araçlarına bağlıdır.

#### Sonraki Adım

Bu ders modeli tek bir düzeyde tuttu ve o düzeyin neyi söylemediğini saydı. Sıradaki ders
düzeyi değiştirir: aynı 26 olgu ilişkisel bir yapıya çevrilirken iki N:M ilişkisi ara
tabloya açılır, tablo sayısı 5'ten 7'ye çıkar ve beş kısıttan ikisi düşer. Düşen iki
kısıtın neden düştüğü tahmin edilmez; hangi yüklemi hangi aracın yazamadığı tam sayımla
gösterilir.

### Kavramsal, Mantıksal ve Fiziksel Model

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/kavramsal-mantiksal-ve-fiziksel-model

Aynı 26 olgu ilişkisel yapıya çevrildiğinde tablo 5'ten 7'ye çıkıyor, 13 alan modelde adı hiç geçmeden ortaya çıkıyor ve 5 kısıttan 2'si düşüyor; düşen ikisinin yapısal sebebi tam sayımla gösteriliyor.

Önceki ders kavramsal modeli tek bir düzeyde tuttu ve o düzeyin söylemediklerini saydı:
yirmi altı olgu yazılıyordu, ama katılım ve öznitelik zorunluluğu yazılmadığı için aynı
gösterime bir milyondan fazla sistem düşüyordu. Bu ders düzeyi değiştirir.

Sorusu şudur: aynı yirmi altı olgu ilişkisel bir yapıya çevrildiğinde **ne kadarı olduğu
gibi taşınıyor, ne kadarı düşüyor ve modelde hiç yazmayan ne kadar şey ortaya çıkıyor.**
Üç sayı yine yan yana duracak, ama bu kez bedelin iki ayrı bileşeni var: **düşen kısıt** ve
**uydurulan alan.** İkisi ayrı ayrı sayılır, çünkü biri kayıp, öteki eklemedir.

#### Üç Düzey

**Kavramsal model** alanın olgularını taşır ve hiçbir saklama kararı içermez: varlık,
öznitelik, ilişki, kısıt. **Mantıksal model** bu olguları belirli bir veri modelinin
yapılarına çevirir; burada o yapı ilişkiseldir, yani tablo, alan, anahtar ve yabancı
anahtar. **Fiziksel model** aynı yapıyı saklanabilir hâle getirir: tip, uzunluk, boş
geçilebilirlik, dizin. Üç düzeyin hiçbiri bir ürün adı içermez; fiziksel düzey bile
**karar türlerini** taşır, ürünü değil.

- **VM8** — Üç düzey birbirinin üstüne oturur ve aşağı inildikçe karar sayısı artar. Bir
  düzeyin yazmadığı her şey aşağıdaki düzeyde ya türetilir ya da uydurulur.
- **VM9** — Mantıksal geçiş kuralı sabittir: her varlık bir tabloya çevrilir, her N:M
  ilişkisi bir **bağlantı bağıntısına** açılır, her N:1 ve 1:N ilişkisi çok tarafına konan bir
  yabancı anahtar alanına döner ve her tabloya bir birincil anahtar alanı eklenir.
- **VM10** — Bir kısıt, ilişkisel yapının anahtar, benzersizlik ve yabancı anahtar
  araçlarından biriyle yazılabiliyorsa **taşınır**; yazılamıyorsa **düşer**.

Anahtar çeşitleri, yabancı anahtarın silme ve güncelleme eylemleri, bütünlük kısıtları ve
normalleştirme bu derste öğretilmez; hepsi Veritabanları müfredatının İlişkisel Kuram
kursunda kuruldu. Burada o araçlar yalnız **birer taşıma aracı** olarak kullanılıyor ve
sorulan tek şey, hangi olgunun taşınıp hangisinin taşınamadığıdır.

```python
"""M01/K06 ortak tanim (kesit): kavramsaldan mantiksala gecis ve gecisin bilancosu."""
KISITLAR = [
    {"metin": "her is emrinin tek ustasi var",      "arac": "yabanci anahtar"},
    {"metin": "parca kodu benzersiz",               "arac": "benzersizlik"},
    {"metin": "belge yalnizca kendi is emrine ait", "arac": "yabanci anahtar"},
    {"metin": "bir is emri en az bir parca ister",  "arac": None},
    {"metin": "bir usta ayni anda tek tezgahta",    "arac": None},
]
KAVRAMSAL = {
    "varliklar": ["IsEmri", "Usta", "Parca", "Tezgah", "Belge"],
    "oznitelikler": {"IsEmri": ["no", "acilis", "durum"], "Usta": ["ad", "uzmanlik"],
                     "Parca": ["kod", "ad", "birim"], "Tezgah": ["kod", "tur"],
                     "Belge": ["tur", "tarih"]},
    "iliskiler": [("IsEmri", "Usta", "N:1"), ("IsEmri", "Parca", "N:M"),
                  ("Usta", "Tezgah", "N:M"), ("IsEmri", "Belge", "1:N")],
    "kisitlar": KISITLAR,
}


def mantiksal(kavramsal):
    """N:M iliskiler bağlantı bağıntısına acilir; kisitlar tasinabilirligine gore ayrilir."""
    tablolar = {}
    for v in kavramsal["varliklar"]:
        tablolar[v] = ["anahtar"] + list(kavramsal["oznitelikler"][v])
    ara = []
    for a, b, c in kavramsal["iliskiler"]:
        if c == "N:M":
            ad = f"{a}_{b}"
            tablolar[ad] = ["anahtar", f"{a}_anahtar", f"{b}_anahtar"]
            ara.append(ad)
        elif c == "N:1":
            tablolar[a].append(f"{b}_anahtar")
        else:
            tablolar[b].append(f"{a}_anahtar")
    tasinan = [k for k in kavramsal["kisitlar"] if k["arac"]]
    dusen = [k for k in kavramsal["kisitlar"] if not k["arac"]]
    return {"tablolar": tablolar, "baglanti_bagintisi": ara, "tasinan": tasinan, "dusen": dusen}


M = mantiksal(KAVRAMSAL)
print("tablo           alan  alanlar")
for ad, alanlar in M["tablolar"].items():
    print(f"{ad:14s}  {len(alanlar):4d}  {', '.join(alanlar)}")
print()
alan = sum(len(v) for v in M["tablolar"].values())
oznitelik = sum(len(a) for a in KAVRAMSAL["oznitelikler"].values())
anahtar = sum(v.count("anahtar") for v in M["tablolar"].values())
yabanci = sum(1 for v in M["tablolar"].values() for a in v if a.endswith("_anahtar"))
print("varlik", len(KAVRAMSAL["varliklar"]), "-> tablo", len(M["tablolar"]),
      "( bağlantı bağıntısı:", ", ".join(M["baglanti_bagintisi"]), ")")
print("oznitelik", oznitelik, "-> alan", alan,
      "| kavramsal modelde adi hic gecmeyen alan:", alan - oznitelik)
print("  ", anahtar, "birincil anahtar +", yabanci, "yabanci anahtar =", anahtar + yabanci)
print("kisit", len(KISITLAR), "-> tasinan", len(M["tasinan"]), "| dusen", len(M["dusen"]))
for k in M["dusen"]:
    print("   DUSEN:", k["metin"])
```

```
tablo           alan  alanlar
IsEmri             5  anahtar, no, acilis, durum, Usta_anahtar
Usta               3  anahtar, ad, uzmanlik
Parca              4  anahtar, kod, ad, birim
Tezgah             3  anahtar, kod, tur
Belge              4  anahtar, tur, tarih, IsEmri_anahtar
IsEmri_Parca       3  anahtar, IsEmri_anahtar, Parca_anahtar
Usta_Tezgah        3  anahtar, Usta_anahtar, Tezgah_anahtar

varlik 5 -> tablo 7 ( bağlantı bağıntısı: IsEmri_Parca, Usta_Tezgah )
oznitelik 12 -> alan 25 | kavramsal modelde adi hic gecmeyen alan: 13
   7 birincil anahtar + 6 yabanci anahtar = 13
kisit 5 -> tasinan 3 | dusen 2
   DUSEN: bir is emri en az bir parca ister
   DUSEN: bir usta ayni anda tek tezgahta
```

**Sistem:** 26 olgu. **Gösterim:** 7 tablo ve 25 alan. **Bedel:** 2 düşen kısıt ve
**13 uydurulan alan.** Üçüncü sayı en az bakılanıdır ama en açıklayıcı olanıdır: mantıksal
model, kavramsal modelin adını hiç anmadığı **on üç alan** taşıyor. Yedisi tabloların
birincil anahtarı, altısı ilişkileri kuran yabancı anahtar. Bunların hiçbiri alanın bir
olgusu değildir — atölyede kimse iş emrinin "anahtarından" söz etmez. Bunlar **ilişkisel
yapının kendi kayıt tutma gereçleridir** ve modelden değil, düzeyden gelirler.

Tablo sayısının 5'ten 7'ye çıkması da aynı yerden gelir. İlişkisel yapı bir N:M ilişkisini
doğrudan tutamaz; iki tarafın anahtarlarını taşıyan bir **bağlantı bağıntısı** ister. İki N:M
ilişkisi olduğu için iki bağlantı bağıntısı doğar ve alan sayısı altı artar. Bu, bir tasarım tercihi
değildir; ilişkisel yapının **ifade sınırının** doğrudan sonucudur.

#### Düşen İki Kısıt Neden Düşüyor

Beş kısıttan üçü taşınıyor: "her iş emrinin tek ustası var" bir yabancı anahtarla, "parça
kodu benzersiz" bir benzersizlik kısıtıyla, "belge yalnızca kendi iş emrine ait" yine bir
yabancı anahtarla yazılabiliyor. Kalan ikisi düşüyor ve düşme sebebi unutkanlık değil,
**yüklemin türüdür.**

Anahtar, benzersizlik ve yabancı anahtar araçlarının üçü de aynı biçimdedir: bir **tek
satıra** bakarlar ya da iki satırın belirli alanlarının **eşitliğini** karşılaştırırlar.
Düşen iki kısıt bu iki biçimin dışındadır. "Bir iş emri en az bir parça ister" tek satıra
bakarak yanıtlanamaz; bir iş emrine bağlı satırların **sayısına** bakar ve sayı için bir
**alt sınır** ister. "Bir usta aynı anda tek tezgahta" ise iki satırın zaman
aralıklarının **kesişimini** sorar, oysa benzersizlik yalnız **eşitliği** görür.

- **VM11** — Fazla kabul sayımında iki iş emri, iki parça, iki usta ve iki tezgah alınır.
  Örnek uzayı, bağlantı bağıntısının alabileceği bütün satır alt kümeleridir; sayım tamdır.
- **VM12** — Örnekler tek bir andaki durumu gösterir; tabloda zaman alanı yoktur.

```python
"""Dusen iki kisit neden dusuyor: iliskisel arac hangi yuklemi yazamiyor."""
from itertools import combinations, product

IS_EMRI, PARCA = ("o1", "o2"), ("p1", "p2")
USTA, TEZGAH = ("u1", "u2"), ("t1", "t2")


def tum_ornekler(sol, sag):
    """Ara tablonun alabilecegi butun degerler: satir kumesinin butun alt kumeleri."""
    satir = list(product(sol, sag))
    return [frozenset(k) for n in range(len(satir) + 1) for k in combinations(satir, n)]


def araclar_kabul(ornek, sol, sag):
    """Bilesik birincil anahtar satir yinelemesini , yabanci anahtar bos basvuruyu keser.
    Ikisi de TEK SATIRA bakan yuklemlerdir."""
    return all(a in sol and b in sag for a, b in ornek)


def en_az_bir_parca(ornek, sol):
    """Grup BUYUKLUGUNE bakan yuklem: her is emrinin en az bir satiri olmali."""
    return all(any(kaynak == x for kaynak, _ in ornek) for x in sol)


def tek_tezgah(ornek):
    """Yine grup buyuklugu: bir usta en cok bir satirda gorunmeli."""
    kullanan = [a for a, _ in ornek]
    return len(kullanan) == len(set(kullanan))


toplam_arac, toplam_dogru = 1, 1
for ad, sol, sag, gercek in (("IsEmri_Parca", IS_EMRI, PARCA,
                              lambda o: en_az_bir_parca(o, IS_EMRI)),
                             ("Usta_Tezgah", USTA, TEZGAH, tek_tezgah)):
    hepsi = tum_ornekler(sol, sag)
    arac = [o for o in hepsi if araclar_kabul(o, sol, sag)]
    dogru = [o for o in arac if gercek(o)]
    toplam_arac *= len(arac)
    toplam_dogru *= len(dogru)
    print(f"{ad:13s} olasi ornek {len(hepsi):3d} | arac kabul {len(arac):3d}"
          f" | sistemde dogru {len(dogru):3d} | fazla kabul {len(arac) - len(dogru):3d}")
    print(f"{'':13s} en kucuk fazla kabul: "
          f"{sorted(sorted(o) for o in arac if not gercek(o))[0]}")
print()
print("iki bağlantı bağıntısı birlikte: arac kabul", toplam_arac, "| sistemde dogru", toplam_dogru,
      "| fazla kabul", toplam_arac - toplam_dogru)
print()


def ortusuyor(x, y):
    return x[1] < y[2] and y[1] < x[2]


SATIR = [("u1", 0, 4), ("u1", 2, 6)]
print("zaman alani eklense bile:")
print("  iki satirin degerleri farkli -> benzersizlik gecer:", len(set(SATIR)) == len(SATIR))
print("  araliklar ortusuyor -> kisit ihlal:", ortusuyor(SATIR[0], SATIR[1]))
```

```
IsEmri_Parca  olasi ornek  16 | arac kabul  16 | sistemde dogru   9 | fazla kabul   7
              en kucuk fazla kabul: []
Usta_Tezgah   olasi ornek  16 | arac kabul  16 | sistemde dogru   9 | fazla kabul   7
              en kucuk fazla kabul: [('u1', 't1'), ('u1', 't2')]

iki bağlantı bağıntısı birlikte: arac kabul 256 | sistemde dogru 81 | fazla kabul 175

zaman alani eklense bile:
  iki satirin degerleri farkli -> benzersizlik gecer: True
  araliklar ortusuyor -> kisit ihlal: True
```

Her iki bağlantı bağıntısı için de araçlar **16 örneğin 16'sını** kabul ediyor, oysa sistemde
doğru olan yalnız **9'u**. Yedişer örnek, şemanın kabul ettiği ama alanda hiç var olmaması
gereken durumlardır — kursun terimiyle **fazla kabul**. İki tablo birlikte ele alındığında
şema 256 durumu kabul ediyor, sistemde doğru olan 81, aradaki fark **175**.

En küçük karşı örnekler kısıtların türünü çıplak biçimde gösteriyor. "En az bir parça"
kısıtının en küçük ihlali **boş tablodur**: hiçbir satır yoksa hiçbir anahtar ve hiçbir
yabancı anahtar ihlal edilmez, ama her iş emri parçasız kalmıştır. Bir alt sınır kısıtını
satır düzeyinde çalışan bir araçla yazmak yapısal olarak mümkün değildir, çünkü ihlal
**var olan bir satırda değil, olmayan bir satırdadır.** İkinci kısıtın en küçük ihlali iki
satırdır: `('u1','t1')` ve `('u1','t2')`. Bileşik anahtar bu iki satırı ayrı sayar, çünkü
gerçekten farklıdırlar; sorulan soru eşitlik değil, **aynı ustanın kaç kez göründüğüdür.**

Son iki satır ise kısıtı zaman alanı ekleyerek kurtarma girişiminin neden yetmediğini
gösteriyor. `('u1', 0, 4)` ile `('u1', 2, 6)` farklı değerlerdir, bu yüzden her benzersizlik
kısıtından geçerler; ama aralıkları örtüşür ve kısıt ihlal edilmiştir. **Eşitlik ile
kesişim ayrı yüklemlerdir** ve biri ötekini ifade edemez.

#### İkinci Yapılandırma

Bir ölçüm, yalnız değiştirilerek sınandığında anlaşılır. İki değişiklik denenir:
kardinaliteleri değiştirmek ve modele yeni bir alan eklemek.

- **VM13** — Zaman alanı iki dilimlidir (0 ve 1); `zaman` alanı kavramsal modelde
  bulunmayan, mantıksal düzeyde eklenen bir alandır.

```python
"""Ikinci yapilandirma: dusen kisiti tasimanin iki yolu ve ikisinin de bedeli."""
from itertools import combinations, product

USTA, TEZGAH, ZAMAN = ("u1", "u2"), ("t1", "t2"), (0, 1)


def alt_kumeler(satir):
    return [frozenset(k) for n in range(len(satir) + 1) for k in combinations(satir, n)]


def sema(iliskiler, varlik=5, oznitelik=12):
    tablo = varlik + sum(1 for _, c in iliskiler if c == "N:M")
    alan = tablo + oznitelik + sum(2 if c == "N:M" else 1 for _, c in iliskiler)
    return tablo, alan


print("IsEmri-Parca  Usta-Tezgah  tablo  alan  uydurulan alan")
for c1, c2 in product(("N:M", "N:1"), repeat=2):
    t, a = sema([("IsEmri-Usta", "N:1"), ("IsEmri-Parca", c1),
                 ("Usta-Tezgah", c2), ("IsEmri-Belge", "1:N")])
    print(f"{c1:^12s}  {c2:^11s}  {t:5d}  {a:4d}  {a - 12:14d}")
print()
satir_zamansiz = list(product(USTA, TEZGAH))
satir_zamanli = list(product(USTA, TEZGAH, ZAMAN))


def dogru_zamansiz(o):
    k = [u for u, _ in o]
    return len(k) == len(set(k))


def dogru_zamanli(o):
    k = [(u, z) for u, _, z in o]
    return len(k) == len(set(k))


for ad, satir, dogru, benzersiz in (
        ("zaman alani yok ", satir_zamansiz, dogru_zamansiz, None),
        ("zaman alani var ", satir_zamanli, dogru_zamanli, None),
        ("zaman + benzersiz", satir_zamanli, dogru_zamanli, dogru_zamanli)):
    hepsi = alt_kumeler(satir)
    arac = [o for o in hepsi if benzersiz is None or benzersiz(o)]
    dog = [o for o in arac if dogru(o)]
    print(f"{ad}: arac kabul {len(arac):4d} | sistemde dogru {len(dog):3d}"
          f" | fazla kabul {len(arac) - len(dog):4d}")
```

```
IsEmri-Parca  Usta-Tezgah  tablo  alan  uydurulan alan
    N:M           N:M          7    25              13
    N:M           N:1          6    23              11
    N:1           N:M          6    23              11
    N:1           N:1          5    21               9

zaman alani yok : arac kabul   16 | sistemde dogru   9 | fazla kabul    7
zaman alani var : arac kabul  256 | sistemde dogru  81 | fazla kabul  175
zaman + benzersiz: arac kabul   81 | sistemde dogru  81 | fazla kabul    0
```

Birinci tablo, bağlantı bağıntısının bir tercih olmadığını gösteriyor: her N:M ilişkisi tam olarak
bir tablo ve iki alan ekliyor ve dördüncü satırda hiç N:M kalmayınca tablo sayısı varlık
sayısına, yani 5'e iniyor. Uydurulan alan da 13'ten 9'a düşüyor — çünkü tablo başına bir
anahtar ve ilişki başına en az bir yabancı anahtar her durumda gerekiyor.

İkinci tablo daha ilginçtir. Zaman alanı eklenince tablonun taşıyabildiği **doğru** örnek
sayısı 9'dan **81'e** çıkıyor: aynı ustanın farklı zaman dilimlerinde farklı tezgâhlarda
çalıştığı yetmiş iki durum, zamansız biçimde hiç yazılamıyordu. Üstelik `(usta, zaman)`
üzerine konan bir benzersizlik kısıtı, düşen kısıtı **tam olarak** taşıyor: fazla kabul
175'ten **0'a** iniyor.

Bu sonuç düşen kısıtları geri getirmenin yolunu gösteriyor, ama bedelini de gösteriyor.
Kısıt ancak kavramsal modelde **hiç bulunmayan bir alan** eklendikten sonra yazılabildi.
Yani düşen kısıtı kurtarmanın yolu, modelin söylemediği bir şeyi şemaya koymaktan geçiyor
— ve o alanın oradaki varlığını açıklayan hiçbir olgu kavramsal modelde yazmıyor. Bu,
sonraki dersin konusunun ilk örneğidir: **mantıksal ve fiziksel düzey yalnız kaybetmez,
aynı zamanda uydurur.**

#### Özet

- Kavramsal düzey alanın olgularını, mantıksal düzey bunların ilişkisel yapıdaki
  karşılığını, fiziksel düzey saklama kararlarını taşır; aşağı inildikçe karar sayısı artar.
- 26 olgu mantıksal düzeyde 7 tabloya ve 25 alana dönüşüyor. İki N:M ilişkisi iki ara
  tablo doğuruyor ve tablo sayısını 5'ten 7'ye çıkarıyor.
- 25 alanın 13'ünün adı kavramsal modelde hiç geçmiyor: 7 birincil anahtar ve 6 yabancı
  anahtar. Bunlar alanın olgusu değil, ilişkisel yapının kayıt tutma gereçleridir.
- 5 kısıttan 3'ü taşınıyor, 2'si düşüyor. Düşme sebebi yüklemin türüdür: biri satır
  sayısına alt sınır koyar, öteki zaman aralıklarının kesişimini sorar; anahtar ve
  benzersizlik ise tek satıra bakar ya da eşitliği karşılaştırır.
- Düşen kısıtların bedeli sayıldı: iki bağlantı bağıntısında şema 256 örneği kabul ederken sistemde
  doğru olan 81, yani 175 fazla kabul. En küçük ihlaller boş tablo ve aynı ustanın iki
  satırıdır.
- Kısıt, kavramsal modelde bulunmayan bir `zaman` alanı eklenerek tam olarak taşınabiliyor
  (fazla kabul 175'ten 0'a) ve taşınabilen doğru örnek sayısı 9'dan 81'e çıkıyor; bedeli,
  modelin söylemediği bir alanı şemaya koymaktır.

#### Sonraki Adım

Bu ders bir alanın modelde adı geçmeden ortaya çıkabildiğini gösterdi ve on üç tanesini
saydı. Sıradaki ders bu sayımı fiziksel düzeye taşır ve orada durum köklü biçimde değişir:
yedi tablo ile yirmi beş alan, yüz alan kararı ve on dört tablo kararı ister. Toplam yüz on
dört karar, kavramsal modelin söylediği yirmi altı olgunun kaç katıdır, bu kararları kim
verir ve verilen kararın yanlış olduğu nereden anlaşılır.

### Modelden Şemaya

Source: https://academia.sh/tr/kurslar/modelleme-ve-gosterim/modelden-semaya

Yedi tablo ve yirmi beş alan için 100 alan kararı ve 14 tablo kararı veriliyor: toplam 114, kavramsal modelin söylediği 26 olgunun 4,4 katı. Modelin söylemediği her karar birinin verdiği ve modelde görünmeyen bir karardır.

Önceki ders mantıksal düzeyde on üç alanın modelde adı hiç geçmeden ortaya çıktığını
saydı ve düşen bir kısıtı kurtarmanın yolunun yine modelde bulunmayan bir alan eklemekten
geçtiğini gösterdi. Bu ders son düzeye iner.

Fiziksel şema, mantıksal modeli saklanabilir hâle getirir. Sorusu şudur: bu dönüşüm kaç
karar ister, bu kararların kaçını kavramsal model belirler ve belirlemediklerini kim
belirler. Yanıt, kursun en büyük oranını üretir ve kursun kuralını son kez ödetir:
**bir gösterimin ölçüsü taşıdığı simge değil, söylemediği için başkasına bıraktığıdır.**

#### Fiziksel Düzeyin Sorduğu Sorular

Bir alanı saklanabilir yapmak için dört sorunun yanıtlanması gerekir: hangi **tip**, ne
**uzunluk**, **boş geçilebilir** mi, **varsayılan değeri** ne. Bir tabloyu saklanabilir
yapmak için iki soru daha vardır: birincil anahtar için bir **dizin** ve bir **karakter
kümesi**. Bu altı sorunun hiçbiri isteğe bağlı değildir; yanıt verilmezse yerine bir
öntanım geçer ve öntanım da bir yanıttır.

- **VM14** — Fiziksel düzeyde her alan dört karar, her tablo iki karar ister. Liste ortak
  tanımındır ve bu derste genişletilmez.
- **VM15** — Bir kararın **uydurulmuş** olması, kavramsal modelin hiçbir olgusunun o
  kararı belirlememesi demektir. Uydurulmuş karar yanlış karar değildir; **kaynağı
  modelde olmayan** karardır.

```python
"""M01/K06 ortak tanim (kesit): fiziksel duzeyin uydurdugu karar sayisi."""
ALAN_KARARI = ["tip", "uzunluk", "bos gecilebilirlik", "varsayilan deger"]
TABLO_KARARI = ["birincil anahtar dizini", "karakter kumesi"]

MANTIKSAL = {
    "IsEmri": ["anahtar", "no", "acilis", "durum", "Usta_anahtar"],
    "Usta": ["anahtar", "ad", "uzmanlik"],
    "Parca": ["anahtar", "kod", "ad", "birim"],
    "Tezgah": ["anahtar", "kod", "tur"],
    "Belge": ["anahtar", "tur", "tarih", "IsEmri_anahtar"],
    "IsEmri_Parca": ["anahtar", "IsEmri_anahtar", "Parca_anahtar"],
    "Usta_Tezgah": ["anahtar", "Usta_anahtar", "Tezgah_anahtar"],
}
KAVRAMSAL_OLGU = 26        # 5 varlik + 12 oznitelik + 4 iliski + 5 kisit


def fiziksel(tablolar):
    alan = sum(len(v) for v in tablolar.values())
    tablo = len(tablolar)
    return {"tablo": tablo, "alan": alan,
            "alan_karari": alan * len(ALAN_KARARI),
            "tablo_karari": tablo * len(TABLO_KARARI),
            "uydurulan_karar": alan * len(ALAN_KARARI) + tablo * len(TABLO_KARARI)}


F = fiziksel(MANTIKSAL)
print("tablo         alan  alan karari  tablo karari  toplam")
for ad, alanlar in MANTIKSAL.items():
    ak = len(alanlar) * len(ALAN_KARARI)
    tk = len(TABLO_KARARI)
    print(f"{ad:13s} {len(alanlar):4d}  {ak:11d}  {tk:12d}  {ak + tk:6d}")
print(f"{'toplam':13s} {F['alan']:4d}  {F['alan_karari']:11d}"
      f"  {F['tablo_karari']:12d}  {F['uydurulan_karar']:6d}")
print()
print("kavramsal modelin soyledigi olgu:", KAVRAMSAL_OLGU)
print("fiziksel semanin uydurdugu karar:", F["uydurulan_karar"])
print("oran:", round(F["uydurulan_karar"] / KAVRAMSAL_OLGU, 4))
print()
print("her karar yalniz iki secenekli olsa bile , ayni mantiksal modele karsilik gelen")
print("fiziksel sema sayisi:", 2 ** F["uydurulan_karar"])
print("basamak sayisi:", len(str(2 ** F["uydurulan_karar"])))
```

```
tablo         alan  alan karari  tablo karari  toplam
IsEmri           5           20             2      22
Usta             3           12             2      14
Parca            4           16             2      18
Tezgah           3           12             2      14
Belge            4           16             2      18
IsEmri_Parca     3           12             2      14
Usta_Tezgah      3           12             2      14
toplam          25          100            14     114

kavramsal modelin soyledigi olgu: 26
fiziksel semanin uydurdugu karar: 114
oran: 4.3846

her karar yalniz iki secenekli olsa bile , ayni mantiksal modele karsilik gelen
fiziksel sema sayisi: 20769187434139310514121985316880384
basamak sayisi: 35
```

**Sistem:** kavramsal model 26 olgu söylüyor. **Gösterim:** fiziksel şema 7 tablo ve 25
alan taşıyor. **Bedel:** bu şemayı yazmak için **114 karar** verilmesi gerekiyor ve
bunların hiçbiri kavramsal modelde yazmıyor. Oran **4,3846**, yani modelin söylediğinin
yaklaşık **4,4 katı** kadar karar, modelin dışında verilir.

Son satır bu sayının gösterim diliyle karşılığıdır. Bir karar en az iki seçenek sunuyorsa
— boş geçilebilir mi, evet ya da hayır — aynı mantıksal modele karşılık gelen fiziksel
şema sayısı **iki üzeri yüz on dörttür**, otuz beş basamaklı bir sayı. Gerçek seçenek
sayısı bundan büyüktür, çünkü tip ve uzunluk ikiden çok değer alır. **Mantıksal model, bu
şema kümesinin hepsine aynı anda uyar** ve hiçbirini ötekine tercih etmez.

- **VM16** — Alt sınır sayımında her kararın yalnız iki seçeneği olduğu varsayılır; gerçek
  seçenek sayısı saklama ürününe göre değişir ve bu yüzden yazılmaz.

#### Kararın Sahibi Kim

Yüz on dört karar ortadan kalkmaz; yalnız **sahibi değişir**. Bir kararın üç olası sahibi
vardır. Model onu bir olgu olarak söylemiş olabilir. Karar başka bir olgudan
**türetilebilir** olabilir. Ya da bir kişi, kod yazarken ya da şema kurarken, kendi
bildiğine göre yanıtlar.

Bu üçünün ayrımı ölçülebilir ve ölçüm iki ayrı davranış gösterir.

- **VM17** — Bir kararın sahibi üçten biridir: modelde yazılı olgu, başka bir olgudan
  türetilmiş sonuç, ya da kişi. Model olgusu sayıldığında kavramsal modelin olgu sayısı
  büyür; türetilmiş karar sayıldığında büyümez.

```python
"""114 kararin sahibi kim: modele tasimak ile bir kuraldan turetmek ayri islerdir."""
ALAN_KARARI = ["tip", "uzunluk", "bos gecilebilirlik", "varsayilan deger"]
TABLO_KARARI = ["birincil anahtar dizini", "karakter kumesi"]
MANTIKSAL = {
    "IsEmri": ["anahtar", "no", "acilis", "durum", "Usta_anahtar"],
    "Usta": ["anahtar", "ad", "uzmanlik"],
    "Parca": ["anahtar", "kod", "ad", "birim"],
    "Tezgah": ["anahtar", "kod", "tur"],
    "Belge": ["anahtar", "tur", "tarih", "IsEmri_anahtar"],
    "IsEmri_Parca": ["anahtar", "IsEmri_anahtar", "Parca_anahtar"],
    "Usta_Tezgah": ["anahtar", "Usta_anahtar", "Tezgah_anahtar"],
}
OZNITELIK = {"IsEmri": ["no", "acilis", "durum"], "Usta": ["ad", "uzmanlik"],
             "Parca": ["kod", "ad", "birim"], "Tezgah": ["kod", "tur"],
             "Belge": ["tur", "tarih"]}

KARARLAR = [(t, a, k) for t, alanlar in MANTIKSAL.items() for a in alanlar
            for k in ALAN_KARARI]
KARARLAR += [(t, None, k) for t in MANTIKSAL for k in TABLO_KARARI]


def sahibi(karar, ayar):
    t, a, k = karar
    kavramsal = a in OZNITELIK.get(t, [])
    if ayar["alan"] and kavramsal and k in ("tip", "uzunluk"):
        return "model"
    if ayar["zorunluluk"] and kavramsal and k == "bos gecilebilirlik":
        return "model"
    if ayar["yabanci"] and a is not None and a.endswith("_anahtar") \
            and k in ("tip", "uzunluk"):
        return "turetilmis"
    if ayar["butunluk"] and a == "anahtar" and k == "bos gecilebilirlik":
        return "turetilmis"
    return "kisi"


AYARLAR = [
    ("kavramsal model oldugu gibi", dict(alan=0, zorunluluk=0, yabanci=0, butunluk=0)),
    ("+ 12 oznitelige alan", dict(alan=1, zorunluluk=0, yabanci=0, butunluk=0)),
    ("+ 12 oznitelige zorunluluk", dict(alan=1, zorunluluk=1, yabanci=0, butunluk=0)),
    ("+ yabanci anahtar turetimi", dict(alan=1, zorunluluk=1, yabanci=1, butunluk=0)),
    ("+ varlik butunlugu", dict(alan=1, zorunluluk=1, yabanci=1, butunluk=1)),
]
print("toplam karar:", len(KARARLAR))
print()
print("yapilandirma                  modelde  turetilmis  kisi  model olgusu  toplam")
for ad, ayar in AYARLAR:
    pay = {"model": 0, "turetilmis": 0, "kisi": 0}
    for kr in KARARLAR:
        pay[sahibi(kr, ayar)] += 1
    olgu = 26 + pay["model"]
    print(f"{ad:28s}  {pay['model']:7d}  {pay['turetilmis']:10d}  {pay['kisi']:4d}"
          f"  {olgu:12d}  {olgu + pay['kisi']:6d}")
```

```
toplam karar: 114

yapilandirma                  modelde  turetilmis  kisi  model olgusu  toplam
kavramsal model oldugu gibi         0           0   114            26     140
+ 12 oznitelige alan               24           0    90            50     140
+ 12 oznitelige zorunluluk         36           0    78            62     140
+ yabanci anahtar turetimi         36          12    66            62     128
+ varlik butunlugu                 36          19    59            62     121
```

Tablonun son sütunu bu dersin en öğretici sayısıdır. İlk üç satırda toplam **140'ta
sabit** duruyor: modelin taşıdığı olgu ile kişinin verdiği karar birbirini **birebir**
takas ediyor. Kavramsal modele on iki özniteliğin tip ve uzunluk bilgisini eklemek olgu
sayısını 26'dan 50'ye çıkarıyor ve kişiye kalan kararı 114'ten 90'a indiriyor. Zorunluluk
bilgisi de eklendiğinde olgu 62, kişiye kalan 78. **Modeli zenginleştirmek karar sayısını
azaltmıyor, kararın sahibini değiştiriyor** — ve bu iyi bir takastır, çünkü modeldeki
karar yazılıdır, okunabilir ve tartışılabilir.

Son iki satır ayrı bir şey yapıyor ve toplamı **düşürüyor**. Yabancı anahtar alanının tipi
ve uzunluğu, başvurduğu birincil anahtardan **türetilebilir**; ayrıca birincil anahtarı
oluşturan alan boş geçilemez — bu, İlişkisel Kuram kursunda kurulan **varlık
bütünlüğünün** doğrudan sonucudur. Bu iki türetimle kişiye kalan karar 78'den **59'a**
iniyor ve toplam 140'tan **121'e** düşüyor. Türetim, takastan farklıdır: modeli
büyütmeden karar sayısını gerçekten azaltır, çünkü aynı bilgiyi iki kez söylemeyi
gereksiz kılar.

#### Modelin Susması Kararı Görünmez Yapar

Kalan elli dokuz kararın her biri bir kişinin yanıtıdır ve bu yanıtın modelde bir izi
yoktur. Bunun sonucu, kararın yanlış olması değildir; **yanlışlığın gösterilemez
olmasıdır.** Tek bir alan üzerinde bakmak yeter.

- **VM18** — Parça kodu havuzu sekiz kodludur ve karar anında yalnız ilk beşi görülmüştür.

```python
"""Tek bir uydurulan karar: Parca.kod alaninin uzunlugu. Model hicbir secenegi elemez."""
KOD = ["MK-01", "MK-002", "TR-08", "PL-7", "GK-1", "RD-1140", "HD-220-A", "SB-33012"]

print("uzunluk  reddedilen kod  hangileri")
for uzunluk in range(4, 11):
    red = [k for k in KOD if len(k) > uzunluk]
    print(f"{uzunluk:7d}  {len(red):14d}  {', '.join(red) if red else '-'}")
print()
print("kavramsal modelin bu karar hakkinda soyledigi olgu sayisi: 0")
print("veriden okunan en kucuk guvenli uzunluk:", max(len(k) for k in KOD))
print()
gorulen = KOD[:5]
secim = max(len(k) for k in gorulen)
sonra = [k for k in KOD if len(k) > secim]
print("karar aninda gorulen kod:", len(gorulen), "| secilen uzunluk:", secim)
print("sonradan gelen kod:", len(KOD) - len(gorulen),
      "| reddedilen:", len(sonra), "->", ", ".join(sonra))
```

```
uzunluk  reddedilen kod  hangileri
      4               6  MK-01, MK-002, TR-08, RD-1140, HD-220-A, SB-33012
      5               4  MK-002, RD-1140, HD-220-A, SB-33012
      6               3  RD-1140, HD-220-A, SB-33012
      7               2  HD-220-A, SB-33012
      8               0  -
      9               0  -
     10               0  -

kavramsal modelin bu karar hakkinda soyledigi olgu sayisi: 0
veriden okunan en kucuk guvenli uzunluk: 8

karar aninda gorulen kod: 5 | secilen uzunluk: 6
sonradan gelen kod: 3 | reddedilen: 3 -> RD-1140, HD-220-A, SB-33012
```

Yüz on dört kararın yalnız biri bu: `Parca.kod` alanının uzunluğu. Kavramsal model bu
karar hakkında **sıfır olgu** söylüyor; parça kodunun benzersiz olduğunu söylüyor, kaç
karakter olduğunu söylemiyor. Bu yüzden 4 ile 10 arasındaki her seçenek modele **eşit
derecede uygundur** ve modele bakarak hiçbiri elenemez.

Kararı eleyen tek şey veridir ve veri karar anında eksiktir. Karar veren kişi beş kod
görmüş, en uzunu altı karakter, uzunluğu 6 seçmiş. Sonradan gelen üç kodun **üçü de**
reddediliyor. Bu bir hata değil, bir **tahmindir** — ve tahmin olduğu modelde yazmıyor,
çünkü modelde bu satır hiç yok. Beş yıl sonra o alana bakan biri, 6 sayısının bir alan
kuralı mı yoksa bir günün tahmini mi olduğunu ayırt edemez.

Buradan kursun kuralının veri modellemedeki karşılığı çıkar: **modelin sustuğu her yer bir
karar yeridir ve orada verilen karar modelde görünmediği için tartışılamaz.** Yüz on dört
sayısı bu yüzden bir şema büyüklüğü ölçüsü değil, bir **görünmezlik** ölçüsüdür.

#### Özet

- Fiziksel şema her alan için dört, her tablo için iki karar ister. Yedi tablo ve yirmi
  beş alan 100 alan kararı ve 14 tablo kararı, toplam **114 karar** üretir.
- Kavramsal model 26 olgu söylüyor; fiziksel şema 114 karar uyduruyor. Oran 4,3846, yani
  modelin söylediğinin yaklaşık 4,4 katı.
- Her karar yalnız iki seçenekli olsa bile aynı mantıksal modele karşılık gelen fiziksel
  şema sayısı 2 üzeri 114, otuz beş basamaklı bir sayıdır; mantıksal model bunların
  hepsine aynı anda uyar.
- Kararı modele taşımak bir **takastır** ve toplamı değiştirmez: 12 özniteliğe alan ve
  zorunluluk bilgisi eklendiğinde olgu 26'dan 62'ye çıkarken kişiye kalan karar 114'ten
  78'e iner, toplam 140'ta sabit kalır.
- Kararı bir kuraldan **türetmek** toplamı gerçekten düşürür: yabancı anahtarın tipi
  başvurduğu anahtardan, anahtarın boş geçilemezliği varlık bütünlüğünden geldiğinde
  kişiye kalan 59, toplam 121 olur.
- Modelin sustuğu bir karar görünmez olur: `Parca.kod` uzunluğu için model sıfır olgu
  söylüyor, karar anında görülen beş kod 6 uzunluğunu seçtiriyor ve sonradan gelen üç
  kodun üçü de reddediliyor.

#### Kurs Kapanışı

On ders tek bir bakım atölyesini modelledi ve tek bir soruyu sordu: bir gösterim, sistemi
kaç başka sistemden ayırt edemiyor. Kursun kuralı buydu — **kaç sistemi birbirinden
ayıramadığı yazılmayan gösterim ölçülmemiş sayılır.** Her derste üç sayı yan yana durdu:
sistemin gerçek olgu sayısı, gösterimin yazdığı simge sayısı ve aradaki bedel.

| Ders | Sistem | Gösterim | Bedel |
|---|---|---|---|
| Gösterim Ailesi ve Kayıp | 5 bağ, 11 gizli alan | 20 simge | **2048** sistem aynı diyagrama düşüyor |
| Sınıf Diyagramları | aynı 5 bağ | 25 ve 31 simge | 25 simgede **64**, 31 simgede **1** sistem kalıyor |
| Bileşen ve Yerleşim Diyagramları | 6 sınıf, **203** bölüntü; 540 örten atama | 3 kutu + 2 bağlantı | en kaba çizim **10 bölüntüyle** uyumlu; bağlantı simgeleri 540'ı 20'ye indiriyor, içerik simgeleri 1'e |
| Kullanım Senaryosu Diyagramları | 20 olgu: 2 aktör, 3 senaryo, 5 bağ, 3 sahiplik, 7 iç adım | 9 simge | **512** sistem aynı diyagrama düşüyor; taban belirsizlik 128 |
| Sıra Diyagramları | 24 iz | 1 diyagram, 1 iz | kapsam **1/24 = 0,0417**; dört diyagram 0,1667 |
| Etkinlik Diyagramları | 10 iş, 13 önkoşul | 23 simge, 1 kısmi sıralama | **168 tam sıralama** kabul ediliyor, tek sıranın kapsamı 0,006; karar düğümü 492'ye taşıyor |
| Durum Makinesi Diyagramları | 6 gerçek dizi | 10 simge (4 durum, 6 geçiş) | eksik kabul **2**, fazla kabul **2**; iki geçiş eklenince 0 ve **26** — on üç kat |
| Varlık–İlişki Modeli | 26 olgu | 26 yazılı öge | **1.048.576** sistem aynı gösterime düşüyor |
| Kavramsal, Mantıksal ve Fiziksel Model | 26 olgu | 7 tablo, 25 alan | **2 düşen kısıt**, 13 uydurulan alan, 175 fazla kabul |
| Modelden Şemaya | 26 olgu | 7 tablo, 25 alan | **114 uydurulan karar**, modelin söylediğinin 4,4 katı |

Tablonun ikinci okuması birincisinden değerlidir: **gösterimi düzeltmek onu daha yanlış
yapabilir.** Durum makinesine iki geçiş eklemek reddedilen diziyi sıfırladı ama fazla
kabulü on üç katına çıkardı. Bir olguyu varlıktan özniteliğe indirmek modeli sadeleştirdi
ama on bir durumu gösterilemez yaptı. Düşen bir kısıtı kurtarmak, modelde hiç bulunmayan
bir alan eklemeyi gerektirdi. Ayrıntı eklemek her zaman kazanç değildir ve **kaybı
sayılmadan eklenmez.**

Üçüncü ve en pahalı sonuç veri modellemeden geldi: **soyutlama düzeyi hem unutur hem
uydurur ve ikisi ayrı ayrı sayılır.** Kavramsal modelden fiziksel şemaya inerken beş
kısıttan ikisi düştü, ama modelde hiç yazmayan 114 karar ortaya çıktı. Unutulan iki kısıt
görünürdü, çünkü modelde bir zamanlar yazıyorlardı; uydurulan 114 karar görünmez, çünkü
hiç yazmadılar. **Bir gösterimin en tehlikeli yanı sildiği şey değil, hiç söylemediği
şeydir.**

Kurs boyunca hiçbir diyagram çizilmedi. Her gösterim, taşıdığı bilgi ögelerinin listesi
olarak kuruldu ve sayıldı; ölçülen şey resmin güzelliği değil, resmin **kaç sistemi tek
resme düşürdüğüydü**. Hangi diyagram türünün hangi soruya uyduğu ve bir diyagram kümesini
güncel tutmanın neye mal olduğu bu kursun soruları değildi; ikisi de Yazılım Mimarlığı
müfredatının Mimari Karar ve Dokümantasyon kursunda ölçüldü ve buraya taşınmadı.

Bir sonraki kurs, **İleri Algoritmalar ve Problem Çözme**, aynı disiplini başka bir
gösterim üzerinde sürdürür. Orada bir problemi tanınmış bir algoritmik kalıba indirgemek
öğretilir — böl ve yönet, açgözlü seçim, dinamik programlama, geri izleme. İndirgeme de
bir gösterim seçimidir: problemi bir kalıba oturtmak onun bazı yanlarını görünmez yapar
ve kalıbın koşulları sağlanmıyorsa yanıt sessizce yanlış çıkar. Bu yüzden o kursun
merkezinde bir gerekçelendirme durur: optimal alt yapı ve örtüşen alt problem koşullarının
**sağlandığının gösterilmesi**. Buradaki kural orada da geçerlidir — bir indirgemenin neyi
düşürdüğü yazılmadıkça, indirgeme ölçülmemiş sayılır.

