youproof.orgDeep Math. Human Access.
Sakk-készlet görbített sakktáblán

Episode I

Alice és Bob

8. fejezet

Alice és Bob biztonsága

Az előző fejezetben tovább osztályoztuk az algoritmikusan eldönthető problémákat aszerint, hogy a döntés milyen hatékonysággal hozható meg. Azt mondtuk, hogy hatékonyság szempontjából az a vízválasztó, hogy egy problémára létezik-e polinomiális időkomplexitású algoritmus vagy nem. Mutattunk néhány problémát, amelyekre jelenleg nem ismeretes ebben az értelemben hatékony algoritmus. Megismerkedtünk a és problémaosztályokkal. Előbbibe azokat a problémákat soroltuk, amelyek eldönthetőek polinomiális időkomplexitású determinisztikus Turing-géppel. Utóbbiba pedig azokat, amelyekkel ugyanez megtehető nemdeterminisztikus Turing-géppel.

A tanú-tételt ismertetve megmutattuk, hogy ez utóbbi ekvivalens azoknak a problémáknak az osztályával, amelyek esetén az "igen" válasznak létezik polinomiális időben, determinisztikus Turing-géppel ellenőrizhető bizonyítéka. Végül megemlítettük a számítástudomány legjelentősebb megválaszolatlan kérdését, miszerint vajon e két problémaosztály megegyezik-e, vagy az általunk nehéznek gondolt problémák valóban nehezek. Ennek megválaszolása ugyanis kulcsfontosságú a kriptográfia szempontjából. De még ha nem is tudjuk ezt a kérdést jelenleg megválaszolni, miért lehetünk majdnem biztosak abban, hogy ? Hogyan tudjuk az algoritmikus problémák nehézségét összehasonlítani egymással? Melyek azok a problémák, amelyek minden más -beli problémánál nehezebbek ilyen értelemben? Ebben a fejezetben erről lesz szó...

Figyelem! Ennek a fejezetnek a megértéséhez erősen ajánlott elolvasni a 6. és a 7. fejezeteket is.

Most visszanyúlunk az előző fejezetben ismertetett két nehéznek gondolt döntési problémához. A 3-színezhetőség problémája így hangzott: adott egy gráf, amelyről el kell dönteni, hogy a csúcsai kiszínezhetők-e legfeljebb színnel úgy, hogy a szomszédos csúcsok különböző színűek legyenek. Azokat a gráfokat, amelyekre ez teljesül, 3-színezhető gráfoknak neveztük. A k-függetlenség problémája pedig így hangzott: adott egy gráf és egy egész szám, és azt kell eldönteni, hogy ki lehet-e választani a gráfból darab csúcsot úgy, hogy ezek között a csúcsok között ne legyen él. Ezt úgy is mondhatjuk, hogy található-e a gráfban darab független csúcs. Azokat a gráfokat, amelyekre ez teljesül, k-független gráfoknak neveztük.

Mivel mindkét fenti probléma igencsak fontos az informatikában, ezért eléggé fájó, hogy egyikre sem ismeretes polinomiális időkomplexitású – azaz hatékony – algoritmus. E két döntési probléma között azonban algoritmikus komplexitási kapcsolat mutatható ki. Nevezetesen: bizonyítható, hogy az egyik "legalább olyan nehéz", mint a másik. Ez azt jelenti, hogyha a "nehezebbre" található polinomiális algoritmus, akkor a "könnyebbre" is. Megfordítva, ha a "könnyebbre" nem található polinomiális algoritmus, akkor a "nehezebbre" sem. De mit jelent pontosan, hogy egy döntési probléma "legalább olyan nehéz", mint egy másik?

Problémák nehézségének összehasonlítása

Ennek megértéséhez döntési problémák helyett ismét az őket reprezentáló formális nyelvekre koncentrálunk, és bevezetjük az úgynevezett Karp-redukció fogalmát. Képzeljük el, hogy van két rekurzív nyelvünk, nevezzük őket -nek és -nak. Ezen kívül tegyük fel, hogy egy olyan rekurzív függvény, amely az összes -beli jelsorozathoz -beli jelsorozatot, míg az összes -en kívüli jelsorozathoz -n kívüli jelsorozatot rendel. A 7.6. szakaszban a tanú-tétel bizonyításánál alkalmazott "akkor és csak akkor" típusú mondatszerkezettel ez így fogalmazható meg: egy tetszőleges jelsorozat akkor és csak akkor mondata az nyelvnek, ha az jelsorozat mondata a nyelvnek.

A 8.1. ábrán egy ilyen tulajdonságú függvény által megvalósított hozzárendelés látható két konkrét jelsorozatra: az jelsorozat mondata az nyelvnek, ezért is mondata a nyelvnek, továbbá az jelsorozat nem mondata az nyelvnek, ezért sem mondata a nyelvnek.

Nyelvbetartozást megtartó függvény
8.1. ábra: Nyelvbetartozást megtartó függvény

Mint ahogyan azt a 7.6. szakaszban már láttuk, az "akkor és csak akkor" a matematikában egy igen szigorú mondatszerkezet, és sokkal többet jelent annál, mint egy sima "ha … akkor" típusú mondat. A fenti "akkor és csak akkor" típusú állítás egyrészt azt jelenti, hogy ha egy jelsorozat eleme az nyelvnek, akkor az jelsorozat eleme a nyelvnek. Ezen túlmenően azonban azt is jelenti, hogy ha egy jelsorozat nem eleme az nyelvnek, akkor az jelsorozat sem eleme a nyelvnek. A 8.2. ábrán látható függvény mindkét tulajdonságot megsérti.

