2076 lines
91 KiB
TeX
2076 lines
91 KiB
TeX
\documentclass[11pt]{article}
|
|
\input{style_guide.tex}
|
|
|
|
% etwas luftigerer Satz fuer Lesbarkeit
|
|
\linespread{1.05}
|
|
\setlength{\parskip}{0.4em}
|
|
|
|
\title{\textbf{\Huge Komplexität verstehen}\\[0.5em]
|
|
\large Der ausführliche, grafische Guide zu\\
|
|
\textit{Analyse von Algorithmen und Komplexität}\\[0.3em]
|
|
\normalsize CAU Kiel -- Sommersemester 2026 \quad$\cdot$\quad Ausgabe 4}
|
|
\author{}
|
|
\date{}
|
|
|
|
\begin{document}
|
|
\maketitle
|
|
\thispagestyle{empty}
|
|
|
|
\begin{center}\itshape\large
|
|
Nicht auswendig lernen -- verstehen.\\
|
|
Jeder Begriff mit Bild, Beispiel und einer Frage zum Selberdenken.
|
|
\end{center}
|
|
|
|
\vfill
|
|
|
|
\noindent\textbf{Was dieser Guide ist.}
|
|
Ein Heft, das dir das \emph{Fundament} des Kurses aufbaut -- gründlich, in Ruhe,
|
|
mit vielen Bildern. Kein Nachschlagewerk zum Überfliegen. Wir nehmen uns für
|
|
jeden Gedanken den Platz, den er braucht. Wenn du es durcharbeitest, verstehst
|
|
du den ganzen Stoff und siehst, wie alles zusammenhängt.
|
|
|
|
\medskip
|
|
\noindent\textbf{So arbeitest du damit.}
|
|
Lies langsam. Schau dir jedes Bild an und frag dich, was es zeigt, bevor du
|
|
weiterliest. Am Ende jedes Kapitels stehen \textbf{Abruf-Fragen}: Beantworte sie
|
|
\emph{schriftlich aus dem Kopf}, \emph{bevor} du im Lösungsteil
|
|
(Anhang~\ref{sec:loesungen}) nachsiehst. Dieses aktive Erinnern ist der
|
|
eigentliche Lerneffekt.
|
|
|
|
\medskip
|
|
\noindent\textbf{Die Kästen.}
|
|
\begin{center}\small
|
|
\begin{tabular}{ll}
|
|
\ding{72}~Intuition & die Idee in einfachen Worten\\
|
|
\ding{43}~Analogie & ein Bild aus dem Alltag\\
|
|
\ding{110}~Definition & die präzise Fassung\\
|
|
\ding{115}~Satz & ein Ergebnis mit erklärter Beweis\emph{idee}\\
|
|
\ding{108}~Beispiel & durchgerechnet, mit echten Zahlen\\
|
|
\ding{52}~Warum in NP? & Zertifikat und Prüfung des Problems\\
|
|
\ding{43}~Idee & die Konstruktion hinter einer Reduktion/einem Beweis\\
|
|
\ding{73}~Aha & die Pointe\\
|
|
\ding{55}~Stolperstein & der häufige Fehler\\
|
|
\ding{228}~Zusammenhang & wie es ins Ganze passt\\
|
|
\textbf{?}~Abruf & prüfe dich -- Lösung nur im Anhang\\
|
|
\end{tabular}
|
|
\end{center}
|
|
|
|
\vfill
|
|
\newpage
|
|
\tableofcontents
|
|
\newpage
|
|
|
|
% ##################################################################
|
|
\section{Ein Problem, das sich wehrt}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Wir treffen ein Problem, das harmlos aussieht und trotzdem jeden Computer
|
|
überfordert. Daran wirst du sehen, warum es überhaupt eine Theorie der
|
|
\glqq schweren\grqq{} Probleme braucht.
|
|
\end{ziel}
|
|
|
|
\subsection{Ein Graph ist ein Netz aus Punkten und Linien}
|
|
|
|
Bevor wir zum Problem kommen, das Vokabular. Ein \emph{Graph} ist einfach ein
|
|
Netz: eine Menge von Punkten, die \emph{Knoten}, und Verbindungslinien zwischen
|
|
manchen von ihnen, die \emph{Kanten}. Mehr steckt zunächst nicht dahinter. Ein
|
|
Graph kann ein Straßennetz sein, ein Freundeskreis, ein Stromnetz -- die
|
|
Mathematik dahinter ist dieselbe.
|
|
|
|
Wir stellen uns die Knoten als \emph{Gäste auf einer Party} vor. Eine Kante
|
|
zwischen zwei Gästen heißt: \glqq die beiden kennen sich\grqq.
|
|
|
|
\subsection{Was ist eine Clique?}
|
|
|
|
\begin{defn}{Clique}
|
|
Eine \emph{Clique} ist eine Gruppe von Knoten, in der \emph{jeder mit jedem}
|
|
direkt verbunden ist. Auf der Party: eine Gruppe von Gästen, die sich
|
|
\emph{alle} gegenseitig kennen.
|
|
\end{defn}
|
|
|
|
Das \emph{Cliquenproblem} fragt: Gibt es in einem gegebenen Graphen eine Clique
|
|
aus mindestens $k$ Knoten? Sieh dir ein kleines Beispiel an und überzeuge dich,
|
|
dass du \glqq Clique\grqq{} verstanden hast.
|
|
|
|
\begin{bsp}{Eine Clique mit dem Auge finden}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(5,3)(-0.6,-0.5)
|
|
\put(0,1){\circle*{0.15}}\put(-0.5,1){\small $1$}
|
|
\put(1.2,2.4){\circle*{0.15}}\put(1.1,2.6){\small $2$}
|
|
\put(2.4,1){\circle*{0.15}}\put(2.55,1){\small $3$}
|
|
\put(1.6,-0.2){\circle*{0.15}}\put(1.5,-0.55){\small $4$}
|
|
\put(3.6,0.3){\circle*{0.15}}\put(3.75,0.2){\small $5$}
|
|
\qbezier(0,1)(0.6,1.7)(1.2,2.4) % 1-2
|
|
\put(0,1){\line(1,0){2.4}} % 1-3
|
|
\qbezier(1.2,2.4)(1.8,1.7)(2.4,1) % 2-3
|
|
\qbezier(2.4,1)(2.0,0.4)(1.6,-0.2) % 3-4
|
|
\qbezier(2.4,1)(3.0,0.65)(3.6,0.3) % 3-5
|
|
\end{picture}
|
|
\end{center}
|
|
Die Gruppe $\{1,2,3\}$ bildet ein Dreieck: die Kanten 1--2, 1--3 und 2--3 sind
|
|
alle da. Also kennen sich alle drei gegenseitig -- eine Clique der Größe~3.
|
|
Die Gruppe $\{2,3,4\}$ ist \emph{keine} Clique: zwischen 2 und 4 gibt es keine
|
|
Kante. Und eine Clique aus vier Gästen existiert hier gar nicht -- probiere es
|
|
aus.
|
|
\end{bsp}
|
|
|
|
Bei fünf Gästen erkennst du die Antwort auf einen Blick. Ein Computer
|
|
\glqq sieht\grqq{} den Graphen aber nicht als Bild. Er muss die Clique
|
|
\emph{ausrechnen}. Und genau das wird ab ein paar hundert Gästen zum Problem.
|
|
|
|
\subsection{Der naheliegende Algorithmus -- und warum er scheitert}
|
|
|
|
Wie würde ein Computer eine $k$-Clique suchen, wenn er keinen cleveren Trick
|
|
kennt? Er würde stur \emph{jede mögliche Gruppe} aus $k$ Gästen bilden und für
|
|
jede prüfen, ob sich wirklich alle kennen. Das ist korrekt -- es findet die
|
|
Clique garantiert, falls es eine gibt. Aber es ist entsetzlich langsam. Der
|
|
Grund liegt in der schieren \emph{Anzahl} der Gruppen.
|
|
|
|
Nehmen wir $n$ Gäste und suchen eine Clique der Größe $k = n/2$. Die Anzahl der
|
|
Gruppen ist dann \glqq $n$ über $n/2$\grqq, und das ist mindestens $2^{n/2}$.
|
|
Diese Zahl wächst \emph{explosionsartig}. Schau dir an, wie schnell:
|
|
|
|
\begin{bsp}{$2^{n/2}$ in Zahlen -- die Explosion}
|
|
\begin{center}
|
|
\begin{tabular}{rrl}
|
|
\toprule
|
|
Gäste $n$ & Gruppen (mind.) & Was das bedeutet\\
|
|
\midrule
|
|
$20$ & rund $1\,000$ & sofort erledigt\\
|
|
$40$ & rund $1$ Million & noch ein Wimpernschlag\\
|
|
$100$ & rund $10^{15}$ & über ein Monat bei einer Milliarde/s\\
|
|
$200$ & rund $10^{30}$ & länger als das Universum existiert\\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\end{center}
|
|
Von 100 auf 200 Gäste wird die Aufgabe nicht doppelt so schwer, sondern um den
|
|
Faktor $10^{15}$ schwerer.
|
|
\end{bsp}
|
|
|
|
Der Kern des Problems: Jeder \emph{einzelne} zusätzliche Gast \emph{verdoppelt}
|
|
ungefähr die Arbeit. Diese Art von Wachstum heißt \emph{exponentiell}, und sie
|
|
ist der natürliche Feind jeder Berechnung. Das folgende Bild stellt sie einem
|
|
gutmütigen \emph{polynomiellen} Wachstum ($n^3$) gegenüber.
|
|
|
|
\begin{bsp}{Zwei Welten: $n^3$ gegen $2^{n/2}$}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(10,5)(-0.7,-0.6)
|
|
\put(0,0){\vector(1,0){9.2}} \put(8.8,-0.5){\small Eingabegröße $n$}
|
|
\put(0,0){\vector(0,1){4.5}} \put(-0.6,4.3){\small Rechenzeit}
|
|
% polynomiell
|
|
\qbezier(0,0)(5,0.5)(9,2.0) \put(8.2,2.1){\small $n^3$}
|
|
\put(6.2,1.0){\small \itshape harmlos, bleibt flach}
|
|
% exponentiell
|
|
\qbezier(0,0)(3.0,0.15)(4.0,4.4) \put(3.7,4.4){\small $2^{n/2}$}
|
|
\put(4.3,3.3){\small \itshape schießt senkrecht hoch}
|
|
% Machbarkeitslinie
|
|
\multiput(0,3.4)(0.35,0){24}{\line(1,0){0.18}}
|
|
\put(5.6,3.55){\small \itshape Grenze des praktisch Machbaren}
|
|
\end{picture}
|
|
\end{center}
|
|
Die polynomielle Kurve bleibt lange in Bodennähe. Die exponentielle durchbricht
|
|
schon bei kleiner Eingabe jede Zeitgrenze und ist danach nicht mehr einzufangen.
|
|
\end{bsp}
|
|
|
|
\begin{intuition}
|
|
Warum hilft schnellere Hardware nicht? Ein doppelt so schneller Computer
|
|
schafft beim exponentiellen Algorithmus genau \emph{einen} Gast mehr -- weil ein
|
|
Gast mehr die Arbeit verdoppelt und die schnellere Hardware genau diese eine
|
|
Verdopplung ausgleicht. Willst du zehn Gäste mehr, brauchst du einen
|
|
\emph{tausendfach} schnelleren Rechner. Exponentielles Wachstum kann keine
|
|
Hardware der Welt einholen.
|
|
\end{intuition}
|
|
|
|
\begin{satz}{Der naive Clique-Algorithmus ist exponentiell}
|
|
Für $k = |V|/2$ braucht er mindestens $2^{|V|/2}$ Schritte.\\[0.3em]
|
|
\emph{Woran das liegt:} Es gibt $\binom{n}{n/2} \ge 2^{n/2}$ Gruppen der Größe
|
|
$n/2$, und jede davon muss wenigstens angefasst werden. Schon das Aufzählen so
|
|
vieler Gruppen kostet exponentiell viel Zeit.
|
|
\end{satz}
|
|
|
|
\subsection{Die Frage, die den ganzen Kurs trägt}
|
|
|
|
Vielleicht ist der naive Algorithmus einfach nur ungeschickt. Vielleicht gibt es
|
|
einen raffinierten Weg, die Clique \emph{schnell} zu finden, ohne alle Gruppen
|
|
durchzuprobieren?
|
|
|
|
Für das Cliquenproblem hat bis heute \emph{niemand} so einen Weg gefunden. Und
|
|
-- das ist der eigentliche Punkt -- niemand hat auch \emph{bewiesen}, dass es
|
|
keinen gibt. Wir stecken in einer Wissenslücke fest.
|
|
|
|
\begin{aha}
|
|
Die Komplexitätstheorie stellt nicht die Frage \glqq Wie löse ich dieses
|
|
Problem schnell?\grqq. Sie stellt die tiefere Frage: \glqq Ist dieses Problem
|
|
\emph{überhaupt} schnell lösbar -- oder gehört es zu einer großen Familie von
|
|
Problemen, die alle gemeinsam schwer sind?\grqq{} Die erste Frage ist offen. Die
|
|
zweite können wir beantworten. Genau darum geht es im ganzen Kurs.
|
|
\end{aha}
|
|
|
|
\begin{abruf}
|
|
\textbf{A1.} Erkläre in eigenen Worten, warum ein 1000-mal schnellerer Computer
|
|
den naiven Clique-Algorithmus kaum brauchbarer macht.\\
|
|
\textbf{A2.} Was ist der Unterschied zwischen \glqq wir kennen keinen schnellen
|
|
Algorithmus\grqq{} und \glqq es gibt keinen\grqq? Welcher der beiden Fälle ist
|
|
für die Clique bewiesen?
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Was heißt eigentlich \glqq schnell\grqq?}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Wir machen \glqq schnell\grqq{} präzise. Das führt uns zur ersten großen Klasse:
|
|
$\Pclass$, die Probleme, die wir effizient lösen können.
|
|
\end{ziel}
|
|
|
|
\subsection{Geschwindigkeit misst man in der Eingabegröße}
|
|
|
|
Es ergibt keinen Sinn zu sagen, ein Algorithmus brauche \glqq drei Sekunden\grqq.
|
|
Drei Sekunden wofür -- für zehn Zahlen oder für zehn Milliarden? Sinnvoll ist
|
|
nur eine Aussage \emph{relativ zur Größe der Eingabe}. Wir schreiben $n$ für
|
|
diese Größe und fragen: Wie viele Rechenschritte braucht der Algorithmus im
|
|
schlimmsten Fall bei Eingabegröße $n$?
|
|
|
|
Warum der \emph{schlimmste} Fall? Weil wir eine \emph{Garantie} wollen. Ein
|
|
Algorithmus, der meistens schnell ist, aber bei ungünstigen Eingaben
|
|
explodiert, gibt uns keine Sicherheit. Der schlimmste Fall über alle Eingaben
|
|
der Größe $n$ ist die ehrliche Messgröße.
|
|
|
|
\subsection{Die Klasse P}
|
|
|
|
\begin{defn}{Klasse P}
|
|
$\Pclass$ ist die Menge aller Entscheidungsprobleme, die ein Algorithmus in
|
|
\emph{polynomieller} Zeit löst -- also mit einer Laufzeit von der Form $O(n^d)$,
|
|
wobei $d$ eine feste Zahl ist ($n$, $n^2$, $n^3$, \dots). Kurz gesagt: die
|
|
\emph{effizient lösbaren} Probleme.
|
|
\end{defn}
|
|
|
|
Beispiele, für die wir schnelle, polynomielle Algorithmen kennen: Zahlen
|
|
sortieren, den kürzesten Weg in einem Straßennetz finden, ein Stromnetz mit
|
|
minimalen Kosten aufspannen (minimaler Spannbaum), Paare optimal zuordnen
|
|
(Matching). All das liegt in $\Pclass$.
|
|
|
|
\begin{intuition}
|
|
\glqq Polynomiell = effizient\grqq{} ist eine \emph{Vereinbarung}, kein
|
|
Naturgesetz. Ein Algorithmus mit Laufzeit $n^{100}$ wäre praktisch nutzlos, zählt
|
|
aber formal als polynomiell. Trotzdem funktioniert die Vereinbarung erstaunlich
|
|
gut: Polynomielle Algorithmen aus der Praxis haben fast immer kleine Exponenten,
|
|
und die Grenze \glqq polynomiell gegen exponentiell\grqq{} bleibt dieselbe, egal
|
|
welchen realistischen Rechnertyp man zugrunde legt. Diese Robustheit macht sie
|
|
zur richtigen Trennlinie.
|
|
\end{intuition}
|
|
|
|
\subsection{Warum wir alles als Ja/Nein-Frage schreiben}
|
|
|
|
Ein Detail, das anfangs überrascht: Die Theorie behandelt fast nur
|
|
\emph{Entscheidungsprobleme} -- Fragen mit Antwort \glqq Ja\grqq{} oder
|
|
\glqq Nein\grqq. Statt \glqq Wie groß ist die größte Clique?\grqq{} fragt man
|
|
\glqq Gibt es eine Clique mit mindestens $k$ Knoten?\grqq.
|
|
|
|
Das wirkt wie ein Verlust an Information, ist aber keiner.
|
|
|
|
\begin{analogie}
|
|
Es ist wie beim Abwiegen ohne Anzeige, nur mit der Frage \glqq schwerer als
|
|
$x$?\grqq. Fragst du \glqq schwerer als 1\,kg? als 2\,kg? als 3\,kg?\grqq{} und
|
|
so weiter, tastest du das genaue Gewicht ein. Die Ja/Nein-Frage für \emph{jede}
|
|
Schranke trägt also dieselbe Information wie die genaue Zahl. Deshalb ist die
|
|
Ja/Nein-Version eines Problems \glqq gleich schwer\grqq{} wie die
|
|
Optimierungsversion -- aber viel einfacher sauber zu vergleichen.
|
|
\end{analogie}
|
|
|
|
Formal kodiert man jede Eingabe als Zeichenkette (ein \emph{Wort}) über einem
|
|
Alphabet, und ein Problem wird zur \emph{Menge aller Ja-Wörter}. Du musst diese
|
|
Brille nicht ständig tragen. Merke dir nur den Kern: \emph{Ein Problem ist die
|
|
Menge seiner Ja-Eingaben.} Beim Cliquenproblem ist das die Menge aller Paare
|
|
$(G,k)$, für die $G$ tatsächlich eine $k$-Clique besitzt.
|
|
|
|
\subsection{Ein Stolperstein, der später wichtig wird}
|
|
|
|
\begin{stolper}
|
|
\textbf{Zahlen sind binär kodiert -- und dadurch \glqq riesig\grqq{} gegenüber
|
|
ihrer Länge.} Eine Zahl $K$ steht als Eingabe nur mit ihren Ziffern da, also mit
|
|
Länge etwa $\log K$. Ihr \emph{Wert} $K$ ist aber exponentiell größer als diese
|
|
Länge. Ein Algorithmus, der \glqq von 1 bis $K$ zählt\grqq, macht $K$ Schritte --
|
|
und das ist exponentiell in der Eingabelänge, nicht polynomiell. An diesem
|
|
scheinbar harmlosen Punkt hängt später, warum \problem{SubSet Sum} schwer ist und
|
|
was das Wort \glqq pseudopolynomiell\grqq{} bedeutet. Merk ihn dir.
|
|
\end{stolper}
|
|
|
|
\begin{abruf}
|
|
\textbf{A3.} Ist ein Algorithmus mit Laufzeit $n^4$ \glqq effizient\grqq{} im
|
|
Sinne der Theorie? Begründe.\\
|
|
\textbf{A4.} \glqq Zähle von 1 bis zur eingegebenen Zahl $K$\grqq{} sieht
|
|
kinderleicht aus. Warum ist dieser Algorithmus trotzdem \emph{nicht}
|
|
polynomiell?
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Prüfen ist leichter als Lösen}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Wir entdecken die zentrale Beobachtung der Theorie: Für viele schwere Probleme
|
|
ist es hart, eine Lösung zu \emph{finden}, aber leicht, eine vorgelegte Lösung
|
|
zu \emph{prüfen}. Daraus entsteht die Klasse $\NP$ -- und ein Rezept, mit dem du
|
|
für jedes Problem zeigst, dass es dazugehört.
|
|
\end{ziel}
|
|
|
|
\subsection{Die Sudoku-Beobachtung}
|
|
|
|
\begin{analogie}
|
|
Stell dir ein schweres Sudoku vor. Es zu \emph{lösen} kann eine halbe Stunde
|
|
dauern. Aber wenn dir jemand ein fertig ausgefülltes Gitter hinlegt und fragt
|
|
\glqq stimmt das?\grqq, brauchst du eine Minute: Du prüfst jede Zeile, jede
|
|
Spalte, jeden Block. \emph{Lösen ist schwer, Prüfen ist leicht.} Diese
|
|
Asymmetrie ist der ganze Kern von $\NP$.
|
|
\end{analogie}
|
|
|
|
Genau so ist es bei der Clique. Eine Clique zu \emph{finden} ist mühsam. Aber
|
|
wenn dir jemand eine Gruppe von Gästen nennt und behauptet \glqq die bilden eine
|
|
Clique\grqq, prüfst du das im Handumdrehen: Du schaust für jedes Paar nach, ob
|
|
die Kante da ist. Die vorgelegte Gruppe ist der Beweis -- wir nennen sie ein
|
|
\emph{Zertifikat}.
|
|
|
|
\subsection{Zertifikat und Verifizierer}
|
|
|
|
\begin{defn}{Verifizierer und Zertifikat}
|
|
Ein \emph{Verifizierer} für ein Problem $L$ ist ein Algorithmus $A$, der
|
|
\emph{zwei} Dinge bekommt: die eigentliche Frage (die Instanz $x$) und einen
|
|
Lösungsvorschlag $c$. Er soll erfüllen:
|
|
\[
|
|
x \in L \quad\Longleftrightarrow\quad \text{es gibt ein } c \text{ mit } A(x,c)=1.
|
|
\]
|
|
Der Vorschlag $c$ heißt \emph{Zertifikat}.
|
|
\end{defn}
|
|
|
|
Lies die beiden Richtungen einzeln, sie sind beide wichtig:
|
|
\begin{itemize}
|
|
\item Ist $x$ eine \emph{Ja}-Instanz, dann \emph{gibt es} ein Zertifikat, das
|
|
$A$ überzeugt.
|
|
\item Ist $x$ eine \emph{Nein}-Instanz, dann überzeugt $A$ \emph{kein}
|
|
Zertifikat -- egal, was man ihm vorlegt.
|
|
\end{itemize}
|
|
|
|
\begin{defn}{Die Klasse NP}
|
|
$\NP$ ist die Menge aller Probleme, die einen Verifizierer besitzen, der ein
|
|
\emph{polynomiell langes} Zertifikat in \emph{polynomieller} Zeit prüft.
|
|
\end{defn}
|
|
|
|
\begin{intuition}
|
|
$\NP$ heißt \glqq effizient \emph{überprüfbar}\grqq, nicht \glqq effizient
|
|
\emph{lösbar}\grqq. Das ist der ganze Witz. Eine Lösung zu finden mag
|
|
exponentiell teuer sein -- aber \emph{hätte} man sie, wäre die Kontrolle billig.
|
|
Das Zertifikat ist die kurze Antwort auf die Frage \glqq und woher weiß ich,
|
|
dass das stimmt?\grqq.
|
|
\end{intuition}
|
|
|
|
\subsection{Der NP-Dreischritt: so beweist man \glqq $\in\NP$\grqq}
|
|
|
|
Für \emph{jedes} Problem läuft der Nachweis \glqq liegt in $\NP$\grqq{} nach
|
|
demselben Muster ab. Dieses Rezept begegnet dir im ganzen Kurs, also lohnt es
|
|
sich, es einmal in Ruhe anzusehen.
|
|
|
|
\begin{idee}{Der NP-Dreischritt}
|
|
\textbf{(1) Zertifikat benennen.} Was ist die \glqq Lösung\grqq{} des Problems?
|
|
Eine Teilmenge, eine Belegung, eine Reihenfolge? Sag außerdem, dass sie
|
|
polynomiell lang ist (sonst könnte man sie nicht schnell lesen).\\[0.4em]
|
|
\textbf{(2) Verifizierer beschreiben.} Ein Algorithmus, der \emph{alle}
|
|
geforderten Eigenschaften prüft. Dazu gehören immer drei Punkte:
|
|
\begin{itemize}
|
|
\item die Prüfschritte selbst,
|
|
\item die Korrektheit in \emph{beiden} Richtungen (Ja-Instanz $\Rightarrow$ ein
|
|
Zertifikat wird akzeptiert; Nein-Instanz $\Rightarrow$ keines),
|
|
\item die Laufzeit, konkret als $O(\cdot)$.
|
|
\end{itemize}
|
|
\textbf{(3) Alternativ: die Rate-Sicht.} Man darf $\NP$ auch über eine
|
|
\glqq ratende\grqq{} Maschine beschreiben, die die Lösung errät und dann prüft.
|
|
Die Rateschritte \emph{sind} das Zertifikat -- es ist nur eine andere Sprache
|
|
für dieselbe Sache.
|
|
\end{idee}
|
|
|
|
Machen wir den Dreischritt einmal ganz konkret.
|
|
|
|
\begin{bsp}{Der NP-Dreischritt für Clique}
|
|
\textbf{Zertifikat:} eine Knotenmenge $C$ (etwa als Liste der gewählten
|
|
Knoten). Sie ist höchstens so lang wie die Knotenzahl, also polynomiell.\\[0.3em]
|
|
\textbf{Verifizierer:} Prüfe zwei Dinge -- erstens, ob wirklich \emph{jedes}
|
|
Paar aus $C$ durch eine Kante verbunden ist (das kostet $O(|C|^2)$ Blicke in
|
|
die Kantenliste); zweitens, ob $|C| \ge k$ ist ($O(|V|)$).\\[0.3em]
|
|
\textbf{Korrektheit:} Gibt es eine $k$-Clique, so ist genau sie ein Zertifikat,
|
|
das akzeptiert wird. Gibt es keine, scheitert jeder Vorschlag an der
|
|
Paar-Prüfung. Beide Richtungen stimmen.\\[0.3em]
|
|
\textbf{Laufzeit:} polynomiell. Also liegt \problem{Clique} in $\NP$.
|
|
\end{bsp}
|
|
|
|
\subsection{Die zweite Sicht: Raten}
|
|
|
|
\begin{intuition}
|
|
Die dritte Zeile des Dreischritts verdient einen eigenen Gedanken. Stell dir
|
|
einen Algorithmus vor, der an jeder Verzweigung nicht \emph{eine} Möglichkeit
|
|
wählt, sondern \emph{alle gleichzeitig} verfolgt -- wie ein Läufer, der sich an
|
|
jeder Kreuzung in Kopien aufteilt und jede Kopie einen Weg gehen lässt. So ein
|
|
Algorithmus heißt \emph{nichtdeterministisch}. Er \glqq akzeptiert\grqq, wenn
|
|
\emph{irgendeine} Kopie ans Ziel kommt. Für eine Nein-Instanz kommt keine Kopie
|
|
an. \glqq Richtig raten\grqq{} und \glqq ein Zertifikat geschenkt bekommen\grqq{}
|
|
sind zwei Namen für genau dieselbe Fähigkeit.
|
|
\end{intuition}
|
|
|
|
\subsection{P steckt in NP -- und die Millionenfrage}
|
|
|
|
\begin{satz}{$\Pclass \subseteq \NP$}
|
|
Jedes effizient \emph{lösbare} Problem ist auch effizient \emph{überprüfbar}.\\[0.3em]
|
|
\emph{Warum:} Wenn du ein Problem selbst schnell lösen kannst, brauchst du das
|
|
Zertifikat gar nicht. Du ignorierst es und rechnest die Antwort direkt aus. Der
|
|
Löser ist damit ein besonders fauler Verifizierer.
|
|
\end{satz}
|
|
|
|
Die spannende Frage ist die \emph{Umkehrung}: Ist auch alles, was man schnell
|
|
\emph{prüfen} kann, schnell \emph{lösbar}? Gilt also $\Pclass = \NP$?
|
|
|
|
\begin{aha}
|
|
Ob $\Pclass = \NP$ gilt, weiß bis heute niemand. Es ist eines der sieben
|
|
Millennium-Probleme, ausgelobt mit einer Million Dollar. Die meisten Fachleute
|
|
vermuten $\Pclass \ne \NP$ -- dass Prüfen also \emph{echt} leichter ist als
|
|
Lösen. Beweisen konnte es keiner. Und der ganze Rest dieses Kurses --
|
|
NP-Vollständigkeit, ETH, Approximation -- ist nichts anderes als der kluge
|
|
Umgang mit genau dieser Unwissenheit.
|
|
\end{aha}
|
|
|
|
\begin{abruf}
|
|
\textbf{A5.} Führe den NP-Dreischritt für \problem{Vertex Cover} durch: Was ist
|
|
das Zertifikat, was prüft der Verifizierer, wie lange dauert das?\\
|
|
\textbf{A6.} Warum bedeutet \glqq $L$ hat einen polynomiellen Verifizierer\grqq{}
|
|
nicht dasselbe wie \glqq $L$ ist in Polynomialzeit lösbar\grqq?
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Reduktionen: Probleme miteinander vergleichen}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Jetzt kommt das wichtigste Werkzeug des ganzen Kurses. Mit der \emph{Reduktion}
|
|
vergleichst du zwei Probleme nach Schwierigkeit -- und zwar, ohne für auch nur
|
|
eines von beiden einen Algorithmus zu kennen. Das klingt paradox. Wir bauen es
|
|
langsam auf.
|
|
\end{ziel}
|
|
|
|
\subsection{Die Grundidee: ein Problem durch ein anderes lösen}
|
|
|
|
Angenommen, du hast ein fertiges Werkzeug für Problem $B$ -- eine Maschine, in
|
|
die du eine $B$-Frage steckst und die Ja oder Nein ausspuckt. Jetzt stehst du
|
|
vor Problem $A$, für das du \emph{kein} Werkzeug hast. Kannst du $A$ trotzdem
|
|
lösen?
|
|
|
|
Ja -- \emph{falls} du jede $A$-Frage so \emph{umformen} kannst, dass die
|
|
$B$-Maschine sie beantwortet. Dann löst du $A$ über den Umweg $B$: erst
|
|
umformen, dann die $B$-Maschine fragen, deren Antwort ist auch die Antwort auf
|
|
deine $A$-Frage.
|
|
|
|
\begin{analogie}
|
|
Du möchtest wissen, ob eine Strecke länger als eine Meile ist, hast aber nur ein
|
|
Lineal mit Kilometer-Skala. Kein Problem: Du rechnest die Frage \glqq länger als
|
|
1 Meile?\grqq{} um in \glqq länger als $1{,}609$\,km?\grqq{} und misst dann mit
|
|
dem km-Lineal. Die \emph{Umrechnung} ist billig, das eigentliche \emph{Messen}
|
|
erledigt das fremde Werkzeug. Genau so arbeitet eine Reduktion: billiges
|
|
Umformen plus fremder Löser.
|
|
\end{analogie}
|
|
|
|
\subsection{Die präzise Definition}
|
|
|
|
\begin{defn}{Polynomielle Reduktion $A \redp B$}
|
|
Eine \emph{Reduktion} von $A$ auf $B$ ist eine Funktion $f$, die jede
|
|
$A$-Eingabe $w$ in eine $B$-Eingabe $f(w)$ übersetzt, sodass die Antworten
|
|
zusammenpassen:
|
|
\[
|
|
w \in A \quad\Longleftrightarrow\quad f(w) \in B.
|
|
\]
|
|
Sie heißt \emph{polynomiell}, wenn ein Algorithmus $f(w)$ in polynomieller Zeit
|
|
berechnet. Wir schreiben dann $A \redp B$.
|
|
\end{defn}
|
|
|
|
Die Bedingung $w \in A \iff f(w) \in B$ verlangt \emph{beide} Richtungen: Aus
|
|
einer Ja-Instanz von $A$ wird eine Ja-Instanz von $B$, und aus einer
|
|
Nein-Instanz von $A$ wird eine Nein-Instanz von $B$. Nur so bleibt die Antwort
|
|
erhalten. Das folgende Bild zeigt den Datenfluss, wenn man mit einer Reduktion
|
|
das Problem $A$ über einen $B$-Löser knackt.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(13.5,2.2)(0,-0.4)
|
|
\put(0,0.3){\framebox(2.4,1.1){\shortstack{\small $A$-Frage\\ \small $w$}}}
|
|
\put(2.4,0.85){\vector(1,0){1.6}}
|
|
\put(2.45,1.05){\small $f$ (billig)}
|
|
\put(4.0,0.3){\framebox(2.6,1.1){\shortstack{\small $B$-Frage\\ \small $f(w)$}}}
|
|
\put(6.6,0.85){\vector(1,0){1.6}}
|
|
\put(6.7,1.05){\small $B$-Löser}
|
|
\put(8.2,0.3){\framebox(2.2,1.1){\shortstack{\small Ja /\\ \small Nein}}}
|
|
\put(10.4,0.85){\vector(1,0){1.5}}
|
|
\put(10.5,1.05){\small ist auch}
|
|
\put(11.9,0.3){\framebox(1.6,1.1){\shortstack{\small Antwort\\ \small auf $w$}}}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\begin{intuition}
|
|
Was bedeutet $A \redp B$ inhaltlich? Genau dies: \glqq $B$ ist \emph{mindestens
|
|
so schwer} wie $A$.\grqq{} Denn wer $B$ schnell lösen kann, löst mit der
|
|
billigen Umformung $f$ auch $A$ schnell. Anders gesagt: Die Schwierigkeit
|
|
\emph{fließt entlang des Pfeils}. Wenn $A$ schwer ist, dann kann $B$ nicht leicht
|
|
sein -- sonst wäre über den Umweg auch $A$ leicht.
|
|
\end{intuition}
|
|
|
|
\subsection{Die Richtung -- lies das zweimal}
|
|
|
|
Hier passiert der häufigste und teuerste Fehler im ganzen Kurs. Nimm dir Zeit.
|
|
|
|
Du willst normalerweise zeigen, dass ein \emph{neues} Problem $Y$ \emph{schwer}
|
|
ist. Dazu nimmst du ein Problem $X$, von dem du \emph{schon weißt}, dass es
|
|
schwer ist, und reduzierst $X$ \emph{auf} $Y$ -- also $X \redp Y$.
|
|
|
|
\begin{stolper}
|
|
Die Richtung ist \textbf{bekannt schwer $\redp$ neu}, niemals umgekehrt. Die
|
|
Reduktion nimmt eine Instanz des \emph{bekannten} Problems und baut daraus eine
|
|
Instanz des \emph{neuen}. Warum genau so? Weil $X \redp Y$ bedeutet \glqq $Y$
|
|
mindestens so schwer wie $X$\grqq. Da $X$ schon als schwer bekannt ist, erbt $Y$
|
|
diese Schwere. Machst du es andersherum ($Y \redp X$), zeigst du nur \glqq $Y$
|
|
höchstens so schwer wie das schwere $X$\grqq{} -- und das sagt über $Y$
|
|
überhaupt nichts.
|
|
\end{stolper}
|
|
|
|
\begin{analogie}
|
|
Du willst beweisen, dass ein neuer Boxer stark ist. Also lässt du den
|
|
\emph{amtierenden Champion} gegen ihn antreten. Besiegt der Neue den Champion,
|
|
ist er stark. Du würdest nie den Neuen gegen einen \emph{Anfänger} antreten
|
|
lassen -- ein Sieg da beweist nichts. \glqq Champion (bekannt stark) gegen
|
|
Neuen.\grqq{} Genau das ist $X_{\text{bekannt}} \redp Y_{\text{neu}}$.
|
|
\end{analogie}
|
|
|
|
\subsection{Reduktionen lassen sich verketten}
|
|
|
|
\begin{satz}{Transitivität}
|
|
Gilt $A \redp B$ und $B \redp C$, dann auch $A \redp C$.\\[0.3em]
|
|
\emph{Warum:} Man schaltet die beiden Umformungen einfach hintereinander -- erst
|
|
$A \to B$, dann $B \to C$. Die Zwischenausgabe ist polynomiell groß, also
|
|
bleibt auch die Gesamt-Umformung polynomiell. Zwei billige Schritte ergeben
|
|
zusammen einen billigen Schritt.
|
|
\end{satz}
|
|
|
|
Das ist mehr als eine technische Note: Es erlaubt uns, eine ganze \emph{Kette}
|
|
von Reduktionen zu bauen. Ist das erste Problem als schwer bekannt, trägt die
|
|
Kette diese Schwere Glied für Glied bis ans Ende. Genau diese Kette bauen wir
|
|
ab dem nächsten Kapitel auf.
|
|
|
|
\begin{abruf}
|
|
\textbf{A7.} Du weißt, dass \problem{Clique} schwer ist, und willst zeigen, dass
|
|
\problem{Vertex Cover} schwer ist. In welche Richtung reduzierst du, und warum
|
|
genau so und nicht andersherum?\\
|
|
\textbf{A8.} Formuliere in einem Satz, was $A \redp B$ über die relative
|
|
Schwierigkeit von $A$ und $B$ aussagt.
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Die härtesten Probleme: NP-vollständig}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Mit der Reduktion in der Hand können wir jetzt sagen, was \glqq die schwersten
|
|
Probleme in $\NP$\grqq{} genau sind -- und warum ein einziger schneller
|
|
Algorithmus für eines von ihnen die gesamte Landschaft zum Einsturz brächte.
|
|
\end{ziel}
|
|
|
|
\subsection{Zwei Begriffe: NP-schwer und NP-vollständig}
|
|
|
|
\begin{defn}{NP-schwer und NP-vollständig}
|
|
\begin{itemize}
|
|
\item $L_0$ heißt \emph{NP-schwer}, wenn sich \emph{jedes} Problem $L \in \NP$
|
|
auf $L_0$ reduzieren lässt: $L \redp L_0$ für alle $L \in \NP$.
|
|
\item $L_0$ heißt \emph{NP-vollständig}, wenn es NP-schwer ist \textbf{und}
|
|
selbst in $\NP$ liegt.
|
|
\end{itemize}
|
|
\end{defn}
|
|
|
|
\begin{intuition}
|
|
Denk an zwei Schranken, die von oben und unten zusammenkommen:
|
|
\begin{itemize}
|
|
\item \emph{NP-schwer} ist eine \textbf{untere} Schranke -- \glqq mindestens so
|
|
schwer wie alles in $\NP$\grqq. Alle NP-Probleme reduzieren auf $L_0$, also ist
|
|
$L_0$ mindestens so hart wie jedes von ihnen.
|
|
\item \emph{$\in \NP$} ist eine \textbf{obere} Schranke -- \glqq nicht schwerer
|
|
als $\NP$\grqq.
|
|
\end{itemize}
|
|
\emph{NP-vollständig} heißt: beide Schranken treffen sich. Das sind genau die
|
|
schwersten Probleme \emph{innerhalb} von $\NP$.
|
|
\end{intuition}
|
|
|
|
\begin{stolper}
|
|
NP-schwer heißt \emph{nicht} automatisch \glqq liegt in $\NP$\grqq. Es gibt
|
|
Probleme, die NP-schwer sind, aber weit außerhalb von $\NP$ liegen -- das
|
|
Halteproblem (Kapitel~\ref{sec:halt}) ist nicht einmal lösbar und trotzdem
|
|
NP-schwer. \glqq Schwer\grqq{} und \glqq überhaupt in NP\grqq{} sind zwei
|
|
verschiedene Achsen.
|
|
\end{stolper}
|
|
|
|
\subsection{Warum ein Algorithmus für eines alle löst}
|
|
|
|
\begin{satz}{NP-vollständig verbindet $\Pclass$ und $\NP$}
|
|
Ist $L_0$ NP-vollständig, dann gilt: $\Pclass = \NP$ genau dann, wenn
|
|
$L_0 \in \Pclass$.\\[0.3em]
|
|
\emph{Warum:} Läge $L_0$ in $\Pclass$, könnte man \emph{jedes} $L \in \NP$
|
|
effizient lösen -- erst die Reduktion $L \redp L_0$ rechnen, dann den schnellen
|
|
$L_0$-Löser anwerfen. Damit läge ganz $\NP$ in $\Pclass$.
|
|
\end{satz}
|
|
|
|
\begin{aha}
|
|
Das ist die Sprengkraft der NP-Vollständigkeit. Fände jemand für \emph{ein
|
|
einziges} NP-vollständiges Problem einen effizienten Algorithmus, dann wären
|
|
\emph{schlagartig alle} Probleme in $\NP$ effizient lösbar -- die Welt wäre eine
|
|
andere. Genau deshalb gilt umgekehrt: Solange das niemandem gelingt, ist ein
|
|
NP-Vollständigkeitsbeweis das stärkste bekannte Indiz dafür, dass ein Problem
|
|
\emph{keinen} effizienten Algorithmus hat.
|
|
\end{aha}
|
|
|
|
\subsection{Der Anker: der Satz von Cook und Levin}
|
|
|
|
Damit die Reduktionskette überhaupt losgehen kann, braucht man ein
|
|
\emph{erstes} NP-vollständiges Problem -- eines, das man von Hand als schwer
|
|
nachweist, ohne sich auf ein anderes stützen zu können. Cook und Levin haben es
|
|
geliefert. Es heißt \problem{SAT}: Gegeben eine aussagenlogische Formel, gibt es
|
|
eine Belegung ihrer Variablen, die sie wahr macht?
|
|
|
|
\begin{satz}{Cook (1971) und Levin (1973)}
|
|
\problem{SAT} ist NP-vollständig -- das \emph{erste} solche Problem.\\[0.3em]
|
|
\emph{Die Beweisidee in einem Bild:} Man nimmt ein \emph{beliebiges} Problem
|
|
$L \in \NP$ mit seiner ratenden Maschine und \glqq gießt\grqq{} deren Rechnung
|
|
in eine große logische Formel. Variablen der Formel beschreiben Aussagen wie
|
|
\glqq zur Zeit $t$ ist die Maschine im Zustand $q$\grqq{} oder \glqq zur Zeit $t$
|
|
steht auf Bandfeld $i$ das Symbol $a$\grqq. Weitere Teilformeln erzwingen, dass
|
|
ein gültiger Rechenablauf beschrieben wird. Das Entscheidende: Eine
|
|
\emph{erfüllende Belegung} der Formel entspricht \emph{genau} einem
|
|
akzeptierenden Rechenweg der Maschine. Also gilt: $L$-Ja-Instanz $\iff$ Formel
|
|
erfüllbar. Da $L$ beliebig war, ist \problem{SAT} schwer für ganz $\NP$.
|
|
\end{satz}
|
|
|
|
Du musst diesen Beweis nicht im Detail beherrschen. Wichtig ist seine Rolle:
|
|
\problem{SAT} ist der \emph{Anker}, an dem die ganze Kette hängt. Ab hier
|
|
braucht man nie wieder \glqq alle $L \in \NP$\grqq{} zu betrachten.
|
|
|
|
\subsection{Das Arbeitspferd: das Vererbungskorollar}
|
|
|
|
\begin{idee}{Vererbungskorollar -- so wächst die Liste}
|
|
Um ein \emph{neues} Problem $Y$ als NP-vollständig nachzuweisen, brauchst du nur
|
|
zwei Dinge:
|
|
\begin{enumerate}
|
|
\item eine Reduktion $X \redp Y$ von \emph{einem} bereits bekannten
|
|
NP-vollständigen Problem $X$, und
|
|
\item den Nachweis $Y \in \NP$ (den NP-Dreischritt aus Kapitel 3).
|
|
\end{enumerate}
|
|
Dann ist $Y$ automatisch NP-vollständig. Denn für jedes $L \in \NP$ gilt
|
|
$L \redp X \redp Y$ (Transitivität) -- also ist $Y$ NP-schwer, und mit
|
|
$Y \in \NP$ auch NP-vollständig.
|
|
\end{idee}
|
|
|
|
Kein Wort mehr über \glqq alle $L \in \NP$\grqq. Eine Reduktion, ein
|
|
NP-Nachweis -- fertig. Genau so entsteht die folgende Landkarte.
|
|
|
|
\subsection{Die Landkarte der Schwere}
|
|
|
|
Alle Probleme des Kurses hängen an \emph{einer} Kette, die bei \problem{SAT}
|
|
beginnt. Jeder Pfeil ist eine Reduktion und heißt \glqq wird reduziert auf\grqq;
|
|
die Schwere fließt von oben nach unten.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(13,8.7)(0,-0.3)
|
|
\put(5.1,7.7){\framebox(2.4,0.7){\textbf{\problem{SAT}}}}
|
|
\put(6.3,7.7){\vector(-2,-1){2.6}}
|
|
\put(6.3,7.7){\vector(0,-1){1.3}}
|
|
\put(6.3,7.7){\vector(2,-1){2.6}}
|
|
\put(2.6,5.7){\framebox(2.0,0.7){\problem{3-SAT}}}
|
|
\put(5.3,5.7){\framebox(2.0,0.7){\problem{$k$-Clique}}}
|
|
\put(8.0,5.7){\framebox(2.0,0.7){\problem{3-DM}}}
|
|
\put(3.6,5.7){\vector(0,-1){1.3}}
|
|
\put(6.3,5.7){\vector(0,-1){1.3}}
|
|
\put(9.0,5.7){\vector(0,-1){1.3}}
|
|
\put(2.6,3.7){\framebox(2.0,0.7){\problem{$k$-Color}}}
|
|
\put(5.1,3.7){\framebox(2.4,0.7){\problem{IS}, \problem{VC}}}
|
|
\put(8.0,3.7){\framebox(2.0,0.7){\problem{3-EC}}}
|
|
\put(3.6,3.7){\vector(0,-1){1.3}}
|
|
\put(6.3,3.7){\vector(0,-1){1.3}}
|
|
\put(9.0,3.7){\vector(0,-1){1.3}}
|
|
\put(2.2,1.7){\framebox(2.8,0.7){$\problem{HK}\to\problem{TSP}$}}
|
|
\put(5.1,1.7){\framebox(2.4,0.7){\problem{FVS}, $\Delta$-Cover}}
|
|
\put(8.0,1.7){\framebox(2.0,0.7){\problem{SubSetSum}}}
|
|
\put(9.0,1.7){\vector(0,-1){1.3}}
|
|
\put(6.6,0.0){\framebox(3.8,0.7){\problem{Partition}, \problem{Knapsack}, $P\|\Cmax$}}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
Im nächsten Kapitel gehen wir jedes dieser Probleme einzeln durch. Danach
|
|
zeichnen wir die wichtigsten Pfeile -- die Reduktionen -- im Detail nach.
|
|
|
|
\begin{abruf}
|
|
\textbf{A9.} Welche zwei Dinge musst du zeigen, um ein neues Problem als
|
|
NP-vollständig zu beweisen? Welches der beiden wird am häufigsten vergessen?\\
|
|
\textbf{A10.} Warum würde $\Pclass = \NP$ folgen, wenn jemand \problem{SubSet
|
|
Sum} in Polynomialzeit löste?
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Der Problem-Zoo}\label{sec:zoo}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Wir lernen alle Probleme des Kurses kennen -- jedes einzeln, mit Ruhe. Zu jedem
|
|
gibt es die Definition (was gefragt ist) und die Begründung, \emph{warum es in
|
|
$\NP$ liegt} (das Zertifikat). Woher die Schwere kommt und wie die Reduktionen
|
|
konkret arbeiten, folgt im nächsten Kapitel. Alle diese Probleme sind
|
|
NP-vollständig.
|
|
\end{ziel}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{SAT -- das Ur-Problem der Logik}
|
|
% ------------------------------------------------------------------
|
|
|
|
\problem{SAT} steht am Anfang von allem. Es geht um aussagenlogische Formeln in
|
|
einer festen Form, der \emph{konjunktiven Normalform} (KNF): ein UND von
|
|
\emph{Klauseln}, wobei jede Klausel ein ODER von \emph{Literalen} ist. Ein
|
|
Literal ist eine Variable $x_j$ oder ihre Verneinung $\neg x_j$.
|
|
|
|
\begin{defn}{SAT}
|
|
Gegeben eine KNF-Formel $\alpha = C_1 \wedge \dots \wedge C_m$. Frage: Gibt es
|
|
eine Belegung der Variablen mit wahr/falsch, die die ganze Formel wahr macht
|
|
(also \emph{jede} Klausel erfüllt)?
|
|
\end{defn}
|
|
|
|
\begin{bsp}{SAT von Hand lösen}
|
|
$\alpha = (x_1 \vee x_{10}) \wedge (x_1 \vee \neg x_{10}) \wedge (x_{10})$.
|
|
Die dritte Klausel besteht nur aus $x_{10}$ -- sie zwingt $x_{10} = \true$.
|
|
Damit die zweite Klausel $(x_1 \vee \neg x_{10})$ wahr wird und $\neg x_{10}$
|
|
nun falsch ist, muss $x_1 = \true$ sein. Mit beiden auf wahr ist auch die erste
|
|
Klausel erfüllt. Die Formel ist also erfüllbar, Zeuge: $x_1 = x_{10} = \true$.
|
|
\end{bsp}
|
|
|
|
\begin{zert}
|
|
\textbf{Zertifikat:} die Belegung $\psi$ (ein Bit pro Variable).
|
|
\textbf{Verifizierer:} setze $\psi$ ein und werte jede Klausel aus; akzeptiere,
|
|
wenn alle wahr sind. Das kostet lineare Zeit in der Formellänge. Also
|
|
$\problem{SAT} \in \NP$.
|
|
\end{zert}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{3-SAT -- SAT mit kurzen Klauseln}
|
|
% ------------------------------------------------------------------
|
|
|
|
\begin{defn}{3-SAT}
|
|
Wie \problem{SAT}, aber jede Klausel hat \emph{höchstens 3} Literale.
|
|
\end{defn}
|
|
|
|
Warum eine eigene Version? Weil kurze Klauseln viel leichter in andere Probleme
|
|
\glqq einzubauen\grqq{} sind. Fast alle späteren Reduktionen starten deshalb bei
|
|
\problem{3-SAT}, nicht beim allgemeinen \problem{SAT}. Der NP-Nachweis ist
|
|
derselbe wie bei \problem{SAT} (Belegung als Zertifikat).
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{Clique, Independent Set, Vertex Cover -- ein Trio}
|
|
% ------------------------------------------------------------------
|
|
|
|
Diese drei Graphprobleme hängen so eng zusammen, dass man sie am besten
|
|
gemeinsam versteht. Zuerst jedes für sich.
|
|
|
|
\begin{defn}{Clique, Independent Set, Vertex Cover}
|
|
Gegeben ein Graph $G$ und eine Zahl $k$.
|
|
\begin{itemize}
|
|
\item \problem{Clique}: eine Knotengruppe, in der \emph{alle} paarweise
|
|
verbunden sind -- gibt es eine der Größe $\ge k$?
|
|
\item \problem{Independent Set (IS)}: eine Knotengruppe, in der \emph{keine} zwei
|
|
verbunden sind -- gibt es eine der Größe $\ge k$?
|
|
\item \problem{Vertex Cover (VC)}: eine Knotenmenge, die \emph{jede} Kante
|
|
berührt (mindestens ein Endpunkt liegt drin) -- gibt es eine der Größe $\le k$?
|
|
\end{itemize}
|
|
\end{defn}
|
|
|
|
\begin{zert}
|
|
Für alle drei ist das Zertifikat die \emph{Knotenmenge} selbst.
|
|
\textbf{Clique:} prüfe, ob alle Paare verbunden sind. \textbf{IS:} prüfe, ob
|
|
kein Paar verbunden ist. \textbf{VC:} prüfe, ob jede Kante einen Endpunkt in der
|
|
Menge hat. Dazu jeweils die Größe. Alles in $O(|V|^2)$ bzw. $O(|E|)$ -- also
|
|
liegen alle drei in $\NP$.
|
|
\end{zert}
|
|
|
|
Jetzt der Grund, warum man sie zusammen lernt. Es ist \emph{ein und dasselbe
|
|
Bild}, nur dreimal anders betrachtet.
|
|
|
|
\begin{aha}
|
|
\textbf{Das Dualitätsdreieck.} Betrachte einen Graphen $G$ und seinen
|
|
\emph{Komplementgraphen} $\bar G$ (dieselben Knoten, aber genau die Kanten, die
|
|
$G$ \emph{nicht} hat). Dann gilt für jede Knotenmenge $C$:
|
|
\[
|
|
C \text{ Clique in } G
|
|
\;\iff\;
|
|
C \text{ Independent Set in } \bar G
|
|
\;\iff\;
|
|
V \setminus C \text{ Vertex Cover in } \bar G.
|
|
\]
|
|
Wer eines der drei versteht, versteht alle drei.
|
|
\end{aha}
|
|
|
|
Das folgende Bild macht es greifbar: links ein Graph $G$, in dem $\{1,2,3\}$
|
|
eine Clique ist; rechts sein Komplement $\bar G$, in dem dieselbe Menge
|
|
$\{1,2,3\}$ ein Independent Set ist -- und der übrige Knoten $\{4\}$ ein Vertex
|
|
Cover.
|
|
|
|
\begin{bsp}{Ein Bild, drei Rollen}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(12,3.2)(0,-0.5)
|
|
% G links
|
|
\put(1.3,2.6){\small $G$: $\{1,2,3\}$ ist \emph{Clique}}
|
|
\put(1,0){\circle*{0.15}}\put(0.6,-0.05){\small $1$}
|
|
\put(1,1.7){\circle*{0.15}}\put(0.6,1.65){\small $2$}
|
|
\put(2.5,0.85){\circle*{0.15}}\put(2.65,0.8){\small $3$}
|
|
\put(3.9,0.85){\circle*{0.15}}\put(4.05,0.8){\small $4$}
|
|
\put(1,0){\line(0,1){1.7}} % 1-2
|
|
\qbezier(1,0)(1.75,0.42)(2.5,0.85) % 1-3
|
|
\qbezier(1,1.7)(1.75,1.27)(2.5,0.85) % 2-3
|
|
% Gbar rechts
|
|
\put(7.0,2.6){\small $\bar G$: $\{1,2,3\}$ ist \emph{IS}, $\{4\}$ ist \emph{VC}}
|
|
\put(7,0){\circle*{0.15}}\put(6.6,-0.05){\small $1$}
|
|
\put(7,1.7){\circle*{0.15}}\put(6.6,1.65){\small $2$}
|
|
\put(8.5,0.85){\circle*{0.15}}\put(8.2,1.0){\small $3$}
|
|
\put(10,0.85){\circle*{0.15}}\put(10.15,0.8){\small $4$}
|
|
\qbezier(7,0)(8.5,0.42)(10,0.85) % 1-4
|
|
\qbezier(7,1.7)(8.5,1.27)(10,0.85) % 2-4
|
|
\put(8.5,0.85){\line(1,0){1.5}} % 3-4
|
|
\end{picture}
|
|
\end{center}
|
|
In $\bar G$ sind genau die Nicht-Kanten von $G$ eingezeichnet. $\{1,2,3\}$ hat
|
|
dort keine innere Kante mehr (Independent Set). Und Knoten 4 allein berührt alle
|
|
drei Kanten von $\bar G$ (Vertex Cover).
|
|
\end{bsp}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{$k$-Color -- die Landkarten-Färbung}
|
|
% ------------------------------------------------------------------
|
|
|
|
\begin{defn}{$k$-Color}
|
|
Gegeben ein Graph $G$ und eine Zahl $k$. Kann man jedem Knoten eine von $k$
|
|
Farben geben, sodass \emph{keine Kante} zwei gleichfarbige Enden verbindet?
|
|
\end{defn}
|
|
|
|
Man denkt an eine Landkarte, deren Länder so gefärbt werden, dass keine zwei
|
|
Nachbarn dieselbe Farbe tragen. Schon $k = 3$ ist NP-vollständig.
|
|
|
|
\begin{bsp}{Eine gültige 3-Färbung}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(4.5,2.6)(-0.3,-0.3)
|
|
\put(0,0){\circle*{0.18}}\put(-0.35,-0.05){\small $r$}
|
|
\put(2,0){\circle*{0.18}}\put(2.1,-0.05){\small $g$}
|
|
\put(1,1.7){\circle*{0.18}}\put(1.1,1.7){\small $b$}
|
|
\put(3.4,0.85){\circle*{0.18}}\put(3.5,0.8){\small $r$}
|
|
\put(0,0){\line(1,0){2}} % r-g
|
|
\qbezier(0,0)(0.5,0.85)(1,1.7) % r-b
|
|
\qbezier(2,0)(1.5,0.85)(1,1.7) % g-b
|
|
\qbezier(2,0)(2.7,0.42)(3.4,0.85) % g-(r)
|
|
\end{picture}
|
|
\end{center}
|
|
Drei Farben $r,g,b$. Jede Kante verbindet zwei \emph{verschiedene} Farben --
|
|
das Dreieck braucht alle drei, der rechte Knoten darf wieder $r$ sein, weil er
|
|
nur mit $g$ benachbart ist.
|
|
\end{bsp}
|
|
|
|
\begin{zert}
|
|
\textbf{Zertifikat:} die Färbung $f$ (eine Farbe pro Knoten).
|
|
\textbf{Verifizierer:} gehe alle Kanten durch und prüfe, ob ihre Enden
|
|
verschiedene Farben haben -- $O(|E|)$. Also $\problem{$k$-Color} \in \NP$.
|
|
\end{zert}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{Hamiltonkreis -- die Rundreise durch alle Knoten}
|
|
% ------------------------------------------------------------------
|
|
|
|
\begin{defn}{Hamiltonkreis (HK)}
|
|
Gegeben ein Graph $G$. Gibt es einen Rundweg, der \emph{jeden} Knoten
|
|
\emph{genau einmal} besucht und wieder am Start endet?
|
|
\end{defn}
|
|
|
|
\begin{bsp}{Ein Hamiltonkreis}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(4,2.8)(-0.4,-0.3)
|
|
\put(0,0){\circle*{0.15}}
|
|
\put(3,0){\circle*{0.15}}
|
|
\put(3,2){\circle*{0.15}}
|
|
\put(0,2){\circle*{0.15}}
|
|
\put(1.5,2.6){\circle*{0.15}}
|
|
\linethickness{1.2pt}
|
|
\put(0,0){\line(1,0){3}} % unten
|
|
\put(3,0){\line(0,1){2}} % rechts
|
|
\qbezier(3,2)(2.25,2.3)(1.5,2.6) % rechts-oben zur Spitze
|
|
\qbezier(1.5,2.6)(0.75,2.3)(0,2) % Spitze zu links-oben
|
|
\put(0,2){\line(0,-1){2}} % links
|
|
\end{picture}
|
|
\end{center}
|
|
Der fette Weg besucht alle fünf Knoten genau einmal und schließt sich -- ein
|
|
Hamiltonkreis.
|
|
\end{bsp}
|
|
|
|
\begin{zert}
|
|
\textbf{Zertifikat:} die Besuchsreihenfolge (eine Permutation der Knoten).
|
|
\textbf{Verifizierer:} prüfe, ob jeder Knoten genau einmal vorkommt und ob jede
|
|
aufeinanderfolgende -- und die schließende -- Kante wirklich existiert;
|
|
$O(|V|+|E|)$. Also $\problem{HK} \in \NP$.
|
|
\end{zert}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{TSP -- die kürzeste Rundreise}
|
|
% ------------------------------------------------------------------
|
|
|
|
\begin{defn}{TSP (Entscheidungsvariante)}
|
|
Gegeben Städte mit paarweisen Distanzen $d(i,j)$ und eine Schranke $L$. Gibt es
|
|
eine Rundreise durch \emph{alle} Städte (jede genau einmal) mit Gesamtlänge
|
|
$\le L$?
|
|
\end{defn}
|
|
|
|
\problem{HK} fragt nur \glqq gibt es überhaupt eine Rundreise?\grqq;
|
|
\problem{TSP} fügt Distanzen und eine Längengrenze hinzu. Als
|
|
Optimierungsproblem (\glqq finde die kürzeste Rundreise\grqq) ist \problem{TSP}
|
|
der Star des Approximationskapitels.
|
|
|
|
\begin{zert}
|
|
\textbf{Zertifikat:} die Reihenfolge der Städte. \textbf{Verifizierer:} addiere
|
|
die Distanzen entlang der Rundreise und vergleiche mit $L$; prüfe, dass jede
|
|
Stadt genau einmal vorkommt. Linear. Also $\problem{TSP} \in \NP$.
|
|
\end{zert}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{Die Mengen- und Zahlprobleme}
|
|
% ------------------------------------------------------------------
|
|
|
|
Die letzte Familie verlässt die Graphen und arbeitet mit Mengen und Zahlen. Wir
|
|
stellen sie kurz nacheinander vor; ihr NP-Nachweis ist überall gleich einfach.
|
|
|
|
\begin{defn}{3-DM, 3-EC, SubSet Sum, Partition, Knapsack}
|
|
\begin{itemize}
|
|
\item \problem{3-dim.\ Matching (3-DM)}: drei gleich große Mengen und eine Liste
|
|
von Tripeln (je ein Element aus jeder Menge). Wähle Tripel, die jedes Element
|
|
\emph{genau einmal} treffen.
|
|
\item \problem{3-Exact Cover (3-EC)}: eine Familie 3-elementiger Teilmengen
|
|
eines Universums. Wähle einige, die das Universum \emph{exakt} überdecken
|
|
(disjunkt, lückenlos).
|
|
\item \problem{SubSet Sum}: ganze Zahlen $c_1,\dots,c_n$ und ein Ziel $K$. Gibt
|
|
es eine Teilmenge mit Summe \emph{genau} $K$?
|
|
\item \problem{Partition}: gibt es eine Teilmenge, die \emph{genau die Hälfte}
|
|
der Gesamtsumme trägt?
|
|
\item \problem{Knapsack (Rucksack)}: Gegenstände mit Gewicht und Profit,
|
|
Kapazität $B$, Zielprofit $P$. Gibt es eine Auswahl mit Gewicht $\le B$ und
|
|
Profit $\ge P$?
|
|
\end{itemize}
|
|
\end{defn}
|
|
|
|
\begin{bsp}{SubSet Sum ausprobiert}
|
|
Zahlen $3, 7, 8, 4$ und Ziel $K = 15$. Probieren: $3+4+8 = 15$ -- ja, die
|
|
Teilmenge $\{3,4,8\}$ trifft das Ziel. Das Zertifikat ist genau diese
|
|
Teilmenge.
|
|
\end{bsp}
|
|
|
|
\begin{zert}
|
|
Für alle diese Probleme ist das Zertifikat die getroffene \emph{Auswahl}
|
|
(Tripelmenge, Mengenauswahl, Teilmenge). Der Verifizierer rechnet die geforderte
|
|
Summe bzw.\ Überdeckung nach und vergleicht mit den Schranken -- alles in $O(n)$
|
|
bis $O(n^2)$. Also liegen alle in $\NP$.
|
|
\end{zert}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{Scheduling: $P\|\Cmax$}
|
|
% ------------------------------------------------------------------
|
|
|
|
\begin{defn}{$P\|\Cmax$ (Scheduling auf identischen Maschinen)}
|
|
Gegeben $n$ Jobs mit Laufzeiten $p_1,\dots,p_n$ und $m$ gleiche Maschinen.
|
|
Verteile die Jobs auf die Maschinen so, dass die \emph{höchste} Maschinenlast --
|
|
der \emph{Makespan} $\Cmax$ -- möglichst klein wird.
|
|
\end{defn}
|
|
|
|
\begin{zert}
|
|
\textbf{Zertifikat:} die Zuordnung \glqq welcher Job auf welche Maschine\grqq.
|
|
\textbf{Verifizierer:} summiere pro Maschine die Laufzeiten, nimm das Maximum,
|
|
vergleiche mit der Schranke -- $O(n)$. Also liegt (die Entscheidungsvariante
|
|
von) $P\|\Cmax$ in $\NP$.
|
|
\end{zert}
|
|
|
|
\begin{abruf}
|
|
\textbf{A11.} Führe den NP-Dreischritt für \problem{Hamiltonkreis} aus:
|
|
Zertifikat, Prüfung, Laufzeit.\\
|
|
\textbf{A12.} Erkläre das Dualitätsdreieck: Wie hängen \problem{Clique},
|
|
\problem{IS} und \problem{VC} zusammen, und über welchen Graphen?
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Reduktionen im Detail}\label{sec:redu}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Jetzt zeichnen wir die Pfeile der Landkarte nach. Für jede Reduktion sehen wir:
|
|
das Ziel, die Konstruktion Schritt für Schritt, ein Bild oder Zahlenbeispiel und
|
|
-- besonders wichtig -- \emph{beide} Richtungen der Korrektheit. Nimm dir für
|
|
jede Reduktion Zeit; hier entsteht das eigentliche Verständnis.
|
|
\end{ziel}
|
|
|
|
Jede Reduktion beweist \glqq $X \redp Y$\grqq, also \glqq $Y$ ist mindestens so
|
|
schwer wie das bekannte $X$\grqq. Der Aufbau ist immer gleich: Wir bauen aus
|
|
einer $X$-Instanz eine $Y$-Instanz und zeigen, dass die Ja/Nein-Antwort dieselbe
|
|
bleibt. \glqq Beide Richtungen\grqq{} heißt: Ja-Instanz von $X$ wird zu
|
|
Ja-Instanz von $Y$ ($\Rightarrow$), \emph{und} umgekehrt ($\Leftarrow$).
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{$\problem{SAT} \redp \problem{Clique}$: aus Logik wird ein Graph}
|
|
% ------------------------------------------------------------------
|
|
|
|
\textbf{Ziel.} Zeige, dass \problem{Clique} mindestens so schwer wie
|
|
\problem{SAT} ist, indem du aus einer Formel einen Graphen baust.
|
|
|
|
\textbf{Die Konstruktion.} Sei $F = F_1 \wedge \dots \wedge F_m$ eine
|
|
KNF-Formel.
|
|
\begin{itemize}
|
|
\item \emph{Ein Knoten pro Literalvorkommen.} Für das $j$-te Literal in Klausel
|
|
$i$ setze einen Knoten $[i,j]$.
|
|
\item \emph{Kanten nur zwischen \glqq verträglichen\grqq{} Literalen.} Verbinde
|
|
$[i,j]$ und $[i',j']$ genau dann, wenn sie in \emph{verschiedenen} Klauseln
|
|
liegen ($i \ne i'$) \emph{und} sich nicht widersprechen (nicht $x$ gegen
|
|
$\neg x$).
|
|
\item \emph{Gesuchte Cliquengröße} $k = m$ (die Zahl der Klauseln).
|
|
\end{itemize}
|
|
Diese Konstruktion ist offensichtlich in Polynomialzeit machbar.
|
|
|
|
\begin{intuition}
|
|
Warum $k = m$? Eine $m$-Clique muss aus \emph{jeder} Klausel genau einen Knoten
|
|
nehmen -- denn Knoten derselben Klausel sind nie verbunden, es passt also höchstens
|
|
einer pro Klausel hinein. Und weil sich verbundene Knoten nicht widersprechen,
|
|
wählt die Clique aus jeder Klausel ein Literal, ohne sich zu widersprechen. Das
|
|
ist \emph{genau} eine erfüllende Belegung.
|
|
\end{intuition}
|
|
|
|
\begin{bsp}{Die Konstruktion an einem Beispiel}
|
|
$F = (x_1 \vee x_2 \vee x_3) \wedge (\neg x_1 \vee \neg x_2) \wedge (x_1 \vee
|
|
\neg x_2 \vee \neg x_3)$, also $m = 3$ und $k = 3$. Es entstehen acht Knoten in
|
|
drei Spalten (eine je Klausel). Fett eingezeichnet ist die Lösungs-Clique
|
|
$\{[1,1],[2,2],[3,1]\}$, die für $x_1,\ \neg x_2,\ x_1$ steht.
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(10,3.6)(-0.7,-0.4)
|
|
% Spalte 1
|
|
\put(1.0,3.3){\small Klausel 1}
|
|
\put(0.5,2.6){\circle*{0.17}}\put(-0.7,2.55){\small $[1,1]\,x_1$}
|
|
\put(0.5,1.5){\circle{0.17}}\put(-0.05,1.42){\small $x_2$}
|
|
\put(0.5,0.5){\circle{0.17}}\put(-0.05,0.42){\small $x_3$}
|
|
% Spalte 2
|
|
\put(4.0,3.3){\small Klausel 2}
|
|
\put(4.5,2.6){\circle{0.17}}\put(4.7,2.55){\small $\neg x_1$}
|
|
\put(4.5,1.5){\circle*{0.17}}\put(4.7,1.42){\small $[2,2]\,\neg x_2$}
|
|
% Spalte 3
|
|
\put(7.6,3.3){\small Klausel 3}
|
|
\put(8.5,2.6){\circle*{0.17}}\put(7.15,2.55){\small $x_1\,[3,1]$}
|
|
\put(8.5,1.5){\circle{0.17}}\put(8.7,1.42){\small $\neg x_2$}
|
|
\put(8.5,0.5){\circle{0.17}}\put(8.7,0.42){\small $\neg x_3$}
|
|
% Clique-Kanten fett
|
|
\linethickness{1.3pt}
|
|
\put(0.5,2.6){\line(4,-1){4}} % [1,1]-[2,2]
|
|
\put(4.5,1.5){\line(4,1){4}} % [2,2]-[3,1]
|
|
\put(0.5,2.6){\line(1,0){8}} % [1,1]-[3,1]
|
|
\end{picture}
|
|
\end{center}
|
|
Die drei fetten Kanten bilden ein Dreieck -- die 3-Clique. (Die vielen dünnen
|
|
Kanten zwischen anderen verträglichen Paaren sind der Übersicht halber
|
|
weggelassen.)
|
|
\end{bsp}
|
|
|
|
\textbf{Korrektheit, beide Richtungen.}
|
|
\begin{itemize}
|
|
\item[$\Rightarrow$] Ist $F$ erfüllbar, wähle in jeder Klausel ein wahres
|
|
Literal. Die zugehörigen Knoten liegen in verschiedenen Klauseln und
|
|
widersprechen sich nicht (alle sind ja wahr) -- sie bilden eine $m$-Clique.
|
|
\item[$\Leftarrow$] Hat der Graph eine $m$-Clique, so enthält sie aus jeder
|
|
Klausel genau einen Knoten, und keine zwei widersprechen sich. Setze die
|
|
zugehörigen Literale auf wahr -- das ist widerspruchsfrei und erfüllt jede
|
|
Klausel, also $F$.
|
|
\end{itemize}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{$\problem{Clique} \redp \problem{VC}$: das Komplement genügt}
|
|
% ------------------------------------------------------------------
|
|
|
|
\textbf{Ziel.} \problem{Vertex Cover} ist mindestens so schwer wie
|
|
\problem{Clique}. Und diesmal brauchen wir gar kein Gadget -- das
|
|
Dualitätsdreieck erledigt alles.
|
|
|
|
\textbf{Die Konstruktion.} Aus der \problem{Clique}-Instanz $(G, k)$ mit $n$
|
|
Knoten mache die \problem{VC}-Instanz $(\bar G,\ n - k)$: nimm den
|
|
\emph{Komplementgraphen} und ersetze die Schranke $k$ durch $n - k$. In
|
|
$O(n^2)$ berechenbar.
|
|
|
|
\begin{intuition}
|
|
Woher kommt das $n - k$? Aus dem Dualitätsdreieck. Eine Clique der Größe $k$ in
|
|
$G$ ist ein Independent Set der Größe $k$ in $\bar G$. Und das Gegenstück eines
|
|
Independent Set ist ein Vertex Cover: Ist $C$ ein Independent Set, so berührt
|
|
$V \setminus C$ jede Kante. Aus einem IS der Größe $k$ wird also ein VC der
|
|
Größe $n - k$.
|
|
\end{intuition}
|
|
|
|
\textbf{Korrektheit.}
|
|
\begin{itemize}
|
|
\item[$\Rightarrow$] Hat $G$ eine Clique $C$ mit $|C| \ge k$, so ist $C$ ein
|
|
Independent Set in $\bar G$, und $V \setminus C$ ein Vertex Cover in $\bar G$
|
|
mit $|V \setminus C| \le n - k$.
|
|
\item[$\Leftarrow$] Hat $\bar G$ ein Vertex Cover $D$ mit $|D| \le n - k$, so
|
|
ist $V \setminus D$ ein Independent Set in $\bar G$ mit $\ge k$ Knoten -- also
|
|
eine Clique der Größe $\ge k$ in $G$.
|
|
\end{itemize}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{$\problem{VC} \redp \problem{FVS}$: ungerichtet wird gerichtet}
|
|
% ------------------------------------------------------------------
|
|
|
|
\problem{Feedback Vertex Set (FVS)} fragt: Kann man aus einem \emph{gerichteten}
|
|
Graphen $\le k$ Knoten entfernen, sodass \emph{kein gerichteter Kreis} mehr
|
|
übrig bleibt?
|
|
|
|
\textbf{Die Konstruktion.} Aus der \problem{VC}-Instanz $(G, k)$ mache jeden
|
|
ungerichteten Kante $\{u,v\}$ zu \emph{zwei antiparallelen Bögen} $u \to v$ und
|
|
$v \to u$ -- also einem kleinen Kreis der Länge 2. Schranke bleibt $k$.
|
|
|
|
\begin{bsp}{Eine Kante wird zu einem 2-Kreis}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(9,1.8)(0,-0.4)
|
|
% links: ungerichtet
|
|
\put(0.6,0.5){\circle*{0.14}}\put(0.3,0.7){\small $u$}
|
|
\put(2.6,0.5){\circle*{0.14}}\put(2.75,0.7){\small $v$}
|
|
\put(0.6,0.5){\line(1,0){2}}
|
|
\put(1.2,-0.05){\small ungerichtet}
|
|
% Pfeil dazwischen
|
|
\put(3.3,0.5){\small $\leadsto$}
|
|
% rechts: zwei Boegen
|
|
\put(5.0,0.5){\circle*{0.14}}\put(4.7,0.7){\small $u$}
|
|
\put(7.0,0.5){\circle*{0.14}}\put(7.15,0.7){\small $v$}
|
|
\put(5.15,0.68){\vector(1,0){1.7}} % u->v oben
|
|
\put(6.85,0.32){\vector(-1,0){1.7}} % v->u unten
|
|
\put(5.2,-0.05){\small zwei antiparallele Bögen}
|
|
\end{picture}
|
|
\end{center}
|
|
\end{bsp}
|
|
|
|
\begin{intuition}
|
|
Der 2-Kreis $u \to v \to u$ existiert genau wegen dieser einen Kante. Um ihn zu
|
|
zerstören, muss man $u$ \emph{oder} $v$ entfernen -- also die Kante
|
|
\glqq überdecken\grqq. Kreise kaputtmachen (FVS) und Kanten überdecken (VC) wird
|
|
so dasselbe.
|
|
\end{intuition}
|
|
|
|
\textbf{Korrektheit.}
|
|
\begin{itemize}
|
|
\item[$\Rightarrow$] Ist $C$ ein Vertex Cover mit $|C| \le k$, so berührt $C$
|
|
jede Kante -- also enthält $C$ von jedem 2-Kreis einen Knoten. Entfernt man $C$,
|
|
verschwindet jeder 2-Kreis. Da alle Kreise im konstruierten Graphen aus solchen
|
|
Kanten bestehen, ist er danach kreisfrei.
|
|
\item[$\Leftarrow$] Ist $X$ ein FVS mit $|X| \le k$, so muss $X$ jeden 2-Kreis
|
|
treffen -- also jede ursprüngliche Kante überdecken. Damit ist $X$ ein Vertex
|
|
Cover.
|
|
\end{itemize}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{$\problem{3-SAT} \redp \problem{3-Color}$: Wahrheit als Farbe}
|
|
% ------------------------------------------------------------------
|
|
|
|
Diese Reduktion ist raffinierter, deshalb nur die tragende Idee -- die reicht
|
|
fürs Verständnis.
|
|
|
|
\textbf{Die Idee.} Man benutzt drei Farben und tauft sie \textsf{Wahr},
|
|
\textsf{Falsch} und \textsf{Neutral}. Für jede Variable $x_i$ baut man ein
|
|
kleines \emph{Gadget} aus den Knoten $x_i$ und $\neg x_i$, die miteinander und
|
|
mit einem gemeinsamen \textsf{Neutral}-Knoten verbunden sind. Dieses Dreieck
|
|
erzwingt, dass $x_i$ und $\neg x_i$ die beiden übrigen Farben bekommen -- eine
|
|
wird \textsf{Wahr}, die andere \textsf{Falsch}. So kodiert die Färbung eine
|
|
Belegung.
|
|
|
|
\begin{bsp}{Das Variablen-Gadget}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(4.5,2.4)(-0.3,-0.3)
|
|
\put(0,0){\circle*{0.16}}\put(-0.9,-0.05){\small $x_i$}
|
|
\put(2,0){\circle*{0.16}}\put(2.15,-0.05){\small $\neg x_i$}
|
|
\put(1,1.6){\circle*{0.16}}\put(1.15,1.6){\small \textsf{Neutral}}
|
|
\put(0,0){\line(1,0){2}}
|
|
\qbezier(0,0)(0.5,0.8)(1,1.6)
|
|
\qbezier(2,0)(1.5,0.8)(1,1.6)
|
|
\end{picture}
|
|
\end{center}
|
|
Das Dreieck braucht alle drei Farben. Der \textsf{Neutral}-Knoten nimmt die
|
|
neutrale Farbe -- also müssen $x_i$ und $\neg x_i$ \textsf{Wahr} und
|
|
\textsf{Falsch} tragen, in irgendeiner Reihenfolge. Genau das ist \glqq die
|
|
Variable ist wahr oder falsch, aber nicht beides\grqq.
|
|
\end{bsp}
|
|
|
|
Für jede \emph{Klausel} baut man ein weiteres Gadget, das genau dann korrekt
|
|
gefärbt werden kann, wenn mindestens eines ihrer Literale die Farbe \textsf{Wahr}
|
|
trägt. Zusammengesetzt gilt: Die Formel ist erfüllbar $\iff$ der Graph ist
|
|
3-färbbar.
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{$\problem{3-EC} \redp \problem{SubSet Sum}$: Mengen werden Zahlen}
|
|
% ------------------------------------------------------------------
|
|
|
|
Das ist die eleganteste Reduktion des Kurses. Sie verwandelt eine
|
|
Mengen-Überdeckung in eine reine Zahlen-Addition.
|
|
|
|
\textbf{Die Idee.} Schreibe jede 3-elementige Menge als \emph{Bitvektor} über
|
|
dem Universum (eine 1 an jeder Stelle, die die Menge enthält). Lies diesen
|
|
Bitvektor dann als \emph{Zahl zur Basis $n+1$}, wobei $n$ die Anzahl der Mengen
|
|
ist. Das Ziel $K$ ist die Zahl zum Bitvektor \glqq überall 1\grqq.
|
|
|
|
\begin{intuition}
|
|
Warum die krumme Basis $n+1$ statt einfach Basis 2? Damit beim Addieren
|
|
\emph{kein Übertrag} entsteht. Es gibt nur $n$ Mengen, also an jeder Stelle
|
|
höchstens $n$ Einsen -- das bleibt unter $n+1$, die Stelle \glqq läuft nie
|
|
über\grqq. Ohne Übertrag zählt jede Stelle für sich, und \glqq Summe trifft
|
|
genau das Ziel\grqq{} bedeutet \glqq jede Stelle genau einmal überdeckt\grqq{} --
|
|
also eine exakte Überdeckung. Bei Basis 2 gäbe es Überträge, und falsche
|
|
Überdeckungen könnten die Zielsumme zufällig treffen.
|
|
\end{intuition}
|
|
|
|
\begin{bsp}{Komplett durchgerechnet}
|
|
Universum $U = \{1,2,3,4,5,6\}$ (also $3m$ mit $m = 2$). Mengen ($n = 4$):
|
|
$S_1 = \{1,2,3\}$, $S_2 = \{4,5,6\}$, $S_3 = \{1,2,4\}$, $S_4 = \{3,5,6\}$.
|
|
Basis $n+1 = 5$; Stelle für Element $i$ ist $5^{\,i-1}$.
|
|
\begin{center}\small
|
|
\begin{tabular}{lll}
|
|
\toprule
|
|
Menge & Bitvektor ($u_1\dots u_6$) & Zahl zur Basis 5\\
|
|
\midrule
|
|
$S_1=\{1,2,3\}$ & $111000$ & $5^0+5^1+5^2 = 31$\\
|
|
$S_2=\{4,5,6\}$ & $000111$ & $5^3+5^4+5^5 = 3875$\\
|
|
$S_3=\{1,2,4\}$ & $110100$ & $5^0+5^1+5^3 = 131$\\
|
|
$S_4=\{3,5,6\}$ & $001011$ & $5^2+5^4+5^5 = 3775$\\
|
|
\midrule
|
|
Ziel $K$ & $111111$ & $5^0+\dots+5^5 = 3906$\\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\end{center}
|
|
Rechne nach: $S_1 + S_2 = 31 + 3875 = 3906 = K$. Und tatsächlich ist
|
|
$\{S_1, S_2\}$ eine exakte Überdeckung von $U$. (Ebenso
|
|
$S_3 + S_4 = 131 + 3775 = 3906$, und $\{S_3, S_4\}$ überdeckt $U$ ebenfalls
|
|
exakt.) Jede Auswahl, deren Zahlen sich zu $3906$ addieren, trifft jede Stelle
|
|
genau einmal -- eine exakte Überdeckung.
|
|
\end{bsp}
|
|
|
|
% ------------------------------------------------------------------
|
|
\subsection{$\problem{SubSet Sum} \redp \problem{Partition}$: zwei Zusatzzahlen}
|
|
% ------------------------------------------------------------------
|
|
|
|
\textbf{Ziel.} \problem{Partition} (Teilmenge mit halber Gesamtsumme) ist
|
|
mindestens so schwer wie \problem{SubSet Sum}.
|
|
|
|
\textbf{Die Konstruktion.} Aus den Zahlen $c_1,\dots,c_n$ mit Ziel $K$ und
|
|
$N = (\sum_j c_j) + 1$ bilde eine neue Zahlenmenge: alle $c_j$ \emph{plus} zwei
|
|
Zusatzzahlen $c_{n+1} = N - K$ und $c_{n+2} = K + 1$.
|
|
|
|
\begin{intuition}
|
|
Die Gesamtsumme der neuen Menge ist $\sum c_j + (N-K) + (K+1) = \sum c_j + N + 1
|
|
= 2N$. Die Hälfte ist also $N$. Der Clou: Die beiden Zusatzzahlen summieren sich
|
|
zu $(N-K)+(K+1) = N+1$ -- das ist schon \emph{mehr} als eine Hälfte. Sie können
|
|
also niemals \emph{beide} in derselben Hälfte liegen; sie werden immer getrennt.
|
|
\end{intuition}
|
|
|
|
\begin{bsp}{Mit echten Zahlen}
|
|
Zahlen $3, 5, 8, 4$ (Summe $20$), Ziel $K = 12$. Dann $N = 21$, die
|
|
Zusatzzahlen sind $N - K = 9$ und $K + 1 = 13$. Neue Menge:
|
|
$\{3, 5, 8, 4, 9, 13\}$ mit Gesamtsumme $42$, Hälfte $21$.\\[0.3em]
|
|
Die Original-Teilmenge $\{8, 4\}$ trifft $K = 12$. Ergänzt um die Zusatzzahl $9$
|
|
ergibt $\{8, 4, 9\}$ die Summe $21$ -- eine gültige Halbierung. Umgekehrt: Jede
|
|
Halbierung enthält genau eine der beiden Zusatzzahlen; zieht man sie ab, bleibt
|
|
eine Original-Teilmenge, die $K$ trifft.
|
|
\end{bsp}
|
|
|
|
\textbf{Korrektheit.}
|
|
\begin{itemize}
|
|
\item[$\Rightarrow$] Trifft eine Teilmenge $S$ der Originalzahlen den Wert $K$,
|
|
so hat $S \cup \{N-K\}$ die Summe $K + (N-K) = N$ -- eine Halbierung.
|
|
\item[$\Leftarrow$] Jede Halbierung enthält genau eine Zusatzzahl. Enthält sie
|
|
$N-K$, so tragen die Originalzahlen darin $N - (N-K) = K$ bei -- eine
|
|
Teilmenge mit Summe $K$.
|
|
\end{itemize}
|
|
|
|
\begin{abruf}
|
|
\textbf{A13.} Erkläre, warum bei $\problem{3-EC} \redp \problem{SubSet Sum}$ die
|
|
Basis $n+1$ (und nicht Basis 2) gewählt wird.\\
|
|
\textbf{A14.} Bei $\problem{SubSet Sum} \redp \problem{Partition}$: Warum können
|
|
die beiden Zusatzzahlen nie in derselben Hälfte landen?\\
|
|
\textbf{A15.} Rechne die $\Rightarrow$-Richtung von $\problem{Clique} \redp
|
|
\problem{VC}$ an einem selbst gewählten kleinen Graphen nach.
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Wie schwer \emph{genau}? Die ETH}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
NP-Vollständigkeit sagt nur \glqq vermutlich nicht polynomiell\grqq. Sie sagt
|
|
nicht, \emph{wie} exponentiell. Die Exponentialzeit-Hypothese (ETH) ist eine
|
|
schärfere Annahme, aus der man konkrete untere Laufzeitschranken herleitet. Wir
|
|
sehen auch, wie so ein Schranken-Beweis wirklich aussieht.
|
|
\end{ziel}
|
|
|
|
\subsection{Die Lücke, die NP-Vollständigkeit offen lässt}
|
|
|
|
NP-Vollständigkeit ist ein grobes Sieb. Sie wirft ein Problem, das $2^n$
|
|
braucht, in denselben Topf wie eines, das nur $2^{\sqrt n}$ braucht -- beide
|
|
heißen schlicht \glqq nicht polynomiell\grqq. Für viele Fragen will man aber
|
|
genauer wissen: Geht es wenigstens \emph{subexponentiell}, also spürbar besser
|
|
als $2^n$?
|
|
|
|
\begin{defn}{Klein-o und \glqq subexponentiell\grqq}
|
|
$f(n) = o(g(n))$ heißt: $f$ wächst \emph{echt langsamer} als $g$, formal
|
|
$f(n)/g(n) \to 0$. Achtung: $\delta n$ ist \emph{nicht} $o(n)$ für ein festes
|
|
$\delta > 0$. Ein \glqq $2^{o(n)}$-Algorithmus\grqq{} hat einen Exponenten, der
|
|
langsamer als linear wächst -- er läuft \emph{subexponentiell}, z.\,B. mit
|
|
$2^{\sqrt n}$.
|
|
\end{defn}
|
|
|
|
Das Bild zeigt die drei Welten nebeneinander: harmlos polynomiell,
|
|
subexponentiell (die mittlere Kurve), und echt exponentiell.
|
|
|
|
\begin{bsp}{Drei Wachstumsklassen}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(10,4.6)(-0.7,-0.6)
|
|
\put(0,0){\vector(1,0){9.2}} \put(8.9,-0.5){\small $n$}
|
|
\put(0,0){\vector(0,1){4.2}} \put(-0.6,4.0){\small Zeit}
|
|
\qbezier(0,0)(5,0.5)(9,1.5) \put(8.5,1.4){\small poly}
|
|
\qbezier(0,0)(4,0.7)(7.2,4.0) \put(6.6,4.0){\small $2^{o(n)}$}
|
|
\qbezier(0,0)(2.5,0.5)(3.3,4.1) \put(2.9,4.15){\small $2^{n}$}
|
|
\end{picture}
|
|
\end{center}
|
|
Die ETH behauptet: Für \problem{3-SAT} gibt es \emph{keinen} Algorithmus der
|
|
mittleren (subexponentiellen) Sorte -- es bleibt echt exponentiell.
|
|
\end{bsp}
|
|
|
|
\subsection{Die Hypothese}
|
|
|
|
\begin{defn}{Exponentialzeit-Hypothese (ETH)}
|
|
Es gibt eine Konstante $\delta > 0$, sodass \problem{3-SAT} mit $n$ Variablen
|
|
\emph{nicht} in Zeit $2^{\delta n} \cdot \poly$ lösbar ist. Kurz: es gibt
|
|
\emph{keinen} $2^{o(n)}$-Algorithmus für \problem{3-SAT}.
|
|
\end{defn}
|
|
|
|
Das ist eine \emph{Annahme} -- stärker als $\Pclass \ne \NP$, aber breit
|
|
geglaubt, weil alle bekannten 3-SAT-Algorithmen $c^n$ brauchen. Aus ihr leitet
|
|
man untere Schranken für viele andere Probleme ab.
|
|
|
|
\subsection{Wie ein ETH-Schranken-Beweis aussieht}
|
|
|
|
Das Beweismuster ist immer \emph{Kontraposition entlang einer Reduktion}: Man
|
|
nimmt an, das Zielproblem hätte einen zu schnellen Algorithmus, und leitet
|
|
daraus einen zu schnellen Algorithmus für \problem{3-SAT} ab -- Widerspruch zur
|
|
ETH.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(13,1.6)(0,-0.3)
|
|
\put(0,0.2){\framebox(4.4,1.0){\shortstack{\small \emph{Annahme:} $2^{o(\cdot)}$-Alg.\\ \small für Zielproblem $Y$}}}
|
|
\put(4.4,0.7){\vector(1,0){1.7}} \put(4.5,0.85){\small Reduktion}
|
|
\put(6.1,0.2){\framebox(3.5,1.0){\shortstack{\small \emph{ergibt:} $2^{o(m)}$-Alg.\\ \small für \problem{3-SAT}}}}
|
|
\put(9.6,0.7){\vector(1,0){1.3}}
|
|
\put(10.9,0.2){\framebox(2.0,1.0){\shortstack{\small Widerspruch\\ \small zur ETH}}}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
Das Entscheidende -- und der Grund, warum viele hier scheitern -- ist die
|
|
\emph{Größenrechnung} im mittleren Pfeil. Machen wir sie einmal konkret.
|
|
|
|
\begin{idee}{Konkret: die Schranke für \problem{3-Color}}
|
|
Es gibt eine Reduktion $\problem{3-SAT} \redp \problem{3-Color}$, die aus einer
|
|
Formel mit $n$ Variablen und $m$ Klauseln einen Graphen mit \emph{$O(n+m)$
|
|
Knoten} baut. Nimm nun an, jemand könnte \problem{3-Color} in $2^{o(N)}$ lösen,
|
|
wobei $N$ die Knotenzahl ist. Setze die Reduktion davor:
|
|
\[
|
|
\underbrace{2^{o(N)}}_{\text{Annahme}} \text{ mit } N = O(n+m)
|
|
\quad\Longrightarrow\quad
|
|
\problem{3-SAT} \text{ in } 2^{o(n+m)}.
|
|
\]
|
|
Nun ist $n + m$ höchstens $O(m)$ (jede Variable kommt in einer Klausel vor, also
|
|
$n \le 3m$). Damit hätten wir einen $2^{o(m)}$-Algorithmus für \problem{3-SAT}.
|
|
Das ist verboten -- \emph{sofern} wir auch $2^{o(m)}$ ausschließen dürfen. Genau
|
|
dafür brauchen wir den nächsten Satz.
|
|
\end{idee}
|
|
|
|
\subsection{Warum das Sparsification-Lemma nötig ist}
|
|
|
|
\begin{satz}{Sparsification-Lemma}
|
|
Unter der ETH gibt es auch \emph{keinen} $2^{o(m)}$-Algorithmus für
|
|
\problem{3-SAT}, wobei $m$ die \emph{Klauselzahl} ist.
|
|
\end{satz}
|
|
|
|
\begin{intuition}
|
|
Beachte den feinen Unterschied: Die ETH selbst spricht über die
|
|
\emph{Variablenzahl} $n$. Die Größenrechnung oben landete aber bei einer
|
|
Schranke in der \emph{Klauselzahl} $m$. Und $m$ kann viel größer als $n$ sein
|
|
(bis $\sim n^3$). Deshalb folgt \glqq kein $2^{o(m)}$\grqq{} \emph{nicht} direkt
|
|
aus \glqq kein $2^{o(n)}$\grqq. Das Sparsification-Lemma füllt genau diese
|
|
Lücke: Es überträgt die Härte von $n$ auf $m$. Erst mit ihm schließt sich der
|
|
Widerspruch im Bild oben.
|
|
\end{intuition}
|
|
|
|
\begin{stolper}
|
|
Immer wenn die Größe deiner konstruierten Instanz an der \emph{Klauselzahl} $m$
|
|
hängt (und das ist fast immer so), musst du das Sparsification-Lemma zitieren.
|
|
Es ist der am häufigsten vergessene Schritt in ETH-Beweisen.
|
|
\end{stolper}
|
|
|
|
Mit demselben Muster bekommt man unter der ETH untere Schranken $2^{o(n)}$ auch
|
|
für \problem{Clique}, \problem{Vertex Cover}, \problem{Independent Set},
|
|
\problem{SubSet Sum} und \problem{Partition} -- jeweils mit der passenden
|
|
Größenrechnung.
|
|
|
|
\begin{abruf}
|
|
\textbf{A16.} Wenn die ETH \emph{falsch} ist -- folgt daraus $\Pclass = \NP$?
|
|
Begründe.\\
|
|
\textbf{A17.} Skizziere die Größenrechnung für die \problem{3-Color}-Schranke.
|
|
An welcher Stelle kommt das Sparsification-Lemma ins Spiel?
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Damit leben: gute Näherungen}\label{sec:approx}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Wenn ein Optimierungsproblem (vermutlich) keine schnelle exakte Lösung hat,
|
|
berechnet man in Polynomialzeit eine \emph{beweisbar gute} Näherung. Wir lernen,
|
|
was \glqq beweisbar gut\grqq{} heißt, und sehen die wichtigsten Algorithmen --
|
|
den TSP-Algorithmus zeichnen wir Schritt für Schritt.
|
|
\end{ziel}
|
|
|
|
\subsection{Was heißt \glqq gute Näherung\grqq?}
|
|
|
|
\begin{defn}{Multiplikative Güte}
|
|
Sei $\OPT(I)$ der optimale Wert einer Instanz $I$. Ein Algorithmus $A$ hat
|
|
\emph{Güte $\alpha$}, wenn für \emph{alle} Instanzen gilt:
|
|
\begin{itemize}
|
|
\item bei Minimierung (TSP, Scheduling): $A(I) \le \alpha \cdot \OPT(I)$ --
|
|
die Lösung ist höchstens $\alpha$-mal so teuer wie das Optimum;
|
|
\item bei Maximierung (Knapsack): $\OPT(I) \le \alpha \cdot A(I)$ -- die Lösung
|
|
liefert mindestens ein $\alpha$-tel des Optimums.
|
|
\end{itemize}
|
|
Die Güte heißt \emph{scharf}, wenn es Instanzen gibt, die den Faktor (fast)
|
|
erreichen -- sie ist dann nicht zu pessimistisch.
|
|
\end{defn}
|
|
|
|
\begin{intuition}
|
|
Güte $\alpha$ ist eine \emph{Garantie für den schlimmsten Fall}. Güte 2 bei
|
|
einem Minimierungsproblem heißt: Egal welche Eingabe, meine Lösung ist nie mehr
|
|
als doppelt so teuer wie die bestmögliche. Kleineres $\alpha$ ist besser;
|
|
$\alpha = 1$ wäre exakt optimal.
|
|
\end{intuition}
|
|
|
|
Manche Probleme erlauben sogar eine einstellbare Genauigkeit -- eine ganze
|
|
Familie von Algorithmen, bei der du $\alpha = 1 + \varepsilon$ so nah an 1
|
|
wählst, wie du willst.
|
|
|
|
\begin{defn}{PTAS, EPTAS, FPTAS}
|
|
Eine Familie $(A_\varepsilon)$ mit Güte $1 + \varepsilon$ für jedes
|
|
$\varepsilon > 0$ heißt:
|
|
\begin{itemize}
|
|
\item \emph{PTAS}, wenn die Laufzeit für jedes feste $\varepsilon$ polynomiell
|
|
in $n$ ist ($\varepsilon$ darf im Exponenten stecken, z.\,B. $n^{1/\varepsilon}$);
|
|
\item \emph{EPTAS}, wenn die Laufzeit $f(1/\varepsilon) \cdot \poly(n)$ ist --
|
|
$\varepsilon$ ist aus dem Exponenten von $n$ heraus;
|
|
\item \emph{FPTAS}, wenn die Laufzeit polynomiell in $n$ \emph{und} $1/\varepsilon$
|
|
ist -- die stärkste Form.
|
|
\end{itemize}
|
|
Ein Wort noch: \emph{pseudopolynomiell} heißt eine Laufzeit, die polynomiell in
|
|
den \emph{Zahlenwerten} der Eingabe ist -- was wegen des Stolpersteins aus
|
|
Kapitel 2 \emph{nicht} dasselbe ist wie polynomiell in der Eingabelänge.
|
|
\end{defn}
|
|
|
|
\subsection{TSP ist im Allgemeinen gar nicht approximierbar}
|
|
|
|
\begin{satz}{Kein Näherungsalgorithmus für allgemeines TSP}
|
|
Für beliebige Distanzen gibt es \emph{keinen} Näherungsalgorithmus mit
|
|
beschränkter Güte -- außer $\Pclass = \NP$.\\[0.3em]
|
|
\emph{Die Beweisidee:} Man reduziert \problem{Hamiltonkreis}. Echte Kanten
|
|
bekommen Distanz 1, fehlende Kanten eine \emph{riesige} Distanz. Gäbe es einen
|
|
Algorithmus mit fester Güte $\alpha$, müsste er die billige Hamilton-Tour (Länge
|
|
$|V|$) von jeder teuren Tour unterscheiden -- und könnte damit \problem{HK}
|
|
exakt entscheiden. Das ist NP-schwer.
|
|
\end{satz}
|
|
|
|
Der Ausweg ist eine realistische Zusatzannahme: das \emph{metrische} TSP. Die
|
|
Distanzen sind symmetrisch und erfüllen die \emph{Dreiecksungleichung}
|
|
$d(i,j) \le d(i,k) + d(k,j)$ -- ein Umweg ist nie kürzer als der direkte Weg.
|
|
Echte Entfernungen erfüllen das immer. Und hier funktioniert ein schöner
|
|
Algorithmus.
|
|
|
|
\subsection{$\Delta$TSP$_1$: der Algorithmus als Bilderfolge}
|
|
|
|
\begin{idee}{Der Dreisprung}
|
|
$\Delta$TSP$_1$ baut zuerst ein billiges Gerüst, das alle Städte verbindet (einen
|
|
\emph{minimalen Spannbaum}), macht daraus einen Rundweg über alle Kanten
|
|
(\emph{Eulerkreis}, indem alle Knotengrade gerade werden) und kürzt diesen zur
|
|
Tour ab. Wir gehen es an einem festen Beispiel durch -- vier Bilder, ein
|
|
Algorithmus.
|
|
\end{idee}
|
|
|
|
\noindent Unser Beispiel: die Städte $A,B,C,D,E$ mit $d(A,E)=1$, $d(B,C)=1$,
|
|
$d(A,C)=2$, $d(C,D)=2$ (die übrigen Distanzen sind 2 oder 3). Das Layout der
|
|
fünf Städte bleibt in allen Bildern gleich.
|
|
|
|
\medskip
|
|
\noindent\textbf{Bild 1 -- die optimale Tour (zum Vergleich).} So sieht die
|
|
beste mögliche Rundreise aus. Sie hat Länge~8. Der Algorithmus kennt sie nicht;
|
|
wir zeigen sie nur, um am Ende zu vergleichen.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(5.2,3.4)(-0.3,-0.3)
|
|
\put(0.5,2.2){\circle*{0.14}}\put(0.05,2.25){\small $A$}
|
|
\put(0.5,0.3){\circle*{0.14}}\put(0.05,0.15){\small $B$}
|
|
\put(2.6,1.3){\circle*{0.14}}\put(2.35,1.45){\small $C$}
|
|
\put(4.6,1.3){\circle*{0.14}}\put(4.75,1.3){\small $D$}
|
|
\put(2.6,3.0){\circle*{0.14}}\put(2.75,3.0){\small $E$}
|
|
\qbezier(2.6,1.3)(1.55,0.8)(0.5,0.3) % C-B
|
|
\qbezier(0.5,0.3)(2.55,0.5)(4.6,1.3) % B-D
|
|
\qbezier(4.6,1.3)(3.6,2.15)(2.6,3.0) % D-E
|
|
\qbezier(2.6,3.0)(1.55,2.6)(0.5,2.2) % E-A
|
|
\qbezier(0.5,2.2)(1.55,1.75)(2.6,1.3) % A-C
|
|
\put(-0.2,-0.2){\small Tour $[C,B,D,E,A,C]$, Länge $8 = \OPT$}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\medskip
|
|
\noindent\textbf{Bild 2 -- Schritt 1: minimaler Spannbaum.} Der Algorithmus
|
|
verbindet alle Städte so billig wie möglich zu einem Baum (keine Kreise). Das
|
|
sind die Kanten $A$--$E$, $B$--$C$, $A$--$C$, $C$--$D$ mit Gesamtgewicht~6.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(5.2,3.4)(-0.3,-0.3)
|
|
\put(0.5,2.2){\circle*{0.14}}\put(0.05,2.25){\small $A$}
|
|
\put(0.5,0.3){\circle*{0.14}}\put(0.05,0.15){\small $B$}
|
|
\put(2.6,1.3){\circle*{0.14}}\put(2.35,1.45){\small $C$}
|
|
\put(4.6,1.3){\circle*{0.14}}\put(4.75,1.3){\small $D$}
|
|
\put(2.6,3.0){\circle*{0.14}}\put(2.75,3.0){\small $E$}
|
|
\linethickness{1.3pt}
|
|
\qbezier(0.5,2.2)(1.55,2.6)(2.6,3.0) % A-E
|
|
\put(1.3,2.75){\small $1$}
|
|
\qbezier(0.5,0.3)(1.55,0.8)(2.6,1.3) % B-C
|
|
\put(1.3,0.55){\small $1$}
|
|
\qbezier(0.5,2.2)(1.55,1.75)(2.6,1.3) % A-C
|
|
\put(1.35,1.95){\small $2$}
|
|
\put(2.6,1.3){\line(1,0){2.0}} % C-D
|
|
\put(3.5,1.4){\small $2$}
|
|
\put(0.0,-0.2){\small Spannbaum, Gewicht $w(T)=6$}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\begin{intuition}
|
|
Warum ein Spannbaum? Weil er \emph{garantiert billiger} ist als die optimale
|
|
Tour: Nimm die optimale Tour und lösche eine ihrer Kanten -- übrig bleibt ein
|
|
Weg durch alle Städte, also ein (spezieller) Spannbaum. Der \emph{minimale}
|
|
Spannbaum ist höchstens so teuer wie dieser. Also $w(T) \le \OPT$. Das ist der
|
|
Kern der Güte-Garantie.
|
|
\end{intuition}
|
|
|
|
\medskip
|
|
\noindent\textbf{Bild 3 -- Schritt 2 und 3: verdoppeln, dann Eulerkreis.} Jetzt
|
|
verdoppelt der Algorithmus jede Baumkante (im Bild als \glqq $\times 2$\grqq).
|
|
Dadurch hat \emph{jeder} Knoten geraden Grad -- die Bedingung für einen
|
|
Eulerkreis, einen Rundweg, der jede Kante genau einmal nutzt. Sein Gewicht ist
|
|
$2 \cdot 6 = 12$.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(5.2,3.4)(-0.3,-0.3)
|
|
\put(0.5,2.2){\circle*{0.14}}\put(0.05,2.25){\small $A$}
|
|
\put(0.5,0.3){\circle*{0.14}}\put(0.05,0.15){\small $B$}
|
|
\put(2.6,1.3){\circle*{0.14}}\put(2.35,1.45){\small $C$}
|
|
\put(4.6,1.3){\circle*{0.14}}\put(4.75,1.3){\small $D$}
|
|
\put(2.6,3.0){\circle*{0.14}}\put(2.75,3.0){\small $E$}
|
|
\linethickness{1.3pt}
|
|
\qbezier(0.5,2.2)(1.55,2.6)(2.6,3.0)
|
|
\put(1.25,2.75){\small $\times 2$}
|
|
\qbezier(0.5,0.3)(1.55,0.8)(2.6,1.3)
|
|
\put(1.25,0.5){\small $\times 2$}
|
|
\qbezier(0.5,2.2)(1.55,1.75)(2.6,1.3)
|
|
\put(1.3,1.9){\small $\times 2$}
|
|
\put(2.6,1.3){\line(1,0){2.0}}
|
|
\put(3.4,1.4){\small $\times 2$}
|
|
\put(-0.2,-0.2){\small Multigraph, Gewicht $12$, alle Grade gerade}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\noindent Ein Eulerkreis in diesem Multigraphen ist z.\,B.
|
|
$[C, A, E, A, C, B, C, D, C]$ -- er benutzt jede der verdoppelten Kanten einmal
|
|
und hat Länge~12. Beachte: Manche Städte (hier $A$, $C$) werden dabei
|
|
\emph{mehrfach} besucht.
|
|
|
|
\medskip
|
|
\noindent\textbf{Bild 4 -- Schritt 4: abkürzen zur Tour.} Eine echte Rundreise
|
|
darf jede Stadt nur einmal besuchen. Also läuft man den Eulerkreis ab und
|
|
\emph{überspringt} bereits besuchte Städte. Aus $[C,A,E,A,C,B,C,D,C]$ wird so
|
|
die Tour $[C,A,E,B,D,C]$.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(5.2,3.4)(-0.3,-0.3)
|
|
\put(0.5,2.2){\circle*{0.14}}\put(0.05,2.25){\small $A$}
|
|
\put(0.5,0.3){\circle*{0.14}}\put(0.05,0.15){\small $B$}
|
|
\put(2.6,1.3){\circle*{0.14}}\put(2.35,1.45){\small $C$}
|
|
\put(4.6,1.3){\circle*{0.14}}\put(4.75,1.3){\small $D$}
|
|
\put(2.6,3.0){\circle*{0.14}}\put(2.75,3.0){\small $E$}
|
|
\linethickness{1.1pt}
|
|
\qbezier(2.6,1.3)(1.55,1.75)(0.5,2.2) % C-A
|
|
\qbezier(0.5,2.2)(1.55,2.6)(2.6,3.0) % A-E
|
|
\qbezier(2.6,3.0)(1.55,1.65)(0.5,0.3) % E-B
|
|
\qbezier(0.5,0.3)(2.55,0.5)(4.6,1.3) % B-D
|
|
\put(2.6,1.3){\line(1,0){2.0}} % D-C
|
|
\put(-0.2,-0.2){\small Tour $[C,A,E,B,D,C]$, Länge $10 \le 2\cdot\OPT$}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\begin{intuition}
|
|
Warum ist Abkürzen nie schädlich? Weil eine Abkürzung zwei Kanten durch eine
|
|
direkte Kante ersetzt, und die \emph{Dreiecksungleichung} garantiert, dass der
|
|
direkte Weg nicht länger ist. Deshalb bleibt die Tour $\le 12 = 2 w(T) \le 2
|
|
\OPT$. Hier: Länge 10, garantiert $\le 16$, tatsächlich nah an $\OPT = 8$.
|
|
\end{intuition}
|
|
|
|
\subsection{Christofides: schlauer verdoppeln}
|
|
|
|
$\Delta$TSP$_1$ verdoppelt \emph{alle} Kanten -- das kostet zusätzlich etwa
|
|
$w(T) \approx \OPT$, daher die Güte 2. Christofides bemerkt: Wir müssen gar nicht
|
|
alle Grade reparieren, sondern nur die \emph{ungeraden}. Und die repariert man
|
|
viel billiger.
|
|
|
|
\begin{idee}{Nur die schiefen Knoten reparieren}
|
|
Ein Eulerkreis braucht nur, dass \emph{jeder} Knoten geraden Grad hat. Im
|
|
Spannbaum haben aber ohnehin nur \emph{manche} Knoten ungeraden Grad. Statt
|
|
alles zu verdoppeln, verbindet Christofides genau diese ungeraden Knoten durch
|
|
ein \emph{minimales perfektes Matching} -- die billigste Art, sie paarweise zu
|
|
verkuppeln. Das kostet höchstens $\OPT/2$, und daraus folgt Güte $1{,}5$.
|
|
\end{idee}
|
|
|
|
\noindent\textbf{Bild 1 -- der Spannbaum (wie zuvor).} Wir starten mit demselben
|
|
minimalen Spannbaum wie bei $\Delta$TSP$_1$.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(5.2,3.4)(-0.3,-0.3)
|
|
\put(0.5,2.2){\circle*{0.14}}\put(0.05,2.25){\small $A$}
|
|
\put(0.5,0.3){\circle*{0.14}}\put(0.05,0.15){\small $B$}
|
|
\put(2.6,1.3){\circle*{0.14}}\put(2.35,1.45){\small $C$}
|
|
\put(4.6,1.3){\circle*{0.14}}\put(4.75,1.3){\small $D$}
|
|
\put(2.6,3.0){\circle*{0.14}}\put(2.75,3.0){\small $E$}
|
|
\linethickness{1.3pt}
|
|
\qbezier(0.5,2.2)(1.55,2.6)(2.6,3.0)
|
|
\qbezier(0.5,0.3)(1.55,0.8)(2.6,1.3)
|
|
\qbezier(0.5,2.2)(1.55,1.75)(2.6,1.3)
|
|
\put(2.6,1.3){\line(1,0){2.0}}
|
|
\put(0.0,-0.2){\small Spannbaum $T$, Gewicht 6}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\noindent\textbf{Bild 2 -- die ungeraden Knoten finden.} Wir zählen die Grade im
|
|
Baum: $A$ hat Grad 2 (gerade), alle anderen ungerade. Die ungeraden Knoten
|
|
$X = \{B, C, D, E\}$ sind mit einem Ring markiert.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(5.2,3.4)(-0.3,-0.3)
|
|
\put(0.5,2.2){\circle*{0.14}}\put(0.05,2.25){\small $A$}
|
|
\put(0.5,0.3){\circle*{0.14}}\put(0.05,0.15){\small $B$}\put(0.5,0.3){\circle{0.34}}
|
|
\put(2.6,1.3){\circle*{0.14}}\put(2.35,1.5){\small $C$}\put(2.6,1.3){\circle{0.34}}
|
|
\put(4.6,1.3){\circle*{0.14}}\put(4.75,1.3){\small $D$}\put(4.6,1.3){\circle{0.34}}
|
|
\put(2.6,3.0){\circle*{0.14}}\put(2.75,3.0){\small $E$}\put(2.6,3.0){\circle{0.34}}
|
|
\linethickness{1.3pt}
|
|
\qbezier(0.5,2.2)(1.55,2.6)(2.6,3.0)
|
|
\qbezier(0.5,0.3)(1.55,0.8)(2.6,1.3)
|
|
\qbezier(0.5,2.2)(1.55,1.75)(2.6,1.3)
|
|
\put(2.6,1.3){\line(1,0){2.0}}
|
|
\put(-0.3,-0.2){\small ungerade Grade: $X=\{B,C,D,E\}$ (markiert)}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\noindent\textbf{Bild 3 -- das Matching hinzufügen.} Unter den möglichen
|
|
Paarungen der vier Knoten ist $\{B\text{--}C,\ D\text{--}E\}$ die billigste
|
|
(Kosten $1 + 2 = 3$). Diese zwei Matching-Kanten (dünn) kommen zum Baum dazu.
|
|
Jetzt haben \emph{alle} Knoten geraden Grad.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(5.2,3.4)(-0.3,-0.3)
|
|
\put(0.5,2.2){\circle*{0.14}}\put(0.05,2.25){\small $A$}
|
|
\put(0.5,0.3){\circle*{0.14}}\put(0.05,0.15){\small $B$}
|
|
\put(2.6,1.3){\circle*{0.14}}\put(2.35,1.5){\small $C$}
|
|
\put(4.6,1.3){\circle*{0.14}}\put(4.75,1.3){\small $D$}
|
|
\put(2.6,3.0){\circle*{0.14}}\put(2.75,3.0){\small $E$}
|
|
\linethickness{1.3pt}
|
|
\qbezier(0.5,2.2)(1.55,2.6)(2.6,3.0)
|
|
\qbezier(0.5,0.3)(1.55,0.8)(2.6,1.3)
|
|
\qbezier(0.5,2.2)(1.55,1.75)(2.6,1.3)
|
|
\put(2.6,1.3){\line(1,0){2.0}}
|
|
% Matching-Kanten duenn: B-C (schon da -> zweite, versetzt) und D-E
|
|
\linethickness{0.4pt}
|
|
\qbezier(0.6,0.25)(1.65,0.72)(2.7,1.22) % zweites B-C (Matching), leicht versetzt
|
|
\qbezier(4.6,1.3)(3.6,2.15)(2.6,3.0) % D-E (Matching)
|
|
\put(3.7,2.2){\small $M$}
|
|
\put(1.7,0.35){\small $M$}
|
|
\put(-0.3,-0.2){\small $+$ Matching $\{B\text{--}C, D\text{--}E\}$, Kosten 3}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\noindent\textbf{Bild 4 -- Eulerkreis und abkürzen.} Aus $T + M$ gewinnt man
|
|
einen Eulerkreis und kürzt ihn ab. Ergebnis: die Tour $[C,B,A,E,D,C]$ mit
|
|
Länge~\textbf{9} -- besser als die 10 von $\Delta$TSP$_1$.
|
|
|
|
\begin{center}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{picture}(5.2,3.4)(-0.3,-0.3)
|
|
\put(0.5,2.2){\circle*{0.14}}\put(0.05,2.25){\small $A$}
|
|
\put(0.5,0.3){\circle*{0.14}}\put(0.05,0.15){\small $B$}
|
|
\put(2.6,1.3){\circle*{0.14}}\put(2.35,1.5){\small $C$}
|
|
\put(4.6,1.3){\circle*{0.14}}\put(4.75,1.3){\small $D$}
|
|
\put(2.6,3.0){\circle*{0.14}}\put(2.75,3.0){\small $E$}
|
|
\linethickness{1.1pt}
|
|
\qbezier(2.6,1.3)(1.55,0.8)(0.5,0.3) % C-B
|
|
\put(0.5,0.3){\line(0,1){1.9}} % B-A
|
|
\qbezier(0.5,2.2)(1.55,2.6)(2.6,3.0) % A-E
|
|
\qbezier(2.6,3.0)(3.6,2.15)(4.6,1.3) % E-D
|
|
\put(4.6,1.3){\line(-1,0){2.0}} % D-C
|
|
\put(0.1,-0.2){\small Tour $[C,B,A,E,D,C]$, Länge $9 \le 1{,}5\cdot\OPT$}
|
|
\end{picture}
|
|
\end{center}
|
|
|
|
\begin{stolper}
|
|
Zwei Dinge werden bei Christofides oft falsch gemacht: Das Matching wird
|
|
\emph{nur} über die ungerad-gradigen Knoten des Spannbaums gebildet, nicht über
|
|
alle. Und ohne die Dreiecksungleichung bricht wieder das Abkürzen zusammen.
|
|
\end{stolper}
|
|
|
|
\subsection{Knapsack: warum pure Gier scheitert}
|
|
|
|
Der Rucksack als Optimierungsproblem: Pack Gegenstände mit maximalem
|
|
Gesamtprofit ein, ohne die Kapazität $B$ zu überschreiten.
|
|
|
|
\begin{idee}{Greedy -- und sein Versagen}
|
|
Der naheliegende Weg (\emph{Greedy}): sortiere nach \glqq Profit pro Gewicht\grqq{}
|
|
und pack der Reihe nach ein, was noch passt. Das ist oft gut, hat aber
|
|
\emph{keine} Garantie.
|
|
\end{idee}
|
|
|
|
\begin{bsp}{Greedy kann beliebig schlecht sein}
|
|
Zwei Gegenstände: einer mit Gewicht 1 und Profit 1, ein anderer mit Gewicht $B$
|
|
und Profit $B-1$. Die Kapazität ist $B$. Greedy schaut auf die Dichte: der
|
|
kleine hat Dichte 1, der große Dichte $(B-1)/B < 1$. Also nimmt Greedy den
|
|
kleinen -- Profit \textbf{1}. Optimal wäre der große -- Profit $B-1$. Das
|
|
Verhältnis $B-1$ wächst mit $B$ ins Unendliche. Keine feste Güte.
|
|
\end{bsp}
|
|
|
|
\begin{idee}{Die Reparatur: Modified Greedy (MGA), Güte 2}
|
|
Rechne zwei Kandidaten aus -- das Greedy-Ergebnis \emph{und} \glqq nimm nur den
|
|
einen profitabelsten Gegenstand\grqq{} -- und gib den besseren aus. Warum das
|
|
reicht: Greedy verliert seinen Profit immer nur an dem \emph{einen}
|
|
\glqq Split-Item\grqq, das gerade nicht mehr passte. Dessen Profit fängt der
|
|
Einzel-Gegenstand ab. Damit ist man nie schlechter als halb so gut wie das
|
|
Optimum. Noch näher kommen der \emph{Sahni}-Algorithmus (probiert alle kleinen
|
|
Vorauswahlen, ein PTAS) und das \emph{FPTAS} (rundet die Profite und löst exakt
|
|
per dynamischer Programmierung, Güte $1+\varepsilon$).
|
|
\end{idee}
|
|
|
|
\subsection{Scheduling: einfache Regeln, sichtbar im Gantt-Bild}
|
|
|
|
Zurück zu $P\|\Cmax$: $n$ Jobs auf $m$ Maschinen, minimiere die höchste Last.
|
|
|
|
\begin{defn}{List Scheduling und LPT}
|
|
\emph{List Scheduling:} Gehe die Jobs der Reihe nach durch und lege jeden auf die
|
|
\emph{momentan am wenigsten belastete} Maschine. \emph{LPT} (Longest Processing
|
|
Time): Sortiere die Jobs zuerst \emph{absteigend}, wende dann List Scheduling an.
|
|
\end{defn}
|
|
|
|
Das folgende Gantt-Bild macht sichtbar, warum die Reihenfolge zählt. Drei Jobs
|
|
der Größen $1, 1, 2$ auf zwei Maschinen. Die Balkenlänge ist die Zeit.
|
|
|
|
\begin{bsp}{List Scheduling gegen LPT}
|
|
\setlength{\unitlength}{1cm}
|
|
\begin{center}
|
|
\begin{picture}(9,4.2)(-1.6,-0.5)
|
|
% Zeitachse
|
|
\put(0,-0.1){\vector(1,0){4.2}} \put(3.9,-0.5){\small Zeit}
|
|
\multiput(0,-0.18)(1,0){4}{\line(0,1){0.12}}
|
|
\put(-0.05,-0.5){\small 0}\put(0.95,-0.5){\small 1}\put(1.95,-0.5){\small 2}\put(2.95,-0.5){\small 3}
|
|
% List Scheduling
|
|
\put(-1.6,3.2){\small \textbf{List Scheduling} (Reihenfolge $1,1,2$):}
|
|
\put(-1.3,2.4){\small $M_1$}
|
|
\put(0,2.2){\framebox(1,0.6){\small $1$}}
|
|
\put(1,2.2){\framebox(2,0.6){\small $2$}}
|
|
\put(-1.3,1.5){\small $M_2$}
|
|
\put(0,1.3){\framebox(1,0.6){\small $1$}}
|
|
\put(3.3,2.3){\small Makespan $3$}
|
|
% LPT
|
|
\put(-1.6,0.85){\small \textbf{LPT} (sortiert $2,1,1$):}
|
|
\put(-1.3,0.3){\small $M_1$}
|
|
\put(0,0.1){\framebox(2,0.6){\small $2$}}
|
|
\put(-1.3,-0.0){\small }
|
|
\put(2.3,0.2){\small Makespan $2$}
|
|
\end{picture}
|
|
\end{center}
|
|
Links stapelt List Scheduling die große $2$ auf eine schon belegte Maschine --
|
|
Makespan 3. Rechts legt LPT die große $2$ zuerst, die zwei Einsen wandern auf
|
|
$M_2$ -- Makespan 2, das Optimum.
|
|
\end{bsp}
|
|
|
|
\begin{satz}{Die Güten -- und die Idee dahinter}
|
|
List Scheduling hat Güte $2 - \tfrac1m$, LPT die bessere Güte
|
|
$\tfrac43 - \tfrac1{3m}$ -- beide scharf.\\[0.3em]
|
|
\emph{Die Idee (List Scheduling):} Betrachte die Maschine mit der höchsten Last
|
|
und den \emph{letzten} Job $J_k$, der auf ihr landete. In dem Moment, als $J_k$
|
|
zugewiesen wurde, war diese Maschine die \emph{leerste} -- also waren \emph{alle}
|
|
Maschinen mindestens so voll wie $L - p_k$. Mit den zwei Universalschranken
|
|
$\OPT \ge \frac1m \sum p_i$ (die Gesamtlast verteilt sich auf $m$ Maschinen) und
|
|
$\OPT \ge p_{\max}$ (der größte Job muss irgendwo laufen) folgt die Schranke.
|
|
\end{satz}
|
|
|
|
\subsection{MAX-3-SAT: Güte 2 fast geschenkt}\label{sec:max3sat}
|
|
|
|
\begin{idee}{Zwei Belegungen genügen}
|
|
Beim Optimierungsproblem MAX-3-SAT will man \emph{möglichst viele} Klauseln
|
|
erfüllen. Erstaunlich einfacher Algorithmus mit Güte 2: Werte die Formel nur
|
|
\emph{zweimal} aus -- einmal mit \glqq alle Variablen falsch\grqq{} ($\beta_0$),
|
|
einmal mit \glqq alle wahr\grqq{} ($\beta_1$) -- und nimm die bessere.\\[0.3em]
|
|
Warum das reicht: Jede Klausel enthält mindestens ein Literal, entweder ein
|
|
positives oder ein negatives. Ein positives Literal wird von $\beta_1$ erfüllt,
|
|
ein negatives von $\beta_0$. Also erfüllt \emph{jede} Klausel mindestens eine
|
|
der beiden Belegungen. Damit erfüllen $\beta_0$ und $\beta_1$ zusammen $\ge m$
|
|
Klauseln, die bessere von beiden also $\ge m/2$. Da $\OPT \le m$, ist das
|
|
mindestens $\OPT/2$.
|
|
\end{idee}
|
|
|
|
\begin{abruf}
|
|
\textbf{A18.} Nenne die vier Schritte von $\Delta$TSP$_1$ und sage bei jedem,
|
|
warum er die Güte-2-Schranke stützt.\\
|
|
\textbf{A19.} Warum ist Christofides besser als $\Delta$TSP$_1$, obwohl beide
|
|
mit demselben Spannbaum starten?\\
|
|
\textbf{A20.} Warum genügt beim Greedy-Rucksack der zusätzliche Vergleich mit
|
|
dem \glqq besten Einzel-Gegenstand\grqq, um von \glqq unbeschränkt schlecht\grqq{}
|
|
auf Güte 2 zu kommen?
|
|
\end{abruf}
|
|
|
|
% ##################################################################
|
|
\section{Jenseits von NP: das Halteproblem}\label{sec:halt}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Ein kurzer Blick über den Rand. Wir treffen ein Problem, das NP-schwer ist, aber
|
|
\emph{nicht} in $\NP$ liegt -- weil es überhaupt nicht lösbar ist. Das zeigt,
|
|
dass \glqq schwer\grqq{} und \glqq in NP\grqq{} wirklich zwei verschiedene
|
|
Dinge sind.
|
|
\end{ziel}
|
|
|
|
\begin{defn}{Halteproblem}
|
|
Gegeben die Beschreibung eines Programms $M$ und einer Eingabe $w$: Hält $M$ auf
|
|
$w$ irgendwann an, oder läuft es für immer?
|
|
\end{defn}
|
|
|
|
Das Halteproblem ist \emph{unentscheidbar} -- kein Algorithmus löst es, mit
|
|
keiner noch so großen Laufzeit. Das ist ein tiefes, bewiesenes Resultat (Turing).
|
|
Und trotzdem ist es NP-schwer.
|
|
|
|
\begin{aha}
|
|
Man reduziert \problem{SAT} darauf. Zu einer Formel $\varphi$ baut man ein
|
|
Programm $M_\varphi$, das \emph{alle} Belegungen der Reihe nach durchprobiert und
|
|
genau dann anhält, wenn es eine erfüllende findet. Dann gilt: $\varphi$ erfüllbar
|
|
$\iff$ $M_\varphi$ hält. Der Clou liegt im Zeitverhalten: $M_\varphi$ läuft im
|
|
Nein-Fall \emph{ewig} -- aber die \emph{Konstruktion} von $M_\varphi$ aus
|
|
$\varphi$ ist billig (polynomiell), und nur darauf kommt es bei einer Reduktion
|
|
an. Also ist das Halteproblem mindestens so schwer wie \problem{SAT}. In $\NP$
|
|
liegt es aber nicht -- es ist ja nicht einmal entscheidbar.
|
|
\textbf{NP-schwer ist nicht dasselbe wie NP-vollständig.}
|
|
\end{aha}
|
|
|
|
% ##################################################################
|
|
\section{Das große Ganze}
|
|
% ##################################################################
|
|
|
|
\begin{ziel}
|
|
Wir ziehen die Fäden zusammen: eine Übersicht der ganzen Reise und ein
|
|
Wahr/Falsch-Test zur Selbstkontrolle.
|
|
\end{ziel}
|
|
|
|
\subsection{Die Reise auf einen Blick}
|
|
|
|
\begin{center}\small
|
|
\begin{tabular}{p{3.4cm}p{10.2cm}}
|
|
\toprule
|
|
Station & Kernidee \\
|
|
\midrule
|
|
$\Pclass$ & effizient \emph{lösbar} (polynomielle Laufzeit)\\
|
|
$\NP$ & effizient \emph{überprüfbar} (Zertifikat prüfen bzw.\ raten)\\
|
|
$\Pclass \subseteq \NP$ & Lösen ist mindestens so schwer wie Prüfen; Gleichheit offen\\
|
|
$A \redp B$ & \glqq $B$ mindestens so schwer wie $A$\grqq; Richtung: bekannt $\redp$ neu\\
|
|
NP-vollständig & die schwersten in $\NP$; \problem{SAT} ist der Anker (Cook--Levin)\\
|
|
Vererbungskorollar & neues Problem schwer zeigen: eine Reduktion \emph{plus} Nachweis $\in\NP$\\
|
|
ETH & schärfer als NP-Vollständigkeit: konkrete $2^{o(\cdot)}$-Schranken\\
|
|
Approximation & für schwere Optimierung: beweisbar gute Näherung mit Gütegarantie\\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\end{center}
|
|
|
|
\subsection{Wahr oder falsch? (Die Begründung zählt)}
|
|
|
|
Wenn du das Fundament verstanden hast, kannst du jede dieser Aussagen begründen.
|
|
|
|
\begin{center}\small
|
|
\begin{tabular}{p{7.2cm}cp{4.9cm}}
|
|
\toprule
|
|
Aussage & W/F & Begründung \\
|
|
\midrule
|
|
Löst eine ratende Maschine ein Problem in Polyzeit, dann auch eine gewöhnliche. &
|
|
F$^{*}$ & Das wäre $\Pclass=\NP$ -- unbekannt. \\
|
|
\addlinespace
|
|
$A$ NP-schwer $\Rightarrow A \in \NP$. & F & Halteproblem: NP-schwer, nicht
|
|
einmal lösbar. \\
|
|
\addlinespace
|
|
$L \in \NP$ und $L \redp \problem{3-SAT}$ $\Rightarrow$ $L$ NP-vollständig. &
|
|
F & Falsche Richtung -- \emph{auf} 3-SAT reduzieren zeigt keine Schwere. \\
|
|
\addlinespace
|
|
$\problem{3-SAT} \redp L$ und $L \redp \problem{3-SAT}$ $\Rightarrow$ $L$
|
|
NP-vollständig. & W & Erstes gibt Schwere, zweites gibt $L \in \NP$. \\
|
|
\addlinespace
|
|
ETH falsch $\Rightarrow \Pclass = \NP$. & F & $2^{o(n)}$ kann superpolynomiell
|
|
bleiben. \\
|
|
\bottomrule
|
|
\end{tabular}
|
|
\end{center}
|
|
{\footnotesize $^{*}$ nicht als wahr beweisbar; äquivalent zu $\Pclass=\NP$.}
|
|
|
|
\begin{aha}
|
|
Du hast jetzt das \emph{Warum} beisammen: was ein Problem schwer macht, wie
|
|
Schwere von einem Problem zum anderen fließt, wo die Grenzen liegen, und was man
|
|
tut, wenn exakte Lösungen zu teuer sind. Das ist das Fundament des ganzen
|
|
Kurses.
|
|
\end{aha}
|
|
|
|
\noindent\textbf{Der nächste Schritt.} Dieses Heft hat dir das Verständnis
|
|
gegeben (Schritt 1 und 2 deines Lernmodells). Jetzt kommt die Anwendung
|
|
(Schritt 3 und 4): Nimm die Präsenz-, Haus- und Klausuraufgaben und führe dort
|
|
selbst aus, was hier als Idee stand -- Reduktionen \emph{vollständig} beweisen
|
|
(beide Richtungen!), Güte-Schranken herleiten, Worst-Case-Instanzen bauen. Viel
|
|
Erfolg.
|
|
|
|
% ##################################################################
|
|
\appendix
|
|
\renewcommand{\thesection}{\Alph{section}}
|
|
\section{Lösungen zu den Abruf-Fragen}\label{sec:loesungen}
|
|
% ##################################################################
|
|
|
|
Erst selbst beantwortet, dann hier vergleichen -- nur so wirkt das aktive
|
|
Abrufen.
|
|
|
|
\loes{A1.} Ein konstanter Faktor wie 1000 ($\approx 2^{10}$) verschiebt die
|
|
exponentielle Kurve nur um eine \emph{additive} Konstante: Du schaffst rund 20
|
|
Knoten mehr -- ein einziges Mal. Danach wächst das Problem exponentiell weiter,
|
|
die Hardware bleibt gleich. Exponentielles Wachstum lässt sich nicht durch
|
|
schnellere Hardware einholen.
|
|
|
|
\loes{A2.} \glqq Kennen keinen\grqq{} = niemand hat bisher einen Algorithmus
|
|
gefunden (eine Wissenslücke). \glqq Gibt keinen\grqq{} = die Nichtexistenz ist
|
|
bewiesen. Für die Clique gilt nur das Erste; ein Nichtexistenzbeweis fehlt (die
|
|
Frage $\Pclass$ vs.\ $\NP$ ist offen).
|
|
|
|
\loes{A3.} Ja. $n^4$ ist polynomiell (fester Exponent $d=4$), also liegt das
|
|
Problem in $\Pclass$ und gilt im Sinne der Theorie als effizient.
|
|
|
|
\loes{A4.} Bis $K$ zu zählen kostet $K$ Schritte. Aber $K$ ist als Eingabe nur
|
|
$O(\log K)$ Zeichen lang, sein \emph{Wert} ist exponentiell in dieser Länge. Die
|
|
Laufzeit ist also exponentiell in der Eingabegröße.
|
|
|
|
\loes{A5.} \textbf{Zertifikat:} eine Knotenmenge $C$. \textbf{Verifizierer:}
|
|
prüfe, ob jede Kante mindestens einen Endpunkt in $C$ hat ($O(|E|)$), und ob
|
|
$|C| \le k$. \textbf{Korrektheit:} Gibt es ein Vertex Cover der Größe $\le k$,
|
|
wird es akzeptiert; sonst keines. \textbf{Laufzeit} polynomiell. (Rate-Sicht:
|
|
$C$ raten, dann prüfen.)
|
|
|
|
\loes{A6.} Der Verifizierer bekommt das Zertifikat \emph{geschenkt} und muss es
|
|
nur prüfen. Der Löser hat niemanden, der ihm die Lösung vorlegt -- er muss sie
|
|
selbst finden, und dafür können exponentiell viele Kandidaten in Frage kommen.
|
|
Prüfen beginnt einen Schritt weiter als Lösen.
|
|
|
|
\loes{A7.} $\problem{Clique} \redp \problem{Vertex Cover}$ -- vom bekannt
|
|
schweren \problem{Clique} auf das neue \problem{VC}. So erbt \problem{VC} die
|
|
Schwere. Die Gegenrichtung würde über \problem{VC} nichts aussagen (sie zeigte
|
|
nur \glqq höchstens so schwer wie das schwere Clique\grqq).
|
|
|
|
\loes{A8.} $A \redp B$ bedeutet: $B$ ist \emph{mindestens so schwer} wie $A$.
|
|
|
|
\loes{A9.} (1) eine Reduktion von einem bekannten NP-vollständigen Problem
|
|
\emph{auf} das neue; (2) der Nachweis, dass das neue Problem in $\NP$ liegt.
|
|
Vergessen wird am häufigsten (2) -- ohne ihn hat man nur NP-\emph{Schwere}, nicht
|
|
Vollständigkeit.
|
|
|
|
\loes{A10.} \problem{SubSet Sum} ist NP-vollständig. Läge \emph{ein}
|
|
NP-vollständiges Problem in $\Pclass$, könnte man jedes $L \in \NP$ über
|
|
$L \redp \problem{SubSet Sum}$ effizient lösen -- also $\Pclass = \NP$.
|
|
|
|
\loes{A11.} \textbf{Zertifikat:} die Besuchsreihenfolge (Permutation der Knoten).
|
|
\textbf{Verifizierer:} prüfe, ob jeder Knoten genau einmal vorkommt und jede
|
|
aufeinanderfolgende sowie die schließende Kante existiert -- $O(|V|+|E|)$.
|
|
(Rate-Sicht: Reihenfolge raten, dann prüfen.)
|
|
|
|
\loes{A12.} Für eine Knotenmenge $C$ gilt: $C$ ist Clique in $G$ $\iff$ $C$ ist
|
|
Independent Set im Komplementgraphen $\bar G$ $\iff$ $V \setminus C$ ist Vertex
|
|
Cover in $\bar G$. Die drei Probleme sind dasselbe, betrachtet über den
|
|
Komplementgraphen und die Komplement-Knotenmenge.
|
|
|
|
\loes{A13.} Bei Basis $n+1$ und höchstens $n$ Summanden entsteht an keiner Stelle
|
|
ein Übertrag -- jede Ziffer zählt für sich. Dann bedeutet \glqq Summe trifft das
|
|
Ziel\grqq{} genau \glqq jede Stelle wird genau einmal überdeckt\grqq. Bei Basis 2
|
|
gäbe es Überträge, und eine falsche Auswahl könnte das Ziel zufällig treffen.
|
|
|
|
\loes{A14.} Die beiden Zusatzzahlen sind $N-K$ und $K+1$; ihre Summe ist $N+1$.
|
|
Eine Hälfte hat aber nur den Wert $N$. Zwei Zahlen mit Summe $N+1 > N$ passen
|
|
also nie zusammen in dieselbe Hälfte -- sie werden immer getrennt.
|
|
|
|
\loes{A15.} Beispiel: $G$ mit $V=\{1,2,3,4\}$ und Kanten $\{1,2\},\{2,3\},\{1,3\}$
|
|
(ein Dreieck plus isolierter Knoten 4), $n=4$, $k=3$. Clique $C=\{1,2,3\}$. Im
|
|
Komplement $\bar G$ (Kanten $\{1,4\},\{2,4\},\{3,4\}$) ist $V \setminus C=\{4\}$
|
|
ein Vertex Cover der Größe $n-k = 1$ -- Knoten 4 berührt alle Kanten von $\bar G$.
|
|
|
|
\loes{A16.} Nein. \glqq ETH falsch\grqq{} heißt nur: \problem{3-SAT} geht in
|
|
$2^{o(n)}$ -- das kann immer noch superpolynomiell sein, z.\,B.\ $2^{\sqrt n}$.
|
|
Umgekehrt gilt aber: $\Pclass = \NP$ würde die ETH sofort widerlegen.
|
|
|
|
\loes{A17.} Die Reduktion $\problem{3-SAT} \redp \problem{3-Color}$ baut aus $n$
|
|
Variablen und $m$ Klauseln einen Graphen mit $O(n+m)$ Knoten. Ein
|
|
$2^{o(N)}$-Algorithmus für \problem{3-Color} ($N$ = Knotenzahl) ergäbe damit
|
|
einen $2^{o(n+m)}$-Algorithmus für \problem{3-SAT}, und wegen $n+m = O(m)$ einen
|
|
$2^{o(m)}$-Algorithmus. Genau hier kommt das \emph{Sparsification-Lemma} ins
|
|
Spiel: Es verbietet $2^{o(m)}$ für \problem{3-SAT} -- der Widerspruch ist
|
|
komplett.
|
|
|
|
\loes{A18.} (1) Minimaler Spannbaum $T$: er ist billiger als die optimale Tour,
|
|
$w(T) \le \OPT$. (2) Kanten verdoppeln: Gesamtlänge $2w(T) \le 2\OPT$. (3)
|
|
Eulerkreis: nutzt die geraden Grade, ändert die Länge nicht. (4) Abkürzen:
|
|
verlängert wegen der Dreiecksungleichung nicht. Zusammen: $d(R) \le 2\OPT$.
|
|
|
|
\loes{A19.} $\Delta$TSP$_1$ verdoppelt \emph{alle} Baumkanten und zahlt dafür
|
|
zusätzlich etwa $w(T) \approx \OPT$ -- Güte 2. Christofides fügt stattdessen nur
|
|
ein minimales perfektes Matching auf den ungerad-gradigen Knoten hinzu, das
|
|
höchstens $\OPT/2$ kostet. Deshalb landet er bei $w(T) + \OPT/2 \le 1{,}5\,\OPT$.
|
|
|
|
\loes{A20.} Greedy verliert seinen Profit immer nur an dem einen
|
|
\glqq Split-Item\grqq, das gerade nicht mehr in den Rucksack passte. Dessen Profit
|
|
ist höchstens der maximale Einzelprofit. Der zweite Kandidat (bester
|
|
Einzel-Gegenstand) deckt genau diesen Fall ab. Also ist das Bessere von beiden
|
|
mindestens halb so gut wie das Optimum -- Güte 2.
|
|
|
|
\end{document}
|