<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Zufallsbit - P vs. NP</title>
    <link>http://zufallsbit.de/blog/</link>
    <description>...jetzt quasi gleichverteilt</description>
    <dc:language>de</dc:language>
    <generator>Serendipity 1.5.3 - http://www.s9y.org/</generator>
    <pubDate>Sun, 17 Feb 2008 16:23:56 GMT</pubDate>

    <image>
        <url>http://zufallsbit.de/blog/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Zufallsbit - P vs. NP - ...jetzt quasi gleichverteilt</title>
        <link>http://zufallsbit.de/blog/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>NP Vollständigkeit</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/52-NP-Vollstaendigkeit.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/52-NP-Vollstaendigkeit.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=52</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=52</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;br /&gt;
&lt;p&gt;Eigentlich hatte ich das P vs. NP Problem bereits abgeschlossen, aber es gibt da so eine Sache, die gehört zum Thema einfach dazu. Außerdem ist es eine großartige Sache um damit auf Cocktailpartys Wissen raushängen zu lassen.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Also, wir hatten ja festgestellt, dass Probleme aus NP in polynomieller Zeit auf nichtdeterministischen Turingmaschinen entschieden werden können. Die P vs. NP Frage ist jetzt, ob die Problemklassen P und NP gleich sind oder nicht. Essentiell heißt das, dass wir nicht wissen, ob es für heutzutage praktisch nicht effizient lösbare Probleme wirklich keinen effizienten Algorithmus gibt, oder ob wir ihn nur einfach noch nicht gefunden haben. Nun ist es ziemlich schwierig, untere Schranken zu finden. Ich nehme da immer gerne das Beispiel mit der Orangenkiste. Man stelle sich vor, man will möglichst effizient Orangen in eine Kiste packen. Dabei kommt es natürlich zu Luft zwischen den einzelnen Kugeln. Was ist die optimale Packstrategie? Einfach zufällig reinwerfen, die Orangen wie Blöcke übereinander stapeln oder die Orangen leicht versetzt anordnen, so dass sie gegenseitig die Hohlräume füllen? Intuitiv würden wir natürlich die letztere Möglichkeit wählen, aber können wir denn sicher sein, dass nicht in 2000 Jahren irgendein schlauer Mensch daher kommt und eine revolutionäre Idee hat? Hierzu braucht man untere Schranken, man will mathematisch beweisen, dass es kein besseres Verfahren geben &lt;em&gt;kann&lt;/em&gt;. Das ist natürlich eine ganze Ecke schwieriger, denn man muss ja auch alle Fälle ausschließen können, die man noch nicht kennt.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Das ist auch im Grunde das Problem bei P vs. NP. Beide Komplexitätsklassen beinhalten eine Menge Probleme, aber wir können nicht erwarten, wirklich alle Probleme bereits identifiziert zu haben. Wie können wir also z.B. P=NP behaupten, wenn wir vielleicht morgen ein Problem entdecken, das in NP aber nicht in P ist? Anders herum: Wir können auch nicht einfach P!=NP sagen wenn wir ein Problem haben, das in NP, aber nicht in P ist. Es könnte ja einen Algorithmus geben, den wir nur noch nicht entdeckt haben.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Der Ausweg sind so genannte Reduktionen. Wenn man Problem A auf Problem B reduziert, bedeutet das, dass man die Eingabe für Problem A so umbasteln kann, dass man sie in einen Algorithmus für Problem B füttern kann, der das Problem löst und dabei die Antwort für A liefert. Ein Beispiel hilft wie immer:&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Problem A ist &amp;quot;Ist die Zahl x gerade?&amp;quot;. Problem B ist &amp;quot;Ist x mod 2=1?&amp;quot;. Nun, für uns mit unserer menschlichen Intuition sehen die Probleme gleich aus, denn eine gerade Zahl modulo 2 ist eben immer null. Aber unsere Intuition macht nichts anderes als eine Reduktion. Wenn wir Problem A lösen wollen, rechnen wir eigentlich x mod 2 und entscheiden Aufgrund dieser Rechnung (des Problems B!) das Problem A. Und damit (und hier kommt der Knackpunkt), ist das Problem A in der gleichen Zeit entscheidbar wie B. Wenn B einen O(n) Algorithmus hat, dann ist auch A in dieser Zeit entscheidbar. Nicht für alle Probleme allerdings ist das so offensichtlich wie hier, es gibt teilweise die abenteuerlichsten Reduktionen. Wer hätte z.B. gedacht dass Tetris komplexitätstechnisch so schwer ist, wie die optimale Anordnung von Sicherheitskameras zu finden?&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Zurück zu den unteren Schranken. Sicher wäre es doch äußerst praktisch, wenn man sagen könnte, dass ein Problem das &lt;em&gt;schwerste&lt;/em&gt; aus NP ist. Dann könnte wir nämlich sagen, dass wir nur noch einen P-Algorithmus für dieses schwerste Problem finden müssten. Wenn sich dieses allerschwerste Problem nämlich effizient lösen ließe, müssten einfachere Probleme aus NP ja wohl auch effizient lösbar sein. Und interessanterweise hat Stephen A. Cook bewiesen, dass es ein Problem gibt, das das schwerste in NP ist. Das ist natürlich überraschend, denn auch hier muss man ja über potentiell noch nicht entdeckte Probleme argumentieren, trotzdem schafft dieser großartige Beweis genau das.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Wie immer reiße ich die Beweisidee nur kurz an, denn die Details dürften nur sehr wenige interessieren. Wer näheres Wissen will schreibt mir eine Mail oder kauft sich ein Buch über theoretische Informatik ;)&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Das schwerste Problem aus NP heisst &amp;quot;SAT&amp;quot; und hat nichts mit deutschen Fernsehsendern zu tun. Das Kürzel steht viel mehr für &amp;quot;satisfiability&amp;quot;. Stellen wir uns eine Klausel aus boolschen Variablen vor. &amp;quot;x&lt;sub&gt;1&lt;/sub&gt;&amp;quot; wäre so eine Klausel mit nur einer Variablen. x1 AND x2 wäre eine andere, auch (x&lt;sub&gt;1&lt;/sub&gt; AND x&lt;sub&gt;3&lt;/sub&gt;) OR (x&lt;sub&gt;5&lt;/sub&gt; AND x&lt;sub&gt;1&lt;/sub&gt; AND NOT(x&lt;sub&gt;3&lt;/sub&gt;)) ist so eine. Die Frage die das SAT-Problem stellt ist: Ist diese Klausel erfüllbar? D.h. gibt es eine Belegung von Variablen, wo die ganze Klausel &amp;quot;true&amp;quot; wird? x&lt;sub&gt;1&lt;/sub&gt; AND NOT(x&lt;sub&gt;1&lt;/sub&gt;) zum Beispiel ist trivialerweise nicht erfüllbar. Es gibt nur eine Variable, und wenn diese 1 wäre, wäre der NOT(..) Teil nicht mehr erfüllbar und umgekehrt. Dieses Problem ist aus NP, wir kennen keine bessere Idee als &amp;quot;Belegungen ausprobieren&amp;quot;. Im schlechtesten Fall müssen wir deshalb alle möglichen Belegungen ausprobieren und das sind exponentiell viele. Deshalb ist es auf TMs nicht effizient lösbar.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Warum ist SAT jetzt das schwerste Problem im NP? Ganz einfach, Turingmaschinen lassen sich auf trickreiche Weise in Boolschen Ausdrücken codieren. Dabei stellt man durch allerlei Kniffe sicher, dass eine sehr lange Klausel entsteht, &lt;strong&gt;die genau und ausschließlich dann erfüllbar ist, wenn die Turingmaschine terminiert und ein Ergebnis liefert&lt;/strong&gt;. Dann löst man diese Klausel auf und sieht: Wenn die Klausel erfüllbar ist, dann liefert die codierte TM &amp;quot;true&amp;quot;, sonst &amp;quot;false&amp;quot;. Und diese Idee ist geradezu genial, denn wer würde schon darauf kommen, ein so umfangreiches Modell wie eine TM in eine lange boolsche Formel umzusetzen um das Ergebnis der SAT Berechnung als Ergebnis der TM zu nehmen?&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Aber warum ist damit SAT das schwerste Problem aus NP? Nun, man stelle sich ein schwereres Problem als SAT vor, so ein richtig scheiße schweres Problem. Der Michael Moore unter den Problemen. Nun könnte man doch einfach die entsprechende TM in eine Klausel umbasteln (und der Satz von Cook stellt sicher dass das in poynomieller Zeit passiert). Wenn man diese Klausel hat, kann man sie in den SAT Problemlöser füttern, der dann das Ergebnis berechnet. D.h. also, dass jedes noch so schweres NP-Problem nicht schwerer zu lösen sein kann als SAT. Und das ist genial, denn wir haben damit das schwerste Problem aus NP identifiziert.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Und die Implikationen sind enorm, denn jetzt können wir die oben angesprochene Reduktion anwenden und wiederum SAT-Eingaben in Eingaben von anderen Problemen umbasteln. Z.B. gibt es ein Problem, das DHC heisst. Wenn wir ein DHC-Probleminstanz so bauen können, dass ein DHC-Algorithmus genau dann &amp;quot;wahr&amp;quot; entscheidet, wenn die Klausel vom SAT &amp;quot;wahr&amp;quot; entscheiden würde, könnten wir auch DHC als &amp;quot;schwerstes&amp;quot; Problem identifizieren. Nun, schwerer als SAT kann es aber auch nicht sein, also müssen beide Probleme &lt;em&gt;gleich schwer&lt;/em&gt; sein. Solche Probleme heißen NP-Vollständig. Sie gehören einer Unterklasse von NP an, die die schwersten Probleme aus NP umfasst. Tausende Probleme sind NP Vollständig und wenn man auch nur für ein einiziges von diesen einen P-Algorithmus finden würde, hätte man automatisch P=NP bewiesen. Denn wenn ein schwerstes Problem aus NP effizient lösbar wäre, wären es auch alle einfacheren. Der Fakt allerdings, dass für kein einziges dieser tausenden Probleme ein guter Algorithmus existiert, lässt wenig Hoffnung übrig, dass es einen solchen gibt&lt;/p&gt;&lt;br /&gt;
&lt;p&gt; &lt;/p&gt; 
    </content:encoded>

    <pubDate>Tue, 29 May 2007 20:27:00 +0200</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/52-guid.html</guid>
    <category>algorithmus</category>