Nyelvbetartozást megsértő függvény
8.2. ábra: Nyelvbetartozást megsértő függvény

Azaz vagy egyszerre mindkettő állítás teljesül, vagy egyik sem, de olyan nincs, hogy az egyik igen, a másik pedig nem. De miért is olyan jó dolog ilyen függvényt találni?

Képzeljük el azt a szituációt, hogy egy olyan algoritmust szeretnénk készíteni, amely eldönti az nyelvbe tartozást, de sehogyan sem jövünk rá a megoldásra. Van viszont algoritmusunk a nyelvbe tartozás eldöntésére. Ha sikerülne találnunk egy olyan rekurzív függvényt, amely teljesíti a fenti tulajdonságot, akkor tulajdonképpen meglenne az algoritmusunk eldöntésére is. Ha ugyanis egy jelsorozatra el kell dönteni, hogy -be tartozik-e, nincs más dolgunk, mint kiszámítani az jelsorozatot, majd erre a jelsorozatra lefuttatni a már létező, -ba tartozást eldöntő algoritmust. Ennek "igen" vagy "nem" válasza egyben megválaszolja az jelsorozat -be tartozásának kérdését is az függvény fenti tulajdonsága miatt. Ráadásul minden jelsorozatra véges időn belül megkapjuk a választ, hiszen az függvény rekurzív, tehát létezik olyan őt kiszámító Turing-gép, amely soha nem keveredik végtelen ciklusba.

Ha a fentieken kívül az függvényre még az is teljesül, hogy polinomiális időkomplexitású Turing-géppel kiszámítható, akkor azt mondjuk, hogy az függvény az nyelv Karp-redukciója a nyelvre. Ennek a fogalomnak a segítségével lényegében összehasonlíthatóvá válnak a döntési problémák a nehézségük szempontjából. Egy ilyen Karp-redukció létezése ugyanis azt jelenti, hogy az nyelv felismerése nem lényegesen nehezebb, mint a nyelv felismerése, leszámítva egy polinomiális időkomplexitású kis extra munkát, amit az függvény kiszámítása jelent. Az nyelv Karp-redukcióját a nyelvre így jelöljük: . Most példaként megadunk egy Karp-redukciót a 3-színezhetőség és a k-függetlenség eldöntésének problémája között.

Példa Karp-redukcióra

Ehhez egy olyan polinomiális időkomplexitású algoritmust kell találnunk, amely egy tetszőleges gráfból (azaz a 3-színezhetőség problémájának egy példányából) előállít egy gráfot és egy egész számot (azaz a k-függetlenség problémájának egy példányát), méghozzá úgy, hogy a gráf akkor és csak akkor legyen k-független, ha a gráf 3-színezhető. Az "akkor és csak akkor" mondatszerkezetet ismét a 8.1. szakaszban már említett szigorú értelemben kell venni.

A gráf és a egész szám előállítása -ből (tehát maga a Karp-redukció) a következő: másoljuk le a gráfot három példányban, és kössük össze azokat a csúcsokat éllel, amelyek ugyanannak az eredeti -beli csúcsnak a másolatai. Az így kapott "nagy" gráf legyen a , valamint értéke legyen az eredeti gráf csúcsainak száma, azaz jelen esetben .

A 8.3. ábrán egy konkrét problémapéldány konverziója látható. Itt jelen esetben a gráf egy öt csúcsból álló kör, de a gondolatmenetünk bármilyen tetszőleges gráfra alkalmazható.

Példa Karp-redukcióra
8.3. ábra: Példa Karp-redukcióra

A fenti gráf a 3-színezhetőség problémának egy konkrét példánya, a csúcsokhoz rendelt , és számok a gráf egy konkrét színezését jelölik. Ebből a fenti Karp-redukció szerint képeztük a lenti gráfot és a egész számot, mint a k-függetlenség problémájának egy példányát. A gráf vízszintes szintjei a gráf kiterített másolatai. Mindegyik -beli színhez tartozik egy szint a gráfban: a színhez a felső, az színhez a középső, a színhez pedig az alsó szint. A függőleges irányítású élek azokat a csúcsokat kötik össze, amelyek ugyanannak a -beli csúcsnak a másolatai.

Most kezdjünk el végigmenni a gráf csúcsain szép sorban, és mindegyikhez jelöljük meg az ő -beli színének megfelelő szinten lévő másolatát a gráfban. Az így megjelölt csúcsokat vastagított körökkel jelöltük. Például -ben az csúcs színe , ezért jelöljük meg -ban az csúcsot. Hasonlóan, a csúcs színe , ezért jelöljük meg a csúcsot. És így tovább. Mire az eljárás végére érünk, épp darab csúcs lesz megjelölve, hiszen az eredeti gráfnak épp ennyi csúcsa volt.

