{"id":1616,"date":"2013-05-20T20:28:23","date_gmt":"2013-05-20T18:28:23","guid":{"rendered":"http:\/\/fernuni.digreb.net\/?p=1616"},"modified":"2025-11-25T23:06:50","modified_gmt":"2025-11-25T22:06:50","slug":"tib-np-vollstandige-probleme-lernziele-ke4-23","status":"publish","type":"post","link":"https:\/\/fernuni.digreb.net\/?p=1616","title":{"rendered":"TIB: NP-Vollst\u00e4ndige Probleme (Lernziele KE4 2\/2, Update)"},"content":{"rendered":"<h2>Lernziel 3<\/h2>\n<p style=\"padding-left: 30px;\"><em>Wie ist der Vollst\u00e4ndigkeitsbeweis zu \\(SAT\\)?<\/em><\/p>\n<p>\\(SAT\\) steht f\u00fcr das englische\u00a0<i>satisfiability.\u00a0<\/i>Also ein Erf\u00fcllbarkeitsproblem. Es wird gefragt ob eine aussagenlogische Formel erf\u00fcllbar ist (erinnert ihr euch an KNF\/DNF aus der technischen Informatik? Das hier ist nicht weit weg&#8230;).<\/p>\n<p>Da eine Formel nur endlich viele variablen enth\u00e4lt, die nur mit \\(1\\) und \\(0\\) belegt werden k\u00f6nnen, haben wir eine endliche Anzahl an M\u00f6glichkeiten. Wenn wir alle durchprobieren, kommen wir (oder nicht) irgendwann dahin, dass die Formel wahr wird. Haben wir \\(n\\) Variablen, so m\u00fcssen wir im worst case \\(2^n\\) Kombinationen betrachten. Damit ben\u00f6tigen wir f\u00fcr \\(SAT\\) einen Exponentialzeitalgorithmus und diese gelten f\u00fcr die Praxis als unwichtig, steigt der Aufwand f\u00fcr gr\u00f6\u00dfere \\(n\\) doch massiv an. H\u00e4tten wir zu dem Problem einen Polynomialzeitalgorithmus, s\u00e4he die Sache ganz anders aus.<\/p>\n<p>Aber es gibt einen Lichtblick: Wenn wir nicht jede M\u00f6glichkeit durchprobieren wollen, kann das Pr\u00fcfen einer vorgegebenen L\u00f6sung f\u00fcr \\(SAT\\) in Linearzeit erfolgen. Haben wir \\(n\\) Variablen, so m\u00fcssen wir sie erst kurz belegen und die Formel dann auswerten. Beides geht jeweils in Linearzeit. Damit haben wir schon einmal den ersten Schritt getan: wir haben eine \\(KTM\\) angegeben, die die Hilfseingabe (unsere zu pr\u00fcfende Belegung der \\(n\\) Variablen) auf wahr oder falsch kontrolliert. Okay, haben wir nicht. Aber wir k\u00f6nnten es mit wenig Aufwand (vielleicht reiche ich so eine \\(KTM\\) bei Gelegenheit hier nach) tun. Damit ist der erste Schritt vollbraucht \\(SAT\\in NP\\).<\/p>\n<p>K\u00fcmmern wir uns nun um den zweiten Schritt, die \\(NP\\)-H\u00e4rte. Aber ohne die Abk\u00fcrzung der Reduktion zu nehmen.\u00a0Das folgende Beispiel basiert auf dem Buch von\u00a0<a href=\"http:\/\/www.amazon.de\/gp\/product\/3446426396?ie=UTF8&amp;tag=fernblog09-21&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=3446426396\">Prof. Dr. Dirk W. Hoffmann<\/a>\u00a0(oben rechts verlinkt).\u00a0Die Credits also ausnahmslos an ihn. Und auch wenn ich mich wie eine kaputte Schallplatte anh\u00f6re: das Buch ist ein Lifesaver f\u00fcr theoretische Informatik und geh\u00f6rt in jedes IT-B\u00fccherregel, daher absolute Kaufempfehlung. Der Herr geh\u00f6rt unbedingt unterst\u00fctzt.<\/p>\n<p>Wir m\u00fcssen hier also beweisen, dass wir ausnahmslos <strong>alle<\/strong> Probleme aus \\(NP\\) auf \\(SAT\\) reduzieren k\u00f6nnen. Da wir keines haben, m\u00fcssen wir uns eins basteln, wo einzusehen ist, dass es alle Probleme aus \\(NP\\) &#8222;widerspiegelt&#8220; und dieses auf \\(SAT\\) reduzieren. Nehmen wir also ein beliebiges Problem \\(L\\in NP\\) und eine \\(TM\\) namens \\(T\\), die das Problem entscheidet. Wir m\u00fcssen jetzt zeigen, dass wir f\u00fcr jedes Eingabewort \\(\\omega\\) f\u00fcr \\(T\\) eine Formel \\(F\\) konstruieren k\u00f6nnen, f\u00fcr die gilt:<\/p>\n<blockquote><p>\\(T(\\omega)\\) terminiert im Endzustand \\(\\Leftrightarrow F(\\omega)\\) ist erf\u00fcllbar.<\/p><\/blockquote>\n<p>D.h. nur wenn unsere Maschine mit dem Eingabewort terminiert, so ist auch unsere Formel mit dem gleichen Eingabewort erf\u00fcllbar und andersrum. Wir m\u00fcssen \\(F\\) in polynomieller Zeit konstruieren. Dazu werden zun\u00e4chst Variablen eingef\u00fchrt:<\/p>\n<blockquote><p>\\(B_{i,k,\\sigma}=1\\) Nach \\(i\\) Schritten, steht an Position \\(k\\) das Zeichen \\(\\sigma\\).<\/p>\n<p>\\(S_{i,S}=1\\) Maschine \\(T\\) befindet sich nach \\(i\\) Schritten im Zustand \\(S\\).<\/p>\n<p>\\(P_{i,k}=1\\) Maschine \\(T\\) befindet sich nach \\(i\\) Schritten auf Bandposition \\(k\\).<\/p><\/blockquote>\n<p>Die Laufzeit der Maschine ist polynomiell durch das Polynom \\(p(n)\\) beschr\u00e4nkt, denn \\(n\\) ist die L\u00e4nge der Eingabe \\(\\omega\\). Die Indizes von \\(i,s\\) liegen also im Intervall \\([0;p(n)]\\). Auch bewegt sich der Schreib-Lese-Kopf maximal \\(p(n)\\) Positionen nach links oder rechts, so dass wir den Bandinhalt auf dem Teilst\u00fcck \\(-p(n),&#8230;,p(n)\\) betrachten m\u00fcssen. Der Kopf steht \u00fcber der Position \\(0\\). Ausprobiert wird das an der Sprache \\(L:=\\{\\#^n\\mid n\\in{\\mathbb{N}}\\}\\) mit dem Alphabet \\(\\Sigma=\\{\\#\\}\\).<\/p>\n<p>Diese Sprache wird von einer \\(TM\\) erkannt, die nur zwei Zust\u00e4nde hat. \\(s_0\\) wenn das Zeichen auf dem Band eine \\(\\#\\) ist (Eingabewort \\(\\omega\\in L\\)) und \\(s_1\\) wenn es ein \\(B\\) (Blank) ist.\u00a0Da die Berechnung hier bereits nach einem Schritt endet, ist die Laufzeit der Maschine \\(p(n)=1\\). Wir haben also ein &#8222;Problem&#8220;, dass in polynomieller Zeit durch die \\(T\\) entschieden werden kann und damit in \\(P\\) liegt (das \\(N\\) ist ja nur das Orakeln der Eingabe). Nun m\u00fcssen wir \\(T\\) nur noch polynomiell in eine \\(SAT\\)-Instanz codieren.<\/p>\n<p>Um den Bandzustand, den Zustand der Maschine und die Position des Lesekopfes als eine Formel zu codieren, werden die oben eingef\u00fchrten Variablen verwendet. Ist z.B. \\(B_{0,1,\\#}=1\\), so befindet sich auf dem Band jetzt auf Position \\(1\\) das Zeichen \\(\\#\\). Durch die oben gemachten Einschr\u00e4nkungen, haben wir \\(12\\) verschiedene Bandvariablen, die wir mit \\(0\\) oder \\(1\\) belegen k\u00f6nnen um den\u00a0<strong>Bandzustand<\/strong>\u00a0zu repr\u00e4sentieren (\\(B\\) ist das Blank).<\/p>\n<blockquote>\\(B_{0,-1,B},B_{0,-1,\\#},B_{1,-1,B},B_{1,-1,\\#}\\)\n\\(B_{0,1,B},B_{0,1,\\#},B_{1,1,B},B_{1,1,\\#}\\)\n\\(B_{0,0,B},B_{0,0,\\#},B_{1,0,\\#},B_{1,0,\\#}\\)<\/blockquote>\n<p>Der\u00a0<strong>Zustand<\/strong>\u00a0von \\(T\\) codieren wir mit:<\/p>\n<blockquote>\\(S_{0,S_0},S_{0,S_1},S_{1,S_0},S_{1,S_1}\\)<\/blockquote>\n<p>F\u00fcr die\u00a0<strong>Kopfposition<\/strong>\u00a0haben wir sechs Variablen:<\/p>\n<blockquote>\\(P_{0,-1},P_{0,0},P_{0,1}\\)\n\\(P_{1,-1},P_{1,0},P_{1,1},\\)<\/blockquote>\n<p>Mit diesen Variablen haben wir alle Variablen repr\u00e4sentiert, die die Maschine \\(T\\) einnehmen kann.\u00a0Wenn wir die Maschine also in \\(SAT\\) abbilden wollen, sieht die Formel \\(F\\) dann so aus:<\/p>\n<blockquote>\\(F=S\\wedge R\\wedge T\\wedge A\\)<\/blockquote>\n<p>Was bedeutet es?<\/p>\n<blockquote><p>\\(S\\): Startbedingung. Initiale Konfiguration von \\(T\\). Die Maschine befindet sich in \\(s_0\\), das Eingabewort \\(\\omega\\) ist auf dem Band, der Rest ist leer und der Kopf befindet sich auf Position \\(0\\).<\/p>\n<p>\\(R\\): Randbedingungen, die \\(T\\) zu jeder zeit erf\u00fcllen muss, d.h. \\(R=(R_1\\wedge R_2\\wedge R_3)\\) Diese sind:<\/p>\n<p style=\"padding-left: 30px;\">\\(R_1\\): Maschine befindet sich zu jedem Zeitpunkt in nur einem Zustand<\/p>\n<p style=\"padding-left: 30px;\">\\(R_2\\): Der Schreib-Lese-Kopf befindet sich immer nur an einer Position.<\/p>\n<p style=\"padding-left: 30px;\">\\(R_3\\): Es befindet sich nur ein Symbol an jeder Bandstelle zu jedem Zeitpunkt.<\/p>\n<p>\\(T\\): Transitionsbedingungen. In dieser Teilformel werden die m\u00f6glichen Konfigurations\u00fcberg\u00e4nge codiert, d.h.\u00a0\\(T=(T_1\\wedge T_2\\wedge T_3)\\)\u00a0Sie bestehen aus:<\/p>\n<p style=\"padding-left: 30px;\">\\(T_1\\): Maschine geht in Folgekonfiuration \u00fcber.<\/p>\n<p style=\"padding-left: 30px;\">\\(T_2\\): Inaktive Maschine, terminiert.<\/p>\n<p style=\"padding-left: 30px;\">\\(T_3\\): Bandinhalt wird ge\u00e4ndert.<\/p>\n<p>\\(A\\): Akzeptanzbedingung. Hier wird codiert, dass die \\(TM\\) das Wort \\(\\omega\\) dann annimmt wenn es im Endzustand anh\u00e4lt. Der Zustand muss in weniger als \\(p(n)\\) Berechnungsschritten erreicht werden.<\/p><\/blockquote>\n<p>Und nun kommt der Spa\u00df an der Sache. Alle Bedingungen k\u00f6nnen wir als Formel codieren.<\/p>\n<p><strong>Beispiel<\/strong>: nehmen wir an, das Wort \\(\\omega\\) besteht aus \\(\\#\\), d.h. auf dem Band steht \\(B\\# B\\). Die oben in Prosa verfasste Startbedingung, w\u00e4re dann:<\/p>\n<p style=\"padding-left: 60px;\">\\(S=S_{0,s_0}\\wedge{P_{0,0}}\\wedge{B_{0,-1,B}}\\wedge{B_{0,0,\\#}}\\wedge{B_{0,1,B}}\\)<\/p>\n<p style=\"padding-left: 30px;\">In Worten ausgedr\u00fcckt: Die Maschine befindet sich nach \\(0\\) Schritten im Zustand \\(s_0\\) (erste Bedingung), der Lesekopf nach \\(0\\) Schritten auf Position \\(0\\) (zweite Bedingung) und auf dem Band steht auf Positionen \\(-1,0,1\\) eben \\(B,\\#,B\\) (dritte, vierte und f\u00fcnfte Bedingung). Und wenn das alles stimmt, die Variablen also alle mit einer \\(1\\) belegt sind, dann evaluiert die Formel \\(S\\) bei Auswertung zu \\(1\\).\u00a0Oh mein Gott! Das ist genau das, was wir f\u00fcr die Maschine \\(T\\) festgelegt und nun in eine Formel gequetscht haben.<\/p>\n<p style=\"padding-left: 30px;\">Haben wir z.B. ein leeres Wort \\(\\epsilon\\), d.h.\u00a0auf dem Band steht \\(BBB\\), so sieht unsere Startbedingung wie folgt aus:<\/p>\n<p style=\"padding-left: 60px;\">\\(S=S_{0,s_0}\\wedge{P_{0,0}}\\wedge{B_{0,-1,B}}\\wedge{B_{0,0,B}}\\wedge{B_{0,1,B}}\\)<\/p>\n<p style=\"padding-left: 30px;\">Gleiches gilt f\u00fcr Rand-, Transitions- und Akzeptanzbedingungen, die wir eben auch als Formel darstellen k\u00f6nnen. Ist nur alles ziemliche Schreibarbeit.\u00a0Wenn die alle erf\u00fcllt sind, evaluiert auch unsere Gesamtformel \\(F\\) (siehe oben) zu einer \\(1\\). Eventuell schreibe ich die kompletten Rand- und Transitionsbedingungen bei Gelegenheit hier nochmal hin.<\/p>\n<p>Wie wir also sehen k\u00f6nnen, k\u00f6nnen wir die Bedingungen f\u00fcr eine Maschine \\(T\\) in eine Formel \\(F\\) quetschen, die genau das tut, was wir wollen. Wir haben also gezeigt, wie eine \\(NTM\\) \\(T\\) polynomiell auf eine aussagenlogische Formel reduziert werden kann, die genau dann erf\u00fcllbar ist, wenn \\(T\\) in einem Endzustand terminiert.<\/p>\n<p>Ein ausf\u00fchrlicher Beweis ist z.B. auch\u00a0<a href=\"http:\/\/www.grundstudium.info\/theorie\/node28.php\">hier<\/a>\u00a0zu finden.<\/p>\n<p>Hier entfaltet \\(SAT\\) seinen Charme: wir k\u00f6nnen viele Algorithmen auf \\(SAT\\) zur\u00fcckf\u00fchren, indem wir den Ablauf in die Formel hineincodieren und damit das Problem auf \\(SAT\\) reduzieren. Und was passt hier besser als Beispiel, als \\(3SAT\\)?<\/p>\n<p><strong>Antwort zum Lernziel<\/strong>: wir codieren eine komplette Aussagenlogische Formel in ein Wort f\u00fcr eine Turingmaschine, deren Laufzeit polynomiell beschr\u00e4nkt ist. Die Maschine terminiert nur wenn die aussagenlogische Formel wahr ist. Es ist leicht einzusehen, dass diese initiale Turingmaschine, also praktisch unser \\(NP\\)-vollst\u00e4ndiges Problem (wo leicht einzusehen ist, dass es tats\u00e4chlich in \\(NP\\) liegt), in polynomzeit durch eine Kontroll-Turingmaschine entschieden werden kann.<\/p>\n<p>In die Eingabe dieser Maschine dieses wird dann die zu pr\u00fcfende, aussagenlogische \\(SAT\\)-Formel codiert und von dieser \\(KTM\\) ebenfalls in Polynomzeit entschieden.<\/p>\n<h2>Lernziel 4<\/h2>\n<p style=\"padding-left: 30px;\"><em>Wie f\u00fchrt man eine einfache, polynomielle Reduktion\u00a0\\({}\\leq_{pol}\\)\u00a0\u00a0aus?<\/em><\/p>\n<h3>Reduktion von \\(SAT\\) auf \\(3SAT\\)<\/h3>\n<p>Die Frage bei \\(3SAT\\) ist:<\/p>\n<p style=\"padding-left: 30px;\"><em>Gibt es eine erf\u00fcllende Bedingung bei \\(n\\) aussagenlogischen Klauseln mit maximal \\(3\\) Literalen (atomare Aussage, z.B. \\(\\neg{A}\\) oder \\(A\\))?<\/em><\/p>\n<p>Damit ist \\(3SAT\\) eine abgeschw\u00e4chte Form von \\(SAT\\). Einschr\u00e4nkung ist, dass die Formel f\u00fcr \\(3SAT\\) in der Konjunktivform (mit \\(\\wedge\\) verkn\u00fcpft) vorhanden sein muss. Um also zu zeigen, dass \\(3SAT\\) ebenfalls \\(NP\\)-hart ist, m\u00fcssen wir \\(SAT\\) auf \\(3SAT\\)\u00a0<strong>polynomiell<\/strong>\u00a0reduzieren, formal ausgedr\u00fcckt:<\/p>\n<blockquote>\\(SAT\\leq_{pol}3SAT\\)<\/blockquote>\n<p>Was wir tun m\u00fcssen, ist also eine allgemeine Formel nehmen und sie so umformen, dass die beliebig viele Klauseln, aber nur drei Literale pro Klausel hat. Das machen wir mit Hilfe von Hilfsvariablen. Haben wir also ein Term in der folgenden Form in KNF mit \\(n\\) Variablen:<\/p>\n<blockquote>\\((\\upsilon_{1,1}\\vee\\upsilon_{1,2}\\vee &#8230;\\vee\\upsilon_{1,n})\\wedge(\\upsilon_{m,1}\\vee\\upsilon_{m,2}&#8230;\\vee\\upsilon_{m,n_{m}})\\)<\/blockquote>\n<p>F\u00fcr jede Klausel mit \\(n\\) Variablen entstehen \\(n-2\\) neue Klauseln mit \\(n-3\\) neuen Variablen:<\/p>\n<blockquote>\\((\\upsilon_{1,1}\\vee\\upsilon_{1,2}\\vee a_{1,1})\\wedge(\\overline{a_{1,1}}\\vee\\upsilon_{1,3}\\vee a_{1,2})\\wedge &#8230;\\wedge(\\overline{a_{1,n-3}}\\vee \\epsilon_{1,n_{1}-1}\\vee\\epsilon_{1,n_{1}})\\)<\/blockquote>\n<p>Hilfsvariablen? Ja, Hilfsvariablen. Diese Variablen zeigen uns an, welcher Teil aus der zerteilen Klausel das ganze Konstrukt hat wahr werden lassen.<\/p>\n<p><strong>Beispiel<\/strong>? Klar:\u00a0\\((A\\vee\\overline{B}\\vee C\\vee\\overline{D})\\wedge(E\\vee F\\vee G)\\)<\/p>\n<p style=\"padding-left: 30px;\">Die erste Klausel wandeln wir also um in \\(2\\) Klauseln mit einer neuen Variable. Die zweite Klauseln k\u00f6nnen wir so lassen, da wir da bereits drei Literale drin haben. Nennen wir unsere neue Hilfsvariable also einfach \\(h_1\\). Damit sehen unsere beiden neuen Klauseln nun so aus:<\/p>\n<blockquote style=\"padding-left: 30px;\">\n<p style=\"padding-left: 30px;\">\\((A\\vee\\overline{B}\\vee h_1)\\wedge(C\\vee\\overline{D}\\vee\\overline{h_1})\\)<\/p>\n<\/blockquote>\n<p style=\"padding-left: 30px;\">Der Trick hierbei ist, dass die Hilfsvariable \\(h_1\\) dann falsch wird, wenn die erste Teilklausel wahr wird und wahr wird wenn die zweite Teilklausel wahr wird.\u00a0Stellen wir doch eine kleine Wertetabelle f\u00fcr den umgeformten Term zusammen, wie wir das auch in der technischen Informatik (Computersysteme 1&amp;2) gemacht haben:<\/p>\n<p style=\"padding-left: 30px; text-align: center;\"><a href=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/wertetabelle.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-2446\" style=\"margin-left: 50px; margin-right: 50px;\" alt=\"wertetabelle\" src=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/wertetabelle.png\" width=\"422\" height=\"238\" srcset=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/wertetabelle.png 586w, https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/wertetabelle-300x168.png 300w\" sizes=\"auto, (max-width: 422px) 100vw, 422px\" \/><\/a><\/p>\n<p style=\"padding-left: 30px;\">Ich habe Excel etwas vergewaltigt, nehmt mir das nicht \u00fcbel. Die Spalten haben folgende Bedeutung:<\/p>\n<ul style=\"list-style-type: disc; padding-left: 60px;\">\n<li style=\"padding-left: 30px;\">In den Spalten A-D stehen alle unsere Variablenbelegungen \\(A,B,C,D\\).<\/li>\n<li style=\"padding-left: 30px;\">In Spalte E steht die umzuformende Klausel \\((A\\vee\\overline{B}\\vee C\\vee\\overline{D})\\).<\/li>\n<li style=\"padding-left: 30px;\">In Spalte F steht die so entstandene erste Teiltklausel,<\/li>\n<li style=\"padding-left: 30px;\">In G die zweite.<\/li>\n<li style=\"padding-left: 30px;\">In Spalte H steht unsere Hilfsvariable \\(h_1\\), die falsch wird wenn die erste Teilklausel in Spalte F wahr ist und wahr wird wenn die zweite Teilklausel in Spalte G wahr wird. Der Inhalt von \\(h_1\\) spielt keine Rolle wenn die Klausel sowieso negativ werden w\u00fcrde (gr\u00fcnes K\u00e4stchen).<\/li>\n<li style=\"padding-left: 30px;\">In Spalte I und J stehen unsere neuen Teilklausen mit der Hilfsvariable, die wir dann verwenden um die alte Klausel zu repr\u00e4sentieren.<\/li>\n<li style=\"padding-left: 30px;\">Spalte K beherbergt dann beide Klauseln aus I und J mit einem \\(\\wedge\\) verkn\u00fcpft. Genau diese Klausel<\/li>\n<li style=\"padding-left: 30px;\">in Spalte K ist dann:\u00a0\\(((A\\vee\\overline{B}\\vee h_1)\\wedge(C\\vee\\overline{D}\\vee\\overline{h_1})\\)<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">Und sie tut genau das gleiche wie die initiale Klausel aus den vier Literalen, die wir umformen wollten: \\((A\\vee\\overline{B}\\vee C\\vee\\overline{D})\\). Lange Rede, kurzer Sinn:<\/p>\n<blockquote style=\"padding-left: 30px;\">\n<p style=\"padding-left: 30px;\">\\((A\\vee\\overline{B}\\vee C\\vee\\overline{D})\\)\u00a0\\(\\Leftrightarrow\\)\u00a0\\(((A\\vee\\overline{B}\\vee h_1)\\wedge(C\\vee\\overline{D}\\vee\\overline{h_1})\\)<\/p>\n<\/blockquote>\n<p>Klauseln mit nur einem Literal bekommen zwei Hilfsvariablen, Klauseln mit zwei Literalen eine, Klauseln mit drei Literalen werden nicht angefasst und Klauseln mit mehr als drei Literalen werden nach dieser Vorgehensweise rekursiv in Klauseln mit drei Literalen umgewandelt.\u00a0Die Anzahl der Literale hat sich also nur linear erh\u00f6ht und wir haben einen Weg gefunden \\(SAT\\) auf \\(3SAT\\) in Polynomzeit zu reduzieren. Nun k\u00f6nnen wir auch \\(3SAT\\) f\u00fcr andere Schweinereien benutzen!<\/p>\n<p><strong>Antwort zum Lernziel<\/strong>: am beispiel von \\(3SAT\\) sehen wir die Reduktion, indem wir eine aussagenlogische Formel so umformen, dass wir zwar beliebig viele Klauseln, aber nur drei Literale pro Klausel haben. Schaffen wir diese Reduktion in Polynomzeit durchzuf\u00fchren, so ist sie uns gelungen.<\/p>\n<h2>Lernziel 5<\/h2>\n<p style=\"padding-left: 30px;\"><em>Angabe einiger NP-vollst\u00e4ndigen Probleme<\/em><\/p>\n<p>Im Skript werden noch weitere Probleme besprochen, die \\(NP\\)-vollst\u00e4ndig sind. Zwei davon sind \\(CLIQUE\\) und \\(IND\\_SET\\). Fangen wir doch zun\u00e4chst mit \\(CLIQUE\\) an. Definition (erneut geklaut aus dem Buch von Hr. Hoffmann):<\/p>\n<blockquote><p>Graph \\(G\\) mit Knotenmenge \\(V\\) und Kantenmente \\(E\\)<\/p>\n<p>Fragestellung: Existieren \\(n\\) Knoten \\(v_1,&#8230;,v_n\\), die paarweise durch eine Kante aus \\(E\\) verbunden sind?<\/p>\n<p>Menge \\(C=\\{v_1,&#8230;,v_n\\}\\) mit dieser Eigenschaft hei\u00dft \\(CLIQUE\\) der Gr\u00f6\u00dfe \\(n\\)<\/p><\/blockquote>\n<p>In klaren Worten ist eine \\(CLIQUE\\) eine Menge von Knoten, die alle miteinander verbunden sind.<\/p>\n<p><strong>Beispiel<\/strong>:\u00a0\\(G_1\\) mit<\/p>\n<p style=\"padding-left: 30px;\">\\(V_1=\\{1,2,3,4,5,6\\}\\) und<\/p>\n<p style=\"padding-left: 30px;\">\\(E=\\{\\{1,2\\},\\{1,3\\},\\{2,3\\},\\{2,4\\},\\{2,5\\},\\{4,5\\},\\{5,6\\},\\{6,3\\},&#8230;\\}\\) (die Kanten in die andere Richtung habe ich aus Faulheit ausgelassen, denkt sie euch einfach dazu)<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/graph.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-1636\" style=\"margin-left: 100px; margin-right: 130px;\" alt=\"graph\" src=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/graph.png\" width=\"261\" height=\"223\" srcset=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/graph.png 373w, https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/graph-300x255.png 300w\" sizes=\"auto, (max-width: 261px) 100vw, 261px\" \/><\/a><\/p>\n<p>Hier haben wir Cliquen mit den Knoten \\(\\{1,2,3\\},\\{2,4,5\\},\\{2,3,5\\},\\{3,5,6\\}\\) identifiziert. Um zu beweisen, dass wir eine Clique der Gr\u00f6\u00dfe \\(n\\) gefunden haben, m\u00fcssen wir nur eine geeignete Knotenmenge raten und pr\u00fcfen ob paarweise durch eine Kante verbunden sind. Raten wir z.B. \\(C=\\{1,5,6\\}\\), m\u00fcssen wir auf folgende Kanten pr\u00fcfen: \\(\\{1,5\\},\\{1,6\\},\\{5,1\\},\\{5,6\\},\\{6,1\\},\\{6,5\\}\\). Jaja, ungerichteter Graph, ich wei\u00df: ein vorhandener Weg von \\(A\\) nach \\(B\\) impliziert den Weg von \\(B\\) nach \\(A\\). Aber wir tun uns mit der Pr\u00fcfung aller M\u00f6glichkeiten nicht weh, da dieser sowieso polynomiell beschr\u00e4nkt bleibt. So k\u00f6nnen wir aber auch ungerichtete Graphen in die Betrachtung mit einbeziehen.<\/p>\n<p>Liegen die Kanten also in unserer Menge \\(E\\), so haben wir eine Clique gefunden. Man sieht leicht, dass mit der zu suchenden Cliquen-Gr\u00f6\u00dfe der Aufwand, d.h. die Anzahl der zu pr\u00fcfenden Kanten, quadratisch (\\(n^2\\)) in Abh\u00e4ngigkeit von \\(n\\) zunimmt. Da wir eine L\u00f6sung raten und sie mit quadratischem Aufwand pr\u00fcfen k\u00f6nnen, liegt unsere \\(CLIQUE\\in NP\\) .<\/p>\n<p>Jetzt k\u00fcmmern wir uns um den aufwendigeren Teil, die \\(NP\\)-H\u00e4rte von \\(CLIQUE\\). Dazu reduzieren wir einfach \\(3SAT\\) auf \\(CLIQUE\\). Wir m\u00fcssen also eine Formel \\(M\\) konstruieren, dass gilt:<\/p>\n<p style=\"padding-left: 30px;\">\\(M\\) ist erf\u00fcllbar \\(\\Leftrightarrow G\\) enth\u00e4lt eine Clique der Gr\u00f6\u00dfe \\(n\\)<\/p>\n<p>Achtung: wir verfolgen den Weg von einer Formel zum Graphen und nicht anders herum. Wir \u00fcberf\u00fchren also eine Formel, die wahr wird wenn sie eine Belegung hat in einen Graphen, der genau bei dieser Belegung eine Clique hat. Machen wir das am besten an einem Beispiel:<\/p>\n<p><strong>Beispiel<\/strong>: \\((A)\\vee(\\neg{A}\\wedge{B})\\vee(\\neg{A}\\wedge{C})\\)<\/p>\n<p>Wie basteln wir uns daraus einen Graphen? Nach folgenden Regeln:<\/p>\n<ul style=\"list-style-type: disc;\">\n<li>Jedes Literal wird ein Knoten<\/li>\n<li>Zwischen jedem Knoten gibt es eine Kante wenn\n<ul>\n<li>sie nicht in der selben Klausel stehen und<\/li>\n<li>wenn sie gleichzeitig erf\u00fcllbar sind (\\(A\\) und \\(\\neg{A}\\) sind z.B. nicht gleichzeitig erf\u00fcllbar)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Ganz einfach. Um es deutlicher zu machen, beschriften wir die Knoten mit \\(i,j\\). \\(i\\) ist die Nr. der Klausel und \\(j\\) die Nummer des Literals in der Klausel. Z.B. w\u00e4re der Knoten, der das Literal \\(A\\) in der ersten Klausel beschreibt, beschriftet mit \\((1,1)\\).<\/p>\n<p style=\"text-align: center;\">\u00a0<a href=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/clique.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-1644\" style=\"margin-left: 100px; margin-right: 300px;\" alt=\"clique\" src=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/clique.png\" width=\"286\" height=\"281\" srcset=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/clique.png 358w, https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/clique-300x294.png 300w\" sizes=\"auto, (max-width: 286px) 100vw, 286px\" \/><\/a><\/p>\n<p>Mit den Knoten k\u00f6nnen wir auch direkt eine Belegung f\u00fcr die Formel ableiten, die sie wahr werden l\u00e4sst: \\(A=B=C=1\\). W\u00e4re ein Knoten negativ, so w\u00fcrden wir das Literal \\({}=0\\) setzen. Probiert es mal selbst an der folgenden Wertetabelle aus und bastelt euch eine Formel und den dazugeh\u00f6rigen Graphen<\/p>\n<p><strong>\u00dcbung<\/strong>:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/cliquewerte.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1646\" style=\"margin-left: 100px; margin-right: 300px;\" alt=\"cliquewerte\" src=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/cliquewerte.png\" width=\"105\" height=\"171\" \/><\/a><\/p>\n<p style=\"text-align: left;\"><a class=\"spoiler_link_show\" href=\"javascript:void(0)\" onclick=\"wpSpoilerToggle(document.getElementById('id1319932716'), this, 'L\u00f6sung zeigen', 'L\u00f6sung verstecken')\">L\u00f6sung zeigen<\/a>\n<div class=\"spoiler_div\" id=\"id1319932716\" style=\"display:none\">\u00a0<!--more--><\/p>\n<p style=\"text-align: left;\">Die Formel ist: \\((\\neg{A}\\vee\\neg{B})\\wedge(B\\vee{A})\\wedge(C)\\). Der dazugeh\u00f6rige Graph:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/clique_uebung.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-1647\" style=\"margin-left: 150px; margin-right: 300px;\" alt=\"clique_uebung\" src=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/clique_uebung.png\" width=\"270\" height=\"251\" srcset=\"https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/clique_uebung.png 385w, https:\/\/fernuni.digreb.net\/wp-content\/uploads\/2013\/05\/clique_uebung-300x278.png 300w\" sizes=\"auto, (max-width: 270px) 100vw, 270px\" \/><\/a><\/p>\n<p>Abgelesene Knotenbelegung am Graph: \\(A\\neg {B}{C}\\) und\u00a0\\(\\neg{A} {B}{C}\\)<\/p>\n<p><\/div>\n<\/p>\n<p>Viele fragen sich auch, wie man eine Reduktion von \\(CLIQUE\\) zu \\(3SAT\\) erreichen kann, also genau der umgekehrte Weg weil es irgendwie nat\u00fcrlicher erscheint einen Graphen in eine Formel statt eine Formel in einen Graphen zu stecken. Es sei gesagt, dass es nat\u00fcrlich geht. Jedes Problem, dass \\(NP\\)-Vollst\u00e4ndig ist, l\u00e4sst sich polynomiell in ein anderes, \\(NP\\)-vollst\u00e4ndiges Problem \u00fcberf\u00fchren. Jedoch evtl. nicht direkt. Der Weg von \\(CLIQUE\\) zu \\(3SAT\\) ist kein direkter, sondern f\u00fchrt \u00fcber Teilgraph-Isomorphismus nach \\(SAT\\), \\(3SAT\\) und schlie\u00dflich auf Vertex Cover, was wiederum auf \\(CLIQUE\\) zur\u00fcckgef\u00fchrt werden kann. Ein Weg dazu wurde von Larcheri Paolo <a href=\"http:\/\/profs.sci.univr.it\/~rrizzi\/classes\/Complexity\/provette\/Larcheri\/report.pdf\">hier<\/a> beschrieben.<\/p>\n<p>Ein weiteres Problem, dass im Skript angesprochen wurde war \\(IND\\_SET\\). Damit beschreibt man die Frage ob es in einem Graphen eine Menge unabh\u00e4ngiger Knoten gibt. Die Suche nach der maximalen Anzahl ist \\(NP\\)-Vollst\u00e4ndig. Da \\(CLIQUE\\) und\u00a0\\(IND\\_SET\\) sehr nah verwand sind (ein unabh\u00e4ngiges Set ist im\u00a0<a href=\"http:\/\/de.wikipedia.org\/wiki\/Komplementgraph\">Komplementgraph<\/a> eines Graphen eine Clique) kann man beide aufeinander reduzieren. Ich spare mir hier die Reduktion (erstmal), Details k\u00f6nnt Ihr z.B. <a href=\"http:\/\/en.wikipedia.org\/wiki\/Independent_set_(graph_theory)\">hier<\/a>, <a href=\"http:\/\/algo2.iti.kit.edu\/info3\/klausur\/klausur-L.fm.pdf\">hier<\/a>\u00a0oder <a href=\"http:\/\/www8.cs.umu.se\/kurser\/TDBAfl\/VT06\/algorithms\/BOOK\/BOOK3\/NODE109.HTM\">hier<\/a> nachlesen.<\/p>\n<p>Weitere \\(NP\\)-vollst\u00e4ndige Probleme sind z.B.<\/p>\n<ul style=\"list-style-type: disc;\">\n<li>Hamilonkreis (siehe <a href=\"https:\/\/fernuni.digreb.net\/?p=1471\">Beitrag zu KE3<\/a>)<\/li>\n<li><a href=\"http:\/\/de.wikipedia.org\/wiki\/Problem_des_Handlungsreisenden\">Traveling Salesman<\/a><\/li>\n<li><a href=\"http:\/\/de.wikipedia.org\/wiki\/Vier-Farben-Satz\">Vier-Farben-Problem<\/a><\/li>\n<li><a href=\"http:\/\/de.wikipedia.org\/wiki\/Rucksackproblem\">Rucksack<\/a><\/li>\n<li><a href=\"http:\/\/de.wikipedia.org\/wiki\/Partitionsproblem\">Partition<\/a><\/li>\n<li>&#8230;<\/li>\n<\/ul>\n<p>Im Skript wird auch \u00fcber Optimierungsprobleme gesprochen. Ein klassischer Vertreter davon ist das Scheduling: die Verteilung von Prozessen mit entsprechenden Ausf\u00fchrungszeiten auf eine bestimmte Anzahl von Prozessoren, so dass die Gesamtzeit minimal ist. Vielen \\(NP\\)-vollst\u00e4ndige Problemen kann man ein Optimierungsproblem zuordnen, was deren Bedeutung f\u00fcr die Informatik unterstreicht.<\/p>\n<p>Da sie alle \\(NP\\)-hart sind und sich f\u00fcr gro\u00dfe Eingaben eben einer effizienten L\u00f6sung entziehen, muss man nach sog. Approximationsalgorithmen ausschau halten, die sich einem optimalen Ergebnis m\u00f6glichst nah ann\u00e4hren. Ein schlecht approximierbares Problem ist das angesprochene \\(CLIQUE\\) (das Verh\u00e4ltnis zwischen der gr\u00f6\u00dften Clique im Graphen und der gr\u00f6\u00dften gefundenen Clique l\u00e4sst sich nicht durch eine Konstante beschreiben), w\u00e4hrend das Rucksackproblem mit dem Greedy-Algorithmus sehr nah an einer guten L\u00f6sung sein kann.<\/p>\n<p><strong>Antwort zum Lernziel<\/strong>: einige \\(NP\\)-vollst\u00e4ndige Probleme sind Hamilton, CLIQUE, Traveling Salesman, Rucksack und Partition. Weitere Probleme finden sich z.B. <a href=\"http:\/\/de.wikipedia.org\/wiki\/Karps_21_NP-vollst%C3%A4ndige_Probleme\">hier<\/a>.<\/p>\n<h2>Lernziel 6<\/h2>\n<p style=\"padding-left: 30px;\"><em>Warum ist \\(GAP\\) vollst\u00e4ndig f\u00fcr \\(NLOGSPACE\\)?<\/em><\/p>\n<p>Letztes Lernziel! Also, was ist \\(GAP\\)? Es ist ein einfaches Erreichbarkeitsproblem in einem Graphen. Gibt es einen Weg von Knoten \\(a\\) zu Knoten \\(b\\)? Die Tiefen- und Breitensuche l\u00f6st das Problem in Polynomzeit. F\u00fcr den Platzbedarf sind wir aber bei \\(O(\\#V)\\) (d.h. der Platzbedarf entspricht der Anzahl der Knoten), ein Algorithmus, der nur logarithmischen Platz beansprucht, ist nicht bekannt.<\/p>\n<p>Eine \\(NTM\\) kann das Problem jedoch mit der Bandschranke \\(O(log)\\) erkennen. Die Achillesferse dabei ist: der Algorithmus ist ged\u00e4chnislos. Besuchte Knoten und Wege werden vergessen, wir haben evtl. das Problem von Zyklen. Entsch\u00e4rft wird das durch die von uns gegebene Schranke: der Knotenanzahl im Graphen. Der Algorithmus bricht ab wenn die maximale Anzahl der Knoten (\\(\\#V\\)) besucht wurde.<\/p>\n<p>Der Beweis im Skript zeigt einen sehr engen Zusammenhang zwischen \\(NLOGSPACE\\) und \\(GAP\\):<\/p>\n<p>Also warum beansprucht \\(GAP\\) tats\u00e4chlich nur logarithmischen Platzverbrauch wenn er von einer \\(NTM\\) erkannt wird (hier bitte Vorsicht, nutzen wir eine normale \\(TM\\), m\u00fcssen wir alle Knoten durchprobieren und d\u00fcrfen uns mit \\(O(\\#V)\\) begn\u00fcgen)? Der beschriebene Algorithmus arbeiten in etwa wie folgt (\\(a\\) ist Start- und \\(b\\) ist Endknoten):<\/p>\n<ol style=\"padding-left: 60px;\">\n<li>\\(c:=a;i=\\#V\\) (setze Startknoten und maximale Knotenanzahl als l\u00e4ngster Weg gesetzt)<\/li>\n<li>Wenn \\(c=b\\), akzeptiere, ansonsten Schritt 3 (wenn Endknoten erreicht).<\/li>\n<li>rate neuen Knoten \\(d\\). Setze \\(i:=i-1\\), Schritt 4 (neuer Knoten aus Graph wird geraten und ein Schritt vom Weg abgezogen).<\/li>\n<li>Wenn \\(i=0\\) oder \\((c,d)\\notin E\\), verwerfen und nochmal neu raten: Schritt 3. Sonst Schritt 5 (wenn maximale Anzahl an Knoten besucht wurde, d.h. der l\u00e4ngste Weg beschritten, ist der Weg mist. Gleiches gilt wenn ein Folgeknoten \\(d\\) geraten wurde, und es zu diesem keine Kante\/keinen direkten Weg gibt).<\/li>\n<li>\\(c = d\\), Schritt 2 (es gibt also einen direkten Weg von \\(c\\) nach \\(d\\), d.h. das wird unser n\u00e4chster Knoten von dem wir losgehen).<\/li>\n<\/ol>\n<p>Alle Knoten und Zahlen (insg. 5) werden als Dualzahlen gespeichert und wir verbrauchen damit weniger Speicherplatz als die anderen Algorithmen mit \\(O(\\#V)\\). Da der Algorithmus ged\u00e4chnislos ist, speichern wir auch keine Adjazenzmatrix und auch nicht den Weg. Raten wir also in Schritt 3 mehrmals ziemlich bl\u00f6d, so laufen wir ggf. die ganze Zeit im Kreis. Wir fragen aber nicht nach dem k\u00fcrzesten Weg, sondern ob es \u00fcberhaupt einen gibt.<\/p>\n<p>Damit ist zun\u00e4chst \\(GAP\\in NLOGSPACE\\). Nun m\u00fcssen wir eine Reduktion \\(L\\leq_{log}GAP\\) zeigen. Dazu wird eine Maschine mit Bandschranke \\(O(log)\\) erstellt, die \\(L\\) entscheidet und die Eingabe der Maschine als Graph codiert. Die Knoten sind alle Konfigurationen der Maschine bei der Eingabe von \\(x\\). Gibt es bei der Eingabe von \\(x\\) von einem Zustand ausgehend einen Folgezustand, so ist das eine Kante im Graphen. F\u00fchrt \\(x\\) also zu einer Endkonfiguration, so gibt es auch einen Weg in diesem Graphen von \\(x\\) zum Endzustand. Damit sind wir mit der Reduktion auch schon durch.<\/p>\n<p><strong>Achtung<\/strong>: die Reduktionen \\(\\leq_{pol}\\) beziehen sich immer auf Zeit. Polynomialplatz ist zu m\u00e4chtig f\u00fcr Reduktionen. W\u00e4hrend\u00a0\\(\\leq_{log}\\) sich immer auf Platz bezieht, da wir zeitlich nicht einmal die Eingabe h\u00e4tten lesen k\u00f6nnen bei dieser Reduktion.<\/p>\n<p><strong>Antwort zum Lernziel<\/strong>: das Erreichbarkeitsproblem wird mit logarithmischem Platzverbrauch mit einer \\(NTM\\) entschieden weil der Algorithmus ged\u00e4chnislos ist. Es k\u00f6nnen also Zyklen entstehen, die wir nicht erkennen k\u00f6nnen. Der maximale Platzverbrauch ist jedoch die maximale Anzahl an Knoten weil der Algorithmus abbricht wenn die Anzahl der besuchten Knoten der Anzahl der Knoten im Graph entspricht.\u00a0Da wir aber nicht nach dem k\u00fcrzesten Weg fragen, sondern nur ob es einen gibt reicht uns das aus.<\/p>\n<p>Die Reduktion der Eingabe auf eine Maschine mit Bandschranke \\(O(log)\\) erfolgt wie oben beschrieben.<\/p>\n<p>Wieder: wer Fehler findet, bitte ab damit in die Kommentare oder eine Mail an mich.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lernziel 3 Wie ist der Vollst\u00e4ndigkeitsbeweis zu ? steht f\u00fcr das englische\u00a0satisfiability.\u00a0Also ein Erf\u00fcllbarkeitsproblem. Es wird gefragt ob eine aussagenlogische Formel erf\u00fcllbar ist (erinnert ihr euch an KNF\/DNF aus der technischen Informatik? Das hier ist nicht weit weg&#8230;). Da eine Formel nur endlich viele variablen enth\u00e4lt, die nur mit und belegt werden k\u00f6nnen, haben wir &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/fernuni.digreb.net\/?p=1616\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eTIB: NP-Vollst\u00e4ndige Probleme (Lernziele KE4 2\/2, Update)\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-1616","post","type-post","status-publish","format-standard","hentry","category-theoretische-informatik"],"_links":{"self":[{"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=\/wp\/v2\/posts\/1616","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1616"}],"version-history":[{"count":41,"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=\/wp\/v2\/posts\/1616\/revisions"}],"predecessor-version":[{"id":3531,"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=\/wp\/v2\/posts\/1616\/revisions\/3531"}],"wp:attachment":[{"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1616"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1616"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fernuni.digreb.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1616"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}