<category>determinismus</category>
<category>informatik</category>
<category>komplexitã¤t</category>
<category>komplexitã¤tsklasse</category>
<category>laufzeit</category>
<category>millenium-probleme</category>
<category>nichtdeterminismus</category>
<category>np</category>
<category>p</category>
<category>p vs. np</category>
<category>tm</category>
<category>turing-maschine</category>

</item>
<item>
    <title>P vs. NP Inhaltsverzeichnis</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/38-P-vs.-NP-Inhaltsverzeichnis.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/38-P-vs.-NP-Inhaltsverzeichnis.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=38</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=38</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;p&gt;Die Serie &amp;uuml;ber P vs. NP ist komplett und hier sind nochmal alle Links dazu in chronologischer Reihenfolge. Falls ihr Fehler findet oder etwas nicht ganz klar ist, sagt mir Bescheid.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Die O-Notation, &amp;uuml;ber Wachstum und wie man Algorithmen vergleicht&lt;br /&gt;&lt;br /&gt;
&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/zufallsbit.de/blog/index.php?/archives/3-O-Notation.html&#039;);&quot;  href=&quot;http://zufallsbit.de/blog/index.php?/archives/3-O-Notation.html&quot;&gt;O-Notation&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Turingmaschinen, wie man Rechner abstrahiert und minimale Rechner daraus bastelt.&lt;br /&gt;&lt;br /&gt;
&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/zufallsbit.de/blog/index.php?/archives/7-Turingmaschinen.html&#039;);&quot;  href=&quot;http://zufallsbit.de/blog/index.php?/archives/7-Turingmaschinen.html&quot;&gt;Turingmaschinen&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Warum man die Grenze f&amp;uuml;r effektive Algorithmen bei &amp;quot;exponentiell&amp;quot; zieht&lt;br /&gt;&lt;br /&gt;
&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/zufallsbit.de/blog/index.php?/archives/11-Polynomiell-vs.-exponentiell.html&#039;);&quot;  href=&quot;http://zufallsbit.de/blog/index.php?/archives/11-Polynomiell-vs.-exponentiell.html&quot;&gt;Polynomiell vs. Exponentiell&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Was sind Komplexit&amp;auml;tsklassen, was ist P?&lt;br /&gt;&lt;br /&gt;
&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/zufallsbit.de/blog/index.php?/archives/19-Komplexitaetsklassen.html&#039;);&quot;  href=&quot;http://zufallsbit.de/blog/index.php?/archives/19-Komplexitaetsklassen.html&quot;&gt;Komplexit&amp;auml;tsklassen&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Andersartige Turingmaschinen und die Bedeutung des Zufalls&lt;br /&gt;&lt;br /&gt;
&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/zufallsbit.de/blog/index.php?/archives/22-Randomisierung-und-ZPP.html&#039;);&quot;  href=&quot;http://zufallsbit.de/blog/index.php?/archives/22-Randomisierung-und-ZPP.html&quot;&gt;Randomisierung und ZPP&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Noch mehr Zufallsbits und mehr Fehlerm&amp;ouml;glichkeiten&lt;br /&gt;&lt;br /&gt;
&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/zufallsbit.de/blog/index.php?/archives/26-Einseitige-Fehler,-RP-und-co-RP.html&#039;);&quot;  href=&quot;http://zufallsbit.de/blog/index.php?/archives/26-Einseitige-Fehler,-RP-und-co-RP.html&quot;&gt;Einseitige Fehler, RP und co-RP&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Nichtdeterminismus, noch mehr Turingmaschinen und die P vs. NP Frage&lt;br /&gt;&lt;br /&gt;
&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/zufallsbit.de/blog/index.php?/archives/36-Nichtdeterminismus-und-NP.html&#039;);&quot;  href=&quot;http://zufallsbit.de/blog/index.php?/archives/36-Nichtdeterminismus-und-NP.html&quot;&gt;Nichtdeterminismus und NP&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Was es noch zu NP zu sagen g&amp;auml;be und der Satz von Cook&lt;br /&gt;&lt;br /&gt;
&lt;a onclick=&quot;javascript: pageTracker._trackPageview(&#039;/extlink/zufallsbit.de/blog/index.php?/archives/52-NP-Vollstaendigkeit.html&#039;);&quot;  href=&quot;http://zufallsbit.de/blog/index.php?/archives/52-NP-Vollstaendigkeit.html&quot;&gt;NP Vollst&amp;auml;ndigkeit&lt;/a&gt;&lt;/p&gt; 
    </content:encoded>

    <pubDate>Thu, 03 May 2007 17:01:34 +0200</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/38-guid.html</guid>
    
</item>
<item>
    <title>Nichtdeterminismus und NP</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/36-Nichtdeterminismus-und-NP.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/36-Nichtdeterminismus-und-NP.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=36</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=36</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;p&gt;Heute ist es soweit, die Serie &amp;uuml;ber P vs. NP kommt zum Abschluss. Dieser letzte Eintrag k&amp;ouml;nnte noch einmal etwas verzwickt werden, aber wer bis hierhin durchgehalten hat, wird den letzten Schritt auch noch schaffen ;)&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Wir hatten ja Turingmaschinen besprochen und dabei implizit festgestellt, dass diese deterministisch arbeiten. Das hei&amp;szlig;t, f&amp;uuml;r eine bestimmte Eingabe werden immer die gleichen Arbeitsschritte erledigt, das Verhalten ist damit perfekt vorhersagbar. Dieses Prinzip ist &amp;uuml;brigens universell anwendbar. In der Tat ist die Frage nach Determinismus in der Natur noch weitestgehend unbeantwortet. Die ganzen Atome und Elektronen die um uns herum schwirren - sind die alle nur vom vorherigen Zustand abh&amp;auml;ngig? Wenn mich ein Atom trifft, tut es das dann nur weil es vorher mit einem anderen zusammen gesto&amp;szlig;en ist? Wenn ja, war dieses Zusammensto&amp;szlig;en nicht aus einem vorherigen Zustand berechenbar? Ultimativ, ist seit Beginn des Universums nur ein Zustand nach dem n&amp;auml;chsten passiert, und m&amp;uuml;sste damit streng formal aus einem derzeitigen Zustand der Ursprungszustand berechenbar sein?&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Ich wei&amp;szlig; es nicht, aber diese Modellvorstellung nennt man eben &amp;quot;Determinismus&amp;quot;. Was ist aber mit den ebenfalls besprochenen randomisierten Turingmaschinen? Mal abgesehen davon, dass es in einem deterministischen Natur eh keinen echten Zufall g&amp;auml;be. Nun ja, randomisierte Turingmaschinen sind irgendwie nicht deterministisch, denn die Folge von Rechenschritten h&amp;auml;ngt ja nicht nur von der Eingabe ab, sondern auch von all den Zufallsbits. Aber bevor wir Randomisierung und Nichtdeterminismus vergleichen, m&amp;uuml;ssten wir vielleicht erst kurz besprechen was letzteres in der Informatik bedeutet.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Eins vorweg: Nichtdeterministische Turingmaschinen (&amp;quot;NTM&amp;quot;) sind in der Praxis unrealistisch. Nie wird jemand eine NTM wirklich bauen k&amp;ouml;nnen. Warum sie trotzdem relevant ist, wird erst sp&amp;auml;ter deutlich, also akzeptiert diesen Fakt erst mal.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Stellen wir uns also folgendes vor: Wir suchen eine TM die &amp;quot;wahr&amp;quot; ausgibt, falls entweder &amp;quot;0011&amp;quot; oder &amp;quot;0110&amp;quot; als Eingabe kommt. Ein deterministischer Algorithmus s&amp;auml;ge so aus:&lt;br /&gt;&lt;br /&gt;