Most megmutatjuk, hogy épp egy k-független csúcshalmazt sikerült kijelölnünk -ban, azaz a megjelölt csúcsok között nincs él. Az adott szinten belül azért nincs közöttük él, mivel ha lenne, akkor a -beli eredetijük között is lenne, és így nem kerülhettek volna azonos szintre -ban, mivel kaphatták volna ugyanazt a színt. Függőleges irányú él pedig azért nincs, mert mindegyik oszlopból csak egy csúcsot jelöltünk meg -ban. Ez a gondolatmenet tetszőleges 3-színezhető gráf tetszőleges színezésére működik. Azt tehát már tudjuk, hogy ha a gráf 3-színezhető, akkor a gráf k-független.

Azt kell még megmutatnunk, hogy ha viszont a gráf nem 3-színezhető, akkor a gráf sem lehet k-független. Tegyük fel tehát, hogy a gráf nem 3-színezhető, azaz minimum szín kell a kiszínezéséhez. Ekkor a gráfban sem lehet darab független csúcs, hiszen ha lenne, akkor végigmehetnénk rajtuk, és mindegyikük -beli eredetijét kiszínezhetnénk annak a -beli szintnek megfelelő színnel, amelyben helyet foglalnak. Így viszont -nek egy jó 3-színezését kapnánk, tehát mégiscsak 3-színezhető lenne, és ez ellentmondana a feltételezésünknek.

Természetesen egy Turing-gép vagy valódi számítógép számára ennél jóval pontosabb leírást kéne adnunk a fenti "átalakító" algoritmusra. A lényegen azonban ez nem változtatna. Most vizsgáljuk meg ennek az "átalakító" algoritmusnak a lépésszámát. Könnyen látható, hogy az a bemeneti gráf méretének polinomiális függvénye. Hiszen ha csúcsainak száma , éleinek száma pedig , akkor a belőle létrehozott gráf darab csúcsot és darab élet fog tartalmazni. Másrészt értéke is könnyen számítható, hiszen csak meg kell számolni csúcsait. A fenti "átalakító" algoritmus tehát valóban egy a Karp-redukció a 3-színezhetőségről a k-függetlenség problémájára.

Az NP problémaosztály krémje

A Karp-redukció fogalmának segítségével tehát egy adott nyelv felismerésének feladatát vissza lehet vezetni egy másik nyelv felismerésének feladatára. Egy Karp-redukció létezése azt jelenti számunkra, hogy az nyelv felismerése nem lényegesen nehezebb a nyelv felismerésénél, leszámítva egy polinomiális időkomplexitású extra munkát. Ebből következik, hogy ha felismerésére van polinomiális idejű algoritmusunk, akkor -re is van. Fordítva: ha -re nincs polinomiális algoritmus, akkor -ra sincs. Az nyelvosztály érdekes tulajdonsága, hogy léteznek benne ilyen értelemben "legnehezebb" nyelvek. Ezt világítjuk meg a következő definícióval.

Tegyük fel, hogy egy -beli nyelv. Amennyiben tetszőleges, szintén -beli nyelv esetén létezik Karp-redukció, akkor azt mondjuk, hogy a nyelv NP-teljes. Az NP-teljes nyelvek felismerése tehát "legalább olyan nehéz", mint bármilyen más NP-beli nyelv felismerése. Amennyiben a kérdéses nyelvtől nem követeljük meg, hogy maga is -ben legyen, úgy a nyelvet NP-nehéznek nevezzük. Az NP-teljes nyelvek tehát olyan speciális NP-nehéz nyelvek, amelyek maguk is -ben vannak.

A fenti definíció egyszerű következménye, hogy amennyiben akár egyetlen NP-teljes nyelv eldöntésére is találnánk polinomiális algoritmust, abból következne, hogy . Ha ugyanis akár egyetlen egy NP-teljes nyelv is a osztályban lenne, azaz felismerhető lenne polinomiális időkomplexitású algoritmussal, úgy minden -beli nyelv szintén a osztályban lenne, hiszen az Karp-redukció létezése miatt ebben az esetben az nyelvet is fel tudnánk ismerni polinomiális időkomplexitással. De megfordítva is igaz: amennyiben akár egyetlen NP-teljes nyelvről is kiderülne, hogy nem létezik őt felismerő polinomiális algoritmus, abból következne – azon kívül, hogy nyilván lenne – , hogy egyetlen NP-teljes nyelv felismerésére sem létezik polinomiális algoritmus. Ha ugyanis egy NP-teljes nyelvről bebizonyosodna, hogy a osztályon kívül van, akkor nem létezhet olyan NP-teljes nyelv, ami -ben van, máskülönben az Karp-redukció létezése miatt az nyelvet is fel tudnánk ismerni polinomiális algoritmussal.

Vagyis minden NP-teljes nyelv vagy egyszerre polinomiális vagy egyszerre exponenciális időkomplexitású. Rendkívül sok algoritmikus probléma vezethető vissza NP-teljes nyelvek felismerésének feladatára. Éppen ezért eléggé bosszantó, hogy eddig – számtalan próbálkozás ellenére – egyetlen ilyen nyelvről sem tudtuk bizonyítani egyik eshetőséget sem.

A 8.4. ábrán az eddig megismert bonyolultsági osztályok egymáshoz való viszonya látható esetén.

Bonyolultságtérkép P nem egyenlő NP esetén
8.4. ábra: Bonyolultságtérkép esetén

A 8.5. ábrán pedig esetén.

Bonyolultságtérkép P egyenlő NP esetén
8.5. ábra: Bonyolultságtérkép esetén

