<?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; Programmieren</title>
	<atom:link href="http://www.robertnitsch.de/category/programmieren/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>Virtual server / VPS vs. Java: &#8220;Could not reserve enough space for object heap&#8221;</title>
		<link>http://www.robertnitsch.de/2009/12/18/virtual-server-vps-vs-java-could-not-reserve-enough-space-for-object-heap/</link>
		<comments>http://www.robertnitsch.de/2009/12/18/virtual-server-vps-vs-java-could-not-reserve-enough-space-for-object-heap/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 22:44:17 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Informatik]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[PC]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/?p=375</guid>
		<description><![CDATA[Today I encountered the following error message on my virtual server: Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine. This error message occurred every single time Java was involved in something&#8230; Even &#8220;java -version&#8221; crashed&#8230; After several hours I figured out it [...]]]></description>
			<content:encoded><![CDATA[<p>Today I encountered the following error message on my virtual server:</p>
<blockquote><p>Error occurred during initialization of VM<br />
Could not reserve enough space for object heap<br />
Could not create the Java virtual machine.</p></blockquote>
<p>This error message occurred every single time Java was involved in something&#8230; Even &#8220;java -version&#8221; crashed&#8230;</p>
<p>After several hours I figured out it was not a problem of having too less memory but instead a problem of having too much free memory. In particular, my system (a <em>virtual</em> server) always seems to have a lot of free memory, which is in fact used by the other virtual server instances on the same physical machine. Thus, Java attempts to allocate a very big part of the memory (expecting it is not used otherwise). The memory allocation fails and Java crashes with the deceptive message &#8220;Could not reserve enough space for object heap&#8221;. At least this is my explanation so far&#8230;</p>
<h3>The solution</h3>
<p>The problem can be fixed by manually specifying the <strong>maximum</strong> heapsize. E.g., execute &#8220;java -Xmx128m -version&#8221; instead of &#8220;java -version&#8221;.</p>
<p>Since it is a pain and sometimes almost impossible to enable this commandline parameter (think of applications making use of java indirectly) you can make it the default by changing the environment variable <strong>_JAVA_OPTIONS</strong>. Either edit <em>/etc/environment</em> (persistent solution) or execute</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">export _JAVA_OPTIONS=&quot;-Xmx128m&quot;</pre></div></div>

<p>(solves the issue only for the current session).</p>
<p>It worked for me and I&#8217;m running Ubuntu 8.04 on a VPS hosted by Hosteurope.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2009/12/18/virtual-server-vps-vs-java-could-not-reserve-enough-space-for-object-heap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TU Darmstadt: Rückblick auf 2 Semester Informatik</title>
		<link>http://www.robertnitsch.de/2009/11/28/tu-darmstadt-ruckblick-auf-2-semester-informatik/</link>
		<comments>http://www.robertnitsch.de/2009/11/28/tu-darmstadt-ruckblick-auf-2-semester-informatik/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 15:00:52 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Erfahrungsberichte]]></category>
		<category><![CDATA[Informatik]]></category>
		<category><![CDATA[PC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Real Life]]></category>
		<category><![CDATA[Studium]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/?p=316</guid>
		<description><![CDATA[Wie man dem Willkommenstext ganz oben auf der Startseite entnehmen kann studiere ich momentan Informatik an der TU Darmstadt. Ich strebe den Abschluss M.Sc. (Master of Science) Informatik an. Inzwischen habe ich die ersten 2 Semester hinter mir, befinde mich also noch im Bachelor-Stadium; das 3. Semester hat seit einigen Wochen begonnen. Dieser Artikel soll [...]]]></description>
			<content:encoded><![CDATA[<p>Wie man dem Willkommenstext <a href="http://www.robertnitsch.de" class="liinternal">ganz oben auf der Startseite</a> entnehmen kann studiere ich momentan Informatik an der <a href="http://www.tu-darmstadt.de" class="liexternal">TU Darmstadt</a>. Ich strebe den Abschluss <strong>M.Sc.</strong> (<em>Master of Science</em>) Informatik an.</p>
<p>Inzwischen habe ich die ersten 2 Semester hinter mir, befinde mich also noch im Bachelor-Stadium; das 3. Semester hat seit einigen Wochen begonnen. Dieser Artikel soll einen kurzen Rückblick darstellen, der sich wahrscheinlich besonders für diejenigen lohnt, die ein Informatik-Studium in Betracht ziehen.</p>
<p>Hinweis: Ich gebe hier meine Sicht der Dinge wieder, also <em>meine</em> Meinung.</p>
<h3>Wintersemester 08/09</h3>
<p>Im WS 08/09 habe ich mein Informatik-Studium an der TU Darmstadt begonnen. Für diejenigen, die vllt. Informatik studieren werden, dürfte dieser Teil am spannendsten sein.</p>
<h4>Grundlagen der Informatik 1</h4>
<p>In GdI 1 gab es eine Einführung in das Programmieren. Von einer Einführung kann dabei aber kaum die Rede sein, denn es ging durchaus ziemlich in die Tiefe. Angefangen haben wir mit <strong>Scheme</strong>, einer <strong><em>funktionalen</em> Programmiersprache</strong>, die mit LISP verwandt ist und mit der ich und die meisten meiner Kommilitonen zuvor nichts zu tun gehabt haben. Funktionale Programmierung war für die meisten, mich eingeschlossen, absolutes Neuland.</p>
<p>Das war insofern ein Problem, als dass viele meiner Kommilitonen Schwierigkeiten beim Einstieg in die funktionale Programmierung hatten &#8211; nicht nur die absoluten Neulinge, sondern auch einige der Erfahreneren. Bei Scheme werden nämlich fast alle Probleme mit rekursiven Funktionen gelöst. Schleifen im klassischen Sinne stehen quasi nicht zur Verfügung. Und wie sortiert man bspw. eine Liste rekursiv, wenn man bisher nur iterative Implementierungen kennt? Erstmal gar nicht so einfach!</p>
<p>Es stellte sich jedoch sehr schnell heraus, dass die Erfahrung mit Scheme eine echte Bereicherung war. Wer GdI 1 mit einer guten Note übersteht, der dürfte hinterher keine Probleme mehr mit Rekursionen haben. <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Der zweite und geringfügig größere Teil drehte sich um <strong>Java</strong>. Das Verhältnis Scheme : Java kann man ungefähr mit 40 : 60 beschreiben. Beinhaltet waren solche Themen wie Objektorientierte Programmierung, d.h. was sind Klassen/Objekte, was ist Vererbung und wie funktioniert sie, Polymorphismus, Generische Typen (Generics) und ähnliches.</p>
<p><strong>Klausuren:</strong> Im Dezember gab es eine Semestralklausur, in der es nur um Scheme ging. Nach Ende der Lehrveranstaltungen (während der Semesterferien) gab es dann noch eine endgültige Prüfung, die zu etwa 40% aus Scheme und zu 60% aus Java-bezogenen Aufgaben bestand.</p>
<p><strong>Bewertung:</strong> Der Veranstalter ist den Studenten bei Problemen fast immer entgegengekommen, die Folien &#038; die Übungen waren gut gemacht und die Klausuren waren sehr fair. Für Einsteiger ohne Programmiererfahrung aber trotzdem ein gewaltiges Stück Arbeit!</p>
<h4>Technische Grundlagen der Informatik 1</h4>
<p>TGdI 1 beinhaltete Grundlagen der Digitaltechnik, also boolesche Algebra / boolesche Funktionen, kombinatorische und sequenzielle Logik, KV-Diagramme, digitale Schaltungen, Signalpfade, wichtige digitale Schaltungen (Multiplexer, Decoder, &#8230;), darunter auch Speicherelemente (Flipflops), Automaten (Mealy und Moore) uvm.</p>
<p><strong>Klausuren:</strong> Auch hier gab es eine Semestralklausur im Dezember und eine Prüfung am Ende des Semesters.</p>
<p><strong>Bewertung:</strong> Die Folien waren relativ gut gemacht, teilweise habe ich aber den roten Faden vermisst. Insgesamt aber immer noch sehr gut gemacht, auch die Übungen und die Klausur ließen nicht viel zu wünschen übrig. Allerdings ist der Stoff einfach einfach. Wer hier durchfällt sollte sich Gedanken machen!</p>
<h4>Mathematik für Informatiker und Wirtschaftsinformatik 1</h4>
<p>Mathematik für Inf und WInf 1 war zusammen mit FGdI 1 die einzige Herausforderung im 1. Semester. Dazu muss ich etwas weiter ausholen.</p>
<p>Inhaltlich gesehen ist Mathe 1 nicht sonderlich schwer. Im Wesentlichen geht es um die <strong>gewöhnliche Analysis</strong> (mit einstelligen Funktionen), d.h. Folgen, Reihen, Grenzwerte, Funktionen, Differential- und Integralrechnung. Jedoch wird das Ganze sehr mathematisch aufgezogen. Der Vorlesung kann man kaum folgen, die wichtigen Informationen gehen in einem Schwall unnötiger mathematischer Sätze und Beweise völlig unter. Dazu muss man sagen, dass die Veranstaltung vom Fachbereich Mathematik organisiert wird. Sie wird also auch von einem Mathematik-Professor gehalten. Das merkt man auch sehr deutlich.</p>
<p><strong>Klausuren:</strong> Es gab nur 1 Klausur am Ende des Semesters.</p>
<p><strong>Bewertung:</strong> In Mathe 1 wird relativ leichter Stoff mit mathematischen Beweisen derart aufgeblasen, dass die eigentliche Leistung darin besteht, die wenigen wichtigen Informationen zu filtern bzw. überhaupt zu erfassen, ohne sich dabei von der gigantischen Menge unnötigen Wissens, das ebenfalls vermittelt wird, erschlagen zu lassen. Die Übungen waren anfangs schwer, weil man mathematische Beweise führen musste. Und das ist erstmal schwer bis unmöglich. Später wurden die Übungen aber besser. Die Klausur war schließlich ausgesprochen fair, aber vor allem eines: leichter, als alle erwartet hatten. Trotzdem sind hier viele gescheitert. <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<h4>Formale Grundlagen der Informatik 1</h4>
<p>FGdI 1 ist mir bis heute noch ein Rätsel. Wie man dem Titel der Veranstaltung ansehen kann geht es hier um die <strong>theoretische Informatik</strong>.</p>
<p>Rätsel deshalb, weil im Grunde genommen extrem einfacher Stoff (Sprachen, Reguläre Ausdrücke, Grammatiken, Chomsky-Hierarchie und dazugehörend <abbr title="deterministic finite automaton">DFAs</abbr>, <abbr title="non-deterministic finite automaton">NFAs</abbr>, <abbr title="pushdown automaton">PDAs</abbr>) dermaßen mit formaler Sprache aufgeblasen wird, dass man sich erstmal immer fragt: &#8220;WHAT THE FUCK SOLL DAS HEISSEN?&#8221; Und wenn man es dann verstanden hat, denkt man sich: &#8220;Ist ja total easy. -.-&#8221;</p>
<p>Die Verantwortung liegt hier nicht nur bei den Veranstaltern, denn schließlich muss man sich an die formale Sprache erst gewöhnen, bis man sie wirklich verstehen kann. Aber es gab quasi keinerlei Erklärendes. Im Wesentlichen wurde wild drauflos definiert und wir mussten dann erraten, wozu die einzelnen Definitionen jeweils im Gesamtzusammenhang gebraucht wurden. Wie man es auch dreht und wendet: Wenn man gerade erst mit dem Studium anfängt, dann ist das eine echte Herausforderung!</p>
<p><strong>Klausuren:</strong> Es gab wie in Mathe 1 nur eine Klausur am Ende des Semesters. :/</p>
<p><strong>Bewertung:</strong> Während die Vorlesung inkl. Folien ziemlich bescheiden war, so waren die Übungen einigermaßen in Ordnung und die Klausur war sehr fair. Man konnte 60 Punkte erreichen, für eine 1.0 brauchte man aber nur 48 Punkte. Hier kann man eigentlich nur durchfallen, wenn man das falsche lernt. Ein gutes Auge für das Wesentliche hilft Wunder!</p>
<h3>Sommersemester 2009</h3>
<h4>Grundlagen der Informatik 2</h4>
<p>GdI 2 war eine monströse Veranstaltung, in der sich alles um <strong>Algorithmen und Datenstrukturen</strong> drehte, auch mehrere Index-Strukturen waren dabei; Laufzeit- und Speicherkomplexität von Algorithmen inklusive uvm. Alles in allem war es vor allem eines: verdammt viel, für die meisten <em>zu</em> viel! Nicht ohne Grund ist GdI 2 als <strong>&#8220;Exmatrikulator&#8221;</strong> berüchtigt (womit sich die Veranstalter für meinen Geschmack allzu oft gebrüstet haben, so als wären sie besonders stolz darauf).</p>
<p>Hier noch ein paar Stichworte zur Illustration: Komplexität von Algorithmen, Sortierverfahren, Graphenalgorithmen, Allgemeine Bäume und Binärbäume, Binäre Suchbäume, Mehrwegbäume, B-Baum u. Varianten, Digitale Suchbäume, Hashverfahren (intern, extern, erweiterbar), Graphische Datenstrukturen, Spezielle Themen (Bitmap Index, Indexstrukturen für &#8220;broadcast data&#8221;, etc.)</p>
<p><strong>Klausuren:</strong> Nur eine Klausur am Ende des Semesters, für die man sich einen Bonus von bis zu einem ganzen Notensprung erarbeiten konnte.</p>
<p><strong>Bewertung:</strong> Die Vorlesung war in Ordnung, soweit ich das beurteilen kann. Unser Professor schien aber häufig unvorbereitet zu sein; er selbst sagte entschuldigend, er hätte dieses Semester sehr viel zu tun.<br />
Wie bereits geschrieben konnte man sich einen Bonus erarbeiten. Ab 191 Punkten in den bewerteten Hausübungen und Programmieraufgaben hat man einen vollen Notensprung für die Prüfung erhalten. Das war insofern manchmal ärgerlich, als dass die Hausübungen und Programmieraufgaben in mehreren Fällen unklar/missverständlich formuliert waren und die Folien oft erst verspätet ins Netz gestellt wurden. Ansonsten waren die Übungen und die Programmieraufgaben durchaus sehr hilfreich und man konnte sehr viel dabei lernen.<br />
Die Klausur am Ende war ziemlich fair, es wurden sogar diejenigen belohnt, die sich den letzten Foliensatz nochmal komplett durchgeschaut haben (dazu kam eine sehr leichte Aufgabe dran, die man aber ohne diesen Foliensatz nicht bearbeiten konnte). Ich bin sehr zufrieden mit dieser Veranstaltung, einzig die Tatsache, dass man sich ständig als &#8220;Exmatrikulator&#8221; aufgeführt hat, ist mir mehrfach übel aufgestoßen. Man stand quasi dauernd unter Verdacht, Lösungen von Kommilitonen zu kopieren. Das nervt irgendwann&#8230;</p>
<h4>Technische Grundlagen der Informatik 2</h4>
<p>In TGdI 2 wurde uns im Wesentlichen beigebracht wie <strong>Prozessoren</strong> funktionieren. Das beinhaltet die verschiedenen binären Zahlen-Darstellungen (1er-Komplement, 2er-Komplement, Gleitkommazahlen uvm.), die Begriffe Steuerwerk &#038; Operationswerk, ALUs und eine Einführung in die MIPS-Prozessorarchitektur (Eintaktimplementierung, Mehrtaktimplementierung und eine Implementierung mit Pipelining und alles was dazugehört, also z.B. Forwarding und Hazard Detection uvm.). In der Praxis haben wir mit Verilog gearbeitet, einer Hardware-Beschreibungssprache. Mit dieser Sprache haben wir in vielen Übungen digitale Schaltungen beschrieben und simuliert; eine sehr spannende Angelegenheit. Eine kleine Einführung in die Assembler-Programmierung hat es hier ebenfalls gegeben.</p>
<p><strong>Klausuren:</strong> 1 Semestralklausur, die für das Ergebnis nur insofern relevant war, als dass man sich hier einen Bonus für die eigentliche Klausur am Ende des Semesters holen konnte.</p>
<p><strong>Bewertung:</strong> Die Veranstaltung war sehr gut gemacht! Gute Folien, gute Übungen und eine fordernde, aber faire Klausur zum Schluss. Die Semestralklausur war ebenfalls in Ordnung. Außerdem &#8211; gut, das ist jetzt eher subjektiv &#8211; war das Thema sehr interessant. <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h4>Mathematik für Inf und WInf 2</h4>
<p>Von der Qualität der Veranstaltung her genauso schlimm wie Mathe 1. Die eigentliche Leistung bestand wieder darin rechtzeitig vor den Klausuren den ganzen Schmodder, den man sich umsonst reingezogen hat, wieder loszuwerden und einen freien Kopf zu kriegen. Dann erst kann man sich richtig auf die Klausur vorbereiten.</p>
<p>Inhaltlich bot Mathe 2 lineare Algebra, Analysis mit mehrstelligen Funktionen und einfache Differentialgleichungen (DGL), lineare Systeme von DGL usw.</p>
<p><strong>Klausuren:</strong> Wie bei Mathe 1 gab es nur eine Klausur am Ende des Semesters. Diese Klausur war &#8211; anders als bei Mathe 1 &#8211; <strong>viel schwerer</strong> als wir erwartet hatten. So kam dann auch eine <strong>Durchfallquote von 60%</strong> bzw. eine <strong>Durchschnittsnote von 4.27</strong> zustande. Ich habe es dennoch geschafft unter die besten 10% zu kommen, trotzdem bin ich etwas enttäuscht von der <em>absoluten</em> Note.</p>
<p><strong>Bewertung:</strong> Ja, was soll man dazu sagen? Die Vorlesung ist grauenvoll, weil sie zu 90% unbrauchbares mathematisches Gedöns enthält, das eine riesige Belastung darstellt, weil man eben erstmal nicht weiß, was davon nun Gedöns ist und was man wirklich braucht. Also zieht man sich <em>alles</em> rein und ordnet den Stoff <em>hinterher</em> in &#8220;Unbrauchbar&#8221; und &#8220;Brauchbar&#8221;. Sorry, aber das muss einfach mal gesagt werden: Die Vorlesung ist scheiße.<br />
Die Übungen hingegen waren einigermaßen in Ordnung. Es gab übrigens viele betreute Extra-Übungen vor der Klausur &#8211; eine super Gelegenheit zur Vorbereitung, die man bei anderen Veranstaltungen meist nicht bekommt.</p>
<h4>Formale Grundlagen der Informatik 2</h4>
<p>Kurzfassung: Nach FGdI 2 habe ich mich kaum noch über FGdI 1 beschwert.<br />
Das liegt daran, dass FGdI 2 letzteres nochmals deutlich unterboten hat. Erklärungen gab es keine und die wenigen Beispiele in den Folien verstehe ich heute noch nicht &#8211; trotz guter Prüfungsnote. Hier hat man sich keine Mühe gegeben, so viel steht fest. Mal wieder hat sich mein Motto <strong>&#8220;schlimmer geht immer&#8221;</strong> bestätigt. Dagegen war die Mathe 2 &#8211; Vorlesung fast schon wieder genießbar.</p>
<p>Inhaltlich ging es in FGdI 2 um die <strong>Aussagenlogik</strong> (quasi boolesche Algebra) und die <strong>Prädikatenlogik</strong> (im Wesentlichen Aussagenlogik erweitert um All- und Existenzquantoren).</p>
<p><strong>Klausur:</strong> Nur eine Klausur am Ende des Semesters (48 Punkte brauchte man für 100%, 60 gab es insgesamt). Naja: <em>eigentlich</em>! Leider gab es während der Klausur in einem der Gebäude einen Feueralarm. Dadurch konnten etwa 2 Drittel der Studenten die Klausur nicht weiterschreiben und mussten die Klausur etwa 3 Wochen später wiederholen &#8211; der neue Termin für FGdI 2 lag zudem direkt hinter 2 anderen knackigen Klausuren. Einen Vorteil hatten wir Wiederholenden (ich war einer der Unglücklichen) also nicht, denn wir mussten uns auf die anderen Klausuren konzentrieren (unter anderem auf den &#8220;Exmatrikulator&#8221;: GdI 2). Trotzdem war die Wiederholungsklausur schwerer als die 1. Klausur. Schwerer ist eigentlich der falsche Ausdruck: <strong>Die Wiederholungsklausur war um Längen schwerer!</strong> Es gab in jeder Ecke irgendeine Falle, und die meisten sind voll ins Messer gelaufen.<br />
Hier die Notenspiegel der beiden Klausuren im Vergleich (PDF von mir erstellt, Angaben ohne Gewähr!): <a href="http://www.robertnitsch.de/wp-content/uploads/2009/10/Notenspiegel_FGdI2_SS09.pdf" class="lipdf">Notenspiegel FGdI2 SS09</a><br />
Unbedingt zu beachten sind die Punktegrenzen auf Seite 2. Ursprünglich benötigte man 24 Punkte zum Bestehen (50% von 48). Diese Grenze wurde bereits bei der 1. Klausur deutlich herabgesetzt. Bei der Wiederholungsklausur brauchte man schließlich nur noch 15 Punkte! Das sind etwa 31%!<br />
Man kann sich also ungefähr ausmalen wie viel schwerer die Wiederholungsklausur war. Für mich war das Ganze nicht mehr nachvollziehbar.</p>
<p><strong>Bewertung:</strong> Die Vorlesung &#038; die Folien waren grauenvoll, die Übungen mäßig und die Klausuren wurden insofern versaut, als dass die Wiederholungsklausur in einem völlig unangebrachten Ausmaß schwerer war als die 1. Klausur. FGdI 2 war sehr bitter!</p>
<h3>Fazit</h3>
<p>Die ersten 2 Semester sind definitiv eine <strong>Durststrecke</strong>. Besonders diejenigen Veranstaltungen, die vom Fachbereich Mathematik organisiert werden (das sind Mathe 1 &#038; 2 und Formale Grundlagen 1 &#038; 2), leiden an grauenvollen Vorlesungen und schwer nachvollziehbaren Folien/Skripten. Genausogut könnten wir auch die normalen Mathe-Vorlesungen hören, da bräuchte es kein Mathematik <strong>für Informatiker</strong> (das beziehe ich jetzt wirklich nur auf die Vorlesung; was die Übungen und die Klausur angeht habe ich nichts einzuwenden <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). Mich haben also keineswegs die Veranstaltungen gestört, in denen es etwas theoretischer zuging. Nein, mich stört, dass sich der FB Mathematik bei Veranstaltungen <strong>für Informatiker</strong> scheinbar nicht die allergeringste Mühe zu geben scheint. Die Veranstaltungen tragen zwar &#8220;für Informatiker&#8221; im Namen, inhaltlich ist das jedoch (abgesehen vllt. von der Klausur) kaum zu spüren. Mag sein, dass sie den Stoff tatsächlich ein wenig für die Informatiker angepasst haben. Für mich steht aber fest: Da ist noch viel zu viel Luft nach oben.</p>
<p>Das 3. Semester hingegen sieht bisher ausgesprochen gut aus. Das liegt ganz gewiss auch daran, dass sämtliche Veranstaltungen vom FB Informatik organisiert werden. Man spürt sofort, dass die Veranstalter einen ganz anderen Blick auf die Dinge haben und vermitteln.</p>
<h4>Fallt mir nicht in den Rücken&#8230;</h4>
<p>Ich habe schon mehrfach die Lehrveranstaltungen des FB Mathematik im Fachschaftsforum kritisiert, da hier wie gesagt einiges im Argen liegt. Dabei sind mir viele Kommilitonen in den Rücken gefallen mit scheinheiligen Argumenten wie &#8220;schau dir doch Erklärungen im Internet an&#8221; oder &#8220;das ist der Anspruch einer Universität&#8221; usw. Sinngemäß wurde mir viel zu oft vermittelt: &#8220;Wenn du zu dumm dafür bist, dann studier etwas anderes oder organisiere dich besser.&#8221; Das möchte ich an dieser Stelle gerne vermeiden.</p>
<p>Niemand konnte mir bisher erklären, warum sich manche Veranstalter (des FB Mathematik) auf die faule Haut legen dürfen, während man sich bei anderen bereits über Kleinigkeiten aufregt (mehrfach geschehen).<br />
<strong>Die Grundlagen-Veranstaltungen der ersten 2 Semester, die vom FB Mathematik organisiert werden, sind einfach <em>scheiße</em>.</strong> Diese meine Ansicht habe ich jetzt an mehreren Stellen mehr oder weniger grob erklärt (Kurzfassung: es steht zwar &#8220;für Informatiker&#8221; drauf, das ist aber nicht drin!). Findet euch damit ab, dass man mich nicht von dieser Ansicht abbringt, indem man mir immer wieder erklärt, dass es Veranstaltungen gibt, die noch schlechter sind oder dass ich zu dumm oder zu faul bin. Ich habe Mathe 1/2 und FGdI 1/2 auf Anhieb bestanden und außer bei FGdI 2 habe ich jedes Mal zu den besten 10% gehört (bei FGdI 2 nur zu den besten 16% mangels Motivation). Von Dummheit oder Faulheit möchte ich nichts mehr hören, egal wie ihr diese Anschuldigungen verpackt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2009/11/28/tu-darmstadt-ruckblick-auf-2-semester-informatik/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Java Generics vs. Java Listen</title>
		<link>http://www.robertnitsch.de/2009/03/31/java-generics-vs-java-listen/</link>
		<comments>http://www.robertnitsch.de/2009/03/31/java-generics-vs-java-listen/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 20:09:35 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Informatik]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Studium]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/?p=211</guid>
		<description><![CDATA[Beim Thema Generics in Verbindung mit Listen geht vieles drunter und drüber. Dabei ist die Sache gar nicht so schwer, wenn man das Prinzip einmal verstanden hat&#8230; Zunächst einmal: Generics ermöglichen mittels formaler Typparamter, dass Klassen (und Funktionen), die bestimmte Dienste zur Verfügung stellen, mit mehreren Datentypen umgehen können. Wenn wir zum Beispiel zwei beliebige [...]]]></description>
			<content:encoded><![CDATA[<p>Beim Thema Generics in Verbindung mit Listen geht vieles drunter und drüber. Dabei ist die Sache gar nicht so schwer, wenn man das Prinzip einmal verstanden hat&#8230;</p>
<p>Zunächst einmal: Generics ermöglichen mittels <em>formaler Typparamter</em>, dass Klassen (und Funktionen), die bestimmte Dienste zur Verfügung stellen, mit mehreren Datentypen umgehen können.<br />
Wenn wir zum Beispiel zwei beliebige Objekte als &#8220;Paar&#8221; verwalten wollen, dann benötigen wir eine entsprechende Klasse mit zwei Attributen, einer Möglichkeit die Objekte darin zu speichern und wieder auszulesen.</p>
<p>An sich nichts schweres:</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
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Pair <span style="color: #009900;">&#123;</span>
    <span style="color: #003399;">Object</span> obj1, obj2<span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">// Das Einspeichern von Objekten ist der Einfachheit halber nur beim Erzeugen des Paares möglich...</span>
    Pair<span style="color: #009900;">&#40;</span><span style="color: #003399;">Object</span> obj1, <span style="color: #003399;">Object</span> obj2<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">obj1</span> <span style="color: #339933;">=</span> obj1<span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">obj2</span> <span style="color: #339933;">=</span> obj2<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Object</span> getFirst<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">obj1</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Object</span> getSecond<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">obj2</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Diese Klasse hat aber einen Haken. Beim Einspeichern gehen die Informationen über den Typ der eingespeicherten Objekte verloren. Wenn wir den Typ wiederherstellen wollen müssen wir einen expliziten Cast durchführen. Andernfalls erhalten wir immer nur <em>Object</em>s.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">Pair paar <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Pair<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> MeinApfel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #000000; font-weight: bold;">new</span> MeinApfel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
MeinApfel apfel <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>MeinApfel<span style="color: #009900;">&#41;</span>paar.<span style="color: #006633;">getFirst</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Bei Listen ist das Problem noch dramatischer. Ohne Generics muss man bei jeder Leseoperation auf einer Liste explizit casten:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #003399;">Vector</span> liste <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Vector</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i<span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span><span style="color: #cc66cc;">10</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    liste.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> MeinApfel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #000000; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i<span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span>liste.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    esseApfel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>MeinApfel<span style="color: #009900;">&#41;</span> liste.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Bei so vielen expliziten Casts riskiert man außerdem <em>ClassCastException</em>s, falls das referenzierte Objekt nicht zu dem entsprechenden Typ konvertiert werden kann.</p>
<p>Abhilfe schaffen hier die Generics. Das soll erstmal am Beispiel der obigen Pair-Klasse demonstriert werden, die folgendermaßen generisch gemacht werden kann:</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
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Pair<span style="color: #339933;">&lt;</span>A,B<span style="color: #339933;">&gt;</span> <span style="color: #009900;">&#123;</span>
    A obj1<span style="color: #339933;">;</span>
    B obj2<span style="color: #339933;">;</span>
    Pair<span style="color: #009900;">&#40;</span>A obj1, B obj2<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">obj1</span> <span style="color: #339933;">=</span> obj1<span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">obj2</span> <span style="color: #339933;">=</span> obj2<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">public</span> A getFirst<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">obj1</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">public</span> B getSecond<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">obj2</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>A und B sind sogenannte formale Typparameter, die in diesem Fall für beliebige Typen stehen.<br />
Folgendermaßen erzeugen wir jetzt Paare von Integer-Objekten:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// anschaulich wird hier A = Integer und B = Integer gesetzt</span>
Pair<span style="color: #339933;">&lt;</span>Integer, Integer<span style="color: #339933;">&gt;</span> paar <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Pair<span style="color: #339933;">&lt;</span>Integer, Integer<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Integer</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span>, <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Integer</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// kein Cast mehr nötig, weil auch die Signatur von getFirst() quasi dynamisch an Integer angepasst wurde</span>
<span style="color: #003399;">Integer</span> zahl <span style="color: #339933;">=</span> paar.<span style="color: #006633;">getFirst</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Dasselbe ist natürlich auch bei Listen möglich, die bei der Einführung der Generics auch gleich generisch gemacht wurden. Bei Listen gibt es im Gegensatz zu dem Pair-Beispiel nur <em>einen</em> formalen Typparameter, der den Typ der gespeicherten Elemente festlegt.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Eine Liste von Elementen des Typs &quot;MeinApfel&quot; anlegen...</span>
Vector<span style="color: #339933;">&lt;</span>MeinApfel<span style="color: #339933;">&gt;</span> liste <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Vector<span style="color: #339933;">&lt;</span>MeinApfel<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
liste.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> MeinApfel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// ...</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// funktioniert problemlos, da die Signatur von get() genau wie getFirst() aus dem ersten Beispiel an den ggb. Typ angepasst wurde</span>
MeinApfel apfel <span style="color: #339933;">=</span> liste.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Richtig trickreich wird es, wenn Funktionen, die Listen entgegennehmen, generisch gemacht werden sollen. Angenommen wir wollen eine Funktion schreiben, die eine Liste von Nahrungsmitteln entgegennimmt und ihr Gewicht bestimmt.<br />
In diesem Fall werden sogenannte Wildcards benötigt.</p>
<p>Intuitiv müsste die Funktion folgendermaßen aussehen:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">double</span> wiege<span style="color: #009900;">&#40;</span>List<span style="color: #339933;">&lt;</span>Nahrungsmittel<span style="color: #339933;">&gt;</span> liste<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Diese Funktion würde aber entgegen unserer Intuition bspw. keine Liste mit Äpfeln annehmen, obwohl Äpfel in der Klassenhierarchie ganz klar ein Subtyp von Nahrungsmittel darstellen würden (<em>public class Apfel extends Nahrungsmittel</em>).<br />
Es funktioniert deshalb nicht, weil List&lt;Apfel&gt; einfach nicht kompatibel ist zu List&lt;Nahrungsmittel&gt;. Beispiel:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">Vector<span style="color: #339933;">&lt;</span>Nahrungsmittel<span style="color: #339933;">&gt;</span> liste1 <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Vector<span style="color: #339933;">&lt;</span>Nahrungsmittel<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// OK!</span>
Vector<span style="color: #339933;">&lt;</span>Apfel<span style="color: #339933;">&gt;</span> liste2 <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Vector<span style="color: #339933;">&lt;</span>Apfel<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// OK!</span>
liste1 <span style="color: #339933;">=</span> liste2<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// FEHLER: cannot convert from Vector&lt;Apfel&gt; to Vector&lt;Nahrungsmittel&gt;</span></pre></td></tr></table></div>

<p>Dieser Code wird vom Compiler deshalb nicht akzeptiert, weil man in eine Liste von Äpfeln keine Nahrungsmittel einfügen kann. Wenn <em>liste1</em> vom Typ List&lt;Nahrungsmittel&gt; auf <em>liste2</em> vom Typ List&lt;Apfel&gt; verweisen würde, dann würde das bspw. die Signatur von liste1.add(&#8230;) verletzen, denn liste1.add(new Nahrungsmittel()) wäre nicht möglich, weil liste1 auf eine Liste von Äpfeln (und nur Äpfel!) zeigen würde. Das meine ich, wenn ich schreibe, dass List&lt;Apfel&gt; nicht kompatibel ist zu List&lt;Nahrungsmittel&gt;.</p>
<p>Das Problem löst man mit besagten Wildcards:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">double</span> wiege<span style="color: #009900;">&#40;</span>List<span style="color: #339933;">&lt;?</span> <span style="color: #000000; font-weight: bold;">extends</span> Nahrungsmittel<span style="color: #339933;">&gt;</span> liste<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// akzeptiert alle Listen, deren Elemente Nahrungsmittel oder Subtypen davon sind</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>? steht für einen unbekannten Typ. Bekannt ist bei einer List&lt;?&gt; nur, dass &#8211; wie bei jeder typ-parametrisierten Liste &#8211; die Elemente, die in der Liste gespeichert sind, alle vom selben (unbekannten) Typ sind.<br />
Das &#8220;extends Nahrungsmittel&#8221; schränkt die möglichen Typen hier aber insofern ein, als dass Nahrungsmittel die &#8220;obere Schranke&#8221; darstellt. ? darf hier also vom Typ Nahrungsmittel oder ein Subtyp davon sein.</p>
<p>Es gibt auch die Möglichkeit eine untere Schranke zu definieren: List&lt;? super Nahrungsmittel&gt; bzw. allgemein List&lt;? super X&gt;. Erlaubt sind dann Elemente vom Typ X oder Supertypen davon.</p>
<p>Bleiben wir zunächst bei unserer List&lt;? extends Nahrungsmittel&gt;. Wir können zumindest eingeschränkt mit einer solchen Liste arbeiten: Lesen, aber nicht Einfügen. Das Einfügen klappt deshalb nicht, weil der genaue Typ der Liste nicht bekannt ist. Zwar kann man einen Apfel zu einem Nahrungsmittel konvertieren. Aber die Liste enthält ja nicht notwendigerweise Nahrungsmittel. Sie kann genausogut Birnen enthalten &#8211; daher darf man in eine solche Liste keine neuen Objekte einfügen.</p>
<p>Im Folgenden eine Tabelle, die die erlaubten Operationen auf einer Liste dokumentiert:</p>
<table border="1" class="data">
<tr>
<th>Typ</th>
<th>Lesen</th>
<th>Typ der gelesenen Objekte</th>
<th>Einfügen</th>
<th>Einfügbare Typen</th>
</tr>
<tr>
<th style="text-align:left;">List</th>
<td>Ja</td>
<td>Object</td>
<td>Ja</td>
<td>Beliebig</td>
</tr>
<tr>
<th style="text-align:left;">List&lt;?&gt;</th>
<td>Ja</td>
<td>Object</td>
<td>Nein</td>
<td>-</td>
</tr>
<tr>
<th style="text-align:left;">List&lt;X&gt;</th>
<td>Ja</td>
<td>X</td>
<td>Ja</td>
<td>X oder Subtypen von X</td>
</tr>
<tr>
<th style="text-align:left;">List&lt;? extends X&gt;</th>
<td>Ja</td>
<td>X</td>
<td>Nein</td>
<td>-</td>
</tr>
<tr>
<th style="text-align:left;">List&lt;? super X&gt;</th>
<td>Ja</td>
<td>Object</td>
<td>Ja</td>
<td>X oder Subtypen von X</td>
</tr>
</table>
<p>Bleibt nur noch die Frage zu klären, warum man in eine List&lt;? super X&gt; Elemente vom Typ X und Subtypen von X einfügen darf. Bei List&lt;? extends X&gt; ist das schließlich auch nicht möglich. Nunja, bei <em>extends X</em> sind die Elemente der Liste vom Typ X oder Subtypen davon, d.h. <em>spezieller</em>. Bei <em>super X</em> sind die Elemente vom Typ X oder Supertypen von X, d.h. <em>allgemeiner</em>. Daher kann man Objekte vom Typ X oder von einem Subtyp von X nach Belieben in eine solche Liste einfügen, weil man Objekte von einem bestimmten Typ immer zu einem allgemeineren Typ konvertieren kann.<br />
Faustregel: Jeder Apfel ist ein Obst, aber nicht jedes Obst ein Apfel!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2009/03/31/java-generics-vs-java-listen/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Motivationskurve beim Erlernen einer Programmiersprache</title>
		<link>http://www.robertnitsch.de/2008/09/19/motivationskurve-beim-erlernen-einer-programmiersprache/</link>
		<comments>http://www.robertnitsch.de/2008/09/19/motivationskurve-beim-erlernen-einer-programmiersprache/#comments</comments>
		<pubDate>Fri, 19 Sep 2008 15:31:36 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[Freaky]]></category>
		<category><![CDATA[Informatik]]></category>
		<category><![CDATA[Lustiges]]></category>
		<category><![CDATA[PC]]></category>
		<category><![CDATA[Programmieren]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/?p=115</guid>
		<description><![CDATA[Peter Kroener hat eine geniale Grafik / Motivationskurve veröffentlicht, die die Motivation beim Erlernen einer neuen Programmiersprache beschreibt. Ich musste herzhaft lachen, weil mich die Kurve so sehr an meine eigenen Erfahrungen erinnert.]]></description>
			<content:encoded><![CDATA[<p>Peter Kroener hat eine <a href="http://www.peterkroener.de/die-neue-programmiersprache-lernen/" class="liexternal">geniale Grafik / Motivationskurve veröffentlicht</a>, die die Motivation beim Erlernen einer neuen Programmiersprache beschreibt. Ich musste herzhaft lachen, weil mich die Kurve so sehr an meine eigenen Erfahrungen erinnert. <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p><img style="margin-left:20px;" src="http://www.peterkroener.de/wp-content/uploads/2008/08/die-neue-programmiersprache-lernen-359x477.png" alt="Motivationskurve" border="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2008/09/19/motivationskurve-beim-erlernen-einer-programmiersprache/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>AutoIt3: Vereinfachung der Windows-Funktion &#8220;Ausführen als&#8230;&#8221;</title>
		<link>http://www.robertnitsch.de/2008/09/08/autoit3-vereinfachung-der-windows-funktion-ausfuhren-als/</link>
		<comments>http://www.robertnitsch.de/2008/09/08/autoit3-vereinfachung-der-windows-funktion-ausfuhren-als/#comments</comments>
		<pubDate>Sun, 07 Sep 2008 22:57:52 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[PC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/?p=102</guid>
		<description><![CDATA[Im letzten Artikel habe ich die Programmiersprache AutoIt3 und das Beispielskript &#8220;FensterRetter&#8221; vorgestellt. Dieses Mal möchte ich ein etwas praktikableres Skript vorstellen, das ich schon seit einigen Wochen intensiv nutze: AusfuehrenAls.au3 Unter Windows XP kann man einzelne Anwendungen/Programme unter einem anderen Benutzerkonto ausführen, ohne sich ab- und neu anmelden zu müssen (http://www.zdnet.de/enterprise/os/0,39023494,20000267-43,00.htm). Wenn man z.B. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.robertnitsch.de/2008/07/29/autoit-windows-eigentliche-skriptsprache/" class="liinternal">Im letzten Artikel</a> habe ich die Programmiersprache AutoIt3 und das Beispielskript <em>&#8220;FensterRetter&#8221;</em> vorgestellt. Dieses Mal möchte ich ein etwas praktikableres Skript vorstellen, das ich schon seit einigen Wochen intensiv nutze: <em>AusfuehrenAls.au3</em></p>
<p>Unter Windows XP kann man einzelne Anwendungen/Programme unter einem anderen Benutzerkonto ausführen, ohne sich ab- und neu anmelden zu müssen (<a href="http://www.zdnet.de/enterprise/os/0,39023494,20000267-43,00.htm" class="liexternal">http://www.zdnet.de/enterprise/os/0,39023494,20000267-43,00.htm</a>). Wenn man z.B. <em>Rechtsklick (auf eine Verknüpfung) -> Ausführen als&#8230;</em> anwählt, dann erscheint ein solcher Dialog:<br />
<a href="http://www.robertnitsch.de/wp-content/uploads/2008/09/ausfuehren_als.jpg" class="liimagelink"><img src="http://www.robertnitsch.de/wp-content/uploads/2008/09/ausfuehren_als.jpg" alt="&quot;Ausführen als...&quot; unter Windows XP" title="&quot;Ausführen als...&quot; unter Windows XP" width="383" height="321" class="size-full wp-image-103" /></a></p>
<p>Dieser Dialog hat einige gravierende Mängel:</p>
<ul>
<li>Die Option &#8220;Aktueller Benutzer (&#8230;)&#8221; ist vorausgewählt.</li>
<li>Die Option &#8220;Aktueller Benutzer (&#8230;)&#8221; wird in 99,9% aller Fälle nicht gebraucht, denn wozu macht man Rechtsklick auf eine Anwendung, klickt dann auf &#8220;Ausführen als&#8230;&#8221;, wenn man das Programm ja doch unter dem eigenen Benutzerkonto ausführen möchte. Sinn? Keiner!</li>
<li>Das Eingabefeld für den Benutzernamen unter der Option &#8220;Folgender Benutzer&#8221; speichert zwar die im Laufe der Zeit eingegebenen Namen, aber es ist immer &#8220;Administrator&#8221; voreingegeben.</li>
</ul>
<p>All diese Nachteile haben zur Folge, dass man mehrere Sekunden braucht, um ein Programm endlich unter einem anderen Benutzerkonto auszuführen, vor allem wenn das benötigte Benutzerkonto nicht den Namen &#8220;Administrator&#8221; hat. Wenn man allerdings auf diese Funktion angewiesen ist, dann wird das Ganze sehr schnell nervig.</p>
<p>Abhilfe schafft hier mein Skript:</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
23
24
25
</pre></td><td class="code"><pre class="vb" style="font-family:monospace;">; AusfuehrenAls.au3
;
; Ein Skript zum Vereinfachen der Windows-Funktion <span style="color: #800000;">&quot;Ausführen als...&quot;</span>
; Für Windows XP.
;
; www.robertnitsch.de
&nbsp;
#include <span style="color: #800000;">&quot;Misc.au3&quot;</span>
_Singleton(<span style="color: #800000;">&quot;AusfuehrenAls&quot;</span>)
&nbsp;
; Der Name des auszuwählenden Benutzers
$user = <span style="color: #008000;">'Mein_Administrator_Konto'
</span>
&nbsp;
; Ab hier nichts mehr ändern
Opt(<span style="color: #800000;">&quot;WinWaitDelay&quot;</span>, 500)
ProcessSetPriority(@AutoItPID, 1)
&nbsp;
<span style="color: #000080;">While</span> <span style="color: #000080;">True</span>
	WinWaitActive(<span style="color: #800000;">&quot;Ausführen als&quot;</span>)
	Send(<span style="color: #800000;">&quot;{DOWN 2}&quot;</span>)
	Send($user)
	Send(<span style="color: #800000;">&quot;{TAB}&quot;</span>)
	WinWaitClose(<span style="color: #800000;">&quot;Ausführen als&quot;</span>)
WEnd</pre></td></tr></table></div>

<p>Das Skript wählt bei Erscheinen des &#8220;Ausführen als&#8221;-Dialogs automatisch die Option &#8220;Folgender Benutzer&#8221; aus und gibt einen voreingestellten Benutzernamen (Zeile 12) ein. Ich habe das Skript in meinen Autostart gepackt und bin seither zufrieden damit!</p>
<h3>Download von AusfuehrenAls.au3</h3>
<p><a href="http://www.robertnitsch.de/wp-content/uploads/2008/09/ausfuehrenals.zip" class="lizip">AusfuehrenAls.zip</a> (1 KB)</p>
<p>Zur Ausführung und/oder Kompilierung wird AutoIt3 benötigt: <a href="http://www.autoitscript.com/autoit3/" class="liexternal">http://www.autoitscript.com/autoit3/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2008/09/08/autoit3-vereinfachung-der-windows-funktion-ausfuhren-als/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AutoIt &#8211; Windows&#8217; eigentliche Skriptsprache&#8230;</title>
		<link>http://www.robertnitsch.de/2008/07/29/autoit-windows-eigentliche-skriptsprache/</link>
		<comments>http://www.robertnitsch.de/2008/07/29/autoit-windows-eigentliche-skriptsprache/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 22:13:54 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[PC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.robertnitsch.de/?p=100</guid>
		<description><![CDATA[Ich habe vor einigen Tagen AutoIt wiederentdeckt. AutoIt ist eine BASIC-ähnliche Skriptsprache zur Automatisierung von Windows. Automatisierung umfasst das vielfältige &#8220;Simulieren&#8221; von Benutzerinteraktionen (Mausklicks / Tastatureingaben) oder sogar das direkte Manipulieren von Programmfenstern (verschieben / vergrößern / maximieren / minimieren / verändern uvm.) &#8230; Offizielle Kurzbeschreibung: AutoIt v3 is a freeware BASIC-like scripting language designed [...]]]></description>
			<content:encoded><![CDATA[<p>Ich habe vor einigen Tagen <a href="http://www.autoitscript.com/" class="liexternal">AutoIt</a> wiederentdeckt. AutoIt ist eine BASIC-ähnliche Skriptsprache zur Automatisierung von Windows. Automatisierung umfasst das vielfältige &#8220;Simulieren&#8221; von Benutzerinteraktionen (Mausklicks / Tastatureingaben) oder sogar das direkte Manipulieren von Programmfenstern (verschieben / vergrößern / maximieren / minimieren / verändern uvm.) &#8230;</p>
<p>Offizielle Kurzbeschreibung:</p>
<blockquote><p><em>AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained <strong>and will run on all versions of Windows out-of-the-box with no annoying &#8220;runtimes&#8221; required!</strong></em></p></blockquote>
<p>An AutoIt faszinieren mich vor allem:</p>
<ul>
<li>die unglaubliche Fülle an Funktionen in der Standardauslieferung (das erinnert mich ein wenig an die Standardbibliothek von Python, obgleich diese natürlich noch viel mächtiger ist&#8230; dennoch: <em>&#8220;batteries included&#8221;</em>)</li>
<li>die sehr gute Dokumentation! Fast zu jeder Funktion gibt es auch ein Beispielskript. Es funktioniert ganz einfach so, wie es beschrieben ist! Auf diese Weise macht das Skripten fast so viel Spaß wie mit Python&#8230;</li>
<li>die Möglichkeit, Skripte zu kompilieren. Sie müssen dann nicht mehr interpretiert werden, sondern sind von sich aus lauffähig auf fast allen Windows-Systemen.</li>
</ul>
<h3>Beispielskript: Der Fensterretter</h3>
<p>Ich will auch noch ein ganz kleines Beispielskript vorstellen:<br />
Vorgestern hatte ein Freund von mir das Problem, dass sich ein Programmfenster außerhalb seines Desktops befand. Das Programmfenster war auch herkömmlichem Wege (z.B. neustarten) nicht wiederzubekommen und eine entsprechende Windows-Funktion hat er nicht gefunden (weil sie sehr gut versteckt oder nicht existent ist).<br />
Das Problem tritt relativ häufig dann auf, wenn man mit mehreren Bildschirmen arbeitet.</p>
<p>Zur Lösung dieses Problems habe ich kurzerhand den &#8220;FensterRetter&#8221; ins Leben gerufen. Nach 5 Minuten war er fertig und das Fenster wieder da, wo es sein sollte. Dank AutoIt!</p>
<p>Code:</p>

<div class="wp_syntax"><div class="code"><pre class="autoit" style="font-family:monospace;"><span style="font-style: italic; color: #009933;">; FensterRetter.au3</span>
<span style="font-style: italic; color: #009933;">; www.robertnitsch.de</span>
<span style="font-style: italic; color: #009933;">;</span>
&nbsp;
<span style="color: #F000FF; font-style: italic;">#Include</span> <span style="color: #FF0000; font-weight: bold;">&lt;</span>WinAPI<span style="color: #FF0000; font-weight: bold;">.</span><span style="color: #0000FF; font-style: italic; font-weight: bold;">au3</span><span style="color: #FF0000; font-weight: bold;">&gt;</span>
&nbsp;
<span style="font-weight: bold; color: #AA0000;">$titel</span> <span style="color: #FF0000; font-weight: bold;">=</span> <span style="color: #000080; font-style: italic; font-weight: bold;">InputBox</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="font-weight: bold; color: #008080;">&quot;Fenstertitel&quot;</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="font-weight: bold; color: #008080;">&quot;Den Titel oder wenigstens den Anfang des Titels von dem Fenster, das gerettet werden soll, angeben:&quot;</span><span style="color: #FF0000; font-weight: bold;">&#41;</span>
<span style="color: #0000FF; font-weight: bold;">if</span> <span style="font-weight: bold; color: #AA0000;">$titel</span> <span style="color: #FF0000; font-weight: bold;">=</span> <span style="font-weight: bold; color: #008080;">&quot;&quot;</span> <span style="color: #0000FF; font-weight: bold;">Then</span>
	<span style="color: #000080; font-style: italic; font-weight: bold;">msgbox</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="color: #AC00A9; font-style: italic; font-weight: bold;">32</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="font-weight: bold; color: #008080;">&quot;Fehler&quot;</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="font-weight: bold; color: #008080;">&quot;Ohne Fenstertitel geht hier gar nichts, sorry...&quot;</span><span style="color: #FF0000; font-weight: bold;">&#41;</span>
	<span style="color: #0000FF; font-weight: bold;">exit</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="color: #AC00A9; font-style: italic; font-weight: bold;">1</span><span style="color: #FF0000; font-weight: bold;">&#41;</span>
<span style="color: #0000FF; font-weight: bold;">endif</span>
&nbsp;
<span style="font-weight: bold; color: #AA0000;">$handle</span> <span style="color: #FF0000; font-weight: bold;">=</span> <span style="color: #000080; font-style: italic; font-weight: bold;">WinGetHandle</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="font-weight: bold; color: #AA0000;">$titel</span><span style="color: #FF0000; font-weight: bold;">&#41;</span>
&nbsp;
<span style="color: #0000FF; font-weight: bold;">if</span> <span style="font-weight: bold; color: #AA0000;">$handle</span> <span style="color: #FF0000; font-weight: bold;">=</span> <span style="font-weight: bold; color: #008080;">&quot;&quot;</span> <span style="color: #0000FF; font-weight: bold;">Then</span>
	<span style="color: #000080; font-style: italic; font-weight: bold;">msgbox</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="color: #AC00A9; font-style: italic; font-weight: bold;">32</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="font-weight: bold; color: #008080;">&quot;Fehler&quot;</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="font-weight: bold; color: #008080;">&quot;Sorry, aber dieses Fenster konnte nicht gefunden werden... versuch einen anderen Titel!&quot;</span><span style="color: #FF0000; font-weight: bold;">&#41;</span>
	<span style="color: #0000FF; font-weight: bold;">exit</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="color: #AC00A9; font-style: italic; font-weight: bold;">1</span><span style="color: #FF0000; font-weight: bold;">&#41;</span>
<span style="color: #0000FF; font-weight: bold;">Else</span>
	<span style="color: #0080FF; font-style: italic; font-weight: bold;">_WinAPI_MoveWindow</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="font-weight: bold; color: #AA0000;">$handle</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="color: #AC00A9; font-style: italic; font-weight: bold;">10</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="color: #AC00A9; font-style: italic; font-weight: bold;">10</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="color: #0080FF; font-style: italic; font-weight: bold;">_WinAPI_GetWindowWidth</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="font-weight: bold; color: #AA0000;">$handle</span><span style="color: #FF0000; font-weight: bold;">&#41;</span><span style="color: #FF0000; font-weight: bold;">,</span> <span style="color: #0080FF; font-style: italic; font-weight: bold;">_WinAPI_GetWindowHeight</span><span style="color: #FF0000; font-weight: bold;">&#40;</span><span style="font-weight: bold; color: #AA0000;">$handle</span><span style="color: #FF0000; font-weight: bold;">&#41;</span><span style="color: #FF0000; font-weight: bold;">&#41;</span>
<span style="color: #0000FF; font-weight: bold;">endif</span></pre></div></div>

<p>Das Tool fragt a) den Fenstertitel ab, b) ermittelt das Fenster-Handle und c) schiebt das Fenster per API-Aufruf an die linke obere Bildschirmecke.</p>
<h3>Download</h3>
<p><a href="http://www.robertnitsch.de/wp-content/uploads/2008/07/fensterretter.zip" class="lizip">FensterRetter.zip</a> (290 KB)</p>
<h3>Fazit</h3>
<p>AutoIt ist mächtiger als vergleichbare Skriptsprachen (VBScript *kotz*), wahrscheinlich auch noch viel besser dokumentiert und sehr zuverlässig. AutoIt ist alles in allem <strong>auf jeden Fall</strong> einen Blick wert!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2008/07/29/autoit-windows-eigentliche-skriptsprache/feed/</wfw:commentRss>
		<slash:comments>1</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>PHP: Smarty und die Unterstützung mehrerer Sprachen / Multilingualität</title>
		<link>http://www.robertnitsch.de/2007/05/23/php-smarty-und-die-unterstutzung-mehrerer-sprachen-multilingualitat/</link>
		<comments>http://www.robertnitsch.de/2007/05/23/php-smarty-und-die-unterstutzung-mehrerer-sprachen-multilingualitat/#comments</comments>
		<pubDate>Wed, 23 May 2007 21:27:48 +0000</pubDate>
		<dc:creator>Robert</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://robertnitsch.de/2007/05/23/php-smarty-und-die-unterstutzung-mehrerer-sprachen-multilingualitat/</guid>
		<description><![CDATA[Smarty ist die Templateengine für PHP schlechthin. Smarty ist sehr schnell und kann einfach erweitert werden. In diesem Artikel geht es darum, wie man Smarty mehrsprachig betreiben kann bzw. die Templates sprachunabhängig umsetzen kann. Am Ende des Artikels kann der Code heruntergeladen werden. (Hinweis: In diesem Artikel wird PHP5 verwendet und vorrausgesetzt!) Mit Smarty und [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://smarty.php.net" class="liphp">Smarty</a> ist <em>die</em> Templateengine für PHP schlechthin. Smarty ist sehr schnell und kann einfach erweitert werden. In diesem Artikel geht es darum, wie man Smarty mehrsprachig betreiben kann bzw. die Templates sprachunabhängig umsetzen kann. <strong>Am Ende des Artikels kann der Code heruntergeladen werden.</strong></p>
<p>(Hinweis: <em>In diesem Artikel wird PHP5 verwendet und vorrausgesetzt!</em>)</p>
<p>Mit Smarty und ein paar Tricks ist es im Grunde sehr einfach, ein Projekt mehrsprachig zu gestalten. Dazu liest man alle nötigen Strings aus Sprachdateien aus und fügt sie an den jeweiligen Stellen ein. Freiwillige Übersetzer erstellen dann unterschiedliche Sprachdateien und man kann das Projekt auch in anderen Sprachen veröffentlichen.</p>
<p>Bei Smarty bedient man sich für diesen Zweck eines Prefilters. Ein solcher Prefilter verändert die Templates noch bevor sie von Smarty &#8220;kompiliert&#8221; werden.</p>
<p>So ist es z.B. möglich, ein Template wie folgt zu gestalten:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;table border=&quot;0&quot;&gt;
		&lt;tr&gt;
			&lt;td&gt;##user_form_username##&lt;/td&gt;
			&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;user&quot; value=&quot;&quot; /&gt;&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;##user_form_password##&lt;/td&gt;
			&lt;td&gt;&lt;input type=&quot;password&quot; name=&quot;pass&quot; value=&quot;&quot; /&gt;&lt;/td&gt;
		&lt;/tr&gt;
&lt;/table&gt;</pre></div></div>

<p>Die von Rauten (#) umschlossenen Zeichenketten spezifizieren einen bestimmten Sprach-String, dessen Ersetzung in den jeweiligen Sprachdateien angegeben wird. Eine deutsche Sprachdatei könnte etwa so aussehen:</p>
<pre>
user_form_username=Benutzername
user_form_password=Password
</pre>
<p>Der Prefilter sucht also nach Sprachstrings und fügt an ihrer Stelle die entsprechende Ersetzung ein &#8211; je nachdem, welche Sprache eingestellt ist (z.B. in einer serverseitigen Konfigurationsdatei oder innerhalb der übermittelten Browserdaten des Clients usw.).</p>
<p>Für diese Funktionalität empfehle ich eine Klasse, die das Auslesen der Sprachdateien übernimmt. Der Einfachheit nenne ich sie &#8220;<em>Lang</em>&#8220;.</p>
<p>Ich muss aber darauf hinweisen, dass ich diese Klassen aus einem meiner eigenen Projekte entnommen habe. Daher kann es sein, dass ich teilweise vergessen habe, den Code an diesen Artikel anzupassen. Wenn also irgendetwas von &#8220;OBST&#8221; oder &#8220;XDB&#8221; dasteht, wisst ihr Bescheid. <img src='http://www.robertnitsch.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Die Klasse <em>Lang</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #009933; font-style: italic;">/**
      * @author: Robert Nitsch
      */</span>
    <span style="color: #000000; font-weight: bold;">class</span> Lang <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$lng</span><span style="color: #339933;">;</span>
        protected <span style="color: #000088;">$lng_strings</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/**
          * Lädt alle Sprachstrings aus der entsprechenden Sprachdatei.
          * @param string $lng Die Sprache, die geladen werden soll, als Länderkürzel.
          */</span>
        <span style="color: #000000; font-weight: bold;">function</span> load_lng<span style="color: #009900;">&#40;</span><span style="color: #000088;">$lng</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lng</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$lng</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">/* DIR_ROOT muss außerhalb dieser Datei deklariert werden und muss den Pfad
                 zum Hauptverzeichnis des Webprojekts beinhalten
                 Außerdem setzt diese Klasse eine gewisse Verzeichnisstruktur vorraus... (/include/lng) */</span>
            <span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> DIR_ROOT<span style="color: #339933;">.</span><span style="color: #0000ff;">'/include/lng/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$lng</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'.txt'</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$fh</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$path</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'r'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$matches</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$zeile</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fgets</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fh</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^([^;\s]+)\s*=([^;]*).*$/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$zeile</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                    <span style="color: #009900;">&#123;</span>
                        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lng_strings</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
                    <span style="color: #009900;">&#125;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #b1b100;">else</span>
            <span style="color: #009900;">&#123;</span>
                throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;language file '<span style="color: #006699; font-weight: bold;">$path</span>' doesnt exist&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/**
          * Gibt einen Sprachstring zurück.
          * @param string $name Der Name des Sprachstrings.
          */</span>
        <span style="color: #000000; font-weight: bold;">function</span> get<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lng_strings</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">/*
     -&gt; singleton pattern
     (immer nur eine einzige Instanz dieser Klasse zulassen;
     Instanz(en) werden ausschließlich über diese Funktion erstellt)
    */</span>
    <span style="color: #000000; font-weight: bold;">function</span> getLangInstance<span style="color: #009900;">&#40;</span><span style="color: #000088;">$language</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        static <span style="color: #000088;">$lang_instance</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">is_object</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lang_instance</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$obst</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$lang_instance</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Lang<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$lang_instance</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load_lng</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$language</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$lang_instance</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Die angepasste Smarty-Klasse nenne ich <em>LangSmarty</em>. Dem Konstruktor muss natürlich eine Instanz der Klasse Lang übergeben werden. Alles Weitere steht in den Kommentaren.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #009933; font-style: italic;">/**
      * @author: Robert Nitsch
      */</span>
    <span style="color: #000000; font-weight: bold;">class</span> LangSmarty <span style="color: #000000; font-weight: bold;">extends</span> Smarty <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/**
            * Speichert die Instanz der Klasse Lang ab.
            * @var Lang Instanz der Klasse Lang
            */</span>
        protected <span style="color: #000088;">$lang</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/**
          * Konstruktor
          * @param Lang $lang Eine Instanz der Klasse Lang, die die jeweiligen Sprachdaten beinhaltet.
          */</span>
        <span style="color: #000000; font-weight: bold;">function</span> LangSmarty<span style="color: #009900;">&#40;</span>Lang <span style="color: #339933;">&amp;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lang</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$lang</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// muss an das jeweilige Webprojekt angepasst werden</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">template_dir</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'./template_dir'</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">compile_dir</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'./compile_dir'</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cache_dir</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'./cache_dir'</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// den prefilter registrieren</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">register_prefilter</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'translate_prefilter'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/**
          * Diese sogenannte Callback-Funktion wird für jedes Auftauchen von ##(...)## innerhalb von Templates
          * aufgerufen und gibt die jeweilige Ersetzung zurück.
          * @param string $string Die konkrete Übereinstimmung. Z.B. &quot;##user_form_username##&quot;
          */</span>
        <span style="color: #000000; font-weight: bold;">function</span> _translate_callback<span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$string</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lang</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/**
          * Dies ist der Smarty-Prefilter. Er führt die Ersetzung der Sprachstrings ##(...)##
          * durch die Callback-Funktion _translate_callback() durch.
          */</span>
        <span style="color: #000000; font-weight: bold;">function</span> translate_prefilter<span style="color: #009900;">&#40;</span><span style="color: #000088;">$tpl_source</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$smarty</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #990000;">preg_replace_callback</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/##[^#]*##/&quot;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'_translate_callback'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tpl_source</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/**
          * Jede sprache soll einen eigenen Satz an Compiled- und Cached-Files haben.
          * Dafür wird das jeweilige  Länderkürzel einfach in den Dateinamen dieser Dateien eingebaut.
          */</span>
        <span style="color: #000000; font-weight: bold;">function</span> fetch<span style="color: #009900;">&#40;</span><span style="color: #000088;">$_smarty_tpl_file</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_smarty_cache_id</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_smarty_compile_id</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_smarty_display</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #000088;">$_smarty_compile_id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lang</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lng</span><span style="color: #339933;">.</span><span style="color: #000088;">$_smarty_compile_id</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$_smarty_cache_id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_smarty_compile_id</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">fetch</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$_smarty_tpl_file</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_smarty_cache_id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_smarty_compile_id</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_smarty_display</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Anwendung:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
  <span style="color: #000088;">$lang</span> <span style="color: #339933;">=</span> getLangInstance<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'de'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// instanz der Lang-Klasse erstellen</span>
  <span style="color: #000088;">$smarty</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> LangSmarty<span style="color: #009900;">&#40;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// instanz der LangSmarty-Klasse erstellen, dem Konstruktor wird eine Lang-Instanz übergeben</span>
  <span style="color: #000088;">$smarty</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">display</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'startseite.tpl'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// das Template startseite.tpl kompilieren und das Ergebnis dessen Ausführung (ja, bei Smarty werden Templates ausgeführt) an den Client schicken</span>
  <span style="color: #666666; font-style: italic;">// Sprachstrings werden automatisch eingefügt, sofern im Template vorhanden</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Das Ganze lässt sich aber noch optimieren. Die Lösung mit den oben gezeigten Sprachdateien ist zwar einfach, aber bei großen Projekten kann es in viel Arbeit ausarten alle Sprachdateien aktuell zu halten. Auch wenn man diese Arbeit an freiwillige Übersetzer delegieren kann, so empfiehlt es sich, das System generell zu verbessern.</p>
<p>Dies kann mit Hilfe von <a href="http://de.wikipedia.org/wiki/Gettext" rel="nofollow" class="liwikipedia">gettext</a> erreicht werden.</p>
<p>Zitat Wikipedia:</p>
<blockquote><p>GNU gettext ist die GNU-Internationalisierungsbibliothek. Normalerweise wird sie zur Entwicklung von mehrsprachigen Programmen genutzt. Die derzeit aktuelle Version ist 0.16.1.</p></blockquote>
<p>Und ja, auch in PHP kann man auf gettext zugreifen: <a href="http://de2.php.net/gettext" class="liphp">Gettext-Funktionen</a></p>
<p>Dank der objektorientieren Programmierung müssen wir nur die Klasse <em>Lang</em> an gettext anpassen. Das werde ich in diesem Artikel aber nicht mehr bis ins Detail erklären. Letztendlich läuft es darauf hinaus, dass man nur ein paar Zeilen verändert (nicht aber wesentliche Strukturen).</p>
<p>Der größte Aufwand steckt allerdings in der Gewöhnung an gettext. Bevor man auf gettext umsteigt, sollte man sich daher etwas einlesen. Mir hat der Text <a href="http://www.onlamp.com/pub/a/php/2002/06/13/php.html" class="liexternal">ONLamp.com &#8212; Gettext</a> sehr gefallen&#8230;</p>
<h3>Code herunterladen</h3>
<p>Es macht keinen Sinn, den Code direkt aus dem Beitrag herauszukopieren, da verschiedene Zeichen von WordPress ungünstig umgewandelt werden. Daher hier der Download des ZIP-Archivs mit den Klassen Lang und LangSmarty:</p>
<p><a href="http://www.robertnitsch.de/wp-content/uploads/2008/01/php-smarty-mehrsprachig.zip" title='Code herunterladen (Klassen Lang und LangSmarty)' class="lizip">PHP-Smarty-Mehrsprachig.zip herunterladen</a></p>
<p>Hinweis: Die Dateien sind UTF-8-kodiert. Linux-Benutzer werden damit keine Probleme haben, Windows-Nutzer sollten auf den <a href="http://notepad-plus.sourceforge.net/de/site.htm" class="liexternal">Notepad++ &#8211; Editor</a> zurückgreifen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertnitsch.de/2007/05/23/php-smarty-und-die-unterstutzung-mehrerer-sprachen-multilingualitat/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>