Lese 0, lese 0 oder 1, lese 1, lese 0 oder 1. Wenn das immer gelingt, geben wir &amp;quot;wahr&amp;quot; aus. Oder auch nicht, denn wenn wir bereits 011 gelesen haben, dann w&amp;uuml;rde unser Algorithmus auch 0111 akzeptieren, und das w&amp;auml;re ein Fehler. Wir m&amp;uuml;ssten also, wenn die zweite Stelle eine 1 ist, an der vierten Stelle eine 0 fordern. In der Realit&amp;auml;t w&amp;uuml;rden wir daf&amp;uuml;r if-Konstrukte verwenden, f&amp;uuml;r Turingmaschinen wird das ganze sehr schnell beliebig kompliziert. Deshalb w&amp;uuml;rden wir gerne eine NTM benutzen, denn eine solche kann &amp;quot;w&amp;auml;hlen&amp;quot; bzw. &amp;quot;raten&amp;quot;, welchen Weg sie geht. Und jetzt wird es etwas seltsam. Die NTM hat f&amp;uuml;r jeden Zustands&amp;uuml;bergang mehrere Wahlm&amp;ouml;glichkeiten, welcher Weg einzuschlagen ist. Ein zugegebenerma&amp;szlig;en etwas hingeschludertes Bild sollte das klarer machen.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;img src=&quot;http://zufallsbit.de/blog/uploads/ntm1.png&quot; style=&quot;border: 0px none ; padding-left: 5px; padding-right: 5px;&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Hier sieht man alle m&amp;ouml;glichen Eingaben. Die beiden gr&amp;uuml;n markierten Wege symbolisieren die beiden zu akzeptierenden Eingaben. Wie man au&amp;szlig;erdem erkennt gibt es insgesamt 16 Wege. Das sind &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=2%5E4&quot; title=&quot;2^4&quot; alt=&quot;2^4&quot; \/&gt; Wege, oder allgemein &amp;quot;(Anzahl m&amp;ouml;glicher Buchstaben) hoch (L&amp;auml;nge der Eingabe)&amp;quot;. Oder eben exponentielle viele, was der eigentliche Knackpunkt ist.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Normalerweise sehen Probleme allerdings nicht so aus wie das obige. Normalerweise fragt man sowas wie &amp;quot;gibt es &amp;uuml;berhaupt irgendeinen Weg etwas zu tun?&amp;quot;. Gibt eine eine TSP-Rundreise mit Kosten X? Gibt es Situationen in denen der Prozessor nicht korrekt arbeitet? Und so versteht man auch den Unterschied zwischen TM und NTM besser. Eine TM w&amp;uuml;rde zu diesem Zweck alle Wege ausprobieren und &amp;quot;wahr&amp;quot; ausgeben, falls z.B. eine fehlerhafte Prozessorkonfiguration gefunden wurde. Das dauert nur leider im allgemeinen exponentiell lang, im Zweifelsfall m&amp;uuml;ssen alle Wege ausprobiert werden. Eine NTM hingegen kann wie gesagt &amp;quot;raten&amp;quot;. Wenn es auch nur einen Weg gibt wo die Eingabe akzeptiert wird, so w&amp;auml;hlt die NTM automatisch diesen Weg. Sollte es mehr als einen m&amp;ouml;glichen Weg geben, w&amp;auml;hlt die NTM irgendeinen davon.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Also Beispiel: Wenn eine TSP-Rundreise mit Kosten 20 gesucht wird, &amp;quot;r&amp;auml;t&amp;quot; die NTM immer den richtigen Rechnungsschritt, damit man am Ende bei &amp;quot;Kosten 20&amp;quot; raus kommt. Sollte es schlicht nicht m&amp;ouml;glich sein Kosten 20 zu erreichen, wird das auch erkannt und die NTM gibt &amp;quot;falsch&amp;quot; aus. Die TM hingegen w&amp;uuml;rde im schlechtesten Fall alle m&amp;ouml;glichen (exponentiell viele) Wege ausprobieren und daf&amp;uuml;r eine Ewigkeit brauchen.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Schauen wir uns das obige Bild nochmal genauer an: Wir k&amp;ouml;nnten ja auch einfach sagen, dass die Wege mit den Nullen und Einsen jeweils Zufallsbits darstellen und damit im Grunde auch eine randomisierte TM f&amp;uuml;r dieses Bild passen k&amp;ouml;nnte. In der Tat ist es dank probability amplification (siehe letzter Beitrag) genau so: Eine NTM und eine RTM mit Fehlerwahrscheinlichkeit &amp;lt;1 sind komplexit&amp;auml;tstechnisch gleich.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Und damit k&amp;ouml;nnen wir endlich (tadaa!) die Komplexit&amp;auml;tsklasse NP definieren: In dieser Klasse sind alle Probleme, die von einer NTM in polynomieller Zeit entschieden werden k&amp;ouml;nnen. Klar ist nat&amp;uuml;rlich, dass P eine Untermenge von NP ist. Alles was von einer TM entschieden werden kann, kann trivialerweise auch von einem NTM entschieden werden. Aber ist das umgekehrt auch der Fall? Kann eine TM irgendwie besser werden als &amp;quot;alle Wege ausprobieren&amp;quot;? Genau das ist die gro&amp;szlig;e Frage, die 1 Mio$ wert ist. Daf&amp;uuml;r reicht es nat&amp;uuml;rlich nicht, f&amp;uuml;r irgendein Problem aus NP einen Algorithmus aus P zu finden, denn es kann ja schwerere Probleme in NP geben, die keinen Algorithmus in P haben. Damit w&amp;auml;re dann P!=NP (!= bedeutet &amp;uuml;brigens ungleich&amp;quot;). Zum Gl&amp;uuml;ck ist es den Theoretikern gelungen, schwerste Probleme aus NP zu finden. Es kann keine schwereren Probleme als diese geben. D.h. wenn es f&amp;uuml;r eines dieser schwersten Probleme einen Algorithmus aus P gibt, dann ist P=NP. Das nennt man Satz von Cook und k&amp;ouml;nnte durchaus noch Stoff f&amp;uuml;r einen weiteren Beitrag sein.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Aber um die eigentliche P vs. NP Frage zu verstehen ist das nicht notwendig, eigentlich ist diese Serie also hier abgeschlossen. Trotzdem will ich noch einmal &amp;uuml;ber die Konsequenzen dieser gro&amp;szlig;en Frage referieren. Zum Beispiel ist die Faktorisierung von Primzahlen ein Problem aus NP, das (vermutlich) keinen Algorithmus in P hat. Nun basieren viele wichtige Verschl&amp;uuml;sselungsverfahren darauf, dass es keine solchen Algorithmen gibt. Wer sofort alle Faktoren einer Primzahl errechnen k&amp;ouml;nnte, br&amp;auml;uchte nicht mehr hunderte Jahre um so einen Schl&amp;uuml;ssel zu knacken. Aber auch viele wichtige Algorithmen aus der Bioinformatik sind aus NP und brauchen deshalb sehr lange. W&amp;auml;re P != NP, br&amp;auml;uchten wir keine Hoffnung auf schnellere L&amp;ouml;sung der Probleme machen. Generell w&amp;uuml;rde P != NP bedeuten, dass es f&amp;uuml;r viele wichtige Probleme keine schnellere L&amp;ouml;sungsmethode als &amp;quot;alles ausprobieren&amp;quot; gibt. Und jetzt die schlechte Nachricht: Wahrscheinlich ist P ungleich NP. Es sind tausende schwerste Probleme aus NP bekannt, aber wir kennen keinen einzigen Algorithmus aus P daf&amp;uuml;r. Generationen von Informatikern haben danach gesucht, aber alle sind gescheitert. Nat&amp;uuml;rlich ist das kein Beweis, aber gesunder Menschenverstand sagt einem, dass es vermutlich einen guten Grund daf&amp;uuml;r gibt..&lt;/p&gt; 
    </content:encoded>

    <pubDate>Thu, 03 May 2007 17:01:00 +0200</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/36-guid.html</guid>
    <category>algorithmus</category>
<category>determinismus</category>
<category>fehlerwahrscheinlichkeit</category>
<category>komplexitÃ¤t</category>
<category>komplexitÃ¤tsklasse</category>
<category>millenium-probleme</category>
<category>nichtdeterminismus</category>
<category>np</category>
<category>p vs. np</category>
<category>rp</category>
<category>tm</category>
<category>turing-maschine</category>