E két eshetőség közül a legtöbb matematikus az első elrendezést valószínűsíti. A gyakorlatban is előforduló algoritmikus feladatok között ugyanis nagyon gyakoriak az NP-teljes problémák. A szakirodalomban dokumentált NP-teljes feladatok száma jóval ezer felett van. Azonban ezek intenzív vizsgálata ellenére sem tapasztalható a polinomiális algoritmusok irányába történő legcsekélyebb előrehaladás. Így meglehetősen furcsa lenne, ha kiderülne, hogy ezek mindegyikére létezik hatékony algoritmus. Most mutatunk néhány, a gyakorlatban fontos algoritmikus optimalizálási feladatot, amelyek mind NP-teljes döntési problémákhoz vezetnek.

NP-teljes és NP-nehéz problémák

Az alábbiakban néhány olyan, az informatikában is gyakran felmerülő optimalizálási feladatot ismertetünk, amelyek NP-teljes döntési problémákra vezethetők vissza.

Maximális méretű klikk keresése gráfokban

Egy gráfban klikknek nevezünk egy olyan csúcshalmazt, amelyen belül bármely két csúcs között van él. A feladat egy adott gráfban megtalálni a legnagyobb klikket.

Például a 8.6. ábrán látható gráfban a legnagyobb klikk csúcsból áll, amelyeket fekete körökkel jelöltük.

Gráf 4 méretű maximális klikkel
8.6. ábra: Gráf 4 méretű maximális klikkel

Az ehhez a feladathoz tartozó döntési probléma így hangzik: adott gráf és egész szám esetén létezik-e -ben legalább darab csúcsot tartalmazó klikk? Ez a döntési probléma NP-teljes, amennyiben a bemenet része, azaz nem egy előre rögzített érték, amely az algoritmus létrehozásakor már ismert.

Megjegyezzük azonban, hogy amennyiben egy rögzített érték, úgy ebben az esetben könnyen konstruálhatunk polinomiális időkomplexitású algoritmust. Például ellenőrizhetjük az összes elemű csúcshalmazt, hogy van-e közöttük olyan, amelyik egy klikket alkot -ben. Habár ez egy nem túl hatékony algoritmus, azonban az ellenőrizendő csúcshalmazoknak a száma felülről becsülhető a gráf csúcsainak számának egy polinomjával.

Leghosszabb útvonal keresése gráfokban

Egy gráfban útvonalnak nevezzük csúcsok egy olyan sorozatát, amelyben bármely két egymást követő csúcs között van él, és a csúcsok nem ismétlődnek ebben a sorozatban. A feladat egy adott gráfban megtalálni a lehető leghosszabb (legtöbb élből álló) útvonalat két megadott csúcs között.

A 8.7. ábrán látható példa gráfon vastagított vonallal jelöltük az és csúcsok közötti leghosszabb útvonalat.

Leghosszabb útvonal keresése
8.7. ábra: Leghosszabb útvonal keresése

Az ehhez a feladathoz tartozó döntési probléma így hangzik: adott gráf, valamint csúcsok és egész szám esetén létezik-e -ben legalább hosszúságú útvonal -ból -be? Ez a döntési probléma szintén NP-teljes, amennyiben a bemenet része, azaz nem egy előre rögzített érték, amely az algoritmus létrehozásakor már ismert.

Ez utóbbi esetben viszont ismét könnyen konstruálhatunk polinomiális időkomplexitású algoritmust: egy hosszú útvonal ugyanis csúcsból áll, így ellenőrizhetjük az összes -val kezdődő és -vel végződő elemű csúcsokból álló sorozatot, hogy van-e közöttük olyan, amelyik egy útvonalat alkot -ben. Habár ez szintén egy nem túl hatékony algoritmus, de az ellenőrizendő sorozatoknak a száma ugyanúgy felülről becsülhető a gráf csúcsainak számának egy polinomjával, mint a klikkek esetében.

Érdekes ugyanakkor, hogy a legrövidebb útvonal megtalálására viszont léteznek polinomiális időkomplexitású algoritmusok. A legismertebb példák a használatukra a különböző navigációs alkalmazások útvonalkeresői. Az egyik leggyakrabban használt ilyen eljárás a Dijkstra-algoritmus.

Gráfok színezése

Gráfok színezéséről a 7.1. szakaszban már volt szó. A feladat egy adott gráf csúcsait a lehető legkevesebb szín felhasználásával kiszínezni oly módon, hogy bármely két szomszédos csúcs különböző színű legyen. Az ehhez a feladathoz tartozó döntési probléma így hangzik: adott gráf és egész szám esetén kiszínezhető-e legfeljebb darab szín felhasználásával?

A 7.3. szakaszban már említettük, hogy esetén ennek eldöntésére jelenleg nem ismert polinomiális időkomplexitású algoritmus. Ráadásul nem is várható, hogy bárki felfedez ilyen algoritmust, ugyanis esetén ez a döntési probléma is NP-teljes még abban az esetben is, ha nem a bemenet része, hanem egy előre rögzített érték.

Független csúcshalmaz keresése gráfokban

A független csúcsok problémájáról a 7.3. szakaszban volt szó. A feladat egy adott gráf csúcsai közül kiválasztani a lehető legtöbbet úgy, hogy ezek között ne legyen két egymással szomszédos csúcs. Az ehhez a feladathoz tartozó döntési probléma így hangzik: adott gráf és egész szám esetén létezik-e -ben legalább darab csúcsot tartalmazó független csúcshalmaz?

