předpokládáme konečnost a malou konstantní velikost
slova/řetězce α,β,γ,…
znaky a,b,c…
délka řetězce ∣α∣
prázdný řetězec ε
∣ε∣=0
zřetězení αβ
i-tý znak α[i] (počítáme od nuly)
podřetězec α[i:j] (od i-tého znaku do (j-1). znaku včetně)
prefix α[:j]=α[0:j]
suffix α[i:]=α[i:∣α∣]
α[:]=α
pozorování
prázdný řetězec je prefixem i suffixem jakéhokoliv řetězce
každý řetězec je prefixem i suffixem sebe sama
každý podřetězec se dá zapsat jako prefix nějakého suffixu nebo suffix nějakého prefixu
jak najít jehlu
můžeme hledat jehlu na každém indexu sena → Θ(J⋅S)
můžeme po nenalezení přeskočit dál → nefunguje, viz seno "clanekokokosu", jehla "kokos"
postupně si vytváříme seno
df: stav algoritmu := nejdelší prefix jehly, který je suffixem sena
…
hledání více jehel v kupce sena – algoritmus Aho-Corasicková
automat = trie
stavy = prefixy jehel
dopředné hrany = přidání jednoho znaku na konec (α→αx)
konce jehel (označíme v trii)
zpětné hrany – vedou z α do nejdelšího vlastního suffixu α, který je stavem (tohle obvykle v trii nebývá)
zkratkové hrany – vedou z α do nejbližšího stavu dosažitelného po zpětných hranách, kde končí jehla
reprezentace automatu
stavy očíslujeme – kořen má číslo 0, ostatní vrcholy libovolná různá
pole Dopředu(stav, písmenko) – obsahuje další stav (podle dopředné hrany)
pole Slovo(stav) – končí v daném stavu slovo?
pole Zpět(stav) – číslo stavu, kam vede zpětná hrana (kromě kořene je vždy právě jedno)
pole Zkratka(stav) – číslo stavu, kam vede zkratková hrana
algoritmus
…
Robinův-Karpův algoritmus
hledání jedné jehly (?)
zahashuju si posloupnost J znaků a porovnám s hashem jehly
postupně přehashovávám pro každý takový úsek sena (hashování v lineárním čase, přehashování v konstantním)
průměrná časová složitost Θ(J+S+JV+MSJ) pro rovnoměrnou hashovací funkci
přesnější odhad nebude na zkoušce
Toky v síti
graf
máme zdroj a spotřebič (vrcholy)
trubky (hrany) mají kapacitu (ohodnocení)
trubky jsou orientované
df: síť je čtveřice
orientovaný graf (V,E)
BÚNO symetrický (uv∈E⟹vu∈E)
chybějící hrana má jakoby nulovou kapacitu
zdroj z∈V
spotřebič s∈V,s=z
kapacity c:E→R0+
df: tok je funkce f:E∈R0+ taková, že
∀e∈E:f(e)≤c(e)
Kirchhoffův zákon (zákon zachování, tekutina se nám nikam neztrácí) … ∀v∈V,v=z,s:fΔ(v)=0
df: pro v∈V
přítok f+(v):=∑uv∈Ef(uv)
odtok f−(v):=∑vw∈Ef(vw)
přebytek fΔ(v):=f+(v)−f−(v)
df: velikost toku ∣f∣:=fΔ(s)
pozorování: fΔ(s)=−fΔ(z)
…
df: toku f přiřadíme průtok f∗
f∗(uv):=f(uv)−f(vu)
pozorování
f∗(uv)=−f∗(vu)
f∗(uv)≤c(uv)
−c(vu)≤f∗(uv)
∀v=z,s:∑uv∈Ef∗(uv)=0
tzn. pro takové v platí ∑uv∈Ef∗(uv)=fΔ(v)
r(uv):=c(uv)−f(uv)+f(vu)=c(uv)−f∗(uv)
lemma: pokud funkce f∗:E→R splňuje tato pozorování, pak existuje tok f, jehož průtokem je f∗
důkaz
uv,vu∈E
BÚNO f∗(uv)≥0
f(uv):=f∗(uv)
f(vu)=0
takže můžeme místo s toky počítat s průtoky, přičemž si to pak ekvivalentně převedeme na toky
df: k síti (V,E,z,s,c) a toku f v ní je síť rezerv (V,E,z,s,r), kde r=c−f∗
lemma: pro každý tok f v síti S a každý tok g v síti R(S,f) existuje tok h v síti S takový, že ∣h∣=∣f∣+∣g∣ a h lze najít v čase O(m)
m … počet hran
důkaz: h∗:=f∗+g∗
h∗(uv)=f∗(uv)+g∗(uv)
g∗(uv)≤r(uv)≤c(uv)−f∗(uv)
…
df: tok f je blokující ≡ pro každou cestu P ze z do s existuje e∈P taková, že f(e)=c(e)
df: síť S je vrstevnatá (pročištěná) ≡ každý vrchol i hrana leží na nějaké nejkratší cestě ze z do s
Dinicův algoritmus O(n2m)
f← všude nulový tok
opakujeme (tyto kroky tvoří jednu fázi)
R← síť rezerv vzhledem k f
smažeme z R nulové hrany
pročistíme R
pokud R=∅, skončíme
g← blokující tok v R
vylepšíme f pomocí g
vrátíme f
čištění sítě O(m)
pomocí BFS ze z rozdělíme graf na vrstvy
smažeme vrstvy za s
smažeme hrany, které nevedou o vrstvu vpřed (tzn. ty, které vedou o vrstvu zpět a které vedou uvnitř vrstvy)
smažeme slepé uličky (pomocí fronty)
každý vrchol a každá hrana se účastní nejvýš jednou
blokující tok O(nm)
g←0 (tok, který je všude nulový)
dokud existuje P cesta ze z do s v R
ε←mine∈P(r(e)−g(e))
∀e∈P:g(e)←g(e)+ε a pokud g(e)=r(e), hranu e smažeme
dočistíme síť (kdykoliv smažu hranu, musím se zbavit slepých uliček)
vrátíme g
složitost
krok cyklu (bez čistění) v O(n), cyklus poběží nejvýše m-krát, protože pokaždé smažu alespoň jednu hranu
čištění sítě je za všechny iterace O(m)
lemma: během každé fáze vzroste počet vrstev pročištěné sítě aspoň o jedna
důsledek: počet fází ≤n
intuitivní důkaz (zablokovali jsme cesty dané délky) nefunguje – mezi fázemi nám mohly vzrůst rezervy
rezerva vzroste těm hranám, které vedou o vrstvu zpět
nahlédneme, že žádná cesta, která použije alespoň jednu zpětnou hranu nemůže být krátká
nově vzniklá cesta bude mít aspoň o 2 větší délku než nejkratší cesty
df: f je vlna ≡
∀e∈E:f(e)≤c(e)
∀v=z,s:fΔ(v)≥0
převedení přebytku
fΔ(u)>0
r(uv)>0
δ:=min(fΔ(u),r(uv))
f′(uv):=f(uv)+δ
důsledky
f zůstane vlnou
fΔ(u)−=δ,fΔ(v)+=δ
r(uv)−=δ,r(vu)+=δ
výška h:V→N
Goldbergův algoritmus
f(_)←0
∀zv∈E:f(zv)←c(zv)
h(_)←0,h(z)←n
dokud ∃v=z,s:fΔ(v)>0
pokud ∃vw∈E:r(vw)>0∧h(v)>h(w)
převedeme po vw
jinak h(v)←h(v)+1
vlna: f:E→R0+
f≤c,∀v=z,s:fΔ(v)≥0
převedení po hraně uv
když fΔ(u)>0,r(uv)>0
h(u)>h(v)
tak na hraně uv zvýšíme o δ:=min(r(uv),fΔ(u))
invariant A (základní)
f je vlna
∀v:h(v) neklesá
h(z)=n,h(s)=0
∀v=z:fΔ(v)≥0
invariant S (o spádu)
∄uv∈E:r(uv)>0∧h(u)>h(v)+1
na začátku platí
rozbít se to můžu zvednutím (to se nestane – místo toho se provede převedení) nebo převedením (ale to zvyšuje rezervu jenom do kopce – takže se to taky nemůže stát)
lemma K (korektnosti)
pokud se algoritmus zastaví, finální f je maximální tok
důkaz
f je tok
f je maximální
kdyby nebyl maximální → podle FF existuje nenasycená cesta ze zdroje do spotřebiče
zdroj je ve výšce n, spotřebič ve výšce 0, délka cesty je maximálně n−1, tudíž tam bude hrana se spádem aspoň dva, která ale na nenasycené cestě nemůže existovat
invariant C (cesta do zdroje)
∀v:fΔ(v)>0
∃P nenasycená cesta z v do z
důkaz
A:={t∈V∣∃ nenasycenaˊ cesta v→t}
chceme ukázat z∈A
∑a∈AfΔ(a)=0f(A,A)−≥0f(A,A)
tudíž suma je nekladná
ale v sumě je aspoň jeden prvek kladný
takže tam musí být záporný člen – to je pouze zdroj
invariant V (o výšce)
∀v:h(v)≤2n
invariant C ⟹ invariant V
uvažme první porušení – zvedáme v∈V z výšky 2n
tehdy fΔ(v)>0⟹∃P nenasycená cesta v→z
z ve výšce n, v ve výšce 2n, umíme dostat spor podobně jako v důkazu lemmatu K
lemma Z (zvednutí)
počet zvednutí je nejvýš 2n2
protože každý z n vrcholů vystoupá nejvýše do výšky 2n (z invariantu V)
df: převedení je nasycené ≡ vynuluje rezervu
pozorování: nenasycené převedení po hraně uv vynuluje fΔ(u)
lemma S („sytá“ převedení)
počet nasycených převedení ≤n⋅m
důkaz
uvažme hranu uv
těsně po sytém převedení je r(uv)=0 a uv vede z kopce
před dalším sytým převedení r(uv)>0
mezitím se muselo převést v protisměru … tedy uv do kopce
tzn. posloupnost
syté převedení u→v
aspoň 2 zvednutí v
převedení v→u
aspoň 2 zvednutí u
až pak může přijít další syté převedení u→v
podle invariantu V toto max. n-krát
df: potenciál Φ:=∑v=z,s:fΔ(v)>0h(v)
Φ≥0
na počátku Φ=0
zvednutí: zvýší Φ o 1
celkem ≤2n2
sytá převedení po hraně uv: změní možná o −h(u) a možná o +h(v), takže se Φ zvýší nejvýš o 2n
celkem ≤2n2m
nenasycená převedení po hraně uv: určitě změní o −h(u) a možná o +h(v), přičemž h(u)=h(v)+1, takže se Φ sníží aspoň o 1
lemma N (nenasycená převedení)
počet nenasycených převedení ∈O(n2m)
implementace
S:= seznam vrcholů s přebytkem
údržba O(1) při změně přebytku
výběr v kroku 3 v algoritmu … v O(1)
∀v:K(v):= seznam hran s nenulovou rezervou, které z vrcholu v vedou z kopce
převedení po uv … O(1)
zvednutí u … O(n)
rozbor složitosti
inicializace v čase O(m)
čas celkem O(2n2⋅n+nm⋅1+n2m⋅1)=O(n2m)
vylepšení Goldbergova algoritmu
lemma N'
v algoritmu s výběrem nejvyššího v s fΔ(v)>0 nastane O(n3) nenasycených převedení
důkaz
H:=max{h(x)∣fΔ(v)>0,v=z,s}
fáze končí změnou H
zvýšení zvednutím
max. 2n2-krát
H vždy roste o 1
snížení aspoň o 1
max. 2n2-krát (klesá právě tolikrát, kolikrát roste)
pozorování: během jedné fáze se každý vrchol účastní maximálně jednoho nenasyceného převedení
nenasycené převedení vynuluje přebytek
převádí se z kopce → nemůže se zvýšit jeho přebytek
tudíž během fáze je všech nenasycených převedení nejvýš n
fází je O(n2), takže složitost algoritmus je O(n3)
násobení vektorů (získání všech koeficientů r∗) … Θ(n2)
rovnost polynomů – dvě možnosti
identita P≡Q – stejné vektory koeficientů po normalizaci
rovnost funkcí – ∀x:P(x)=Q(x)
identita ⟹ rovnost funkcí … jednoduchá
identita ⟸ rovnost funkcí … podle věty
věta: nechť P,Q jsou polynomy stupně maximálně d a P(xj)=Q(xj) pro navzájem různá čísla x0,…,xd, potom P≡Q
polynom stupně d je určený d+1 body
lemma: pro polynom P stupně d≥0 je počet x takových, že P(x)=0 nejvýše d
dk:
R:=P−Q
∀j:R(xj)=P(xj)−Q(xj)=0
stupeň R≤d
podle lemmatu R≡0, takže P≡Q
kdyby byl d≥0, tak by to byl spor s lemmatem, protože se R(x) rovná nule v d+1 bodech → d=−1 → R≡0
graf polynomu
…
násobení polynomů a grafy
…
postřehy
násobením polynomů dostaneme polynom s dvojnásobným stupněm, takže řekneme, že u násobených polynomů je horních 2n koeficientů nulových
teorie ke komplexním číslům
…
df: ω∈C je primitivní n-tá odmocnina z 1 ≡ωn=1 a ω1,…,ωn−1=1
pozorování: ωj=ωk pro 0≤j<k<n
kdyby ωj=ωk, pak ωk−jωjωk=1, což je spor
pozorování: pro sudé n … ωn/2=−1
protože kroužím od 1 k 1
pro ∣x∣=1:x−1=x
pozorování: ω2 je primitivní n/2-tá odmocnina z 1
algoritmus FFT
vstup
n=2k
ω … primitivní n-tá odmocnina z 1
(p0,…,pn−1) … koeficienty polynomu
výstup
(y0,…,yn−1) … graf polynomu P v bodech (ω0,…,ωn−1)
algoritmus
…
inverzní Fourierovu transformaci můžeme počítat jako tu dopřednou, jen vydělením n
celé násobení polynomů umíme v čase Θ(nlogn)
Ωjk=ωjk
lemma: Ω−1=n1⋅Ω
důkaz
poznámka k FFT – dá se implementovat nerekurzivně; lze nahlédnout, že tam vzniká permutace odpovídající seřazení binárních čísel pozpátku
věta: nechť x∈Rn a y=F(x); potom yj=yn−j pro všechna j
tím pádem můžeme každý reálný vektor zapsat jako lineární kombinaci navzorkovaných sinů a kosinů
Paralelní algoritmy
hradlo arity k má k vstupů a jeden výstup
počítá funkci f:Σk→Σ
Σ … konečná abeceda, typicky {0,1}
booleovská hradla
binární: AND, OR, XOR, ≤ (implikace), … (je jich 16)
unární: NOT (a „buffer“)
nulární, konstanty: 0, 1
Majorita(x,y,z)=(x∧y)∨(x∧z)∨(y∧z)
hradlová síť obsahuje
hradla
vstupní porty
výstupní porty
acyklické propojení
výpočet probíhá v taktech
takt: ohodnotíme vstupní porty a konstanty
(i+1). takt: ohodnotíme hradla a porty, jejichž vstupy byly ohodnoceny nejpozději v i. taktu
tak dostáváme rozklad sítě na vrstvy, kde v i-té vrstvě jsou hradla a porty, které byly ohodnoceny v i. taktu
čas = počet vrstev
prostor = počet hradel
nemohli bychom použít počet hradel v největší vrstvě, protože ne všechny hrany vedou o jednu vrstvu (někdy je potřeba, aby si hradlo pamatovalo svůj výsledek během několika taktů)
je nutné omezit počet vstupů a výstupů – jinak bychom mohli cokoliv počítat v konstantním čase
kombinační obvody … na obecné abecedě Σ
booleovské obvody … Σ={0,1}
hradlová síť má pevnou velikost vstupu
tedy ekvivalent programu ve světě hradlových sítí by byla sada různých hradlových sítí pro různé velikosti vstupu
tedy výpočetní model je neuniformní
chceme tyto sítě efektivně generovat – ale stačí nám polynomiální čas
co se týče časové složitosti hradlových sítí – obvykle chceme polylogaritmickou složitost (tedy nějakou mocninu logaritmu)
OR(x1,…,xn)
lze v lineárním čase – vždycky vezmeme výsledek a přiORujeme xi
nebo v logaritmickém čase – ORujeme po dvojicích
Θ(logn) vrstev
Θ(n) hradel
binární sčítání
zi=xi⊕yi⊕ci
kde ⊕ je XOR
ci+1=Majorita(xi,yi,ci)
jednoduchá implementace má Θ(n) hladin a Θ(n) hradel – musíme čekat na přenosy (ci)
jak předpovídat přenosy?
blok – souvislá posloupnost bitů
chování bloku – závislost cout na cin
fáze (ručního?) výpočtu
chování kanonických bloků
zahušťuji přenosy
finální XORy (jedna vrstva)
binární násobení
pomocí ANDu a bitového posunu v O(1) dostaneme n mezivýsledků, ty chceme sčítat
kdybychom sčítali po dvojicích, dostali bychom se na O(log2n)
ale my ke sčítání použijeme kompresor – ze 3 sčítanců uděláme dva
v první vrstvě n čísel, v druhé 32n čísel, ve třetí (32)2n čísel, …, v poslední 2 čísla, ty sečteme klasickou sčítačkou
kompresorových vrstev bude O(logn), hloubka kompresoru je O(1)
závěrečná sčítačka bude O(logn)
takže celková složitost násobení bude O(logn)
v reálných počítačích se používá hradlová síť založena na Fourierově transformaci, protože má menší prostorovou složitost
komparátorová síť
má n vstupů a n výstupů
výstupem je setříděná posloupnost vstupních dat
mezi vrstvami se vždy převádí permutace vstupu – BÚNO výstupy se nevětví
bubble sort lze paralelizovat v Θ(n) vrstvách
df: posloupnost x0,…,xn−1 je
čistě bitonická ≡∃k:x0<x1<⋯<xk>⋯>xn−1
bitonická ≡ má čistě bitonickou rotaci
tedy ∃l:xl,xl+1,…,xl+n−1 (kde indexy jsou modulo n) je čistě bitonická
separátor Sn
na vstupu bitonická posloupnost
na výstupu dvě poloviční bitonické posloupnosti, kde všechny prvky jedné jsou menší než všechny prvky druhé
princip
rozdělím vstup na poloviny
nainstaluju komparátory mezi i-tým prvkem v první polovině a i-tým prvkem v druhé polovině (takže vlastně xi a xn/2+i)
prvky rozdělím na horu (n/2 největších prvků) a údolí (n/2 nejmenších prvků)
hora i údolí jsou souvislé
xk … prvek, kterým začíná hora
xk+n/2 … prvek, kterým končí hora
k je BÚNO menší než n/2
jak fungují komparátory?
pro i<k neprohazujeme
pro i≥k prohazujeme
levý výstup = rotace údolí
pravý výstup = rotace hory
bitonická třídička Bn
na vstupu bitonická posloupnost
na výstupu rostoucí posloupnost
logn pater separátorů
na začátku jeden separátor délky n
každý z výsledků pošleme do separátoru délky n/2
nakonec dostaneme n posloupností délky 1, které jsou vzájemně setříděné
čas O(logn)
prostor O(nlogn)
slévačka Mn
vstup: dvě monotónní rostoucí posloupnosti o n prvcích
výstup: monotónní posloupnost o 2n prvcích
jednu z nich otočíme na klesající → dostaneme bitonickou posloupnost, proženeme ji B2n
třidička Sn
na vstupu je n prvků
na výstupu je monotónní rostoucí posloupnost n prvků
budeme mít logn pater slévaček, každá má nejhůř logn pater, takže celkem O(log2n)
prostorová složitost O(nlog2n)
pozorování: prostorová složitost komparátorové sítě může být nejhůř n-krát větší než časová složitost
pozorování: z dolního odhadu složitosti třídění plyne, že hloubka každé třídicí sítě je Ω(logn)
dá se to O(logn), ale konstanta je obrovská
algoritmy odvozené od komparátorových sítí se velmi snadno vektorizují
Dvojrozměrné úlohy
oplocení jabloní
nejlevější jabloň určitě bude součástí plotu
ukotvíme polopřímku v jabloni, otáčíme jí, než se dotkne další jabloně
tenhle postup opakujeme, nakonec dostaneme konvexní obal množiny x1,…,xn∈R2
předpokládáme body v obecné poloze
budeme „zametat“ rovinu – rovinu přejíždíme přímkou, body na jedné straně jsme zpracovali, body na druhé budeme zpracovávat, bod na přímce právě zpracováváme
máme konvexní obal zpracovaných bodů
H … horní obálka – stáčí se doprava
D … dolní obálka – stáčí se doleva
přidáváme bod
pro obě obálky zkontrolujeme, zda do nich bod můžeme přidat, aniž bychom porušili konvexnost
jinak z dané obálky odstraňujeme body tak dlouho, dokud bod nepůjde napojit
časová složitost
třídění bodů podle x-ové souřadnice v Θ(nlogn)
odstraňování bodů v O(n) … každý bod odstraníme nejvýše jednou
jak poznat, zda můžu napojit bod (neboli kam se křivka stáčí) – pomocí znaménka determinantu matice složené ze souřadnic posledních dvou vektorů
jak řešit body, které nejsou v obecné poloze?
představíme si pootočení soustavy souřadnic o ε
tedy nebudeme třídit body zleva doprava, ale lexikograficky podle souřadnic (zleva doprava, shora dolů)
průsečíky n úseček
průsečíků je Θ(n2)
chceme složitost O(hezkaˊ funkce(n+p))
p … počet průsečíků
předpokládáme obecnou polohu úseček (v daném bodě se protínají právě dvě přímky, žádná z nich nekončí v průsečíku)
zametáme přímkou shora dolů
události: začátky, konce, průsečíky
v danou chvíli máme průřez ≡ množina úseček proťatých zametací přímkou
průřez je seřazen zleva doprava
pozorování: těsně před zametením průsečíku sousedí protínající se úsečky v průřezu
kalendář událostí
algoritmus
…
reprezentace
…
celkem O((n+p)logn) čas
O(n) paměť
umí se O(nlogn+p) čas
Voroného diagram
místa a oblasti
oblast oi odpovídá místu xi, je to část roviny, jejíž body jsou k místu xi blíže než k jinému místu
Voroného diagram je rozkladem roviny na mnohoúhelníkové oblasti, z nichž některé jsou otevřené do nekonečna
mezi nekonečnými paprsky se dá binárně vyhledávat, takže si to zjednodušíme na konečnou verzi
oblast je určena průnikem polorovin
lze zkonstruovat v čase O(nlogn), ale algoritmus přeskočíme
lokalizace bodu
datová struktura pro rozklad roviny na oblasti – mnohoúhelníky
dotaz: do jaké oblasti patří zadaný bod?
přístup 1
nařežeme rozklad roviny na vodorovné pásy podle vrcholů mnohoúhelníků
takže pro daný dotaz nejdříve binárně vyhledáváme, ve kterém pásu se bod nachází
a potom v pásu binárně vyhledáváme, mezi jaké dvě přímky se bod trefil
dotaz v O(logn)
paměť O(n2)
přístup 2
použijeme algoritmus z průsečíků přímek
použijeme (semi)perzistentní datovou strukturu
pamatuje si historii
zápis → nová verze
dotaz: dostane verzi
umí se semiperzistentní BVS
O(logn) čas na operaci
O(logn) paměť na verzi
časová složitost algoritmu
O(n) operací s průřezem → čas O(nlogn)
O(n) verzí → prostor O(nlogn)
perzistence stromu kopírováním cest
AVL vyvažování taky funguje u perzistentního stromu
umí se i konstantní paměť na verzi
Složitost algoritmů
rozhodovací problém ≡ funkce f:{0,1}∗→{0,1}
problém existence párování velikosti k
vstup: bipartitní graf a k∈N
df: problém A je převoditelný na problém B ≡∃f:{0,1}∗→{0,1}∗ taková, že ∀α∈{0,1}∗:A(α)=B(f(α)) a f lze spočítat v čase polynomiálním v ∣α∣
začíme A→B nebo A≤PB
příklad
párování
dán bipartitní graf G a k∈N
existuje párování velikosti aspoň k?
tok
dána síť S a t∈N
existuje tok velikosti ≥t?
párování → tok
lemma
nechť A→B, B řešitelné v polynomiálním čase
potom A je řešitelné v polynomiálním čase
princip
vstup pro Af vstup pro B ALG(B) výstup
algoritmus pro B je polynomiální, ale k délce vstupu pro B (což je výstup f)
důkaz
…
vlastnosti relace převoditelnosti (→)
A→A
AfB∧BgC⟹Af∘gC
∃A,B:A→B∧B→A
A: vstup má sudou délku
B: vstup má lichou délku
není to antisymetrické
∃A,B:A→B∧B→A
A: konstantní 0
B: konstantní 1
částečné kvaziuspořádání
SAT
splnitelnost booleovských formulí
vstup: formule v CNF
CNF … konjunkce klauzulí
klauzule … disjunkce literálů
literál … proměnná nebo její negace
výstup: ∃ dosazení za proměnné takové, že formule je pravdivá (= splňující ohodnocení)
3-SAT: navíc každá klauzule obsahuje max. 3 literály
problém: nezávislá množina (NzMna)
…
pozor: převoditelnost z 3-SAT na SAT není identita
je potřeba zvalidovat vstup, jestli je 3-SAT – pro nevalidní vstupy chceme vrátit NE
zajímavější je převod SAT → 3-SAT
vyrábíme ekvisplnitelnou formuli
(α∨β)→(α∨ζ)∧(β∨¬ζ)
převod funguje i naopak (viz rezoluce)
jak rozštípnout dlouhou klauzuli délky ℓ?
α nechť má délku 2
β nechť má délku ℓ−2
po přidání ζ dostanu konjunkci klauzulí délky 3 a ℓ−1
klauzuli délky ℓ−1 štípu dál (pokud je moc dlouhá)
počet štípnutí je shora omezen délkou formule
v polynomiálním čase postupně rozštípeme všechny dlouhé klauzule při zachování splnitelnosti
3-SAT → NzMna
…
NzMna → SAT
BÚNO V(G)=[n]
∀i∈[n]:xi=1⟺i∈ NzMna
∀ij∈E:(¬xi∨¬xj)
vytvoříme si tabulku pro nezávislou množinu
yij=1≡ vrchol j je i-tým v NzMna
i=1,…,k
j=1,…,n
ve sloupci je maximálně 1 jednička
∀i,i′,j:(¬yij∨¬yi′j)
v řádku je právě jedna jednička
∀i,j,j′:(¬yij∨¬yij′)
∀i:(yi1∨yi2∨⋯∨yin)
propojíme klauzule
∀ij:(yij⟹xj)∼(¬yij∨xj)
tedy umíme SAT ↔ 3-SAT → NzMna → SAT
nahlédneme NzMna ↔ Klika
3,3-SAT … každá proměnná se vyskytuje v nejvýše třech klauzulích
převod 3,3-SAT → 3-SAT je opět identita s kontrolou syntaxe
3-SAT → 3,3-SAT
nechť x je proměnná s k>3 výskyty
pro každý výskyt si pořídíme nové proměnné x1,…,xk
ekvivalenci všech xi zajistíme řetězcem implikací
x1⟹x2
x2⟹x3
⋮
xk⟹x1
každá proměnná xi se tudíž vyskytne třikrát
3,3-SAT* … navíc každý literál max. 2×
použijeme předchozí algoritmus pro všechny proměnné s ≥3 výskyty
3D-párování
vstup: konečné množiny H,D,K + množina T⊆H×D×K
výstup: ∃T′⊆T taková, že každý prvek H,D,K je v právě jedné trojici v T′
ukážeme 3,3-SAT → 3D-párování
za cvičení 3D-párování → 3,3-SAT
3,3-SAT → 3D-párování
gadget pro proměnnou
gadget pro klauzuli
zbude zvířátek: 2 × počet proměnných – počet klauzulí
přidáme tolik párů k,d a pro ně trojice se všemi zvířátky
v Průvodci je chyba
Třídy problémů
df: třída problémů P
L∈P≡∃A algoritmus ∃p polynom takový, že ∀x vstup platí, že A(x) doběhne do p(∣x∣) kroků ∧A(x)=L(x)
lemma: nechť K,L∈NP, K→L, K je NP-úplný, pak L je NP-úplný
důkaz
nechť M∈NP
pak M→K→L
tedy M→L
NP-úplné problémy
logické
(CNF) SAT
3-SAT
3,3-SAT
obvodový SAT
grafové
nezávislá množina
klika
k-obarvitelnost (pro k≥3)
hamiltonovská cesta/kružnice
3D-párování
číselné
součet podmnožiny
batoh
2 loupežníci
nulajedničkové řešení soustavy lineárních rovnic (v Z)
často se stává, že restrikcí polynomiálního problému dostaneme nepolynomiální
částečný důkaz Cookovy věty
ukážeme, že L∈NP lze převést na obvodový SAT
obvodový SAT převedeme na SAT
Co s NP-úplným problémem?
triky a přístupy
uvědomit si, že vstupy, pro něž problém potřebujeme řešit, jsou malé
zjistit, že naše vstupy jsou něčím speciální
např. v případě grafových problémů je náš graf vždycky strom nebo třeba bipartitní
může se stát, že algoritmus bude pro naše vstupy polynomiální
spokojíme se s řešením, které není optimální, ale je blízko optimu – použijeme aproximační algoritmus
typicky jsme schopni dokázat, jak daleko bude výsledek od optimálního řešení
použijeme heuristiku
o takových algoritmech typicky neumíme nic moc dokázat
vše dohromady
největší nezávislá množina ve stromu
lemma: Je-li T strom a ℓ jeho list, pak aspoň jedna největší nezávislá množina obsahuje ℓ.
důkaz
nechť M je nějaká největší nezávislá množina
pokud ℓ∈M, pak máme hotovo
pokud ℓ∈/M, pak ℓ má souseda s
pokud s∈/M, můžu ℓ přidat do M, což je spor, protože M je největší
pokud s∈M, můžu z M odebrat s a přidat tam ℓ, čímž zachovám velikost □
hladový algoritmus
DFS(v):
nz(v) <- ANO
Pro s syny v:
DFS(s)
Pokud nz(s)=ANO:
nz(v) <- NE
složitost O(n)
plánování přednášek
známe časový plán přednášek (jednotlivé intervaly)
zjišťujeme, kolik potřebujeme poslucháren
chceme intervalový graf omezit nejmenším počtem barviček
V:= intervaly
{u,v}∈E≡u∩v=∅
budeme zametat přímku bodem
předpokládejme, že intervaly nezačínají/nekončí stejně (obecná poloha) – z analýzy algoritmu vyplývá, že:
když začínají stejně, nezáleží na pořadí
když končí stejně, nezáleží na pořadí
když jeden začíná a druhý končí ve stejnou chvíli, pořadí zpracování vyplývá z rozhodnutí, jak s takovou situací nakládat (můžeme intervaly chápat jako uzavřené nebo jako otevřené)
udržujeme množinu volných barviček, postupně procházíme po přímce – pokud potkáme začátek intervalu, vezmeme barvičku (když není žádná volná přidáme novou), pokud potkáme konec intervalu, vrátíme barvičku
algoritmus barvení intervalového grafu minimálním počtem barev
setřídíme začátky i konce intervalů [xi,yi]
b <- 0, V <- ∅
procházíme začátky a konce:
xi:
pokud V=∅:bi← libovolný prvek odebraný z V
jinak
b←b+1
bi←b
yi: do V přidáme bi
třídění v O(nlogn)
průchod začátků a konců v 2n krocích
takže celkem O(nlogn)
batoh
předměty 1,…,n
hmotnosti h1,…,hn
ceny c1,…,cn
nosnost batohu H
chceme I⊆{1,…,n} takovou, že h(I)≤H, c(I) je maximální
chceme algoritmus polynomiální v n, C=∑ici
df: Ak(c):= minimální hmotnost podmnožiny z {1,…,k}, která má cenu c
může být +∞, pokud taková podmnožina neexistuje
sestavujeme tabulku z hodnot Ak(c), kde po řádcích roste k a po sloupcích roste c
v prvním sloupci c=0, v prvním řádku k=0
v posledním sloupci c=C, v posledním řádku k=n
A0(0)=0
A0(c)=+∞ pro c>0
Ak(c)=min(Ak−1(c),Ak−1(c−ck)+hk)
varianta s Ak−1 připadá v úvahu, jen pokud c−ck≥0
celou tabulku vyplníme v čase O(nC)
maximální dosažielná cena c∗:=max{c∣An(c)≤H}
rekonstrukce optimální množiny
tak, že si u každého políčka tabulky pamatujeme maximální prvek dané podmnožiny
stačí projít konstrukci pozpátku (nejsou potřeba ukazatele, stačí jít zpátky odečtením ceny aktuálního maximálního prvku)
nebo se to dá udělat pomocí ukazatelů
problém batohu řešíme v čase O(nC) … pseudopolynomiální
celý algoritmus lze otočit na počítání maximální ceny pro určitou hmotnost a počet předmětů, pak to bude O(nH)
TSP (problém obchodního cestujícího)
v ohodnoceném grafu hledáme nejkratší hamiltonovskou kružnici (každý vrchol navštíví právě jednou)
omezení
úplný graf
délky hran splňují trojúhelníkovou nerovnost
aproximační algoritmy
máme množinu přípustných řešení, mezi nimi nějaké optimum
máme cenovou funkci c, která jednotlivá řešení ohodnocuje reálnými čísly
chceme přípustné řešení s minimální (někdy naopak maximální) cenou
aproximační poměr α
c(vyˊstup)≤α⋅optimum
…
2-aproximace TSP s Δ nerovností
T <- min. kostra
obejdeme kostru, nachodíme 2T
akorát vrcholy navštěvujeme víckrát
takže přidáme zkratky
díky trojúhelníkové nerovnosti si tím neublížíme
zkratky … ≤2T
pozorování: T≤ optimum
výstup ≤2T≤2 opt.
umí se 1.5-aproximace
dokážeme, že bez trojúhelníkové nerovnosti nelze obchodního cestujícího aproximovat
věta: pokud pro t≥1 existuje algoritmus t-aproximující TSP v úplných grafech bez trojúhelníkové nerovnosti v polynomiálním čase, pak P = NP
důkaz: t-aproximace ⟹ polynomiální algoritmus pro hamiltonovskou kružnici ⟹ P = NP
zadaný graf G doplníme na G′ úplný graf s ohodnocením hran
hrana v G → hrana v G′ délky 1
nehrana v G → hrana v G′ délky c
původní hamiltonovské kružnice budou mít délku n (počet vrcholů)
nové hamiltonovské kružnice budou mít délku ≥n−1+c
potřeujeme tn<n−1+c
c>tn−n+1=(t−1)n+1
splníme c=tn
batoh
umíme řešit v čase O(nC), kde C=∑ici,C≤n⋅cmax
chceme menší C
idea: {0,…,cmax}→{0,…,M}
ci^:=ci⋅cmaxM
chyba pro jeden předmět ≤Mcmax
chyba celkem ≤Mcmax⋅n≤chcemeε⋅c∗
po zahození předmětů s hi>H bude c∗≥cmax
…
ceny můžeme zaokrouhlovat (dostaneme aproximaci), hmotnosti ne, protože by se nám to rozbilo
df: polynomiální aproximační schéma (PTAS) ≡ algoritmus, který pro vstup velikosti n a ε>0 najde aproximaci s chybou ≤ε v čase pro každé ε polynomiálním
df: plně polynomiální aproximační schéma (FPTAS) … čas O(poly(n,1/ε))