</item>
<item>
    <title>Einseitige Fehler, RP und co-RP</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/26-Einseitige-Fehler,-RP-und-co-RP.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/26-Einseitige-Fehler,-RP-und-co-RP.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=26</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=26</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;p&gt;Im letzten Beitrag hatten wir ja ZPP besprochen und dabei festgestellt, dass ZPP-Algorithmen keine Fehler machen, daf&amp;uuml;r aber &amp;quot;?&amp;quot; ausgeben k&amp;ouml;nnen. Deshalb kann man ZPP-Algorithmen einfach &amp;ouml;fter aufrufen und hoffen, dass irgendwann irgendein Ergebnis au&amp;szlig;er &amp;quot;?&amp;quot; kommt. Dann k&amp;ouml;nnen wir n&amp;auml;mlich sicher sein, dass das Ergebnis richtig ist.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Gut, aber es gibt auch andere Fehlerarten. Wenn ein Algorithmus auf einer randomisierten TM in polynomieller Zeit ausgef&amp;uuml;hrt werden kann und der Algorithmus einen einseitigen Fehler machen kann, ordnen wir ihn der Komplexit&amp;auml;tsklasse RP bzw. co-RP zu. Bevor ich erkl&amp;auml;re was ein einseitiger Fehler ist, muss ich noch kurz &amp;uuml;ber Entscheidungsprobleme sprechen.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Man kann ja Algorithmen schreiben, die verschiedene Fragen stellen. Zum Beispiel k&amp;ouml;nnte man ein gro&amp;szlig;es Integer Array als Eingabe nehmen und fragen &amp;quot;Was sind die gr&amp;ouml;&amp;szlig;ten drei Elemente daraus?&amp;quot;. Das w&amp;auml;re ein Optimierungsproblem, denn man gibt drei &amp;quot;optimale&amp;quot; Elemente als Ergebnis aus. Eine andere Frage w&amp;auml;re &amp;quot;Was ist die Summe der gr&amp;ouml;&amp;szlig;ten drei Elemente?&amp;quot;. Das wiederum ist ein Evaluationsproblem, hier wird eine Zahl ausgegeben, nicht die Elemente selber. Und dann gibt es noch die Fragestellung &amp;quot;Gibt es drei Elemente, deren Summe genau 42 ist?&amp;quot; Hier h&amp;auml;tten wir ein Entscheidungsproblem, es wird nur 0 oder 1 ausgegeben. Aber wie schwer sind die Problemvarianten aus komplexit&amp;auml;tstheoretischer Sicht? Die Antwort ist &amp;quot;meistens sind sie gleich schwer&amp;quot;. Leider eben nur meistens, aber immerhin. Oft kann man in etwa folgeden Argumentationsgang verwenden: Man l&amp;ouml;st das Evaluationsproblem, bekommt damit eine Zahl heraus, z.B. 50 und kann damit auch das Entscheidungsproblem l&amp;ouml;sen. Alle Beziehungen jetzt durch zu exerzieren w&amp;auml;re anstrengend und langweilig, also glaubt mir einfach: Normalereweise sind alle Varianten gleich schwer. Und das bedeutet eigentlich auch nur, dass alle polynomiell schwer sind. Im weiteren Verlauf beschr&amp;auml;nke ich mich deshalb auf Entscheidungsprobleme, denn die jetzt kommenden Komplexit&amp;auml;tsklassen machen nur so Sinn. Und damit ultimativ auch die P vs. NP-Frage.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Zur&amp;uuml;ck zum einseitigen Fehler. Sagen wir, wir h&amp;auml;tten einen Algorithmus der f&amp;uuml;r alle ungeraden Zahlen &amp;quot;1&amp;quot; ausgibt und f&amp;uuml;r alle geraden Zahlen &amp;quot;0&amp;quot;. Der Algorithmus k&amp;ouml;nnte zwei Fehler machen, er k&amp;ouml;nnte f&amp;auml;lschlicherwiese bei ungeraden Zahlen &amp;quot;0&amp;quot; ausgeben oder bei geraden Zahlen eine &amp;quot;1&amp;quot;. Der eine Fehler ist gut und der andere ist schlecht, was an einem anderen Beispiel gut deutlich wird. Wir haben einen Algorithmus, der Bierflaschen auf Verunreinigungen &amp;uuml;berpr&amp;uuml;ft. Schlecht w&amp;auml;re, wenn der Algorithmus &amp;quot;Flasche sauber&amp;quot; (1) ausgibt, wenn in Wirklichkeit eine 0 gefragt w&amp;auml;re. Gut w&amp;auml;re, wenn der Algorithmus &amp;quot;Flasche dreckig&amp;quot; (0) ausgibt, obwohl die Flasche vielleicht doch sauber ist. Ich pers&amp;ouml;nlich habe lieber einen kleinen Produktionsverschlei&amp;szlig; als alte Heroinspritzen in der Flasche.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Also, die erste Art Fehler (die gute Art) ordnet man der Komplexit&amp;auml;tsklasse RP zu, die zweite Art nennt man co-RP. Und nat&amp;uuml;rlich kann man auch hier eine Wahrscheinlichkeit angeben, dass ein Fehler auftritt, streng genommen hei&amp;szlig;en die Klassen also wieder RP(f(n)) bzw co-RP(f(n)). Der probability amplification Trick funktioniert jetzt etwas anders. Wenn der Algorithmus aus RP ist, kann man mit Sicherheit sagen dass eine &amp;quot;1&amp;quot; richtig ist. Wenn wir also jemals eine 1 bekommen, akzeptieren wir die Eingabe als richtig. Wenn es nur Nullen gibt (bei einer Fehlerwahrscheinlichkeit von z.B. 1/2) ist die Wahrscheinlichkeit, dass es immer ein Fehler war genau (1/2)&lt;sup&gt;n&lt;/sup&gt;. Auch hier greift das Prinzip wie bei ZPP: wenn die Fehlerwahrscheinlichkeit &amp;lt;= 1/2 ist, dann kann man die Gesamtfehlerwahrscheinlichkeit durch mehrfaches ausf&amp;uuml;hren exponentiell klein machen. Wir k&amp;uuml;rzen also auch hier wieder ab: RP(1/2)=RP. Au&amp;szlig;erdem ist RP(1)=RP*.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Im &amp;Uuml;brigen ist ZPP eine Teilmenge von RP und von co-RP, denn man k&amp;ouml;nnte einfach einen ZPP-Algorithmus nehmen und jedesmal wenn ein ? ausgegeben wird, einfach irgendwas ausgeben. Damit h&amp;auml;tte man einen einseitigen Fehler gemacht und h&amp;auml;tte nach Definition einen (co-)RP-Algorithmus.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Und damit ist eigentlich erstmal alles gesagt. Wir haben zwei neue Arten Fehler kennengelernt und gesehen, dass auch hier 1/2 als Grenze f&amp;uuml;r die Fehlerwahrscheinlichkeit funktioniert. Im Gegensatz zu ZPP* wird allerdings RP* sehr wichtig, denn &amp;uuml;berraschenderweise ist RP*=NP. Deshalb formuliere ich RP* zum Schluss nochmal aus: RP* ist die Klasse der Algorithmen, die auf einer randomisierten TM in polynomieller Zeit ausgef&amp;uuml;hrt werden k&amp;ouml;nnen und dessen Fehlerwahrscheinlichkeit nicht beschr&amp;auml;nkt ist. Da stellt sich nat&amp;uuml;rlich die Frage, wie wir entscheiden sollen ob wir einen RP(1/4) oder einen RP(3/4) Algorithmus vor uns haben. Wenn wir diesen oft ausf&amp;uuml;hren w&amp;uuml;rden, w&amp;uuml;rde sich entweder der Fehler verst&amp;auml;rken oder egalisieren. Nun, diese praktische irrelevanz zieht sich leider auch durch NP durch, aber dazu im n&amp;auml;chsten Beitrag mehr.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Thu, 12 Apr 2007 10:59:00 +0200</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/26-guid.html</guid>
    <category>algorithmus</category>
<category>cp-RP</category>
<category>fehlerwahrscheinlichkeit</category>
<category>komplexitÃ¤t</category>
<category>komplexitÃ¤tsklasse</category>
<category>millenium-probleme</category>
<category>p vs. np</category>
<category>randomisierung</category>
<category>RP</category>
<category>tm</category>
<category>turing-maschine</category>
<category>zpp</category>