A 7.3. szakaszban már említettük, hogy ennek eldöntésére sem ismert polinomiális időkomplexitású algoritmus. Valószínű, hogy nem is létezik, ugyanis ez a döntési probléma is NP-teljes, amennyiben a bemenet része, azaz nem egy előre rögzített érték, amely az algoritmus létrehozásakor már ismert.

Ez utóbbi esetben viszont – hasonlóan a maximális klikkméretre és leghosszabb útvonalakra vonatkozó döntési problémák esetén – könnyen konstruálhatunk polinomiális időkomplexitású algoritmust. Például ellenőrizhetjük az összes elemű csúcshalmazt, hogy van-e közöttük olyan, amelyik egy független csúcshalmazt alkot -ben. Az ellenőrizendő csúcshalmazoknak a száma ezúttal is felülről becsülhető a gráf csúcsainak számának egy polinomjával.

Az utazóügynök-probléma (egyszerűsített változat)

A feladat egy adott gráfban olyan útvonal keresése, amelyben a gráf összes csúcsa pontosan egyszer szerepel. Az ilyen útvonalakat Hamilton-útvonalaknak nevezzük. Az ehhez a feladathoz tartozó döntési probléma így hangzik: adott egy gráf, és el kell dönteni, hogy létezik-e benne Hamilton-útvonal. Ez a döntési probléma is NP-teljes.

Az utazóügynök-probléma a logisztikai problémákon túl nagy gyakorlati jelentőséggel bír például a nyomtatott áramkörök gyártása során alkalmazott fúrórobotok ideális mozgásának megtervezésében. De ezen kívül is rengeteg optimalizálási feladat vezethető vissza rá.

A hátizsák-probléma

Adott valahány darab tárgy, mindegyiknek meg van adva a súlya és az értéke, valamint adott egy valamilyen teherbírású hátizsák. A feladat a tárgyakból minél nagyobb összeértékű részhalmazt belepakolni a hátizsákba úgy, hogy ne lépjük át a súlyhatárt. Ezzel rokon probléma, amikor különböző méretű dobozokat kell bepakolni egy adott méretű szekrénybe úgy, hogy minél jobban kihasználjuk a rendelkezésre álló helyet. Ki ne bosszankodott volna például, amikor nyaralás előtt minél több mindent szeretett volna bepakolni a csomagtartóba? Most már tudjuk, hogy a bosszankodás oka az volt, hogy ez is egy NP-teljes döntési problémához vezet.

Az NP-nehéz problémák kezelése

Jogosan merül fel a kérdés, hogy mitévők legyünk akkor, ha munkánk során olyan problémába ütközünk, amely bizonyítottan NP-nehéz. Ez ugyanis viszonylag gyakran előfordul, mégsem kell ezen problémák megoldásáról teljesen lemondanunk.

Az egyik lehetőség, hogy megvizsgáljuk, milyen méretű bemenetek várhatók a gyakorlati alkalmazás során, és olyan exponenciális időkomplexitású algoritmust keresünk, amely e bemenetméretek esetén is elfogadható idő alatt lefut. Erről a lehetőségről bővebben a 7.2. szakaszban volt szó.

Előfordulhat az is, hogy egy, a gyakorlatban felmerülő NP-nehéz problémáról kiderül, hogy valójában csak egy speciális esetét kell kezelnünk, amire már elképzelhető, hogy létezik polinomiális algoritmus.

Bevett módszer az is, hogy a problémára optimális, de lassú eljárás helyett az optimumnál rosszabb eredményt produkáló, de gyors algoritmust próbálunk keresni. Amennyiben bizonyítani tudjuk, hogy a gyors algoritmus eredményének az optimálistól való eltérése adott korlát alatt marad, úgy közelítő algoritmusról beszélünk.

Végül előfordulhat, hogy sikerül gyors algoritmust találnunk, amely közelíti ugyan az optimumot, de nem tudjuk bizonyítani azt, hogy a közelítés hibája adott korlát alatt marad, azonban a tapasztalat azt mutatja, hogy megfelelő eredményt ad a legtöbb esetben. Ezeket heurisztikus algoritmusoknak nevezzük.

A Cook-Levin tétel

Előfordulhat, hogy egy algoritmikus problémát próbálunk megoldani, de sehogyan sem sikerül hatékony algoritmust találnunk. Ekkor jó lenne megnyugtatni magunkat, hogy ez nem azért nem sikerül, mert bénák vagyunk, hanem esetleg azért, mert maga a probléma NP-teljes. De hogyan tudnánk ezt igazolni? Ehhez a 8.3. szakaszban leírtak szerint az összes létező -beli problémáról meg kéne mutatnunk, hogy Karp-redukcióval visszavezethető az általunk vizsgált problémára.

Szerencsére van egy ennél egyszerűbb módszer is, amely azon az észrevételen alapszik, miszerint az NP-teljesség a Karp-redukción keresztül "öröklődik". Ez a következőt jelenti: amennyiben egy nyelv NP-teljes, egy nyelv pedig -ben van, továbbá létezik egy Karp-redukció, akkor a nyelv is NP-teljes.

