Ders 08 / 10
co-NP ve Sınıflar Arası İlişkiler
Tümleyen problemlerin durumu ve evet ile hayır yanıtları arasındaki ölçülmüş asimetri: 20 örnekte evet sertifikası 101 adımda kapanırken hayır yanıtı tam tarama ile 81.920 adım istiyor. Yapılı hayır örneklerinde 260 adımlık kısa bir kanıt 20/20 çalışıyor, yapısız örneklerde aynı kanıt 20/20 hiçbir şey söyleyemiyor. Girdi boyu 24'te evet sertifikası 25, hayır kanıtı 16.777.216 adım. Eşik problemi iki yönde de 260 adımda kapanıyor.
İçindekiler
Buraya kadar ölçülen her şey evet yönündeydi: sertifika bir “evet”i doğruluyordu, indirgeme bir “evet”i taşıyordu. Bir yanıt “hayır” olduğunda ne gösterilebilir. Bu ders eksik yönü ölçer ve iki yönün simetrik olmadığını sayar.
Sorunun kaynağı NP tanımının kendisindedir. Tanım yalnız “evet” yanıtı için bir tanık ister; “hayır” yanıtı için hiçbir şey vaat etmez. M01/K07 İleri Algoritmalar kursu bu asimetriyi Hamilton yolu dersinde çoktan gözlemişti: yol bulunmayan çizgelerin hepsinde karar yordamı sayma yordamının gezdiği ağacın tamamını gezmişti. O gözlem burada bir sınıf ayrımına dönüşür.
- KS29. Bir karar probleminin tümleyeni, aynı girdide yanıtı ters çevrilmiş problemdir: “hedefe toplanan bir alt küme var mı” sorusunun tümleyeni “hiçbir alt küme hedefe toplanmıyor mu” sorusudur.
- KS30. co-NP, tümleyeni NP sınıfında olan karar problemlerinin sınıfıdır. Eşdeğer okunuşu şudur: “hayır” yanıtının kısa ve hızlı sınanabilir bir tanığı olan problemler.
- KS31. Üç örnek kümesi kurulur. Evet kümesi: ortak tanımın 20 örneği. Yapılı hayır kümesi: bütün sayılar ikiye katlanır, hedef tek yapılır. Yapısız hayır kümesi: aynı sayılar, hedef olarak erişilemeyen bir değer seçilir.
- KS32. Yapısız kümenin hedefi seçilirken erişilen toplamlar tam olarak çıkarılır. Bu bir kurulum adımıdır, hakem değildir, ve adımı ölçüme katılmaz.
- KS33. Kısa hayır kanıtı yalnız bir gerek koşulu sınar: bütün sayılar çiftse toplamları da çifttir, dolayısıyla tek bir hedefe ulaşılamaz. Bu kanıt “hayır” diyebilir, “evet” diyemez; diyemediğinde bilinmiyor döner.
- KS34. Bir adım, kısa kanıt için bir sayı okumasıdır; tam tarama için bir alt kümedir.
- KS35. Bütçe süpürmesi dört değerde yapılır: 13, 100, 1000, 10.000 adım.
- KS36. Örnekler ortak tanımın üretecinden, tohum 20260218. İkinci tohum yoktur.
- KS37. NP ile co-NP’nin eşit olup olmadığı açık bir sorudur ve bu derste yanıtlanmaz. Ölçüm yalnız belirli kanıtların belirli örneklerde çalışıp çalışmadığını sayar.
Tümleyen Neden Ayrı Bir Soru
Bir karar problemini çözen yordam, tümleyenini de çözer: yanıtı ters çevirmek bir adım bile tutmaz. Bu yüzden çözülebilirlik açısından bir problem ile tümleyeni arasında fark yoktur, ve P sınıfı tümleyen almaya kapalıdır — P’deki bir problemin tümleyeni de P’dedir.
Doğrulanabilirlik açısından durum başkadır. “Şu alt küme hedefe toplanıyor” tanığı, “hiçbir alt küme toplanmıyor” iddiasını desteklemez; tersine, o iddiayı çürütür. “Hiçbiri” demek için gösterilecek şeyin ne olduğu ayrı bir tasarım sorusudur ve her problem için bir yanıtı olduğu bilinmez.
Bu yüzden NP ile co-NP ayrı adlar taşır. Alt küme toplamının NP sınıfında olduğu 02’de
gösterildi; co-NP sınıfında olup olmadığı gösterilmedi ve bu ders de göstermez.
İki Yönün Ölçülmesi
Aşağıdaki blok üç örnek kümesini aynı hakemle koşturur, sonra her kümede iki ayrı kısa kanıt dener: “evet” için sertifika, “hayır” için çift-tek gerek koşulu.
TOHUM = 20260218 def ornekler(tohum=TOHUM, n=12, sayi=20): d = tohum kume = [] for _ in range(sayi): sayilar = [] for _ in range(n): d = (d * 1103515245 + 12345) % 2147483648 sayilar.append(d % 97 + 3) d = (d * 1103515245 + 12345) % 2147483648 kume.append({"sayilar": sayilar, "hedef": sum(sayilar) // 3 + d % 7}) return kume def hakem(sayilar, hedef): """Tam tarama. Doner: (var_mi, adim, sertifika).""" adim, n = 0, len(sayilar) for maske in range(1 << n): adim += 1 if sum(sayilar[i] for i in range(n) if maske >> i & 1) == hedef: return True, adim, [i for i in range(n) if maske >> i & 1] return False, adim, None def evet_dogrula(sayilar, hedef, sertifika): """Bir adim = bir indis okumasi.""" adim, toplam = 0, 0 for i in sertifika: adim += 1 toplam += sayilar[i] return toplam == hedef, adim + 1 def hayir_dogrula(sayilar, hedef): """Tek yone calisan kisa kanit: butun sayilar cift ise toplamlari da cifttir , dolayisiyla tek bir hedefe ulasilamaz.""" adim = 0 for s in sayilar: adim += 1 if s % 2: return "bilinmiyor", adim adim += 1 return ("hayir", adim) if hedef % 2 else ("bilinmiyor", adim) def ulasilmayan(sayilar): """Kurulum adimi (hakem degil): erisilen toplamlar cikarilir ve ucte bire en yakin erisilmeyen deger secilir.""" ulasilan = {0} for x in sayilar: ulasilan |= {u + x for u in ulasilan} return min((t for t in range(1, sum(sayilar)) if t not in ulasilan), key=lambda t: abs(t - sum(sayilar) // 3)) ORN = ornekler() EVET = [(o["sayilar"], o["hedef"]) for o in ORN] YAPILI = [([2 * x for x in o["sayilar"]], 2 * o["hedef"] + 1) for o in ORN] YAPISIZ = [(o["sayilar"], ulasilmayan(o["sayilar"])) for o in ORN] print("kume hakem yaniti tam tarama adimi") for ad, kume, bekle in (("evet ", EVET, True), ("yapili ", YAPILI, False), ("yapisiz", YAPISIZ, False)): top = sum(hakem(s, h)[1] for s, h in kume) uyan = sum(1 for s, h in kume if hakem(s, h)[0] == bekle) print(f"{ad} {uyan:2d}/20 beklenen {top:16d}") print() es = sum(evet_dogrula(s, h, hakem(s, h)[2])[1] for s, h in EVET) print("evet sertifikasi (20 ornek) dogrulama adimi:", es) for ad, kume in (("yapili ", YAPILI), ("yapisiz", YAPISIZ)): hy = sum(1 for s, h in kume if hayir_dogrula(s, h)[0] == "hayir") ha = sum(hayir_dogrula(s, h)[1] for s, h in kume) print(f"kisa hayir kaniti {ad} | 'hayir' diyebildigi: {hy:2d}/20 | adim: {ha}") print() print("butce evet sertifikasi yapili hayir kaniti yapisiz tam tarama") for b in (13, 100, 1000, 10000): a1 = sum(1 for s, h in EVET if evet_dogrula(s, h, hakem(s, h)[2])[1] <= b) a2 = sum(1 for s, h in YAPILI if hayir_dogrula(s, h)[0] == "hayir" and hayir_dogrula(s, h)[1] <= b) a3 = sum(1 for s, h in YAPISIZ if hakem(s, h)[1] <= b) print(f"{b:5d} {a1:16d} {a2:19d} {a3:19d}")
kume hakem yaniti tam tarama adimi evet 20/20 beklenen 4321 yapili 20/20 beklenen 81920 yapisiz 20/20 beklenen 81920 evet sertifikasi (20 ornek) dogrulama adimi: 101 kisa hayir kaniti yapili | 'hayir' diyebildigi: 20/20 | adim: 260 kisa hayir kaniti yapisiz | 'hayir' diyebildigi: 0/20 | adim: 39 butce evet sertifikasi yapili hayir kaniti yapisiz tam tarama 13 20 20 0 100 20 20 0 1000 20 20 0 10000 20 20 20
Asimetrinin Okunması
İlk tablo tek başına asimetriyi kuruyor. Evet kümesinde tam tarama 4321 adım harcıyor, çünkü uyan bir alt küme bulununca duruyor. İki hayır kümesinde ise 81.920 adım — yani örnek başına tam 4096, hiçbir indirim yok. Sayı iki kümede birebir aynı çünkü nedeni yordamsal değil mantıksaldır: “hiçbiri” demek için görülmemiş tek bir alt küme kalmamalıdır.
İkinci blok üç sayıyı yan yana getiriyor. Evet sertifikası 101 adım. Yapılı hayır kanıtı 260 adım ve 20 örneğin 20’sinde “hayır” diyebiliyor. Yapısız hayır kanıtı 39 adım harcıyor ve 20 örneğin hiçbirinde bir şey söyleyemiyor — ilk tek sayıyı görünce çekiliyor.
Bu üçlü, co-NP tanımının neden bir varlık iddiası olduğunu gösteriyor. Kısa bir “hayır” tanığı bazı örnekler için vardır ve ölçüldü: 4096 adım yerine 13. Ama tanığın her örnek için var olması ayrı bir iddiadır ve yapısız küme bu iddianın kendiliğinden sağlanmadığını gösteriyor. Ölçümün söylediği şey şudur: bu kanıt bu örneklerde çalışmadı. Söylemediği şey ise, başka bir kısa kanıtın var olmadığıdır; öyle bir kanıt aranmadı, yalnız bu bir tane denendi.
Bütçe süpürmesi aynı ayrımı bir kez daha veriyor. Evet sertifikası ve yapılı hayır kanıtı bütçe 13’te doluyor; bütçeyi bin katına çıkarmak ikisinde de hiçbir şey değiştirmiyor. Yapısız küme ise 1000’de hâlâ sıfırda ve ancak 10.000’de 20’ye çıkıyor.
İki Yönü de Ucuz Olan Problem
Her problemde bu asimetri yoktur. Eşik problemi — sayıların toplamı hedefi aşıyor mu — iki yönde de aynı yordamla kapanır: toplam bir kez hesaplanır ve karşılaştırılır.
TOHUM = 20260218 def ornekler(tohum=TOHUM, n=12, sayi=20): d = tohum kume = [] for _ in range(sayi): sayilar = [] for _ in range(n): d = (d * 1103515245 + 12345) % 2147483648 sayilar.append(d % 97 + 3) d = (d * 1103515245 + 12345) % 2147483648 kume.append({"sayilar": sayilar, "hedef": sum(sayilar) // 3 + d % 7}) return kume def esik(sayilar, hedef): """Toplam hedefi asiyor mu. Iki yon de ayni yordamla kapanir.""" toplam, adim = 0, 0 for s in sayilar: toplam += s adim += 1 return toplam > hedef, adim + 1 ev = hy = ea = ha = 0 for o in ornekler(): y1, a1 = esik(o["sayilar"], o["hedef"]) y2, a2 = esik(o["sayilar"], sum(o["sayilar"]) + 1) ev, hy = ev + y1, hy + (not y2) ea, ha = ea + a1, ha + a2 print("esik problemi | evet:", ev, "/20 ,", ea, "adim | hayir:", hy, "/20 ,", ha, "adim") print() print(" n evet sertifikasi hayir kaniti (tam tarama)") for n in (8, 12, 16, 20, 24): print(f"{n:2d} {n + 1:16d} {1 << n:25d}")
esik problemi | evet: 20 /20 , 260 adim | hayir: 20 /20 , 260 adim n evet sertifikasi hayir kaniti (tam tarama) 8 9 256 12 13 4096 16 17 65536 20 21 1048576 24 25 16777216
Eşik probleminde iki yön de 260 adım: birebir eşit, ve eşitlik bir rastlantı değil yordamın yapısından geliyor. Bu problem hem NP hem co-NP sınıfındadır, çünkü P sınıfındadır ve P her iki sınıfın da içindedir. Yanıtın yönü maliyeti değiştirmiyor.
Alt satırdaki tablo karşıt uçtur. Girdi boyu 8’den 24’e çıkarken evet sertifikası 9’dan 25 adıma, hayır kanıtı 256’dan 16.777.216 adıma gidiyor. İki sütun aynı problemin iki yüzüdür ve aynı hızda büyümüyorlar.
Aynı Hayır, Daha Az Adım
Yapısız kümede tam taramanın 81.920 adım harcaması, o örnekler için “hayır” demenin bedeli
değildir; yalnız tam taramanın bedelidir. Bunu göstermenin yolu, aynı yanıtı daha az adımda
kuran başka bir yordam denemektir. Aşağıdaki blok iki tane dener: kısmi toplam hedefi aştığında
dalı kesen budamalı bir tarama, ve 01’de tanıtılan erişilen toplamlar tablosu.
TOHUM = 20260218 def ornekler(tohum=TOHUM, n=12, sayi=20): d = tohum kume = [] for _ in range(sayi): sayilar = [] for _ in range(n): d = (d * 1103515245 + 12345) % 2147483648 sayilar.append(d % 97 + 3) d = (d * 1103515245 + 12345) % 2147483648 kume.append({"sayilar": sayilar, "hedef": sum(sayilar) // 3 + d % 7}) return kume def ulasilmayan(sayilar): ulasilan = {0} for x in sayilar: ulasilan |= {u + x for u in ulasilan} return min((t for t in range(1, sum(sayilar)) if t not in ulasilan), key=lambda t: abs(t - sum(sayilar) // 3)) def tam_tarama(sayilar, hedef): adim, n = 0, len(sayilar) for maske in range(1 << n): adim += 1 if sum(sayilar[i] for i in range(n) if maske >> i & 1) == hedef: return True, adim return False, adim def budamali(sayilar, hedef): """Kismi toplam hedefi asinca dal kesilir. Bir adim = bir dugum.""" s = sorted(sayilar) n, adim = len(s), 0 def gez(i, toplam): nonlocal adim adim += 1 if toplam == hedef: return True if toplam > hedef or i == n: return False return gez(i + 1, toplam + s[i]) or gez(i + 1, toplam) return gez(0, 0), adim def dinamik(sayilar, hedef): """Erisilen toplamlar tablosu. Bir adim = bir tablo hucresi.""" ulasilan = [False] * (hedef + 1) ulasilan[0] = True adim = 0 for x in sayilar: for t in range(hedef, x - 1, -1): adim += 1 if ulasilan[t - x]: ulasilan[t] = True return ulasilan[hedef], adim YAPISIZ = [(o["sayilar"], ulasilmayan(o["sayilar"])) for o in ornekler()] print("yordam hayir diyen toplam adim butce 1000 butce 10000") for ad, f in (("tam tarama ", tam_tarama), ("budamali tarama", budamali), ("dinamik tablo ", dinamik)): hy = top = b3 = b4 = 0 for s, h in YAPISIZ: y, a = f(s, h) hy += not y top += a b3 += a <= 1000 b4 += a <= 10000 print(f"{ad:15s} {hy:11d} {top:11d} {b3:10d} {b4:11d}")
yordam hayir diyen toplam adim butce 1000 butce 10000 tam tarama 20 81920 0 20 budamali tarama 20 21594 12 20 dinamik tablo 20 15736 16 20
Üç yordam da 20 örneğin 20’sinde “hayır” diyor, yani üçü de aynı yanıtı kuruyor. Adım sayıları ise 81.920, 21.594 ve 15.736: budamalı tarama tam taramanın dörtte birinden azını, tablo yordamı beşte birinden azını harcıyor. Bütçe 1000’de tam tarama sıfırda kalırken budamalı tarama 12, tablo yordamı 16 örneği karara bağlıyor.
Bir bölüm önce “bu kanıt bu örneklerde çalışmadı” denmişti; şimdi aynı örnekler dört beş kat
ucuza kapanıyor. Yine de kapanma n+1 adıma inmedi ve tablo yordamının ucuzluğu 01’de
görüldüğü gibi hedefin değerine bağlıdır. Sonuç iki cümleye sığar: ölçülen en iyi sayı,
ölçülebilecek en iyi sayı değildir; ve daha iyi bir sayı bulmak, bir sınır kanıtlamakla aynı
şey değildir.
Bilinen ve Açık Olan
Bilinenler kısadır. P sınıfı hem NP’nin hem co-NP’nin içindedir, ve tümleyen almaya kapalıdır. NP-tam bir problemin tümleyeninin NP sınıfında olduğu bilinmiyor. Bir problem hem NP hem co-NP sınıfındaysa, iki yönde de kısa tanığı var demektir; bu güçlü bir özelliktir ve her problemde bulunmaz.
Açık olan da kısadır: NP ile co-NP’nin eşit olup olmadığı bilinmiyor. Bu ders o soruyu yanıtlamaz ve yanıtlamaya çalışmaz. Ölçtüğü şey, tek bir kısa kanıtın 20 örnekte çalışıp 20 örnekte çalışmadığıdır. Yapısız kümede kanıtın 0/20 vermesi, o örnekler için kısa bir kanıt olmadığını göstermez; yalnız bu kanıtın onlara uymadığını gösterir. Bu ayrım kursun aşırı iddia yasağının doğrudan uygulanmasıdır.
Mühendislik karşılığı somuttur. Bir doğrulayıcıda “geçerli” yanıtını gerekçelendirmek ile “geçersiz” yanıtını gerekçelendirmek iki ayrı iştir: ilki bir tanık gösterebilir, ikincisi çoğu zaman “her ihtimali gördüm” demek zorundadır. İki yönün adım sayısı ayrı yazılmadıkça doğrulayıcının maliyeti bilinmiş sayılmaz.
Özet
- Bir problemin tümleyeni, çözülebilirlik açısından ondan farksızdır; doğrulanabilirlik açısından ayrı bir sorudur, çünkü sertifika ters çevrilerek kullanılamaz.
- Evet kümesinde tam tarama 4321 adım harcıyor, iki hayır kümesinde 81.920 adım — örnek başına 4096, hiçbir indirim yok.
- Kısa hayır kanıtı yapılı örneklerin 20’sinde 20’sinde çalışıyor ve 260 adım tutuyor; yapısız örneklerin hiçbirinde bir şey söyleyemiyor ve 39 adımda çekiliyor.
- Eşik probleminde iki yön de 260 adımda kapanıyor; bu problem P sınıfında olduğu için hem NP hem co-NP sınıfındadır.
- Girdi boyu 8’den 24’e çıkarken evet sertifikası 9’dan 25 adıma, hayır kanıtı 256’dan 16.777.216 adıma gidiyor.
- NP ile co-NP’nin eşit olup olmadığı açık bir sorudur; bir kanıtın bu örneklerde çalışmaması, hiçbir kısa kanıtın olmadığını göstermez.
Sonraki Adım
Bu dersle birlikte dört sınıf adı ve aralarındaki bilinen ilişkiler kuruldu. Geriye en çok konuşulan, en az yanıtlanan soru kaldı: doğrulanabilir olan her şey aynı zamanda çözülebilir mi. Sonraki ders bu soruyu ifade eder ve ölçemeyeceğini ölçmeye çalışmaz. Ölçebildiği tek şey bilinen en iyi yordam ile bilinen alt sınır arasındaki farktır; o fark daraltılabiliyor mu, daraltılınca kapanıyor mu, ve daralmanın kendisi bir yön göstergesi sayılabilir mi.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.