</item>
<item>
    <title>Randomisierung und ZPP</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/22-Randomisierung-und-ZPP.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/22-Randomisierung-und-ZPP.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=22</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=22</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;p&gt;Im Gegensatz zu den bisher betrachteten deterministischen Algorithmen gibt es die so genannten randomisierten Algorithmen. Dazu wird ein Zufallsgenerator benutzt und der weiter Verlauf des Algorithmus von diesem abh&amp;auml;ngig gemacht. In der Realit&amp;auml;t gibt es nat&amp;uuml;rlich Zufallsgeneratoren beliebiger Qualit&amp;auml;t, aber in der Theorie beschr&amp;auml;nken wir uns mal wieder auf das kleinste Vorstellbare: Unser Zufallgsgenerator produziert perfekt zuf&amp;auml;llige Bits. In jedem Rechenschritt genau eins.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Aber vielleicht ist dem ein oder anderen noch nicht einsichtig, warum wir eigentlich randomisierte Algorithmen brauchen, schlie&amp;szlig;lich produzieren sie Fehlerquellen und nehmen uns doch eine gro&amp;szlig;e Portion der Sicherheit, dass der Algorithmus das macht was er soll. Am Besten hilft auch hier ein Beispiel. Wenn beim Quicksort-Algorithmus immer deterministisch das letzte Element als Pivot-Element nimmt und die Eingabe vorsortiert ist, ist die Laufzeit O(n&lt;sup&gt;2&lt;/sup&gt;). Und das wo doch gerade Quicksort normalerweise O(n*log(n)) macht. Da der Speziallfall der sortierten Liste nicht gerade selten vorkommt, ist das Verhalten nat&amp;uuml;rlich sehr ung&amp;uuml;nstig. Und einfach das erste Element als Pivot zu nehmen verschiebt das Problem auch nur. Die L&amp;ouml;sung ist, einfach ein zuf&amp;auml;lliges Element zu w&amp;auml;hlen. Auch da kann es nat&amp;uuml;rlich ganz bl&amp;ouml;d laufen und O(n&lt;sup&gt;2&lt;/sup&gt;) brauchen, aber die Wahrscheinlichkeit ist doch sehr gering, denn dazu m&amp;uuml;sste immer zuf&amp;auml;llig genau das Element gew&amp;auml;hlt werden, das im unsortierten Teil am gr&amp;ouml;&amp;szlig;ten ist. Hier tr&amp;auml;gt randomisierung also dazu bei, dass es in den meisten F&amp;auml;llen eine gute durschnittliche Laufzeit gibt.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Ein anderes prominentes Beispiel ist der Primzahltest von Solovay-Strassen. Hier wird am Anfang eine zuf&amp;auml;llige Zahl gew&amp;auml;hlt und die zu pr&amp;uuml;fende Zahl damit &amp;quot;bearbeitet&amp;quot;. Die genauen Schritte w&amp;auml;ren hier jetzt zu schwierig, aber auch hier ist es praktisch unm&amp;ouml;glich, eine &amp;quot;fest einprogrammierte&amp;quot; Zahl zu finden die man benutzen kann, denn es w&amp;uuml;rde Primzahlen geben, bei denen der Algorithmus immer &amp;quot;dies ist keine Primzahl&amp;quot; sagen w&amp;uuml;rde. Der Algorithmus w&amp;uuml;rde ohne Randomisierung also nichtmal korrekt funktionieren.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Wir sollten uns also dar&amp;uuml;ber einig sein, dass Algorithmen mit einem Zufallselement sinnvoll sind. Wir erweitern unsere Turingmaschine also dahingehend, dass die Zustands&amp;uuml;bergangsfunktion nicht nur davon abh&amp;auml;ngt in welchem Zustand wir sind und welches Zeichen wir lesen, es wird jetzt auch noch in jedem Rechenschritt ein Zufallsbit generiert. Damit verdoppelt sich zwar die Zahl der &amp;Uuml;berg&amp;auml;nge, aber dass Turingmaschinen in der Praxis eh untauglich sind wissen wir ja auch.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Jetzt habe ich ja im letzten Beitrag mit den Komplexit&amp;auml;tsklassen sozusagen die letzte Abstraktionsstufe erreicht und da passt es nat&amp;uuml;rlich nicht, dass wir wieder in die Tiefen der Turingmaschine gehen. Deshalb gibt es nat&amp;uuml;rlich auch randomisierte Komplexit&amp;auml;tsklassen und eine davon besprechen wir jetzt noch kurz, nur um zu sehen wie man Beziehungen zwischen den Klassen herstellt.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Wir definieren: Die Komplexit&amp;auml;tsklasse ZPP(f(n)) umfasst alle Algorithmen, die auf einer randomisierten TM ausgef&amp;uuml;hrt werden k&amp;ouml;nnen und wo die Fehlerwahrscheinlichkeit durch f(n) beschr&amp;auml;nkt ist. Algorithmen in ZPP k&amp;ouml;nnen entweder das richtige Ergebnis oder &amp;quot;?&amp;quot; ausgeben.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Das klingt jetzt vielleicht etwas h&amp;ouml;lzern, eigentlich geht es nur darum, dass ZPP-Algorithmen vielleicht nicht zu einem Ergebnis kommen und dann &amp;quot;keine Ahnung&amp;quot; ausgeben. Wenn es aber ein Ergebnis gibt, ist es sicher richtig. Die Wahrscheinlichkeit dass ein ? ausgegeben wird, ist dabei durch f(n) angegeben und damit gibt es im Prinzip unendlich viele ZPP-Klassen. Es gibt ZPP(1/4), ZPP(1), ZPP(1/2) usw. Dabei ist ZPP(1/4) nat&amp;uuml;rlich eine Untermenge von ZPP(1/2), denn wir hatten ja gesagt, dass die Fehlerwahrscheinlichkeit durch f(n) beschr&amp;auml;nkt ist, es geht also darum, dass f(n) ausdr&amp;uuml;ckt was der schlechteste m&amp;ouml;gliche Fall ist.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Denken wir kurz dar&amp;uuml;ber nach, was ist denn ZPP(0)? Ein randomisierter Algorithmus, der nie einen Fehler macht, also immer das richtige Ergebnis liefert. Klingt nach der Definition von P. Damit ist P=ZPP(0) und damit eine Untermenge von ZPP(f(n)). Was ist ZPP(1)? Komplett sinnlos, denn diese Algorithmen geben immer &amp;quot;?&amp;quot; aus.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Wenn man jetzt noch weiter nachdenken wollte, k&amp;ouml;nnte man darauf kommen, dass man einen ZPP(1/4)-Algorithmus ja auch einfach zweimal laufen lassen kann, dann w&amp;auml;re die Wahrscheinlichkeit f&amp;uuml;r ein ? nur noch 1/16. Was w&amp;uuml;rde uns denn daran hindern, den Algorithmus einfach so oft auszuf&amp;uuml;hren bis wir kein ? mehr bekommen? Doch nur die exponentielle Grenze, denn irgendwann m&amp;uuml;ssen wir den Algorithmus im Wesentlichen exponentiell oft laufen lassen um ein Ergebnis erwarten zu k&amp;ouml;nnen. Das ist der Fall wenn f(n) &amp;gt; 1/2, also k&amp;ouml;nnen wir mit dieser Technik sagen, dass eigentlich alls Algorithmen mit ZPP(1/2) gleich sind. ZPP(1/4), ZPP(1/3) und ZPP(1/2) unterscheiden sich nur dadurch, dass man hier und da eventuell mehrere Durchl&amp;auml;ufe braucht. Da aber die Laufzeit je Durchlauf polynomiell ist, bleibt die Laufzeit insgesamt auch polynomiell. Nur wenn wir eine exponentielle Anzahl von Durchl&amp;auml;ufen brauchen, kommen wir insgesamt auf exponentielle Laufzeit (das ist dann bei f(n)&amp;gt;1/2 der Fall).&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Mit diesem Wissen k&amp;uuml;rzen wir ZPP(1/2)=ZPP ab und erkennen P als kleine Unterklasse von ZPP. ZPP mit Fehlerwahrscheinlichkeit &amp;gt;1/2 nennt man ZPP*, aber diese Klasse ist relativ uninteressant. Im n&amp;auml;chsten Eintrag wird es dann um andere Komplexit&amp;auml;tsklassen gehen, die tats&amp;auml;chlich Fehler machen k&amp;ouml;nnen (im Sinne von: Das Ergebnis kann falsch sein). Und wenn wir diese Klassen kennen und die Verbindung zu Nichtdeterminismus hergestellt haben, k&amp;ouml;nnen wir die P vs. NP-Frage endlich verstehen.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Noch ein letzter Satz, mit dem man auf Partys wunderbar angeben kann: Diese Technik des &amp;quot;mehrfachen Ausf&amp;uuml;hrens&amp;quot; nennt man probability amplification. Wenn man das in einen Satz mit &amp;quot;Komplexit&amp;auml;tstheorie&amp;quot;, &amp;quot;polynomielle Laufzeit&amp;quot; und &amp;quot;randomisierte Turingmaschine&amp;quot; bringt, kann man sicher sein, dass man von allen anderen Partyg&amp;auml;sten bis auf weiteres gemieden wird.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Sun, 08 Apr 2007 12:56:00 +0200</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/22-guid.html</guid>
    <category>algorithmus</category>
<category>determinismus</category>
<category>informatik</category>
<category>komplexitÃ¤t</category>
<category>komplexitÃ¤tsklasse</category>
<category>laufzeit</category>
<category>millenium-probleme</category>
<category>p</category>
<category>p vs. np</category>
<category>randomisierung</category>
<category>tm</category>
<category>turing-maschine</category>
<category>zpp</category>

</item>
<item>
    <title>Komplexitätsklassen</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/19-Komplexitaetsklassen.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/19-Komplexitaetsklassen.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=19</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=19</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;br /&gt;
Ich bin wieder zu Hause und begrüße erstmal alle heise-Leser. Heute geht es um Komplexitätsklassen, im speziellen um &lt;i&gt;P&lt;/i&gt;. &lt;p&gt;Die Komplexitätstheorie ist ein großer Teil der theoretischen Informatik und das Ziel ist, Probleme so zu gruppieren und in Klassen einzuteilen, so dass man die Klassen untereinander vergleichen kann. Wir hatten ja schon über Turingmaschinen gesprochen, außerdem müssten wir inzwischen den Unterschied zwischen einem Problem und einem Algorithmus kennen. &lt;br /&gt;Nehmen wir erst einmal ganz normale Probleme, solche deren Lösung bekannt ist und für die es effiziente Algorithmen gibt. Das Sortierproblem zum Beispiel, oder auch das Suchproblem. Für diese Probleme kennen wir Algorithmen, die polynomielle Rechenzeit haben, also im Wesentlichen effizient sind. All diese Probleme fassen wir zusammen und sagen, sie sind in der der Komplexitätsklasse P. Etwas formaler gesagt sind all die Probleme in P, die auf einer Turingmaschine in polynomieller Zeit berechnet werden können. Und dass Turingmaschinen im Grunde nur minimalistische Computer sind, darüber haben wir ja auch schon gesprochen.&lt;/p&gt;&lt;p&gt;Die Definition einer Komplexitätsklasse ist natürlich relativ willkürlich und ich könnte auch einfach sagen &amp;quot;Ich packe alle Probleme, die einen Algorithmus haben, wo die Turingmaschine eine gerade Anzahl an Schritten macht in eine Klasse und nenne sie QWERTZ.&amp;quot; Das würde nur nicht viel Sinn machen, weil das keine wirklich relevante Eigenschaft ist. Deshalb würde QWERTZ schlicht nicht benutzt und schnell in der Versenkung verschwinden. Es gibt aber auch relevante Subklassen von P, zum Beispiel L. In L sind alle Probleme, die von einer TM geöst werden können, die einen endlichen Speicher hat (Wir erinnern uns: Eine TM hat formal unendlichen Speicher).&lt;/p&gt;&lt;p&gt;Mit dem Begriff der Komplexitätsklassen haben wir erstmal zu Ende abstrahiert. Wir sind angefangen mit Betrachtungen von Algorithmen, der O-Notation, haben festgestellt dass man Zwecks besserer Vergleichbarkeit zu Turingmaschinen abstrahiert. Dann haben wir irgendwann nur noch zwischen polynomiellen und exponentiellen Laufzeiten unterschieden und jetzt teilen wir die Probleme auch noch in Klassen ein und argumentieren nur noch über diese Klassen und nicht mehr über einzelne Probleme. &lt;/p&gt;&lt;p&gt;Schön, im nächsten Schritt schauen wir uns randomisierte Algorithmen an und definieren dafür einige Komplexitätsklassen. Damit nähern wir uns dann der Frage was NP ist und schließlich wird dann das P vs. NP Problem klar.&lt;br /&gt; &lt;/p&gt; 
    </content:encoded>

    <pubDate>Sun, 01 Apr 2007 20:03:41 +0200</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/19-guid.html</guid>
    <category>algorithmus</category>