Ezt kihasználva tehát egy nyelv NP-teljességének bizonyításához nem szükséges, hogy redukáljuk az összes -beli nyelvet -ra, elegendő ezt megtenni egyetlen NP-teljes nyelvvel. Vegyünk ugyanis egy tetszőleges -beli nyelvet. Mivel a fenti öröklési tulajdonságban szereplő nyelv NP-teljes, ezért az nyelv felismerését polinomiális idejű extra munkával redukálni tudjuk az nyelv felismerésére. Ha az nyelv felismerését szintén polinomiális időben tovább tudjuk redukálni a nyelv felismerésére, akkor e két redukció egymás utáni alkalmazásával tulajdonképpen az nyelvet is redukálni tudjuk -ra polinomiálisan, azaz valóban NP-teljes.

Az öröklési tulajdonság alkalmazásához azonban szükségünk van legalább egy NP-teljes nyelvre, amiről tovább örökíthetnénk ezt a tulajdonságot más nyelvekre. Kiemelt jelentőségű volt emiatt Stephen Cook és Leonid Levin 1971-es eredménye, amely az első NP-teljes nyelvet mutatta meg. Ez az eredmény Cook-Levin tétel néven ismeretes. Ez a nyelv az úgynevezett kielégíthető logikai hálózatok nyelve. Egy logikai hálózat úgynevezett logikai kapukból és a közöttük lévő összeköttetésekből épül fel. Egy logikai kapunak vannak bemenetei, amelyek kétféle logikai értéket vehetnek fel: 1 vagy 0 (igaz vagy hamis). Ezenkívül van egy kimenete, amelyen a kapu szintén egy logikai értéket állít elő a típusának és a bemenetein lévő logikai értékeknek a függvényében.

Egy hálózat építéséhez 3 féle logikai kaput használhatunk:

  • ÉS-kapu: két bemenete van, a kimenetén pedig akkor és csak akkor állít elő 1-et, ha mindkét bemenetének értéke 1.
  • VAGY-kapu: szintén két bemenete van, a kimenetén pedig akkor és csak akkor állít elő 1-et, ha legalább az egyik bemenetének értéke 1.
  • NEM-kapu: egy bemenete van, a kimenetén pedig akkor és csak akkor állít elő 1-et, ha a bemenetének értéke 0.

E háromféle kapu működését az úgynevezett igazságtáblázatukkal adhatjuk meg, amely minden lehetséges bemeneti kombinációra megadja, hogy mi lesz a kimeneten.

A 8.8. ábrán az ÉS-kapu igazságtáblázata és jelölése látható.

ÉS-kapu jelölése és igazságtáblázata
8.8. ábra: ÉS-kapu jelölése és igazságtáblázata

A 8.9. ábrán a VAGY-kapu igazságtáblázata és jelölése látható.

VAGY-kapu jelölése és igazságtáblázata
8.9. ábra: VAGY-kapu jelölése és igazságtáblázata

Végül a 8.10. ábrán a NEM-kapu igazságtáblázata és jelölése látható.

NEM-kapu jelölése és igazságtáblázata
8.10. ábra: NEM-kapu jelölése és igazságtáblázata

Egy logikai hálózat e kapuk segítségével a hálózat darab bemenetéből egy kimenetet állít elő. Egy kapu bármely bemenetére akármelyik másik kapu kimenetét, vagy közvetlenül a logikai hálózat valamely bemenetét köthetjük. Hasonlóan egy kapu kimenetét akármelyik másik kapu (vagy kapuk) bemenetére, vagy közvetlenül a logikai hálózat kimenetére köthetjük. Mindössze két megkötés van. Egyrészt minden kapu-bemenetre illetve a hálózat kimenetére is pontosan egy jel lehet kötve. Másrészt a hálózat tetszőleges bemenetétől a hálózat kimenetéhez vezető útvonalak mentén minden kapu legfeljebb egyszer fordulhat elő. Azaz nem lehetnek "hurkok" a hálózatban. Akkor beszélünk kielégíthető logikai hálózatról, ha létezik a bemeneteinek olyan kombinációja, amelyre a hálózat a kimenetén a logikai 1 értéket állítja elő.

A 8.11. ábrán egy 3 bemenetű logikai hálózatot láthatunk egy ilyen "kielégítő" bemeneti kombinációval.

Kielégíthető logikai hálózat (példa)
8.11. ábra: Kielégíthető logikai hálózat (példa)

A logikai 1 értéket hordozó összeköttetéseket megvastagítottuk, így könnyen látható, hogy ez a bemeneti kombináció valóban a kimenetet eredményezi. Ezek után a döntési feladatunk egy tetszőleges logikai hálózatról eldönteni, hogy kielégíthető-e a fenti értelemben. Formális nyelvekre átfogalmazva: nevezzük -nak az olyan jelsorozatokat tartalmazó nyelvet, amelyek egyrészt valamilyen logikai hálózat leírásai, másrészt az általuk leírt logikai hálózat a fenti értelemben kielégíthető. A feladatunk pedig egy olyan Turing-gép létrehozása, amely tetszőleges jelsorozatra eldönti, hogy a nyelvbe tartozik-e. A Cook-Levin tétel állítása a következő: a nyelv NP-teljes.

