<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PhiLIOsoph &#187; Python</title>
	<atom:link href="http://www.robertnitsch.de/category/programmieren/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.robertnitsch.de</link>
	<description>Ansichten, Erlebnisse und Werke eines Heranwachsenden</description>
	<lastBuildDate>Tue, 20 Jul 2010 19:27:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>RFA: Ein rekursiver Algorithmus für das metrische Traveling-Salesman-Problem</title>
		<link>http://www.robertnitsch.de/2010/01/14/rfa-ein-rekursiver-algorithmus-fur-das-metrische-traveling-salesman-problem/</link>
		<comments>http://www.robertnitsch.de/2010/01/14/rfa-ein-rekursiver-algorithmus-fur-das-metrische-traveling-salesman-problem/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 20:30:04 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Freaky]]></category>
		<category><![CDATA[Informatik]]></category>
		<category><![CDATA[Mathematik]]></category>
		<category><![CDATA[PC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Schule]]></category>
		<category><![CDATA[Studium]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/?p=483</guid>
		<description><![CDATA[In diesem Artikel stelle ich einen rekursiven Algorithmus namens RFA für das metrische bzw. geometrische Traveling-Salesman-Problem (Problem des Handlungsreisenden, auch genannt Rundreiseproblem) vor. Idee &#038; Umsetzung stammen von mir; bei meiner Recherche habe ich den Algorithmus nicht finden können. Ich gehe daher vorläufig davon aus, dass ich der erste damit bin. Bei dem hier betrachteten [...]]]></description>
			<content:encoded><![CDATA[<p>In diesem Artikel stelle ich einen rekursiven Algorithmus namens <strong>RFA</strong> für das metrische bzw. geometrische <a href="http://de.wikipedia.org/wiki/Problem_des_Handlungsreisenden" rel="nofollow" class="liwikipedia">Traveling-Salesman-Problem</a> (<em>Problem des Handlungsreisenden</em>, auch genannt <em>Rundreiseproblem</em>) vor. Idee &#038; Umsetzung stammen von mir; bei meiner Recherche habe ich den Algorithmus nicht finden können. Ich gehe daher vorläufig davon aus, dass ich der erste damit bin. <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Bei dem hier betrachteten Traveling-Salesman-Problem geht es darum, eine möglichst kostengünstige Rundreise durch eine gegebene Menge an &#8220;Städten&#8221; (ich werde bei der Terminologie &#8220;Stadt&#8221; bleiben) zu finden, wobei jede Stadt genau 1 Mal besucht werden muss. Jede Wegstrecke zwischen 2 Städten ist mit bestimmten Reisekosten verbunden. In dem von mir gemeinten Fall des metrischen TSP entsprechen die Reisekosten genau der Luftlinie zwischen den beiden Städten. Daher habe ich die Städte der Einfachheit halber als Punkte in der Ebene modelliert (mit einer X- und einer Y-Koordinate), womit bereits erste Experimente möglich sind.</p>
<h3>Phase 1: Reduktion auf den Trivialfall des TSP</h3>
<div id="attachment_484" class="wp-caption alignright" style="width: 228px"><a href="http://www.robertnitsch.de/wp-content/uploads/2010/01/00_TSP_Trivialfall.png" class="liimagelink"><img src="http://www.robertnitsch.de/wp-content/uploads/2010/01/00_TSP_Trivialfall.png" alt="TSP - Trivialfall mit nur 3 Städten" title="00_TSP_Trivialfall" width="218" height="201" class="size-full wp-image-484" /></a><p class="wp-caption-text">TSP - Trivialfall mit nur 3 Städten</p></div>
<p>Mein Algorithmus greift darauf zurück, dass das Rundreiseproblem für 3 Städte trivial ist, weil es nur 1 mögliche Rundreise durch 3 Städte gibt (siehe Grafik auf der rechten Seite).</p>
<p>Bei 1-3 Städten kann der Algorithmus daher direkt die Lösung zurückgeben, weil sie offensichtlich ist.</p>
<p>Bei mehr als 3 Städten arbeitet der Algorithmus in 2 Phasen.</p>
<p>In der 1. Phase werden die gegebenen Städte solange gefaltet, bis nur noch 3 Städte übrig sind.</p>
<p>Es werden jeweils 2 Städte gefaltet. Das sieht so aus, dass eine neue fiktive Stadt erzeugt wird, deren Koordinate gleich dem Mittelpunkt/Zentrum der 2 gefalteten Städte ist. Die 2 gefalteten Städte werden dann durch die neue fiktive Stadt <em>ersetzt</em>, wobei sich die fiktive Stadt ihre &#8220;Vorbilder&#8221; (<em>&#8220;Kind-Städte&#8221;</em>) merkt. Dadurch wird das Falten zugleich umkehrbar.</p>
<p>Eine naive Implementierung sieht zum Beispiel so aus, dass in jedem Schritt <em>zufällig</em> eine Stadt ausgewählt und ihr nächster Nachbar berechnet wird. Diese beiden Städte werden dann gefaltet. Der Vorgang wird so lange wiederholt, bis wie gesagt nur noch 3 Städte übrig sind. Fiktive Städte können genauso gefaltet werden wie die Ursprungs-Städte. (Dadurch ergibt sich je nach Anzahl der Städte eine beliebig tiefe &#8220;Verschachtelung&#8221;.)</p>
<div style="clear:both;"></div>
<h3>Phase 2: Entfalten der Städte mit optimaler Integration der Kind-Städte</h3>
<p>Nach der 1. Phase sind wir also beim Trivialfall mit 3 Städten angekommen. Das ist auch schon unsere vorläufige Lösung bzw. die vorläufige Rundreise.</p>
<p>In der 2. Phase werden die fiktiven Städte wieder entfaltet, wobei die vorläufige Rundreise bei jedem Schritt erhalten wird.</p>
<div id="attachment_487" class="wp-caption alignright" style="width: 228px"><a href="http://www.robertnitsch.de/wp-content/uploads/2010/01/01_TSP_Entfalten1.png" class="liimagelink"><img src="http://www.robertnitsch.de/wp-content/uploads/2010/01/01_TSP_Entfalten1.png" alt="" title="01_TSP_Entfalten1" width="218" height="201" class="size-full wp-image-487" /></a><p class="wp-caption-text">TSP - Fiktive Stadt (blau) mit Kind-Städten (rot) in einer vorläufigen Rundreise zu Beginn von Phase 2</p></div>
<p>Betrachten wir die Grafik auf der rechten Seite. Nehmen wir an die beiden rot markierten Städte seien die Kind-Städte der blau markierten fiktiven Stadt. (Wie man auch gut sehen kann befindet sich die blaue Stadt genau im Zentrum ihrer beiden Kind-Städte.)</p>
<p>Wenn die fiktive Stadt nun in Phase 2 durch ihre Kinder ersetzt wird, dann gibt es genau 2 Möglichkeiten, wie man die beiden Kind-Städte in die gegebene Rundreise integrieren kann. Dazu muss man sich die blaue Stadt wegdenken, denn diese existiert dann ja nicht mehr.</p>
<div style="clear:both;"></div>
<div id="attachment_594" class="wp-caption alignright" style="width: 228px"><a href="http://www.robertnitsch.de/wp-content/uploads/2010/01/02_TSP_Entfalten2.png" class="liimagelink"><img src="http://www.robertnitsch.de/wp-content/uploads/2010/01/02_TSP_Entfalten2.png" alt="TSP - Entfalten mit beiden Integrationsmöglichkeiten" title="02_TSP_Entfalten2" width="218" height="201" class="size-full wp-image-594" /></a><p class="wp-caption-text">TSP - Entfalten mit beiden Integrationsmöglichkeiten (grün = die bessere Variante)</p></div>
<p>Auf dem nächsten Bild sind die beiden Möglichkeiten eingezeichnet. Die grüne Variante ist offensichtlich die kürzere und damit auch die bessere Wahl.</p>
<p>Halten wir fest: Beim Entfalten muss der Algorithmus nach jedem Schritt entscheiden, wie er die neuen Städte in die bestehende Rundreise integriert. Dabei gilt es zwischen genau 2 Alternativen zu wählen&#8230; und das ist relativ leicht.</p>
<p>Phase 2 endet, wenn keine fiktiven Städte mehr übrig sind, die noch entfaltet werden könnten. Die Rundreise ist damit &#8220;fertig&#8221; und kann vom Algorithmus zurückgegeben werden.</p>
<div style="clear:both;"></div>
<h3>Namensgebung: RFA</h3>
<p>Weil der Algorithmus auf dem Falten &#038; Entfalten der Städte beruht taufe ich ihn <strong>RFA</strong>: <strong>Rekursiver-Falt-Algorithmus</strong> bzw. <em>recursive-fold-algorithm</em>.</p>
<h3>Beispiele</h3>
<div id="attachment_521" class="wp-caption alignleft" style="width: 299px"><a href="http://www.robertnitsch.de/wp-content/uploads/2010/01/03_TSP_Rundreise_100.png" class="liimagelink"><img src="http://www.robertnitsch.de/wp-content/uploads/2010/01/03_TSP_Rundreise_100-289x300.png" alt="TSP - Rundreise mit 100 Städten" title="03_TSP_Rundreise_100" width="289" height="300" class="size-medium wp-image-521" /></a><p class="wp-caption-text">TSP - Rundreise mit 100 Städten</p></div>
<div id="attachment_523" class="wp-caption alignright" style="width: 299px"><a href="http://www.robertnitsch.de/wp-content/uploads/2010/01/04_TSP_Rundreise_500.png" class="liimagelink"><img src="http://www.robertnitsch.de/wp-content/uploads/2010/01/04_TSP_Rundreise_500-289x300.png" alt="TSP - Rundreise mit 500 Städten" title="04_TSP_Rundreise_500" width="289" height="300" class="size-medium wp-image-523" /></a><p class="wp-caption-text">TSP - Rundreise mit 500 Städten</p></div>
<div style="clear:both;"></div>
<p>Die Rundreise auf der linken Seite besteht aus 100 Städten und wurde im Bruchteil einer Sekunde berechnet.</p>
<p>Die Rundreise auf der rechten Seite besteht aus 500 Städten und wurde in nur etwas mehr als 1 Sekunde berechnet.</p>
<p>Wie man an den beiden Beispielen auch gut sehen kann arbeitet der RFA keineswegs optimal, denn an der einen oder anderen Stelle überschneiden sich die Rundreisen sogar (das sicherste Zeichen dafür, dass eine Lösung suboptimal ist).</p>
<p>Nichtsdestotrotz handelt es sich in beiden Fällen um sehr gute Näherungslösungen, die zudem in kürzester Zeit berechnet wurden.</p>
<h3>Performanz &#038; Güte des RFA</h3>
<p>Der RFA befindet sich, was die Laufzeit betrifft, in der Komplexitätsklasse <strong>O(n²)</strong><sup class='footnote'><a href="#fn-483-1" id='fnref-483-1' class="liinternal">1</a></sup> (Faustregel: Verdoppelt man die Anzahl der Städte, so braucht der Algorithmus 4 Mal so lang). Die Speicherkomplexität liegt dagegen bei <strong>O(n)</strong>.</p>
<p>In allen mir bekannten Fällen stellten die vom Algorithmus erzeugten Rundreisen eine gute bis sehr gute Näherung an die optimale Lösung dar.</p>
<p>Dank seiner überragend hohen Geschwindigkeit <strong>eignet sich der RFA in meinen Augen besonders für die Berechnung von Näherungslösungen bei sehr großen Probleminstanzen mit vielen tausenden Städten</strong>. Für <a href="http://www.robertnitsch.de/wp-content/uploads/2010/01/TSP_Rundreise_10000.png" target="_blank" class="liinternal">eine Rundreise durch 10000 Städte *klick*</a> benötigt meine eigene, sehr simple Python-Implementierung beispielsweise ca. 7 Minuten und 20 Sekunden. Gemessen an der Qualität der erhaltenen Näherungslösung ist das ziemlich schnell.</p>
<p>Ausgehend von dieser Näherungslösung kann die Rundreise dann Stück für Stück durch weitere Algorithmen dem Optimum näher gebracht werden.</p>
<p>Zum Vergleich möchte ich außerdem an meinen evolutionären Algorithmus für das TSP erinnern (habe ich damals ebenfalls in Python implementiert). Dieser brauchte bei Städtezahlen jenseits der 100 bereits ewig für eine Näherungslösung. (Für weitere Details siehe <a href="http://www.robertnitsch.de/projekte/lernleistung/" class="liinternal">Projekte -&gt; Lernleistung</a>.)</p>
<h3>Testlauf mit TSP-Instanzen der TSPLIB</h3>
<p>Für TSP &#8211; Testläufe gibt es die sogenannte <a href="http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/" class="liexternal">TSPLIB</a>. Sie enthält dutzende von TSP-Instanzen mit den unterschiedlichsten Eigenschaften. Von kleinen bis sehr großen Städte-Zahlen ist alles dabei. Das besondere ist, dass in der TSPLIB in vielen Fällen die optimale Lösung bereits enthalten ist. Damit kann man die Ergebnisse von TSP-Algorithmen überprüfen oder ihre Güte in der Praxis abschätzen.</p>
<p>Bisher habe ich meinen Algorithmus zwar hoch gelobt, aber ich bin glaubwürdige Aussagen schuldig geblieben. Daher habe ich ihn auf einige metrische TSP-Instanzen der TSPLIB angesetzt (<a href="http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/tsp/" class="liexternal">Quelle</a>):</p>
<table border="1">
<thead>
<tr>
<th>Instanz-Bezeichnung<br /><span class="tiny">(enthält Städte-Anzahl)</span></th>
<th>Gesamtlänge der<br />optimalen Rundreise<span class="tiny"> (<a href="http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/STSP.html" class="liexternal">Quelle</a>)</span></th>
<th>Lösung des RFA</th>
<th>Faktor<sup class='footnote'><a href="#fn-483-2" id='fnref-483-2' class="liinternal">2</a></sup></th>
<th>Laufzeit</th>
</tr>
</thead>
<tbody>
<tr>
<td>a280</td>
<td>2579</td>
<td>3372</td>
<td>130.75%</td>
<td>0.482s</td>
</tr>
<tr>
<td>berlin52</td>
<td>7542</td>
<td>8334</td>
<td>110.5%</td>
<td>0.022s</td>
</tr>
<tr>
<td>bier127</td>
<td>118282</td>
<td>139535</td>
<td>117.97%</td>
<td>0.106s</td>
</tr>
<tr>
<td>brd14051</td>
<td>469385</td>
<td>573675</td>
<td>122.22%</td>
<td>15m 27s</td>
</tr>
<tr>
<td>ch150</td>
<td>6528</td>
<td>7830</td>
<td>119.94%</td>
<td>0.159s</td>
</tr>
<tr>
<td>d18512</td>
<td>645238</td>
<td>779639</td>
<td>120.83%</td>
<td>26m 19s</td>
</tr>
<tr>
<td>eil51</td>
<td>426</td>
<td>524</td>
<td>123.0%</td>
<td>0.023s</td>
</tr>
<tr>
<td>pr76</td>
<td>108159</td>
<td>126086</td>
<td>116.57%</td>
<td>0.049s</td>
</tr>
<tr>
<td>pr107</td>
<td>44303</td>
<td>46578</td>
<td>105.14%</td>
<td>0.078s</td>
</tr>
<tr>
<td>pr439</td>
<td>107217</td>
<td>132462</td>
<td>123.55%</td>
<td>1.079s</td>
</tr>
<tr>
<td>pr1002</td>
<td>259045</td>
<td>323954</td>
<td>125.06%</td>
<td>5.157s</td>
</tr>
<tr>
<td>rat99</td>
<td>1211</td>
<td>1374</td>
<td>113.46%</td>
<td>0.068s</td>
</tr>
<tr>
<td>rat783</td>
<td>8806</td>
<td>10548</td>
<td>119.78%</td>
<td>3.171s</td>
</tr>
</tbody>
</table>
<p></p>
<p>Im Schnitt sind die von meinem Algorithmus berechneten Rundreisen <strong>119.14%</strong> länger als die jeweilige optimale Rundreise.</p>
<p>Damit schlägt sich der RFA bei deutlich besserer Laufzeitkomplexität mindestens genausogut wie die <a href="http://de.wikipedia.org/wiki/Christofides-Heuristik" rel="nofollow" class="liwikipedia">Christofides-Heuristik</a> bzw. der Christofides-Näherungsalgorithmus (mit einer Laufzeitkomplexität von <strong>O(n³)</strong>). Die Christofides-Heuristik hat nämlich für metrische Rundreiseprobleme eine feste Gütegarantie von 50%, d.h. sie garantiert einen Faktor von höchstens 150%, d.h. die Lösungen sind maximal 1,5fach so lang wie die optimale Lösung. (Sie ist damit der bisher beste Algorithmus mit einer festen Gütegarantie.)</p>
<p>Zwar kann ich (noch?) nicht beweisen, dass der RFA ebenfalls über eine Gütegarantie verfügt. Aber in der Praxis zeigt sich, dass der Faktor deutlich unter 150% bleibt.</p>
<h3>Übertragbarkeit auf nicht-metrische Rundreiseprobleme</h3>
<p>Der RFA ist zwar auch übertragbar auf nicht-metrische Rundreiseprobleme (das Falten von 2 &#8220;Städten&#8221; muss man dann entsprechend neu erfinden), allerdings erhoffe ich mir davon keine so guten Resultate. Der RFA beruht nunmal hauptsächlich auf der <a href="http://de.wikipedia.org/wiki/Dreiecksungleichung" rel="nofollow" class="liwikipedia">Dreiecksungleichung</a> (denn für je 2 &#8220;Städte&#8221; muss eine Art fiktive Stadt im Zentrum der 2 Städte konstruierbar sein). Je stärker diese verletzt wird, desto schlechter werden die Ergebnisse vermutlich sein. Daher eignet sich der RFA auch nur bedingt für asymmetrische TSP-Instanzen (also wenn die Reisekosten für A -&gt; B nicht immer auch den Reisekosten B -&gt; A entsprechen (bspw. bergauf vs. bergab)).</p>
<p>Ein dahingehender Test meinerseits steht aber noch aus.</p>
<h3>Verbesserungsmöglichkeiten</h3>
<p>Abgesehen von der Art der Implementierung (bis jetzt nur in Python; viel schneller wäre C++) kann man den Algorithmus selbst, d.h. seine Laufzeitkomplexität, definitiv noch weiter verbessern.</p>
<p>Ich sehe großen Spielraum in Phase 1 beim Falten der Städte. Die wesentliche Rechenleistung in Phase 1 besteht darin, zu einer gegebenen Stadt ihren nächsten Nachbarn zu finden. Das kann man deutlich beschleunigen, indem man die Städte zu Beginn von Phase 1 partitioniert (die &#8220;Landkarte&#8221; wird auf bestimmte Weise in Quadrate aufgeteilt). Dadurch muss man beim Suchen des nächsten Nachbars nicht mehr <em>alle</em> Städte berücksichtigen, sondern nur noch diejenigen Städte, die sich in den umliegenden/benachbarten Partitionen befinden. Beim Falten von 2 Städten muss dann natürlich sichergestellt werden, dass die neu erzeugte fiktive Stadt ihrerseits in die korrekte Partition eingeordnet wird.</p>
<p>Die Güte des Algorithmus kann man womöglich deutlich verbessern, indem man eine Methode entwickelt, die auf intelligente Weise die Städte faltet. In meiner naiven Implementierung geschieht die Auswahl der zu faltenden Städte nämlich <em>zufällig</em>. An dieser Stelle kann man gewiss noch Verbesserungen erzielen, indem man die Reihenfolge des Faltens nicht nur dem Zufall überlässt.</p>
<p>In Phase 2 sehe ich wenig Potenzial zur Verbesserung, weil das Entfalten &#8211; wie beschrieben &#8211; quasi optimal erfolgt. Die Reihenfolge des Entfaltens spielt jedoch mMn. wenigstens eine untergeordnete Rolle, deshalb behalte ich mir eine nähere Untersuchung von Phase 2 vor.</p>
<h3>Zusammenfassung</h3>
<p>Der von mir entwickelte Algorithmus für das metrische TSP hat eine Laufzeitkomplexität von <strong>O(n²)</strong> und eine Speicherkomplexität von <strong>O(n)</strong>. Weil er auf dem Falten &#038; Entfalten der Städte beruht und das TSP dabei (zumindest zwischenzeitlich) auf den Trivialfall reduziert, nenne ich ihn <strong>RFA: Rekursiver-Falt-Algorithmus</strong>.</p>
<p>Obwohl meine Python-Implementierung ausgesprochen naiv vorgeht und ich mir kaum Mühe gegeben habe effizienten Code zu schreiben, bewältigt sie TSP-Instanzen der TSPLIB in sehr kurzer Zeit. Die Länge der dabei gefundenen Lösungen lag im Durchschnitt nur ca. 19% über der jeweils optimalen Lösung (also Faktor 119%; der höchste Faktor betrug 130%).</p>
<p>Daher kann der RFA durchaus mit der <strong>Christofides-Heuristik</strong> &#8211; der bisher beste Algorithmus mit einer festen Gütegarantie für das metrische TSP &#8211; konkurrieren, nicht zuletzt weil diese eine deutlich schlechtere Laufzeitkomplexität von <strong>O(n³)</strong> besitzt (und überdies auch noch sehr viel komplizierter ist). Eventuell kann ich beweisen, dass auch für den RFA eine feste Gütegarantie gilt. In der Praxis schlägt er sich auf alle Fälle sehr gut.</p>
<p>Der RFA ist zwar grundsätzlich auch übertragbar auf nicht-metrische Rundreiseprobleme, allerdings hängt die Güte des RFA sehr wahrscheinlich von der Dreiecksungleichung ab. Je stärker diese verletzt wird, desto schlechter werden die Ergebnisse vermutlich sein.</p>
<p><strong>Dank seiner überragenden Geschwindigkeit eignet sich der Algorithmus in meinen Augen besonders für die Berechnung von Näherungslösungen für sehr große TSP-Instanzen mit vielen Tausend Städten.</strong></p>
<h3>Download meiner Python-Implementierung</h3>
<p><a href="http://www.robertnitsch.de/wp-content/uploads/2010/01/RFA_demo.zip" class="lizip">RFA_demo.zip</a> (2.2 MB)</p>
<p>Der Quelltext befindet sich im Ordner &#8220;src&#8221; (die Dateien sind <strong>UTF-8</strong>-kodiert). Die im Artikel verwendeten TSPLIB-Challenges (und viele weitere) befinden sich im Ordner &#8220;TSPLIB&#8221;.</p>
<p>Die auszuführende Datei ist <strong>src/RFA_demo.py</strong>. Ich habe <a href="http://python.org/download/" class="liexternal">Python 2.6</a> verwendet, es sollte aber auch mit <strong>Python 2.5</strong> laufen.</p>
<p>In der Datei <strong>RFA_demo.py</strong> kann man auch einige Einstellungen verändern. Ich habe die entsprechenden Stellen deutlich hervorgehoben und jede Einstellung in Deutsch beschrieben (ansonsten ist alles in Englisch gehalten). Sogar Laien haben also eine faire Chance die Demonstration auf ihrem PC auszuführen.</p>
<p>Viel Spaß damit!
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-483-1'>Einen Beweis bleibe ich vorerst schuldig. Allerdings ist O(n²) naheliegend, weil der wesentliche Aufwand darin besteht während des Faltens (Phase 1) immer und immer wieder den nächsten Nachbarn zu einer Stadt zu finden. Dort sehe ich übrigens auch schon die ersten vielversprechenden Verbesserungsmöglichkeiten mittels geschickter Partitionierung der Städte (mehr dazu unter &#8220;Verbesserungsmöglichkeiten&#8221;). <span class='footnotereverse'><a href="#fnref-483-1" class="liinternal">&#8617;</a></span></li>
<li id='fn-483-2'>Der Faktor berechnet sich als &lt;RFA-Lösung&gt; / &lt;Optimale-Lösung&gt; und gibt somit die relative Länge der RFA-Lösung zur Länge der optimalen Lösung an. <span class='footnotereverse'><a href="#fnref-483-2" class="liinternal">&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2010/01/14/rfa-ein-rekursiver-algorithmus-fur-das-metrische-traveling-salesman-problem/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Veröffentlichung der Lernleistung</title>
		<link>http://www.robertnitsch.de/2008/07/07/veroffentlichung-der-lernleistung/</link>
		<comments>http://www.robertnitsch.de/2008/07/07/veroffentlichung-der-lernleistung/#comments</comments>
		<pubDate>Mon, 07 Jul 2008 10:46:10 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Freaky]]></category>
		<category><![CDATA[Informatik]]></category>
		<category><![CDATA[Mathematik]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Real Life]]></category>
		<category><![CDATA[Schule]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/?p=99</guid>
		<description><![CDATA[Ich habe nun endlich meine Lernleistung veröffentlicht. Das Ganze hat sich wegen eines Festplattenfehlers verzögert. Außerdem fehlen nun einige ergänzende Texte, die ich speziell für die Veröffentlichung erstellt hatte. Jetzt muss erstmal das reichen, was in den Backups zu finden war, auch wenn es nun teilweise besonders schwer verdaulich ist.]]></description>
			<content:encoded><![CDATA[<p>Ich habe nun endlich <a href="http://www.robertnitsch.de/projekte/lernleistung/" class="liinternal">meine Lernleistung veröffentlicht</a>.<br />
Das Ganze hat sich wegen eines Festplattenfehlers verzögert. Außerdem fehlen nun einige ergänzende Texte, die ich speziell für die Veröffentlichung erstellt hatte. Jetzt muss erstmal das reichen, was in den Backups zu finden war, auch wenn es nun teilweise besonders schwer verdaulich ist.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2008/07/07/veroffentlichung-der-lernleistung/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Besondere Lernleistung: Evolutionäre Algorithmen und das Traveling-Salesman-Problem</title>
		<link>http://www.robertnitsch.de/2008/01/06/besondere-lernleistung-evolutionare-algorithmen-und-das-traveling-salesman-problem/</link>
		<comments>http://www.robertnitsch.de/2008/01/06/besondere-lernleistung-evolutionare-algorithmen-und-das-traveling-salesman-problem/#comments</comments>
		<pubDate>Sat, 05 Jan 2008 23:11:51 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Freaky]]></category>
		<category><![CDATA[Informatik]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Real Life]]></category>
		<category><![CDATA[Schule]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/2008/01/06/besondere-lernleistung-evolutionare-algorithmen-und-das-travelling-salesman-problem/</guid>
		<description><![CDATA[Das offizielle Thema meiner besonderen Lernleistung lautet &#8220;Spieltheorie&#8221; mit Schwerpunkt auf &#8220;evolutionären Algorithmen&#8221;. Ich bringe die Lernleistung zusammen mit einem Freund als Ersatz für das 5. Prüfungsfach ins Abitur, das ich dieses Jahr mache, ein. Der Freund hat natürlich einen anderen thematischen Schwerpunkt, das Hauptthema (Spieltheorie) ist jedoch dasselbe. Für das sogenannte Traveling-Salesman-Problem soll ich [...]]]></description>
			<content:encoded><![CDATA[<p>Das offizielle Thema meiner besonderen Lernleistung lautet &#8220;Spieltheorie&#8221; mit Schwerpunkt auf &#8220;evolutionären Algorithmen&#8221;. Ich bringe die Lernleistung zusammen mit einem Freund als Ersatz für das 5. Prüfungsfach ins Abitur, das ich dieses Jahr mache, ein. Der Freund hat natürlich einen anderen thematischen Schwerpunkt, das Hauptthema (Spieltheorie) ist jedoch dasselbe. <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Für das sogenannte <em>Traveling-Salesman-Problem</em> soll ich außerdem im Rahmen dieser Lernleistung einen evolutionären Algorithmus schaffen.</p>
<h3>Das Traveling-Salesman-Problem</h3>
<p>Das <em>Traveling-Salesman-Problem</em> (TSP) ist einfach formuliert: Ein Handlungsreisender muss <em>n</em> Städte besuchen und am Ende zu seinem Ausgangsort zurückkehren. Gesucht ist die kürzeste Rundreise.</p>
<p>Viele schlaue und dumme Menschen haben sich auf der Suche nach einem effizienten Algorithmus jahrzehntelang den Kopf darüber zerbrochen. Einen Ansatz stellen die sogenannten evolutionären Algorithmen dar, die die <a href="http://de.wikipedia.org/wiki/Evolution" rel="nofollow" class="liwikipedia">Evolution</a> als Vorbild haben.</p>
<h3>Was ist ein evolutionärer Algorithmus?</h3>
<p>Zitat <a href="http://de.wikipedia.org/wiki/Evolution%C3%A4rer_Algorithmus" rel="nofollow" class="liwikipedia">Wikipedia</a>:</p>
<blockquote><p>&#8220;Ein Evolutionärer Algorithmus (EA) ist ein Optimierungsverfahren, das als Vorbild die biologische Evolution hat.&#8221;</p></blockquote>
<p>Prinzipiell prozessiert ein evolutionärer Algorithmus eine <em>Population</em> mit <em>n</em> <em>Individuen</em> nach dem Vorbild der Evolution: <em>&#8220;survival of the fittest&#8221;</em>. Jedes Individuum stellt eine mögliche Lösung des jeweiligen Problems dar. Im Falle des TSP entspricht also jedes Individuum einer möglichen Rundreise.</p>
<p>Im Laufe des Algorithmus pflanzen sich außerdem je zwei Individuen fort und erzeugen ein Kind-Individuum nach Vorbild der Natur mittels <a href="http://de.wikipedia.org/wiki/Rekombination" rel="nofollow" class="liwikipedia">Rekombination</a>. Zusätzlich finden &#8211; ebenfalls nach Vorbild der Natur &#8211; mit einer bestimmten Wahrscheinlichkeit <a href="http://de.wikipedia.org/wiki/Mutation" rel="nofollow" class="liwikipedia">Mutationen</a> statt, also z.B. (normalerweise) zufällige Veränderungen der Route.</p>
<p>Jeder Durchlauf eines evolutionären Algorithmus&#8217; sieht also mehr oder weniger so aus:</p>
<ul>
<li>Entferne <em>x</em> Individuen aus der Population. (Zum Beispiel die beiden schlechtesten Routen.)</li>
<li>Rekombiniere <em>x</em>-Mal zwei Individuen aus der Population. (Zum Beispiel die beiden besten Routen.)</li>
<li>Wende mit einer bestimmten Wahrscheinlichkeit eine Mutation auf die Individuen an. (Zum Beispiel mit einer Wahrscheinlichkeit von 15%.)</li>
<li>Wenn die maximale Anzahl von Durchläufen (Generationen) erreicht ist, beende den Vorgang, ansonsten starte einen neuen Durchlauf.</li>
</ul>
<p>Die Güte bzw. Qualität eines evolutionären Algorithmus hängt vor allem von folgenden Faktoren ab:</p>
<ul>
<li>Populationsgröße</li>
<li>Rekombinationsmethode</li>
<li>Mutationsmethode</li>
<li>Mutationswahrscheinlichkeit</li>
<li>&#8230;</li>
</ul>
<h3>Ein evolutionärer Algorithmus für das Travelling-Salesman-Problem</h3>
<p>Wie oben gesagt ist es meine Aufgabe für das TSP einen evolutionären Algorithmus zu programmieren. Als Programmiersprache habe ich mich für <a href="http://python.org/" class="liexternal">Python</a> und als Entwicklungsumgebung für <a href="http://www.eclipse.org" class="liexternal">eclipse</a> mit <a href="http://pydev.sourceforge.net/" class="liexternal">PyDev</a> entschieden. (Damit lässt sich super arbeiten!)<br />
Mit der Arbeit am evolutionären Algorithmus habe ich heute begonnen, und ich muss sagen: Ich bin bereits jetzt sehr zufrieden. Da die Güte des evolutionären Algorithmus &#8211; siehe oben &#8211; von vielen Faktoren abhängt, habe ich mich für eine Umsetzung entschieden, bei der ich all diese Faktoren leicht ändern kann.</p>
<p>Das ist mir ganz gut gelungen: Alle Parameter und Komponenten des evolutionären Algorithmus sind ganz einfach austauschbar. (Leider werde ich bis zum Erhalt meines Abiturs keine Quelltexte veröffentlichen. Der menschlichen Dummheit sind einfach keine Grenzen gesetzt und ich könnte mir vorstellen, dass man mir vorwirft, meine Arbeit aus dem Internet von einem &#8220;Robert Nitsch&#8221; kopiert zu haben.)</p>
<p>Nun folgt der schwierigste, aber wohl auch spannendste Teil meiner besonderen Lernleistung. Ich werde prüfen welche Parameter den besten evolutionären Algorithmus ausmachen und verschiedene Konfigurationen miteinander vergleichen. Natürlich wird auch eine Begründung nicht fehlen &#8211; also warum Konfiguration A besser ist als Konfiguration B.</p>
<p>Meine Arbeit und meine Ergebnisse muss ich abschließend in einem Skript dokumentieren und in einer Präsentation vorstellen. Meine Ergebnisse werde ich natürlich auch hier auf meiner Homepage festhalten, damit Schüler, die eine ähnliche Lernleistung erbringen, davon vielleicht profitieren können.</p>
<p>Für Tipps und Ratschläge bezüglich meiner besonderen Lernleistung bin ich natürlich jederzeit offen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2008/01/06/besondere-lernleistung-evolutionare-algorithmen-und-das-traveling-salesman-problem/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Status des KDE-Bildschirmschoners abfragen</title>
		<link>http://www.robertnitsch.de/2007/05/20/status-des-kde-bildschirmschoners-abfragen/</link>
		<comments>http://www.robertnitsch.de/2007/05/20/status-des-kde-bildschirmschoners-abfragen/#comments</comments>
		<pubDate>Sun, 20 May 2007 17:03:16 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Kubuntu]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false">http://robertnitsch.de/2007/05/20/status-des-kde-bildschirmschoners-abfragen/</guid>
		<description><![CDATA[Der Status des KDE-Bildschirmschoners lässt sich per Kommandozeile mit diesem Befehl abfragen: robert@zeus:~$ dcop kdesktop KScreensaverIface isBlanked false dcop ist das Kommandozeilenprogramm mit dem man Zugriff auf die DCOP-Schnittstellen (Desktop Communication Protocoll) beliebiger Programme erhält. kdesktop ist eine davon. Und über das KScreensaverIface lässt sich der Bildschirmschoner steuern, bzw. in diesem Fall wird abgefragt, ob [...]]]></description>
			<content:encoded><![CDATA[<p>Der Status des KDE-Bildschirmschoners lässt sich per Kommandozeile mit diesem Befehl abfragen:</p>
<pre>
robert@zeus:~$ <strong>dcop kdesktop KScreensaverIface isBlanked</strong>
false
</pre>
<p><strong>dcop</strong> ist das Kommandozeilenprogramm mit dem man Zugriff auf die DCOP-Schnittstellen (<a href="http://de.wikipedia.org/wiki/DCOP" rel="nofollow" class="liwikipedia">Desktop Communication Protocoll</a>) beliebiger Programme erhält. <strong>kdesktop</strong> <em>ist</em> eine davon. Und über das <strong>KScreensaverIface</strong> lässt sich der Bildschirmschoner steuern, bzw. in diesem Fall wird abgefragt, ob er momentan aktiv ist.</p>
<p>In Python sieht das Ganze dann so aus:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> screensaverActivated<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    checks whether the screensaver is currently activated
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">popen</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'dcop kdesktop KScreensaverIface isBlanked'</span>, <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'true'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Allerdings wird diese Lösung nicht auf Dauer funktionieren. Zitat aus dem Wikipedia-Artikel:</p>
<blockquote><p>KDE 4 wird DCOP nicht mehr enthalten. Stattdessen wird dann das von spezifischen Desktopumgebungen unabhängige <a href="http://de.wikipedia.org/wiki/D-Bus" rel="nofollow" class="liwikipedia">D-Bus</a> verwendet.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2007/05/20/status-des-kde-bildschirmschoners-abfragen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python, das turtle-Modul und Fraktale</title>
		<link>http://www.robertnitsch.de/2007/04/04/python-das-turtle-modul-und-fraktale/</link>
		<comments>http://www.robertnitsch.de/2007/04/04/python-das-turtle-modul-und-fraktale/#comments</comments>
		<pubDate>Wed, 04 Apr 2007 09:54:02 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Informatik]]></category>
		<category><![CDATA[Mathematik]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://robertnitsch.de/2007/04/04/python-das-turtle-modul-und-fraktale/</guid>
		<description><![CDATA[Ich hätte ja nicht gedacht, dass es so lustig sein kann, mit Fraktalen herumzuexperimentieren &#8230; aber das kann es doch. Ein bisschen Interesse natürlich vorrausgesetzt. Mit Hilfe des Lehrmaterials &#8220;Turtle-Grafik und Fraktale Geometrie&#8221; (http://miami.uni-muenster.de/servlets/DocumentServlet?id=1522) konnte ich auch recht schnell einsteigen. Die Schilderungen und die Quelltexte sind auf das Modul turtle bezogen und sind somit grundsätzlich [...]]]></description>
			<content:encoded><![CDATA[<p>Ich hätte ja nicht gedacht, dass es so lustig sein kann, mit Fraktalen herumzuexperimentieren &#8230; aber das kann es doch. Ein bisschen Interesse natürlich vorrausgesetzt.</p>
<p>Mit Hilfe des Lehrmaterials &#8220;Turtle-Grafik und Fraktale Geometrie&#8221; (<a href="http://miami.uni-muenster.de/servlets/DocumentServlet?id=1522" class="liexternal">http://miami.uni-muenster.de/servlets/DocumentServlet?id=1522</a>) konnte ich auch recht schnell einsteigen. Die Schilderungen und die Quelltexte sind auf das Modul turtle bezogen und sind somit grundsätzlich plattformunabhängig. Dennoch empfehle ich Python für diese Experimente, denn dort ist das turtle-Modul bereits integriert und lässt sich phänomenal einfach verwenden.</p>
<h3>Das turtle-Modul</h3>
<p>Das turtle-Modul ist eine Sammlung an Funktionen, mit deren Hilfe sich ein &#8220;Malstift&#8221; bzw. &#8220;turtle&#8221; steuern lässt. Mit Anweisungen wie left(), right(), forward() und backward() kann man einfachste Bewegungen koordinieren. Packt man derartige Anweisungen in rekursive Funktionen, so ergibt sich mit etwas Glück ein immerwiederkehrendes selbstähnliches Gebilde &#8211; ein Fraktal.</p>
<p>Die Dokumentation des pythoneigenen turtle-Moduls ist hier zu finden:</p>
<p><a href="http://docs.python.org/lib/module-turtle.html" class="liexternal">http://docs.python.org/lib/module-turtle.html</a></p>
<h3>Die Kochkurve</h3>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># coding=UTF-8</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">turtle</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> kochkurve<span style="color: black;">&#40;</span>t, s<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span><span style="color: black;">&#40;</span>t==<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># wenn die gewünschte rekursionstiefe (sprich: feinheit der bewegungen) erreich ist,</span>
        <span style="color: #808080; font-style: italic;"># soll das ganze auf dem bildschirm umgesetzt werden</span>
        forward<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #808080; font-style: italic;"># die bewegungen der &quot;turtle&quot; werden rekursiv verfeinert</span>
        kochkurve<span style="color: black;">&#40;</span>t-<span style="color: #ff4500;">1</span>, s/<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
        left<span style="color: black;">&#40;</span><span style="color: #ff4500;">60</span><span style="color: black;">&#41;</span>
        kochkurve<span style="color: black;">&#40;</span>t-<span style="color: #ff4500;">1</span>, s/<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
        left<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">120</span><span style="color: black;">&#41;</span>
        kochkurve<span style="color: black;">&#40;</span>t-<span style="color: #ff4500;">1</span>, s/<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
        left<span style="color: black;">&#40;</span><span style="color: #ff4500;">60</span><span style="color: black;">&#41;</span>
        kochkurve<span style="color: black;">&#40;</span>t-<span style="color: #ff4500;">1</span>, s/<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># koch'sche schneeflocke, zusammengesetzt aus mehreren kochkurven</span>
kochkurve<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
left<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">90</span><span style="color: black;">&#41;</span>
color<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
kochkurve<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
left<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">90</span><span style="color: black;">&#41;</span>
color<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
kochkurve<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
left<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">90</span><span style="color: black;">&#41;</span>
color<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">0</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
kochkurve<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># die methode done(), die die hauptschleife betritt, ist offenbar nicht verfügbar :-(</span>
<span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
done<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<hr />
<p>Die Rekursionstiefe (t) bestimmt die Feinheit der Bewegungen. Der Parameter s definiert die Gesamtlänge der Kochkurve.</p>
<p>Ich habe die Funktion am Ende mehrfach aufgerufen, sodass eine sogenannte Koch&#8217;sche Schneeflocke entsteht. Eine Koch&#8217;sche Schneeflockte besteht aus mehreren Kochkurven, die man aneinandergehängt hat. Und hängt man 4 Kochkurven im Winkel von 90° aneinander, so ergibt sich folgendes Gebilde:</p>
<p><a href="http://robertnitsch.de/wp-content/uploads/2007/04/kochsche_schneeflocke.jpg" title='Koch’sche Schneeflocke' class="liimagelink"><img src='http://robertnitsch.de/wp-content/uploads/2007/04/kochsche_schneeflocke.jpg' alt='Koch’sche Schneeflocke' /></a></p>
<h3>Der fraktale Baum</h3>
<p>Fraktale Bäume haben mich irgendwie schon immer beschäftigt. Man stelle sich einen Körper vor, von dem etliche Zweige und Äste abgehen. Von jedem Zweig und jedem Ast gehen erneut ebensoviele Zweige und Äste ab &#8211; diesmal nur wesentlich kleiner. Und von diesen kleinen Ästen gehen wieder Äste ab &#8230; immer wieder &#8230; und jedes Mal werden sie kleiner. Ich hatte meinen Spaß daran mir den kleinsten denkbaren Ast vorzustellen. Natürlich hatte dieser Gedankengang nie ein Ende. Aber wenn man jung ist&#8230; <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Mit dem turtle-Modul lassen sich natürlich auch fraktale Bäume erzeugen.</p>
<p>Z.Bsp. hiermit:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># coding=UTF-8</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">turtle</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> baum<span style="color: black;">&#40;</span>s,t<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span><span style="color: black;">&#40;</span>t <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>:
        forward<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>
        left<span style="color: black;">&#40;</span><span style="color: #ff4500;">30</span><span style="color: black;">&#41;</span>
        baum<span style="color: black;">&#40;</span>s<span style="color: #66cc66;">*</span><span style="color: #ff4500;">0.6</span>, t-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        right<span style="color: black;">&#40;</span><span style="color: #ff4500;">75</span><span style="color: black;">&#41;</span>
        baum<span style="color: black;">&#40;</span>s<span style="color: #66cc66;">*</span><span style="color: #ff4500;">0.7</span>, t-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        left<span style="color: black;">&#40;</span><span style="color: #ff4500;">45</span><span style="color: black;">&#41;</span>
        backward<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
sety<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
baum<span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span>,<span style="color: #ff4500;">7</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># die methode done(), die die hauptschleife betritt, ist offenbar nicht verfügbar :-(</span>
<span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
done<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<hr />
<p>Mit Hilfe des Parameters t lässt sich auch hier die Rekursionstiefe festlegen.</p>
<p>Der Code ergibt, wenn man ihn mit dem Python-Compiler aufruft, folgendes:</p>
<p><a href="http://robertnitsch.de/wp-content/uploads/2007/04/fraktaler_baum_klein.jpg" title='Fraktaler Baum' class="liimagelink"><img src='http://robertnitsch.de/wp-content/uploads/2007/04/fraktaler_baum_klein.jpg' alt='Fraktaler Baum' /></a></p>
<p>Selbstverständlich lassen sich Winkel und Streckenlängen variieren. In diesem konkreten Fall ist der linke Ast um 30° (nach links), der rechte um 45° (nach rechts) abgewinkelt. Der linke Ast hat die Länge 0,6*s &#8211; das entspricht 60% der Länge des Mutterastes. Der rechte Ast hat jeweils die Länge 0,7*s &#8211; also 70% der Länge des Mutterastes.</p>
<h3>Weitere Anregungen</h3>
<p><a href="http://www.herr-rau.de/wordpress/2007/03/meine-erste-fischpopulation.htm" class="liexternal">Fischpopulationen im Lehrerzimmer</a> mit Tkinter (kleine Andeutung am Rande <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  )</p>
<p><a href="http://miami.uni-muenster.de/servlets/DocumentServlet?id=1522" class="liexternal">Turtle-Grafik und fraktale Geometrie</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2007/04/04/python-das-turtle-modul-und-fraktale/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