<category>determinismus</category>
<category>komplexitã¤t</category>
<category>komplexitã¤tsklasse</category>
<category>millenium-probleme</category>
<category>p</category>
<category>p vs. np</category>
<category>tm</category>
<category>turing-maschine</category>

</item>
<item>
    <title>Polynomiell vs. exponentiell</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/11-Polynomiell-vs.-exponentiell.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/11-Polynomiell-vs.-exponentiell.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=11</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=11</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;br /&gt;
&lt;p&gt;Ich hatte ja schon über die O-Notation gesprochen und schon angedeutet, dass wir nur im wesentlichen polynomielle und exponentielle Laufzeiten auseinander halten wollen. Die Grafik im betreffenden Post war ja schon ganz anschaulich, aber ich will es doch noch ein bisschen plastischer machen um auch die praktisch veranlagten zu überzeugen. &lt;/p&gt;&lt;p&gt;Ich habe ein paar Tests laufen lassen und habe einen kleinen, sinnlosen Algorithmus in Python geschrieben. Dieser füllt ein Array und macht nichts weiter außer ein paar überflüssigen Additionen. Für ein Array der Größe 100 braucht dieser &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28n%5E3%29&quot; title=&quot;O(n^3)&quot; alt=&quot;O(n^3)&quot; \/&gt; Algorithmus ziemlich genau eine Sekunde CPU-Zeit. Natürlich interessiert uns dabei die absolute Zahl überhaupt nicht, mir ist klar dass C schneller wäre und es schnellere Prozessoren gäbe. Das ist sozusagen die Pointe des Ganzen: Uns ist völlig egal, ob es zwei oder hundert Sekunden sind, es geht darum ob es einen andere Algorithmus gibt, der bei gleichen Vorraussetzungen schneller ist. Genau deshalb benutzen wir Turingmaschinen, damit die Voraussetzungen gleich sind. &lt;/p&gt;&lt;p&gt;Aber ich schweife ab. Mein Algorithmus braucht also eine Sekunde für n=100. Das bedeutet für 100&lt;sup&gt;3 &lt;/sup&gt;&amp;quot;Schritte&amp;quot; braucht mein Computer eine Sekunde. Erhöhen wir mal auf n=1000, da wären wir bei runden 17 Minuten für 1000&lt;sup&gt;3 &lt;/sup&gt;Schritte. Das ist schon nicht mehr ganz wenig. Für n=10000 allerdings wären wir bereits bei guten 31000 &lt;b&gt;Jahren&lt;/b&gt;. Das ist bereits utopisch für den realen Einsatz, aber wie siehts denn im Vergleich mit &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%282%5En%29&quot; title=&quot;O(2^n)&quot; alt=&quot;O(2^n)&quot; \/&gt; aus?&lt;/p&gt;&lt;p&gt;Für n=10 haben wir noch überschaubare 17 Sekunden, aber da hört es auch schon auf. Wir erinnern uns: beim &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28n%5E3%29&quot; title=&quot;O(n^3)&quot; alt=&quot;O(n^3)&quot; \/&gt; Algorithmus brauchte mein Computer für n=100 eine Sekunde. Bei &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%282%5En%29&quot; title=&quot;O(2^n)&quot; alt=&quot;O(2^n)&quot; \/&gt; sind es 40196936841331475186983 Jahre. Und das für n=100, was für reale Anwendungen noch sehr wenig ist. Schon die Laufzeit für n=1000 wäre unvorstellbar groß. &lt;/p&gt;&lt;p&gt;Man zieht also die Grenze da, wo das n im Exponent steht. Das führt natürlich auch zu Ungenauigkeiten, so wäre &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28n%5E%7B300%7D%29&quot; title=&quot;O(n^{300})&quot; alt=&quot;O(n^{300})&quot; \/&gt; in Ordnung, während &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%282%5E%7B%280.001%2An%29%2F10%5E5%7D%29&quot; title=&quot;O(2^{(0.001*n)/10^5})&quot; alt=&quot;O(2^{(0.001*n)/10^5})&quot; \/&gt; exponentielles Wachstum hat, wobei es für alle praktischen Werte langsamer wächst als die erste Funktion. Trotzdem ist hier eben die Grenze, die nicht mehr ganz so an den Haaren herbei gezogen wirkt, wenn wir erstmal wissen, was NP genau ist. Im Moment jedoch müssen wir einfach mal akzeptieren dass polynomielle Laufzeit okay ist, während ein n im Exponent nicht okay ist. &lt;/p&gt; 
    </content:encoded>

    <pubDate>Thu, 22 Mar 2007 20:48:00 +0100</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/11-guid.html</guid>
    <category>algorithmus</category>
<category>determinismus</category>
<category>millenium-probleme</category>
<category>o-notation</category>
<category>p vs. np</category>
<category>turing-maschine</category>

</item>
<item>
    <title>Turingmaschinen</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/7-Turingmaschinen.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/7-Turingmaschinen.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=7</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=7</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;p&gt;Im letzten Beitrag hatte ich ja erkl&amp;auml;rt, dass man Algorithmen &amp;auml;u&amp;szlig;erst weit abstrahiert um sie vergleichen zu k&amp;ouml;nnen. Das lag daran, dass man bestimmte Faktoren einfach nicht einbeziehen darf, weil sonst nicht mehr Algorithmen verglichen werden w&amp;uuml;rden, sondern CPU-Power oder Betriebssysteme. Wir haben das gemacht, um sp&amp;auml;ter &amp;uuml;berhaupt eine Argumentationsbasis zu haben. Wenn wir sowas sagen wie &amp;quot;Das Problem A l&amp;ouml;sen wir mit Algorithmus B in O(log(n))&amp;quot;, dann geht das nur weil wir uns &amp;uuml;berhaupt auf die O-Notation und deren Vergleichbarkeit geeinigt haben. Jetzt liegt es nat&amp;uuml;rlich nahe ein m&amp;ouml;glichst allgemeing&amp;uuml;ltiges Computermodell zu entwickeln, um eben diese Vergleichbarkeit zu erreichen.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Das was man &amp;uuml;blicherweise benutzt ist die sogenannte Turingmaschine (kurz: TM). Diese wurde 1936 von Alan Turing entwickelt, was insofern bemerkenswert ist, als dass es da noch keine echten Rechner gab. Ich nehme mal die &amp;quot;Aufl&amp;ouml;sung&amp;quot; vorweg: Turingmaschinen bilden genau unsere aktuellen Rechner ab, d.h. man kann Algorithmen mit akzeptablem Aufwand von einem Athlon64 zu einer Turingmaschine &amp;uuml;bertagen. Was ein akzeptabler Aufwand ist, dar&amp;uuml;ber handelt der n&amp;auml;chste Beitrag. Und dass sich keiner wirklich die M&amp;uuml;he macht, TM-Programme zu schreiben, soviel sei auch schon gesagt. Das ist auch nicht n&amp;ouml;tig. Wichtig ist, dass man damit eine gemeinsame Argumentationsbasis hat. Dann schauen wir uns Turingmaschinen also mal konkret an.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