Annak bizonyítása viszonylag egyszerű, hogy a nyelv -ben van, hiszen egy helyes kiértékelés – mint tanú – ellenőrzése hatékonyan megoldható, ahogy azt az olvasó a fenti példából érzékelhette. Az NP-teljességhez azonban azt is bizonyítani kell, hogy tetszőleges -beli nyelvről létezik Karp-redukció a nyelvre. A Cook-Levin tétel bizonyítása lényegében egy olyan polinomiális időkomplexitású algoritmus leírása, amely egy tetszőleges -beli nyelvhez és tetszőleges jelsorozathoz konstruál egy jelsorozatot (azaz az általa leírt logikai hálózatot) úgy, hogy az jelsorozat akkor és csak akkor tartozik -be, ha az jelsorozat -ba tartozik (azaz az általa leírt logikai hálózat kielégíthető).

A bizonyítás leírása hosszadalmas és erősen technikai jellegű, ezért ettől most eltekintünk. Arra azonban érdemes felhívni a figyelmet, hogy ezek szerint tetszőleges -beli döntési probléma egy adott példányát le lehet írni egyetlen logikai kifejezéssel, vagy egy azt reprezentáló logikai hálózattal. Ez jól mutatja a logika kifejező erejét.

Ezen túlmenően a nyelv NP-teljességének önmagában is komoly jelentősége van. A valódi számítógépek integrált áramkörei ugyanis szintén a fentihez hasonló – persze annál lényegesen bonyolultabb – logikai hálózatokat valósítanak meg. Ezek optimalizálása épp az NP-teljesség miatt általában nem egyszerű. Optimalizálás alatt ebben az esetben ugyanannak a logikai hálózatnak a minél kevesebb logikai kapu használatával történő megvalósítását értjük.

A Cook-Levin tétel fontossága azonban elsősorban abban nyilvánul meg, hogy szinte az összes többi NP-teljességi bizonyítás – például a 8.4. szakaszban már említett 3-színezhetőség vagy k-függetlenség NP-teljessége is – közvetetten vagy közvetlenül a nyelv NP-teljességén alapszik.

Egy meglepő fordulat

2015 novemberében Babai László, a Chicagoi Egyetem professzora bejelentette, hogy egy úgynevezett kvázipolinomiális időkomplexitású algoritmust talált a matematikusokat évtizedek óta foglalkoztató gráf-izomorfizmus problémára. A "kvázipolinomiális" fogalmát itt most nem részletezzük, azonban megpróbáljuk érzékeltetni a felfedezés jelentőségét.

Egy és gráfra akkor mondjuk, hogy izomorfak egymással, ha a csúcshalmazaik között létezik olyan kölcsönösen egyértelmű megfeleltetés, amely megőrzi az éleket illetve azok hiányát is. Ha tehát -ben veszünk két szomszédos csúcsot, akkor a nekik megfeleltetett csúcsok szintén szomszédosak lesznek -ban. Ugyanígy ha a két csúcs nem volt szomszédos -ben, akkor a nekik megfeleltetett csúcsok szintén nem szomszédosak -ban. A kölcsönösen egyértelműség pedig azt jelenti, hogy minden csúcsához pontosan egy csúcs van hozzárendelve -ban, és minden csúcsa pontosan egy -beli csúcshoz van hozzárendelve. Ilyenkor azt mondjuk, hogy a két gráf lényegében ugyanaz, maximum máshogyan lettek felrajzolva, vagy máshogyan neveztük el a csúcsaikat. Ilyenkor ezt a két csúcshalmaz közötti struktúratartó megfeleltetést – vagy ha úgy tetszik, függvényt – izomorfizmusnak nevezzük.

A 8.12. ábrán látható két gráf például izomorf egymással, még ha ez nem is látszik elsőre. Az izomorfizmus alapján egymáshoz rendelt csúcsokat azonos számokkal láttuk el.

Izomorf gráfok (példa)
8.12. ábra: Izomorf gráfok (példa)

A 8.13. ábrán látható két gráf viszont nem izomorf egymással.

Nem izomorf gráfok (példa)
8.13. ábra: Nem izomorf gráfok (példa)

A gráf-izomorfizmus probléma ezek után így fogalmazható meg: adott két gráf, és el kell dönteni, hogy izomorfak-e vagy sem. Mindezidáig nagyon úgy tűnt, hogy ez egy rendkívül nehéz algoritmikus feladat nagy gráfok esetén. Ilyen esetekben korábban mindig az történt, hogy egy nehéznek tűnő problémáról vagy bebizonyosodott, hogy mégis hatékonyan kezelhető (azaz -beli), vagy pedig az, hogy NP-teljes.

Sokáig nyitott volt például az a kérdés, hogy egy egész számról eldönthető-e hatékonyan, hogy prímszám-e vagy összetett. 2002-ben azonban 3 indiai matematikus, Manindra Agrawal, Neeraj Kayal és Nitin Saxena felfedeztek egy polinomiális algoritmust ennek eldöntésére. Ennek neve a felfedezők neveinek kezdőbetűi után AKS-prímteszt, amelyről a 26.11. szakaszban lesz szó bővebben. Eddig is voltak természetesen prímtesztelő algoritmusok, hiszen – mint azt a 23. fejezetben látni fogjuk – fontos jelentőségük van a rejtjelezésben. De ezek mind csak bizonyos valószínűséggel adják meg a választ, azonban ritkán előfordulhat, hogy tévednek. A gyakorlatban továbbra is ezeket a potenciálisan tévedő eljárásokat használjuk prímtesztelésre, mivel jóval gyorsabbak, mint az AKS-algoritmus, és a tévedés valószínűsége az alkalmazás szempontjából elhanyagolható. Az AKS-algoritmusnak inkább elméleti jelentősége van, mivel megmutatta, hogy egy addig nehéznek tartott probléma nemhogy nem NP-teljes, de egyenesen -beli. Jóval gyakoribbak azonban azok az esetek, amikor egy nehéznek gondolt problémáról kiderül, hogy valóban NP-teljes.