&lt;!-- s9ymdb:5 --&gt;&lt;img width=&quot;377&quot; height=&quot;233&quot; alt=&quot;&quot; style=&quot;border: 0px none ; float: left; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://zufallsbit.de/blog/uploads/tm1.png&quot; /&gt;&lt;br /&gt;&lt;br /&gt;
Jedes dieser Zellen steht f&amp;uuml;r eine Speichereinheit, die Punkte links und rechts deuten an, dass die Speichergr&amp;ouml;&amp;szlig;e unendlich ist (den Speicher nennt man &amp;quot;das Band&amp;quot;). Das macht f&amp;uuml;r uns erstmal keine Probleme, auch wenn es nat&amp;uuml;rlich m&amp;ouml;glicherweise nicht &lt;em&gt;komplett&lt;/em&gt; realistisch ist. Die TM hat eine Startposition, auf der hier der Lese/Schreibkopf steht. Dieser kann sich in jedem Rechenschritt entweder nach links oder rechts bewegen, oder dort bleiben wo er gerade ist. Der Rechenschritt l&amp;auml;uft so ab: Der Kopf liest die aktuelle Zelle, berechnet die Ausgabe, schreibt etwas in die aktuelle Zelle und bewegt sich.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Aber wie berechnet die TM die Ausgabe? Daf&amp;uuml;r gibt es die Menge der Zust&amp;auml;nde &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=Q%3D%7Bq_0%2Cq_1%2Cq_2%2C...%2Cq_n%7D&quot; title=&quot;Q={q_0,q_1,q_2,...,q_n}&quot; alt=&quot;Q={q_0,q_1,q_2,...,q_n}&quot; \/&gt;. F&amp;uuml;r jedes m&amp;ouml;gliche Symbol, das auf dem Band steht, definiert man jetzt einen Zustands&amp;uuml;bergang. Am Anfang ist man im Zustand &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=q_0&quot; title=&quot;q_0&quot; alt=&quot;q_0&quot; \/&gt;, und f&amp;uuml;r jedes Symbol (&amp;uuml;blicherweise 0 oder 1) sagt man sowas wie &amp;quot;wenn 0 gelesen wird, schreibe ein Leerzeichen (auch &amp;quot;B&amp;quot; f&amp;uuml;r &amp;quot;Blank&amp;quot; genannt) und bewege dich nach rechts&amp;quot;. Oder &amp;quot;wenn 1 gelesen wird, schreibe die 1 zur&amp;uuml;ck und bewege dich nach links&amp;quot;. Die Bewegung wird gerne mit -1 (links), 0 (stehen bleiben) und 1 (rechts) bezeichnet. Aber auch L,0,R ist &amp;uuml;blich.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Vielleicht macht ein Beispiel das etwas klarer. Sagen wir, auf dem Band steht &amp;quot;010011&amp;quot; und wir wollen alle nullen l&amp;ouml;schen. Wir sind ja im Zustand &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=q_0&quot; title=&quot;q_0&quot; alt=&quot;q_0&quot; \/&gt;, wenn wir hier eine null lesen, l&amp;ouml;schen wir sie und gehen weiter. Also &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=%5C%7Bq_0%2C0%5C%7D%5Crightarrow%5C%7Bq_0%2CB%2C1%5C%7D&quot; title=&quot;\{q_0,0\}\rightarrow\{q_0,B,1\}&quot; alt=&quot;\{q_0,0\}\rightarrow\{q_0,B,1\}&quot; \/&gt; In der ersten Klammer stehen der Zustand in dem wir uns befinden und das gelesene Zeichen. Der Pfeil deutet den Zustands&amp;uuml;bergang an, man kann das so lesen: &amp;quot;Wenn wir uns in &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=q_0&quot; title=&quot;q_0&quot; alt=&quot;q_0&quot; \/&gt; befinden und 0 lesen, gehe nach &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=q_0&quot; title=&quot;q_0&quot; alt=&quot;q_0&quot; \/&gt;, schreibe ein Blank und gehe 1 weiter&amp;quot;.  Was passiert aber wenn 1 gelesen wird? Nun, das m&amp;uuml;ssen wir auch definieren, n&amp;auml;mlich so:&lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=%5C%7Bq_0%2C1%5C%7D%5Crightarrow%5C%7Bq_0%2C1%2C1%5C%7D&quot; title=&quot;\{q_0,1\}\rightarrow\{q_0,1,1\}&quot; alt=&quot;\{q_0,1\}\rightarrow\{q_0,1,1\}&quot; \/&gt; . Wenn eine 1 gelesen wird, schreiben wir sie zur&amp;uuml;ck und gehen weiter. Der letzte Zeichen das gelesen werden kann ist das Leerzeichen B: &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=%5C%7Bq_0%2CB%5C%7D%5Crightarrow%5C%7Bq_0%2CB%2C0%5C%7D&quot; title=&quot;\{q_0,B\}\rightarrow\{q_0,B,0\}&quot; alt=&quot;\{q_0,B\}\rightarrow\{q_0,B,0\}&quot; \/&gt;. Wenn das B gelesen wird  sind wir logischerweise am Ende angekommen, also schreiben wir das B zur&amp;uuml;ck und bleiben wo wir sind.  Jetzt w&amp;uuml;rde die TM unendlich weiter rechnen, diesen Umstand interpretieren wir als &amp;quot;wir haben zu Ende gerechnet&amp;quot;. Diese drei Regeln sind sozusagen die Programmierung der Turingmaschine. Wichtig ist, dass man f&amp;uuml;r jedes Zeichen, das auf dem Band vorkommen kann auch einen Zustands&amp;uuml;bergang definiert.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Das war jetzt kein Entscheidungsproblem, wenn man ein solches hat, wird normalerweise gefordert, dass man die Eingabe komplett l&amp;ouml;scht und eine 0 oder 1 (wahr oder falsch) an die erste Position schreibt. Im obigen Beispiel kamen wir mit einem Zustand aus, normalerweise hat man mehrere. Man kann sich z.B. leicht vorstellen, dass man z&amp;auml;hlen will, ob auf dem Band genau so viele einsen wie nullen stehen. Dann w&amp;uuml;rde man z.B. eine null lesen, in Zustand &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=q_1&quot; title=&quot;q_1&quot; alt=&quot;q_1&quot; \/&gt; gehen, so lange weiter gehen bis man eine 1 findet, wieder in &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=q_0&quot; title=&quot;q_0&quot; alt=&quot;q_0&quot; \/&gt; gehen und  so weiter. Der Fakt, dass man in &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=q_1&quot; title=&quot;q_1&quot; alt=&quot;q_1&quot; \/&gt; ist, w&amp;uuml;rde anzeigen, dass man eine null gelesen hat und nach einer eins sucht.  Zugegeben, es w&amp;auml;re ein bisschen komplizierter als das, denn wir m&amp;uuml;ssten nat&amp;uuml;rlich auch noch zur&amp;uuml;ck laufen, weil man potentiell ein paar Zahlen &amp;uuml;berspringt beim &amp;quot;nach einer 1 suchen&amp;quot;. Jetzt sollte auch klar sein, warum kaum einer Algorithmen auf TMs schreibt. Man stelle sich einen Sortieralgorithmus vor und die wahnsinnige Anzahl der Zust&amp;auml;nde die man br&amp;auml;uchte. Man kann aber zeigen, dass alle Algorithmen auf normalen Computern prinzipiell auch auf TMs berechnen k&amp;ouml;nnte, man kann also ohne Probleme TMs als Argumentationsbasis nehmen, denn hier gibt es keine Variablen wie CPU-Geschwindigkeit.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Formal ist eine TM ein Tupel: &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=M%3D%28Q%2C%5CSigma%2C%5CGamma%2C%5Cdelta%2Cq_0%29&quot; title=&quot;M=(Q,\Sigma,\Gamma,\delta,q_0)&quot; alt=&quot;M=(Q,\Sigma,\Gamma,\delta,q_0)&quot; \/&gt;&lt;br /&gt;&lt;br /&gt;
Hierbei steht Q f&amp;uuml;r die Menge der Zust&amp;auml;nde, das Sigma f&amp;uuml;r das Eingabealphabet. Das Gamma steht f&amp;uuml;r das Bandalphabet (normalerweise ist das das Eingabealphabet plus das B). Das delta ist die Zustands&amp;uuml;bergangsfunktion, beschreibt also mathematisch, was die TM macht. Zuletzt muss noch der Startzustand angegeben werden.&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
Turingmaschinen sind f&amp;uuml;r das P vs. NP Problem zugegebenerma&amp;szlig;en nicht wahnsinnig wichtig. Sp&amp;auml;ter definieren wir noch eine nichtdeterministische TM, aber eigentlich muss man sich nur einig sein, dass man ein Computermodell hat, dass Vergleichbarkeit sicherstellt. Wer sich wirklich mit TMs auseinandersetzen will, dem seien die Stichworte Automatentheorie und Chomsky-0 ans Herz gelegt.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Fri, 16 Mar 2007 12:43:00 +0100</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/7-guid.html</guid>
    <category>determinismus</category>
<category>informatik</category>
<category>millenium-probleme</category>
<category>p vs. np</category>
<category>tm</category>
<category>turing-maschine</category>

</item>
<item>
    <title>O-Notation</title>
    <link>http://zufallsbit.de/blog/index.php?/archives/3-O-Notation.html</link>
            <category>Millenium-Probleme</category>
            <category>P vs. NP</category>
    
    <comments>http://zufallsbit.de/blog/index.php?/archives/3-O-Notation.html#comments</comments>
    <wfw:comment>http://zufallsbit.de/blog/wfwcomment.php?cid=3</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://zufallsbit.de/blog/rss.php?version=2.0&amp;type=comments&amp;cid=3</wfw:commentRss>
    

    <author>nospam@example.com (Turing)</author>
    <content:encoded>
    &lt;br /&gt;
&lt;p&gt;Hier also der erste Beitrag mit Substanz, es geht um die O-Notation. Das werden wir brauchen um uns zu überlegen, was effektive Algorithmen sind und was nicht. Ein Algorithmus ist übrigens eine Abfolge von Schritten, um ein gegebenes Problem zu lösen. Es liegt natürlich nahe, einen Algorithmus in ein Computerprogramm zu verpacken, das ist aber nicht zwingend nötig für eine Laufzeitberechnung. &lt;/p&gt;&lt;p&gt;Womit wir schon beim Thema wären, denn Algorithmen lassen sich nicht exakt vergleichen, dafür gibt es einfach zu viele unbekannte Faktoren. Zum Beispiel ist eine Implementierung in C sicher schneller als in Ruby, es sei denn der Programmierer baut großen Mist. Vielleicht benutzt der eine Programmierer noch einen Pentium 3, während der nächste auf einem Athlon64 sitzt und deshalb besser mit großen Zahlen rechnen kann. Oder vielleicht implementiert die Standard-Library von Betriebssystem A die verkettete Liste etwas langsamer als System B. Kurz gesagt, diese ganzen Unwägbarkeiten müssen raus und man muss sich Zwecks Vergleichbarkeit auf das absolute Minimum eines Algorithmus beschränken. Das wäre eben die Beschreibung der nötigen Schritte pro Element. Formal braucht man auch immer eine Eingabe und Ausgabe dazu, bei der Ausgabe kann man sich aber oft auf &amp;quot;wahr&amp;quot; oder &amp;quot;falsch&amp;quot; beschränken, wie wir später sehen werden.&lt;/p&gt;&lt;p&gt;Ein Beispiel:&lt;br /&gt;Problemstellung: Ich will möglichst betrunken werden.&lt;br /&gt;Erwartete Ausgabe: &amp;quot;wahr&amp;quot; (Ziel erreicht) oder &amp;quot;falsch&amp;quot; (Bier leer)&lt;br /&gt;Algorithmus:&lt;br /&gt;- Aufstehen&lt;br /&gt;- Zum Kühlschrank gehen&lt;br /&gt;- Bier nehmen&lt;br /&gt;- Zum Sessel gehen&lt;br /&gt;- Setzen&lt;/p&gt;&lt;p&gt;Sagen wir, Schritt 1, 3 und 5 brauchen &amp;quot;eine Zeiteinheit&amp;quot;, 2 und 4 brauchen jeweils drei. Pro Bier brauchen wir also neun Schritte, ganz unabhängig davon z.B. welche Biermarke wir haben. Um das Ziel des Algorithmus zu erreichen brauchen wir also ganz allgemein 9*n Schritte, wobei &amp;quot;n&amp;quot; die Anzahl Bier ist, bis man komplett dicht ist (und das variiert von Person zu Person, was hier die &amp;quot;Eingabe&amp;quot; wäre). Aber wie relevant ist die neun denn wirklich? Was, wenn wir einfach den Alkoholgehalt pro Flasche verdoppeln? Dann bräuchten wir nur noch 4,5*n Schritte. Man könnte auch weitere Laufzeitverbesserungen vornehmen indem man zwei Bier pro Lauf mitnimmt, dann wären wir bei &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=%284.5%2F2%29%2An&quot; title=&quot;(4.5/2)*n&quot; alt=&quot;(4.5/2)*n&quot; \/&gt; Schritten. Es stellt sich heraus dass das &amp;quot;n&amp;quot; immer mit im Term steht, also müssen wir weiter abstrahieren und das &amp;quot;n&amp;quot; als Maßstab für die Güte des Algorithmus nehmen. Wir vergessen einfach den Faktor davor und sagen O(n) dazu. Das bedeutet dann soviel wie &amp;quot;der Algorithmus hat im Wesentlichen eine Laufzeit von n&amp;quot;. n ist allgemein die Eingabelänge, üblicherweise ist das eine Array der Größe n oder ähnliches. Man muss sich das mal für sehr große n überlegen. Je größer das n wird, desto kleiner wird der Unterschied, den Faktoren ausmachen und umso größer wird der Einfluss des n.&lt;/p&gt;&lt;p&gt;Dazu auch ein Beispiel: Wir vergleichen &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=10%2An%20%2B%2020&quot; title=&quot;10*n + 20&quot; alt=&quot;10*n + 20&quot; \/&gt; und &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=1%2F2%2An%5E2&quot; title=&quot;1/2*n^2&quot; alt=&quot;1/2*n^2&quot; \/&gt;. Für n=5 braucht der erste Algorithmus 70 Schritte, der zweite 12,5. Man könnte auf die Idee kommen, doch den zweiten einzusetzen, aber schon bei n=100 haben wir 1020 bzw. 5000 Schritte. &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=n%5E2&quot; title=&quot;n^2&quot; alt=&quot;n^2&quot; \/&gt; wächst eben sehr viel schneller als n, deshalb klassifiziert man den ersten Algorithmus als &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28n%29&quot; title=&quot;O(n)&quot; alt=&quot;O(n)&quot; \/&gt; und den zweiten als &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28n%5E2%29&quot; title=&quot;O(n^2)&quot; alt=&quot;O(n^2)&quot; \/&gt;. Wenn man das jetzt mathematischer formulieren würde, könnte man sehen, dass sogar &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=n%5E2%20%2B%207%2An%20%3D%20O%28n%5E2%29&quot; title=&quot;n^2 + 7*n = O(n^2)&quot; alt=&quot;n^2 + 7*n = O(n^2)&quot; \/&gt;, es zählt also nur der höchste Exponent, bzw. der Term, in dem n am schnellsten wächst.&lt;/p&gt;&lt;p&gt;Übrigens umfasst das &amp;quot;O&amp;quot; auch andere Laufzeiten, gibt damit sozusagen eine obere Schranke an. Wenn man O(n) schreibt, meint man &amp;quot;Der Algorithmus schafft das Problem in linearer Zeit, obwohl es vielleicht spezielle Eingabe gibt, wo er nach einem Schritt fertig ist.&amp;quot; In jedem Fall aber braucht er nicht länger als Linearzeit. Wenn man eine genaue Aussage treffen will nimmt man &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=%5CTheta%28n%29&quot; title=&quot;\Theta(n)&quot; alt=&quot;\Theta(n)&quot; \/&gt; und meint &amp;quot;Der Algorithmus braucht für jede Eingabe im wesentlichen Linearzeit&amp;quot;. &lt;/p&gt;&lt;p&gt;Wichtige Laufzeiten sind z.B. &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%281%29&quot; title=&quot;O(1)&quot; alt=&quot;O(1)&quot; \/&gt;,&lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28n%29&quot; title=&quot;O(n)&quot; alt=&quot;O(n)&quot; \/&gt;,&lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28n%5E2%29&quot; title=&quot;O(n^2)&quot; alt=&quot;O(n^2)&quot; \/&gt;,&lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28log%28n%29%29&quot; title=&quot;O(log(n))&quot; alt=&quot;O(log(n))&quot; \/&gt;,&lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%28n%2Alog%28n%29%29&quot; title=&quot;O(n*log(n))&quot; alt=&quot;O(n*log(n))&quot; \/&gt; oder &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=O%282%5En%29&quot; title=&quot;O(2^n)&quot; alt=&quot;O(2^n)&quot; \/&gt;&lt;/p&gt;&lt;p&gt;Dabei bedeutet O(1) nicht, dass in jedem Fall nur ein Schritt nötig ist, es können auch 10000 Schritte nötig sein. In jedem Fall muss die Anzahl der Schritte konstant sein um O(1) genannt werden zu dürfen. Um ein Gefühl für das Wachstumsverhalten zu bekommen, hier zum Schluss nochmal ein Plot der Funktionen.&lt;/p&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://zufallsbit.de/blog/uploads/plot1.gif&quot; class=&quot;serendipity_image_link&quot;&gt;&lt;!-- s9ymdb:2 --&gt;&lt;img width=&quot;110&quot; height=&quot;87&quot; src=&quot;http://zufallsbit.de/blog/uploads/plot1.serendipityThumb.gif&quot; style=&quot;border: 0px none ; float: left; padding-left: 5px; padding-right: 5px;&quot; /&gt;&lt;/a&gt;Hier sieht zugegebenermaßen der Plot für &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=2%5En&quot; title=&quot;2^n&quot; alt=&quot;2^n&quot; \/&gt; nicht besonders beeindruckend aus, aber wie schon erwähnt kommt es vor allem aufs Wachstumsverhalten an, und das betrachtet man in der Regel für große n. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;http://zufallsbit.de/blog/uploads/plot2.gif&quot; class=&quot;serendipity_image_link&quot;&gt;&lt;!-- s9ymdb:3 --&gt;&lt;img width=&quot;110&quot; height=&quot;91&quot; src=&quot;http://zufallsbit.de/blog/uploads/plot2.serendipityThumb.gif&quot; style=&quot;border: 0px none ; float: left; padding-left: 5px; padding-right: 5px;&quot; /&gt;&lt;/a&gt; &lt;br /&gt;
Hier noch ein Plot, diesmal &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=2%5En&quot; title=&quot;2^n&quot; alt=&quot;2^n&quot; \/&gt; vs. &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=n%5E%7B10%7D&quot; title=&quot;n^{10}&quot; alt=&quot;n^{10}&quot; \/&gt;. Und das sind nichteinmal besonders große n, sondern irgendetwas zwischen 60 und 70. Man stelle sich das mal für n&amp;gt;1000 vor. Und schaut euch mal dem Maßstab an der y-Achse an.&lt;/p&gt;&lt;p /&gt;&lt;p&gt;Fassen wir also zusammen: Um Algorithmen zu vergleichen abstrahiert man so viel wie möglich, lässt im wesentlichen alle nicht relevanten Terme weg und betrachtet nur den Teil des Algorithmus, der am schnellsten wächst. Und weil ihr bis hier durchgehalten habt, kommt hier der Clou: Eigentlich interessiert nur, ob das n im Exponent steht oder nicht. &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=n%5E2&quot; title=&quot;n^2&quot; alt=&quot;n^2&quot; \/&gt; oder &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=n%5E%7B100%7D&quot; title=&quot;n^{100}&quot; alt=&quot;n^{100}&quot; \/&gt;? Egal, kommt aufs gleiche raus. Aber &lt;img src=&quot;http://zufallsbit.de/blog/index.php?/plugin/mimetex.php?q=%7B0.1%7D%5E%7Bn%2F100%7D&quot; title=&quot;{0.1}^{n/100}&quot; alt=&quot;{0.1}^{n/100}&quot; \/&gt;? Böse! Warum das so ist, soll jetzt erstmal egal sein. Wichtig ist nur, dass es in der Praxis höchst wichtig ist ob man O(n) oder O(n*log(n)) hat, in der Theorie nicht.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Tue, 06 Mar 2007 11:50:48 +0100</pubDate>
    <guid isPermaLink="false">http://zufallsbit.de/blog/index.php?/archives/3-guid.html</guid>
    <category>algorithmus</category>
<category>laufzeit</category>
<category>millenium-probleme</category>
<category>notation</category>
<category>o-notation</category>
<category>p vs. np</category>
<category>wachstum</category>

</item>

</channel>
</rss>