Babai publikációját éppen ezért a matematikus társadalom, mint az évtized legnagyobb számítástudományi áttörését ünnepelte. Ebből az eredményből ugyanis nagyon úgy tűnik – még ha egyértelműen nem is következik belőle –, hogy a gráf-izomorfizmus problémája se nem NP-teljes, se nem -beli, azaz valahol a kettő között helyezkedhet el. Ha ez valóban így van, akkor ez lenne az első ilyen tulajdonságú probléma, amit felfedeztek, ráadásul a sejtésre is megadná végre a választ. Erre azonban egyelőre még várni kell.

De hogy jön ide a kriptográfia?

Ahhoz, hogy Alice és Bob biztonságosan tudjanak egymással kommunikálni egy olyan csatornán keresztül, amelyet a gonosz Eve képes lehallgatni, szükségük van valamilyen rejtjelezési eljárásra. Ezen kívül szükségük van egy kulcsnak nevezett közös titokra is, amellyel az alkalmazott rejtjelezési eljárást paraméterezni fogják. A rejtjelezési eljárással szembeni legfontosabb követelmény, hogy a kulcs ismeretében "könnyű", annak hiányában viszont "nehéz" algoritmikus feladat legyen a rejtjelezett üzenetek dekódolása. A 6. és 7., valamint az ebben a fejezetben felvázolt bonyolultságelméleti fogalmak ismeretében az Olvasónak mostmár remélhetőleg világos, hogy pontosan mit értünk "könnyű" illetve "nehéz" algoritmikus feladat alatt.

Ezen túlmenően Alice-nak és Bob-nak azt a problémát is meg kell oldania, hogy hogyan tudnak megállapodni ebben a kulcsnak nevezett közös titokban anélkül, hogy személyesen találkozniuk kellene egymással. Ezt a kulcsmegosztás problémájának nevezzük. Ehhez a megállapodáshoz nyilván csak a nembiztonságos csatornát használhatják. De mégis hogyan lehetséges az, hogy a kulcsban való megállapodás érdekében küldött üzeneteket Eve ugyanúgy el tudja olvasni, mint Alice és Bob, mégsem tudja megfejteni magát a kulcsot – pontosabban fogalmazva az egy algoritmikusan roppant "nehéz" feladat a számára?

Erre a látszólagos paradoxonra a számelmélet fogja megadni a választ a következő fejezetekben. A számelmélet évezredekig a matematikának látszólag egy haszontalan területe volt. A 20. század második felére azonban az információs társadalom alapjává vált. Már most megemlítjük azonban, hogy ebben kulcsfontosságú szerepet játszik az úgynevezett prímfaktorizáció feladatának látszólagos algoritmikus nehézsége. Ezen áll vagy bukik ugyanis az egész. A prímszámokról és a prímfaktorizációról bőven lesz még szó a következő fejezetekben. Azt azonban mindenképpen fontosnak tartom megemlíteni ezen a ponton, hogy a prímfaktorizáció feladatáról még nem bizonyított, hogy NP-teljes lenne.

Babai eredménye után jogosan vetődik fel a kérdés: lehetséges, hogy a prímfaktorizáció problémája is a és az NP-teljes problémaosztály között helyezkedik el valahol? Netán egyenesen -beli? A választ nem tudjuk, de nagyon reméljük, hogy nem így van. Egy ilyen felfedezés ugyanis alapjaiban változtatná meg a jelenleg használt rejtjelezési eljárások biztonságába vetett hitünket. Ezen a ponton érdemes feltenni a kérdést, hogy vajon valóban senki nem tudja a választ? Vajon ha igenlő lenne a válasz, és valaki rájönne egy hatékony prímfaktorizációs algoritmusra, biztosan publikálná-e a tudományos közösség számára? Vagy megpróbálna inkább titokban hasznot húzni belőle? Az Olvasó vajon mit tenne?

Ebben a fejezetben tehát megismertük a Karp-redukció fogalmát, amelynek segítségével összehasonlíthatóvá válnak az algoritmikus problémák a nehézségük szempontjából. Definiáltuk az NP-teljes problémák osztályát, amelyekről ugyan nem tudjuk biztosan, hogy valóban olyan nehezek-e, mint amilyennek látszanak, de megmutattuk, hogy miért lenne rendkívül meglepő, ha mégsem ez lenne a helyzet. Most már van egy átfogó képünk arról, hogy mit tekintünk algoritmikusan "nehéz" vagy "könnyű" feladatnak. A 9. és a 10. fejezetekben felvázoljuk egy olyan rejtjelező rendszer alapjait, amellyel Alice és Bob meg tudja oldani a kulcsmegosztás problémáját anélkül, hogy személyesen találkozniuk kéne. Ez a rendszer továbbá az 5.5. szakaszban bemutatott Mallory, mint aktív támadó elleni védelemben is komoly szerepet játszik, mint azt látni fogjuk.