<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Runtux Blog (Einträge über genetic algorithms)</title><link>https://blog.runtux.com/</link><description></description><atom:link href="https://blog.runtux.com/de/categories/genetic-algorithms.xml" rel="self" type="application/rss+xml"></atom:link><language>de</language><copyright>Contents © 2025 &lt;a href="mailto:rsc@runtux.com"&gt;Ralf Schlatterbeck&lt;/a&gt; </copyright><lastBuildDate>Mon, 03 Nov 2025 18:34:11 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>"Wasser": Ein Mehrdimensionales Benchmark Problem</title><link>https://blog.runtux.com/de/posts/2025/06/15/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;div&gt;&lt;p&gt;Dies ist ein kurzes Essay das eigentlich in die Dokumentation von
&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; gehört, aber ich habe es nicht geschafft, &lt;a class="reference external" href="https://plotly.com/"&gt;plotly&lt;/a&gt; Grafiken in
ein github &lt;code class="docutils literal"&gt;README.rst&lt;/code&gt; file einzubinden, nichtmal mit der Proxy-Seite
&lt;code class="docutils literal"&gt;raw.githack.com&lt;/code&gt; (das ist eine Seite die html und javascript files
mit dem richtigen Content-Type ausliefert so dass man sie im Web-Browser
anzeigen kann, github liefert diese Seiten mit dem Content-Type
&lt;code class="docutils literal"&gt;text/plain&lt;/code&gt; aus). Github weigert sich, einen &lt;code class="docutils literal"&gt;iframe&lt;/code&gt; in einer
github Seite zu rendern.&lt;/p&gt;
&lt;p&gt;Das "Wasser Ressourcenplanungs-Problem" &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/15/#rts01" id="citation-reference-1" role="doc-biblioref"&gt;[RTS01]&lt;/a&gt; ist ein technisches
Problem das als Benchmark für das Testen von Optimierungssalgorithmen
mit mehreren Zielfunktionen in der Literatur verwendet wird, unter
andererem in Klassikern wie dem NSGA-II Artikel &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/15/#dpam02" id="citation-reference-2" role="doc-biblioref"&gt;[DPAM02]&lt;/a&gt;. Das Problem
besteht aus sieben Randbedingungen und einer fünfdimensionalen
Zielfunktion.&lt;/p&gt;
&lt;p&gt;Ich nutze dieses Problem seit einiger Zeit als Test meiner NSGA-II
Implementierung in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt;. Es ist im Verzeichnis &lt;code class="docutils literal"&gt;examples/nsgaii&lt;/code&gt;
und kann (nach compilieren) mit dem Test-Problem Index &lt;code class="docutils literal"&gt;12&lt;/code&gt; aufgerufen
werden:&lt;/p&gt;
&lt;pre class="literal-block"&gt;examples/nsgaii/optimize 12&lt;/pre&gt;
&lt;p&gt;Die Ausgabe des Programms kann auch in der folgenden Datei gefunden
werden:&lt;/p&gt;
&lt;pre class="literal-block"&gt;test/nsgaii_optimize_12.data&lt;/pre&gt;
&lt;p&gt;Zum Testen liefere ich auch das Script &lt;code class="docutils literal"&gt;crowdingplot&lt;/code&gt; zum Plotten von
mehrdimensionalen Optimierungsproblemen mit. Es findet sich im selben
Directory wie der Code für das Beispiel.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.runtux.com/de/posts/2025/06/15/"&gt;Weiterlesen…&lt;/a&gt; (3 min verbleiben zum Lesen)&lt;/p&gt;&lt;/div&gt;</description><category>deutsch</category><category>documentation</category><category>genetic algorithms</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2025/06/15/</guid><pubDate>Sun, 15 Jun 2025 11:50:00 GMT</pubDate></item><item><title>Neue Messungen zur Nicht-Dominanz Sortierung</title><link>https://blog.runtux.com/de/posts/2025/06/14/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;div&gt;&lt;p&gt;Dies ist eine Aktualisierung zu einem früheren Beitrag &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/14/#sch25" id="citation-reference-1" role="doc-biblioref"&gt;[Sch25]&lt;/a&gt; zur
Implementierung von Nicht-Dominanz Sortierung in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt;.
Nicht-Dominanz Sortierung ist eine zentrale Komponente von
Optimierungsalgorithmen mit mehreren Zielfunktionen.&lt;/p&gt;
&lt;p&gt;Im früheren Beitrag hatte ich nicht erwähnt für wie viele Generation der
Test lief: Die Anzahl der Generationen im letzten und in diesem Test war
200. Im letzten Test war der Code ohne Optimierung compiliert. Die
folgenden Messungen wurden mit der Option &lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;-O3&lt;/span&gt;&lt;/code&gt; gemacht, der besten
die &lt;a class="reference external" href="https://gcc.gnu.org/"&gt;gcc&lt;/a&gt; anbietet. Ausserdem war mir aufgefallen, dass meine
Implementierung des DTLZ-1 tests &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/14/#dtlz05" id="citation-reference-2" role="doc-biblioref"&gt;[DTLZ05]&lt;/a&gt; quadratisch in der Anzahl der
Zielfunktionen ist und ich befürchtete dass dies die Tests beeinflussen
könnte. Es stellte sich aber heraus dass dies nicht der Fall war, der
Overhead für 20 Zielfunktionen ist immer noch zu klein um bemerkbar zu
sein.&lt;/p&gt;
&lt;p&gt;Zusätzlich zu den ersten Tests messe ich jetzt – neben der Gesamtzeit
– auch die Zeit nur für die Nicht-Dominanz Sortierung. Im folgenden
gibt es also zwei Typen von Grafiken: Wo im Titel "Overall" steht ist
die Zeit für die Zielfunktion und was der Algorithmus sonst noch an
Verwaltung tut inkludiert (Gesamtzeit). Die anderen welche mit
"Non-dominated" anfangen messen nur die Zeit für die Nicht-Dominanz
Sortierung.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.runtux.com/de/posts/2025/06/14/"&gt;Weiterlesen…&lt;/a&gt; (7 min verbleiben zum Lesen)&lt;/p&gt;&lt;/div&gt;</description><category>documentation</category><category>english</category><category>genetic algorithms</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2025/06/14/</guid><pubDate>Sat, 14 Jun 2025 08:30:00 GMT</pubDate></item><item><title>Nicht-Dominanz Sortierung bei Optimierung mit mehreren Zielfunktionen</title><link>https://blog.runtux.com/de/posts/2025/06/09/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;div&gt;&lt;p&gt;Einige Leser hier wissen dass ich &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGApack&lt;/a&gt;, ein Paket für Genetische
Algorithmen, zusammen mit &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt; einer Python Bibliothek pflege
(maintaine). &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; implementiert Optimierung mit mehreren
Zielfunktionen (multi-objective optimization) mit NSGA-II &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/09/#dpam02" id="citation-reference-1" role="doc-biblioref"&gt;[DPAM02]&lt;/a&gt; und
NSGA-III &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/09/#dj14" id="citation-reference-2" role="doc-biblioref"&gt;[DJ14]&lt;/a&gt;, &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/09/#jd14" id="citation-reference-3" role="doc-biblioref"&gt;[JD14]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mehrere Zielfunktionen heisst dass wir mehr als ein Zielfunktion (auch
Fitness-Funktion genannt) haben. Typischerweise widersprechen sich die
Ziele – wenn eine Lösung in einer Zielfunktion besser ist wird, wird
sie typischerweise in einer anderen Lösung schlechter – wir müssen
uns also überlegen was &lt;em&gt;besser&lt;/em&gt; im Kontext von mehreren Zielfunktionen
bedeutet. Eine Lösung &lt;span class="math"&gt;\(A\)&lt;/span&gt; ist strikt besser als eine andere
Lösung &lt;span class="math"&gt;\(B\)&lt;/span&gt; – wir sprechen davon dass Lösung &lt;span class="math"&gt;\(A\)&lt;/span&gt; die
Lösung &lt;span class="math"&gt;\(B\)&lt;/span&gt; &lt;em&gt;dominiert&lt;/em&gt; – wenn &lt;span class="math"&gt;\(A\)&lt;/span&gt; besser oder gleich
&lt;span class="math"&gt;\(B\)&lt;/span&gt; in allen Zielfunktionen ist und strikt besser in mindestens
einer davon.&lt;/p&gt;
&lt;p&gt;Weil wir keine einfache Fitness für Lösungen haben, etablieren
Algorithmen für mehrere Zielfunktionen typischerweise eine Rangfolge
(ranking) der Lösungen nach Dominanz. Lösungen die nicht von einer
anderen Lösung dominiert werden bekommen den Rang 0. Dann entfernt man
alle Lösungen mit Rang 0. Alle Lösungen die dann nicht dominiert sind
bekommen Rang 1 usw. Diese Prozedur heisst typischerweise Nicht-Dominanz
Sortierung (non-dominated sorting). Der Rang ist dann eine der
Komponenten für eine neue Fitness-Funktion.&lt;/p&gt;
&lt;p&gt;Der NSGA-II Artikel &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/09/#dpam02" id="citation-reference-4" role="doc-biblioref"&gt;[DPAM02]&lt;/a&gt; implementiert diese Sortierung indem jede
Lösung gegen jede andere Lösung der Population auf Dominanz verglichen
wird. Dann werden nicht-dominierte Lösungen eine nach der anderen
entfernt und die Ränge zugewiesen wie oben angedeutet. Dieser
Algorithmus zur Sortierung hat eine Laufzeit die mit der Anzahl der
Lösungen quadratisch ansteigt. In der Informatik schreiben wir mit der
&lt;a class="reference external" href="https://de.wikipedia.org/wiki/Landau-Symbole"&gt;O-Notation (auch Landau Symbole)&lt;/a&gt; Aussagen über die Laufzeit auf. Der
quadratische Aufwand wird als &lt;span class="math"&gt;\(O(n^2)\)&lt;/span&gt; notiert, wobei &lt;span class="math"&gt;\(n\)&lt;/span&gt;
die Anzahl der Lösungen ist.&lt;/p&gt;
&lt;p&gt;2003 hat Jensen &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/09/#jen03" id="citation-reference-5" role="doc-biblioref"&gt;[Jen03]&lt;/a&gt; einen Algorithmus publiziert der die
Nicht-Dominanz-Sortierung mit einem Aufwand von
&lt;span class="math"&gt;\(O\left(n\cdot(\log n)^{m-1}\right)\)&lt;/span&gt;
durchführen kann wobei &lt;span class="math"&gt;\(m\)&lt;/span&gt; die Anzahl der Zielfunktionen (und
&lt;span class="math"&gt;\(n\)&lt;/span&gt; wieder die Populationsgröße) ist. Jensen's Algorithmus wurde
zehn Jahre später nochmal geändert publiziert weil das Original nicht
mit gleichen Werten der Zielfunktionen umgehen konnte. Jensen schreibt
zwar das sei einfach, offensichtlich nicht für andere &lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/09/#fgp13" id="citation-reference-6" role="doc-biblioref"&gt;[FGP13]&lt;/a&gt;. Ein Jahr
später gab es dann nochmal eine kleinere Modifikation um formal zu
beweisen dass die Laufzeit-Komplexität wirklich der obigen Formel folgt
&lt;a class="citation-reference" href="https://blog.runtux.com/de/posts/2025/06/09/#bs14" id="citation-reference-7" role="doc-biblioref"&gt;[BS14]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.runtux.com/de/posts/2025/06/09/"&gt;Weiterlesen…&lt;/a&gt; (4 min verbleiben zum Lesen)&lt;/p&gt;&lt;/div&gt;</description><category>deutsch</category><category>documentation</category><category>genetic algorithms</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2025/06/09/</guid><pubDate>Mon, 09 Jun 2025 19:00:00 GMT</pubDate></item><item><title>Optimierung von Fliesskomma-Problemen mit Evolutionären Algorithmen</title><link>https://blog.runtux.com/de/posts/2024/01/07/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;p&gt;[Dies ist ein erweiterter Abstract für einen geplanten Vortrag]&lt;/p&gt;
&lt;p&gt;Evolutionäre Algorithmen (EA) sind ein Oberbegriff für Genetische
Algorithmen (GA) und Verwandte Algorithmen. GA arbeiten üblicherweise
mit Bits oder kleinen Integer-Zahlen.&lt;/p&gt;
&lt;p&gt;Es gibt andere EA die direkt mit Fliesskomma-Zahlen arbeiten können,
unter ihnen Differential Evolution (DE) &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-2" id="footnote-reference-2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-3" id="footnote-reference-3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Der Vortrag gibt eine Einführung in die Optimierung von Fließkomma
Problemen anhand von Beispielen aus der Elektrotechnik sowie der
Optimierung von Kurvenformen zur Ansteuerung von piezoelektrischen
Inkjet Druckern. Bei diesen Druckern hängt die Form des gejetteten
Tropfens (neben anderen Parametern wie der gejetteten Flüssigkeit) von
der zur Ansteuerung verwendeten Kurvenform ab. Diese bestimmt die
Qualität der gejetteten Tropfen.&lt;/p&gt;
&lt;p&gt;Für die Software verwende ich die Python Bindings PGAPy &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-4" id="footnote-reference-4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; für das
ursprünglich an den Argonne National Laboratories entwickelte "Parallel
Genetic Algorithm Package" PGAPack &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-5" id="footnote-reference-5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Beide Open Source Pakete
maintaine ich seit einigen Jahren. Unter anderen wurde diverse
Algorithmen wie Differential Evolution und Strategien zur Optimierung
von Multi-Objective Optimization (also Problemen mit mehreren
Zielfunktionen mit NSGA-II &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-6" id="footnote-reference-6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;) neu implementiert.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="footnote-1" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-reference-1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution -- a simple
and efficient adaptive scheme for global optimization over
continuous spaces. Technical Report TR-95-012, International
Computer Science Institute (ICSI), March 1995.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-reference-2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution -- a simple
and efficient heuristic for global optimization over continuous
spaces. Journal of Global Optimization, 11(4):341–359, December 1997.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-reference-3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Kenneth V. Price, Rainer M. Storn, and Jouni A. Lampinen.
Differential Evolution: A Practical Approach to Global Optimization.
Springer, Berlin, Heidelberg, 2005.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-reference-4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt;, a general-purpose, data-structure-neutral, parallel genetic
algorithm library&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-reference-5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGAPy&lt;/a&gt;: Python Wrapper for PGAPack Parallel Genetic Algorithm Library&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2024/01/07/#footnote-reference-6"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Kalyanmoy Deb, Samir Agrawal, Amrit Pratap, and T. Meyarivan.
A fast elitist non-dominated sorting genetic algorithm for
multi-objective optimization: NSGA-II. In Marc Schoenauer,
Kalyanmoy Deb, Günther Rudolph, Xin Yao, Evelyne Lutton, Juan
Julian Merelo, and Hans-Paul Schwefel, editors, Parallel Problem
Solving from Nature – PPSN VI, volume 1917 of Lecture Notes in
Computer Science, pages 849–858. Springer, Paris, France, September
2000.&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;</description><category>deutsch</category><category>documentation</category><category>genetic algorithms</category><category>howto</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2024/01/07/</guid><pubDate>Sun, 07 Jan 2024 17:00:00 GMT</pubDate></item><item><title>Differential Evolution veranschaulicht</title><link>https://blog.runtux.com/de/posts/2023/04/07/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;p&gt;Dieser Beitrag bezieht sich auf &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; und &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt; oder andere
Genetische Algorithmus (GA) Implementierungen die Differential Evolution
(vielleicht übersetzbar mit Differentielle Evolution, in der Folge
abgekürzt mit DE) unterstützen.&lt;/p&gt;
&lt;p&gt;Differential Evolution (DE) &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-2" id="footnote-reference-2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-3" id="footnote-reference-3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; ist ein
Optimierungsalgorithmus der ähnlich wie andere evolutionäre Algorithmen
auf einer Population basiert. Der Algorithmus ist recht mächtig, in
&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; implementiert und auch in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGAPy&lt;/a&gt; nutzbar. Um einige Punkte zu
diesem Algorithmus zu veranschaulichen habe ich einen einfachen Parcours
in &lt;a class="reference external" href="https://github.com/openscad/openscad"&gt;OpenSCAD&lt;/a&gt; konstruiert.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;img alt="/images/parcours.gif" src="https://blog.runtux.com/images/parcours.gif"&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Um den Optimierer mit diesem Parcours zu testen ist das Gen (DE nennt es
die Parameter) die X- und Y-Koordinate um eine Position im Parcours zu
bestimmen. In der Folge bezeichnen wir diese zwei Werte auch als Vektor,
wie das in der Literatur zu DE üblich ist. Wir initialisieren die
Population in der Gegend beim Start der Rampe. Wir erlauben der
Population, den Initialisierungsbereich zu verlassen.&lt;/p&gt;
&lt;p&gt;Es ist zu beachten, dass die Ecken des Parcours flach sind, dass dort
also alle Punkte die selbe Höhe haben. Solche Bereiche sind generell
schwierig für Optimierungsalgorithmen weil der Algorithmus nicht wissen
kann, in welche Richtung bessere Werte (wenn es diese überhaupt gibt) zu
finden sind. Dies ist auch der Grund, warum wir den
Initialisierungsbereich nicht in den flachen Bereich am Boden des
Parcours legen. Üblicherweise würde man nämlich die Population über den
gesamten zu durchsuchenden Bereich initialisieren. In diesem Fall
möchten wir demonstrieren, dass der Algorithmus auch fähig ist, eine
Lösung weit vom Initialisierungsbereich zu finden.&lt;/p&gt;
&lt;p&gt;Der DE Algorithmus ist recht einfach (siehe z.B. &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-3" id="footnote-reference-4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; S.37-47): Mit jedem
Vektor &lt;span class="math"&gt;\(\mathbf x_{i,g}\)&lt;/span&gt; der Population der aktuellen Generation
&lt;span class="math"&gt;\(g\)&lt;/span&gt;, wobei &lt;span class="math"&gt;\(i\)&lt;/span&gt; der Populationsindex ist wird ein
Genaustausch mit einem Mutanten-Vektor vorgenommen. Der Mutanten-Vektor
wird zufällig (ohne Zurücklegen) aus drei Populations-Vektoren
bestimmt, indem diese wie folgt kombiniert werden.&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
\mathbf v_{i,g} = \mathbf x_{r_0,g}
                  + F \cdot (\mathbf x_{r_1,g} - \mathbf x_{r_2,g})
\end{equation*}
&lt;/div&gt;
&lt;p&gt;Wie man sieht, wird eine gewichtete Differenz von zwei Vektoren der
Population gebildet und zu einem dritten Vektor addiert. Alle Indices
&lt;span class="math"&gt;\(r_0, r_1,\)&lt;/span&gt; und &lt;span class="math"&gt;\(r_2\)&lt;/span&gt; sind voneinander und von &lt;span class="math"&gt;\(i\)&lt;/span&gt;
verschieden. Das Gewicht &lt;span class="math"&gt;\(F\)&lt;/span&gt; ist ein Konfigurationsparameter der
typischerweise &lt;span class="math"&gt;\(0.3 \le F &amp;lt; 1\)&lt;/span&gt; ist. Der beschriebene Algorithmus
ist der &lt;em&gt;klassische&lt;/em&gt; DE Algorithmus, oft auch als &lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;de-rand-1-bin&lt;/span&gt;&lt;/code&gt;
bezeichnet. Eine Variante nutzt statt einem zufälligen Index &lt;span class="math"&gt;\(r_0\)&lt;/span&gt;
den Index des besten Vektors und wird als &lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;de-best-1-bin&lt;/span&gt;&lt;/code&gt; bezeichnet.
Falls mehr als zwei Differenzen addiert werden wäre eine andere Variante
z.B. &lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;de-rand-2-bin&lt;/span&gt;&lt;/code&gt;. Die letzte Komponente der Bezeichnung steht für
Uniform Crossover &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-4" id="footnote-reference-5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, eine binomiale Verteilung. In DE werden die
Parameter des Mutanten-Vektors mit einer bestimmten Wahrscheinlichkeit
&lt;span class="math"&gt;\(Cr\)&lt;/span&gt; ausgewählt. Man beachte, dass DE dafür sorgt, dass zumindest
&lt;em&gt;ein&lt;/em&gt; Parameter des Mutanten-Vektors ausgewählt wird (sonst bliebe der
betrachtete Original-Vektor &lt;span class="math"&gt;\(\mathbf x_{i,g}\)&lt;/span&gt; unverändert).&lt;/p&gt;
&lt;p&gt;Mehr Details zu DE und er Nutzung mit &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; findet sich in den
Abschnitten &lt;a class="reference external" href="https://pgapack.readthedocs.io/en/latest/part1.html#sec-differential-evolution"&gt;Differential Evolution&lt;/a&gt; und &lt;a class="reference external" href="https://pgapack.readthedocs.io/en/latest/part2.html#sec-mutation"&gt;Mutation&lt;/a&gt; der &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt;
Dokumentation.&lt;/p&gt;
&lt;p&gt;Um das &lt;a class="reference external" href="https://github.com/openscad/openscad"&gt;OpenSCAD&lt;/a&gt; Modell in der Optimierung zu verwenden, wird es
mithilfe eines &lt;a class="reference external" href="https://fenrus75.github.io/FenrusCNCtools/javascript/stl2png.html"&gt;STL zu PNG Konverters&lt;/a&gt; in ein Graustufen-Höhenbild
umgewandelt (STL ist ein &lt;a class="reference external" href="https://de.wikipedia.org/wiki/STL-Schnittstelle"&gt;3D-Format&lt;/a&gt; das von &lt;a class="reference external" href="https://github.com/openscad/openscad"&gt;OpenSCAD&lt;/a&gt; generiert werden
kann). Die Bewertungsfunktion des Algorithmus liefert dann einfach den
Graustufen-Wert an der gegebenen X/Y-Position zurück (nach Rundung der
Gen-Werte und Konvertierung in einen Integer-Wert). Werte ausserhalb des
Bildes werden als 0 (schwarz) geliefert. Der resultierende
Optimierungslauf ist unten in einem animierten Bild dargestellt. Die
Population ist ziemlich klein und enthält nur 6 Vektoren. Wir sehen
dass, wenn die Abstände zwischen den Punkten groß werden (auf den geraden
Strecken des Parcours), die Optimierung in größeren Schritten
voranschreitet. Wir sehen auch, dass der Algorithmus in den flachen
Ecken einige Zeit brauchen kann bis er aus diesem Bereich entkommt.
Schließlich, in der letzten Ecke, wird der Kegel erklommen und der
Algorithmus stoppt wenn das erste Individuum eine Bewertung mit dem
größten Graustufen-Wert liefert (entspricht weiss). Bitte beachten, dass
ich ein bisschen geschummelt habe: Viele Optimierungläufe dauern
deutlich länger (Insbesondere in den flachen Bereichen kann der
Algorithmus längere Zeit stecken bleiben). Ich habe einen Lauf
ausgewählt der sich für eine Animation gut eignet. Dieser Lauf ist nicht
im Bereich des Durchschnitts sondern deutlich kürzer.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;img alt="/images/animated.gif" src="https://blog.runtux.com/images/animated.gif"&gt;
&lt;p&gt; &lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="footnote-1" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-reference-1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution – a simple
and efficient heuristic for global optimization over continuous
spaces. &lt;em&gt;Journal of Global Optimization&lt;/em&gt;, 11(4):341–359, December 1997.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-reference-2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution – a simple
and efficient adaptive scheme for global optimization over
continuous spaces. Technical Report TR-95-012, International
Computer Science Institute (ICSI), March 1995.
&lt;a class="reference external" href="ftp://ftp.icsi.berkeley.edu/pub/techreports/1995/tr-95-012.pdf"&gt;Available from the International Computer Science Institute&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-reference-3"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-reference-4"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Kenneth V. Price, Rainer M. Storn, and Jouni A. Lampinen.
&lt;em&gt;Differential Evolution: A Practical Approach to Global Optimization.&lt;/em&gt;
Springer, Berlin, Heidelberg, 2005.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/04/07/#footnote-reference-5"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Gilbert Syswerda. Uniform crossover in genetic algorithms. In J.
David Schaffer, editor, Proceedings of the Third International
Conference on Genetic Algorithms (ICGA), pages 2–9. Morgan
Kaufmann, Fairfax, Virginia, June 1989.&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;</description><category>documentation</category><category>genetic algorithms</category><category>german</category><category>howto</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2023/04/07/</guid><pubDate>Fri, 07 Apr 2023 20:00:00 GMT</pubDate></item><item><title>Notizen zur Vorzeitigen Konvergenz in Genetischen Algorithmen</title><link>https://blog.runtux.com/de/posts/2023/01/06/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;p&gt;Dieser Beitrag beschäftigt sich wieder mit &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; und &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt;, sowie
anderen Implementierungen von Genetischen Algorithmen (GA).&lt;/p&gt;
&lt;p&gt;Bei der Suche von Lösungen mit einem GA passiert es, dass eine
sub-optimale Lösung gefunden wird, weil die Population frühzeitig in
einem Bereich des Suchraumes konvergiert wo keine besseren Lösungen mehr
gefunden werden. Dieser Effekt heisst &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;vorzeitige Konvergenz&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Es ist normalerweise schwierig, &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;vorzeitige Konvergenz&lt;/a&gt; zu entdecken.
Eine gute Metrik ist die mittlere &lt;a class="reference external" href="https://de.wikipedia.org/wiki/Hamming-Abstand"&gt;Hamming Distanz&lt;/a&gt; zwischen
Individuen. In &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; kann man Auswertungen der Hamming Distanz
über die Option &lt;code class="docutils literal"&gt;PGA_REPORT_HAMMING&lt;/code&gt; der Funktion
&lt;code class="docutils literal"&gt;PGASetPrintOptions&lt;/code&gt; aktivieren. In &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt; geht das mit dem
Konstruktor Parameter &lt;code class="docutils literal"&gt;print_options&lt;/code&gt;. Leider ist dies nur für den
binären Datentyp implementiert.&lt;/p&gt;
&lt;p&gt;Ein möglicher Grund für das Auftreten von &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;vorzeitiger Konvergenz&lt;/a&gt; ist die
Verwendung von &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Fitness_proportionate_selection"&gt;proportionaler Selektion&lt;/a&gt; wie in einem früheren Artikel
in diesem Blog &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; ausgeführt. Wenn während der Frühphase der Suche ein
Individuum gefunden wird das viel besser ist als alles bisherige, so ist
die Chance groß, dass dieses Individuum die Population übernimmt wenn
&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Fitness_proportionate_selection"&gt;proportionale Selektion&lt;/a&gt; verwendet wird, wodurch ein weiterer
Fortschritt des Algorithmus verhindert wird. Der Grund dafür ist, dass
ein Individuum das wesentlich besser ist als alle anderen einen
unangemessen hohen Anteil des (gedachten) Roulette-Rades einnimmt wenn
Individuen für die nächste Generation ausgewählt werden, was dazu führt,
dass alles andere genetische Material nur eine geringe Chance hat, in
die nächste Generation zu kommen.&lt;/p&gt;
&lt;p&gt;Ein anderer Grund für &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;vorzeitige Konvergenz&lt;/a&gt; kann eine zu kleine
Populationsgröße sein. Goldberg et. al. &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-9" id="footnote-reference-2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;9&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; geben Abschätzungen der
Populationsgröße für einen klassischen GA mit kleinem Alphabet (mögliche
verschiedene Allele, also 0 und 1 für einen binären GA) der Kardinalität
&lt;span class="math"&gt;\(\chi\)&lt;/span&gt; an. Dabei wird eine maximale Länge einer Symbolfolge (Building
Block) angenommen die irreführende Symbolfolgen (deception) überwindet
mit &lt;span class="math"&gt;\(k \ll n\)&lt;/span&gt; wobei &lt;span class="math"&gt;\(k\)&lt;/span&gt; die Symbolfolgen-Länge (ein Maß für
die Schwierigkeit des Problems) und &lt;span class="math"&gt;\(n\)&lt;/span&gt;
die Gen-Länge ist. Es wird gezeigt, dass die Populationsgröße
&lt;span class="math"&gt;\(O(m\chi^k)\)&lt;/span&gt; sein sollte mit &lt;span class="math"&gt;\(m=n/k\)&lt;/span&gt; so dass mit einer
vorgegebenen Schwierigkeit &lt;span class="math"&gt;\(k\)&lt;/span&gt; die Populationsgröße proportional
zur Gen-Länge &lt;span class="math"&gt;\(n\)&lt;/span&gt; ist. Dieses Ergebnis kann aber nicht auf
Probleme mit einem sehr großen Alphabet wie Fließkomma-Genen wie dem
&lt;code class="docutils literal"&gt;real&lt;/code&gt; Datentyp von &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; verallgemeinert werden. Für Fließkomma
Darstellungen kann man die Schwierigkeit üblicherweise einschätzen wenn
man die Multimodalität, also die Anzahl der &lt;em&gt;Gipfel&lt;/em&gt; oder &lt;em&gt;Täler&lt;/em&gt;
(jenachdem ob es sich um ein Maximierungs- oder Minimierungsproblem handelt)
der Zielfunktion betrachtet.&lt;/p&gt;
&lt;p&gt;Wenn mit einer angemessenen Populationsgröße &lt;em&gt;und&lt;/em&gt; einem sinnvollen
Selektionsmechanismus noch immer &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;vorzeitige Konvergenz&lt;/a&gt; auftritt,
können einige andere Mechanismen zur Anwendung kommen.&lt;/p&gt;
&lt;section id="vermeidung-von-duplikaten"&gt;
&lt;h2&gt;Vermeidung von Duplikaten&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; implementiert einen Mechanismus zur Vermeidung von doppelt
vorkommenden Genen (Individuen). In früheren Implementierungen war der
Aufwand dafür quadratisch in der Populationsgröße &lt;span class="math"&gt;\(N\)&lt;/span&gt;, also
&lt;span class="math"&gt;\(O(N^2)\)&lt;/span&gt; (es wurde jedes neue Individuum mit &lt;em&gt;allen&lt;/em&gt; Mitgliedern
der aktuellen Population verglichen). In der aktuellen Version wird
eine Hashfunktion verwendet um Duplikate zu entdecken, was den Aufwand
auf &lt;span class="math"&gt;\(O(N)\)&lt;/span&gt; reduziert, also einen kleinen konstanten Aufwand für
jedes neue Individuum.&lt;/p&gt;
&lt;p&gt;Für benutzerdefinierte Datentypen bedeutet das, dass eine Hash Funktion
für den Datentyp gebraucht wird, zusätzlich zu einer
Gen-Vergleichsfunktion. Für die eingebauten Datentypen (binary, integer,
real) sind diese Funktionen automatisch verfügbar.&lt;/p&gt;
&lt;p&gt;Die Vermeidung von Duplikaten funktioniert gut für Integer und Binäre
Datentypen, besonders wenn die verwendeten genetischen Operatoren mit
hoher Wahrscheinlichkeit Duplikate erzeugen können. Es funktioniert
nicht so gut mit dem &lt;code class="docutils literal"&gt;real&lt;/code&gt; Datentyp weil Individuen normalerweise
unterschiedlich sind, auch wenn sie genetisch sehr nah
beieinanderliegen.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="restricted-tournament-replacement"&gt;
&lt;h2&gt;Restricted Tournament Replacement&lt;/h2&gt;
&lt;p&gt;Ein Algorithmus der ursprünglich von Harik &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-2" id="footnote-reference-3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-3" id="footnote-reference-4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; &lt;em&gt;Restricted
Tournament Selection&lt;/em&gt; genannt wurde und später von Pelikan &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-4" id="footnote-reference-5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; mit
&lt;em&gt;Restricted Tournament Replacement&lt;/em&gt; (RTR) bezeichnet wurde, verwendet die
alte und die neue Population um zu entscheiden, ob ein Kandidat in die
neue Population aufgenommen wird. Der Algorithmus wählt eine Anzahl von
Individuen der alten Population (das sogenannte Selektionsfenster)
zufällig aus und vergleicht die Bewertung des Indivuums welches
genetisch dem Kandidaten-Individuum am nächsten ist. Nur wenn das
Kandidaten-Individuum besser ist als das genetisch ähnlichste aus dem
Selektionsfenster wird es in die neue Generation übernommen.&lt;/p&gt;
&lt;p&gt;Die Standardeinstellung für die Anzahl der Individuen im
Selektionsfenster ist &lt;span class="math"&gt;\(\min (n, \frac{N}{20})\)&lt;/span&gt; &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-4" id="footnote-reference-6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; wobei
&lt;span class="math"&gt;\(n\)&lt;/span&gt; die Genlänge und &lt;span class="math"&gt;\(N\)&lt;/span&gt; die Populationsgröße ist.
Dies kann vom Benutzer geändert werden durch Aufruf der Funktion
&lt;code class="docutils literal"&gt;PGASetRTRWindowSize&lt;/code&gt; für &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; bzw. mit dem Konstruktor-Parameter
&lt;code class="docutils literal"&gt;rtr_window_size&lt;/code&gt; für &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Der RTR-Algorithmus braucht eine Ähnlichkeitsmetrik um zu entscheiden,
wie ähnlich ein Individuum einem anderen ist. Die Vorgabe ist die
&lt;a class="reference external" href="https://de.wikipedia.org/wiki/Manhattan-Metrik"&gt;Manhattan Distanz&lt;/a&gt; (für binäre Gene identisch mit der &lt;a class="reference external" href="https://de.wikipedia.org/wiki/Hamming-Abstand"&gt;Hamming
Distanz&lt;/a&gt;), also die Summe aller einzelnen Allele-Differenzen. Dies kann
auf die Euclidsche Distanz geändert werden durch Setzen einer
benutzerdefinierten Funktion für die genetische Distanz. Die Verwendung
einer Euclidschen Ähnlichkeitsmetrik sieht man im &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy/blob/master/examples/magic_square.py"&gt;Beispiel: Magisches
Quadrat&lt;/a&gt; in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt; wo man die Euclidsche Metrik über eine
Kommandozeilenoption auswählen kann.&lt;/p&gt;
&lt;p&gt;Restricted Tournament Replacement funktioniert nicht nur für binäre und
Integer Gene gut sondern auch für den &lt;code class="docutils literal"&gt;real&lt;/code&gt; Datentyp. Man kann diesen
Ersetzungsmechanismus mit anderen Einstellungen des GA kombinieren.&lt;/p&gt;
&lt;p&gt;Die Auswirkung von RTR auf ein Problem das zu &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;vorzeitiger Konvergenz&lt;/a&gt;
tendiert kann man im Test-Programm &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/blob/master/examples/mgh/testprog.f"&gt;&lt;code class="docutils literal"&gt;examples/mgh/testprog.f&lt;/code&gt;&lt;/a&gt; sehen.
Dieses Programm implementiert einige Testfunktionen aus einem alten
Benchmark für nichtlineare Optimierungsalgorithmen &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-5" id="footnote-reference-7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Die
Testfunktion mit Tendenz zu &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;vorzeitiger Konvergenz&lt;/a&gt; ist was die Autoren
eine "gausssche Funktion" nennen, beschrieben im Beispiel (9) im Artikel
&lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-5" id="footnote-reference-8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; und implementiert als Funktion 3 in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/blob/master/examples/mgh/objfcn77.f"&gt;&lt;code class="docutils literal"&gt;examples/mgh/objfcn77.f&lt;/code&gt;&lt;/a&gt;.
Diese Funktion wird angegeben als&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
f(x) = x_1 \cdot e^{\frac{x_2(t_i - x_3)^2}{2}} - y_i
\end{equation*}
&lt;/div&gt;
&lt;p&gt;mit&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
t_i = (8 - i) / 2
\end{equation*}
&lt;/div&gt;
&lt;p&gt;Und tabellierten Werten für &lt;span class="math"&gt;\(y_i\)&lt;/span&gt; im Artikel bzw. der
Implementierung in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/blob/master/examples/mgh/objfcn77.f"&gt;&lt;code class="docutils literal"&gt;examples/mgh/objfcn77.f&lt;/code&gt;&lt;/a&gt;. Das Minimierungsproblem
aus diesen Gleichungen ist&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
f (x) = \sum_{i=1}^{m} f_i^2(x)
\end{equation*}
&lt;/div&gt;
&lt;p&gt;mit &lt;span class="math"&gt;\(m=15\)&lt;/span&gt; für dieses Testproblem. Die Autoren &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-5" id="footnote-reference-9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; geben den
Vektor &lt;span class="math"&gt;\(x_0 = (0.4, 1, 0)\)&lt;/span&gt; für das Minimum
&lt;span class="math"&gt;\(f(x_0) = 1.12793 \cdot 10^{-8}\)&lt;/span&gt;
an. Die Original Fortran-Implementierung in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/blob/master/examples/mgh/testprog.f"&gt;&lt;code class="docutils literal"&gt;examples/mgh/testprog.f&lt;/code&gt;&lt;/a&gt;
verwendet eine Populationsgröße von 10000 mit den Standardeinstellungen
für den &lt;code class="docutils literal"&gt;real&lt;/code&gt; Datentyp von &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt;. Die große Populationsgröße wird
gewählt weil das Problem sonst vorzeitig konvergiert. Nach 100
Generationen wird die Lösung
&lt;span class="math"&gt;\(x_0=(0.3983801, 0.9978369, 0.009918243)\)&lt;/span&gt;
mit einem Evaluationswert von
&lt;span class="math"&gt;\(f(x_0)=2.849966\cdot 10^{-5}\)&lt;/span&gt; gefunden.
Die Anzahl der Funktionaufrufe der Zielfunktion waren 105459 (etwas
weniger als &lt;span class="math"&gt;\(10000 + 100 \cdot 1000\)&lt;/span&gt; also Bewertung der initialen
Population plus etwa 10% der Population in jeder Generation, die
Wahrscheinlichkeit für Crossover und Mutation ist nicht 100%, daher
kommt es vor dass keiner der Operatoren angewandt wird und die
Evaluationsfunktion daher nicht aufgerufen wird)&lt;/p&gt;
&lt;p&gt;Ich habe das gleiche Problem mit Differential Evolution &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-6" id="footnote-reference-10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-7" id="footnote-reference-11" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-8" id="footnote-reference-12" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/blob/master/examples/mgh/testprogde.c"&gt;&lt;code class="docutils literal"&gt;examples/mgh/testprogde.c&lt;/code&gt;&lt;/a&gt; implementiert (das Treiberprogramm ist
in C geschrieben weil ich nicht wirklich Fortran spreche, verwendet
aber die gleichen Funktionen wie das Fortran Treiberprogramm und linkt
Fortran und C Code in einem gemeinsamen ausführbaren Programm). Es
verwendet eine Populationsgröße von 2000 (was für Differential Evolution
groß ist wieder aus Gründen von &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;vorzeitiger Konvergenz&lt;/a&gt;) und findet
die Lösung &lt;span class="math"&gt;\(x_0=(0.3992372, 0.9990791, -0.0007697923)\)&lt;/span&gt;
mit einer Bewertungsfunktion von
&lt;span class="math"&gt;\(f(x_0)=7.393123\cdot 10^{-7}\)&lt;/span&gt; in nur 30 Generationen.
Dies entspricht 62000 Funktionsaufrufen der Zielfunktion (Differential
Evolution berechnet eine komplette Generation und entscheidet dann
welche Individuen in die neue Generation übernommen werden).&lt;/p&gt;
&lt;p&gt;Wenn man RTR für dieses Problem verwendet wie in
&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/blob/master/examples/mgh/testprogdertr.c"&gt;&lt;code class="docutils literal"&gt;examples/mgh/testprogdertr.c&lt;/code&gt;&lt;/a&gt;, kann die Populationsgröße auf 250
reduziert werden und sogar nach 100 Generationen konvergiert die Suche
nicht vorzeitig auf eine suboptimale Lösung. Nach 100 Generationen
finden wir &lt;span class="math"&gt;\(x_0=(0.398975, 1.000074, -6.719886 \cdot 10^{-5})\)&lt;/span&gt;
und &lt;span class="math"&gt;\(f(x_0)=1.339766\cdot 10^{-8}\)&lt;/span&gt; (allerdings mit ein paar
anderen Einstellungen für den Differential Evolution Algorithmus).
Dies entspricht 25250 Funktionsaufrufen der Zielfunktion.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="restart"&gt;
&lt;h2&gt;Restart&lt;/h2&gt;
&lt;p&gt;Das letzte Mittel wenn die obigen Mechanismen versagen ist ein
regelmässiger Restart des GA wann immer die Population zu stark
konvergiert. Der Restart-Mechanismus in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; verwendet das beste
Individuum der Population um eine neue Population mit durch Mutation
erzeugten Varianten dieses Individuums zu initialisieren. Restarts kann man mit
&lt;code class="docutils literal"&gt;PGASetRestartFlag&lt;/code&gt; in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; oder dem &lt;code class="docutils literal"&gt;restart&lt;/code&gt; Konstruktor
Parameter in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt; einschalten. Die Frequenz der Restarts (Standard ist
alle 50 Generationen) kann mit &lt;code class="docutils literal"&gt;PGASetRestartFrequencyValue&lt;/code&gt; in
&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; und dem &lt;code class="docutils literal"&gt;restart_frequency&lt;/code&gt; Konstruktor Parameter in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt;
gesetzt werden.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="footnote-1" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Ralf Schlatterbeck. &lt;a class="reference external" href="https://blog.runtux.com/de/posts/2022/12/03/"&gt;Proportionale Selection (Roulette-Rad) in
Genetischen Algorithmen&lt;/a&gt; Blog post, Open Source Consulting, Dezember
2022.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-3"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Georges Harik. Finding multiple solutions in problems of bounded
difficulty. IlliGAL Report 94002, Illinois Genetic Algorithm Lab,
Mai 1994.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-4"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Georges R. Harik. Finding multimodal solutions using restricted
tournament selection. In Larry J.  Eshelman, editor, &lt;em&gt;Proceedings
of the International Conference on Genetic Algorithms (ICGA)&lt;/em&gt;,
pages 24–31. Morgan Kaufmann, Juli 1995.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-5"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-6"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Martin Pelikan. &lt;em&gt;Hierarchical Bayesian Optimization Algorithm:
Toward a New Generation of Evolutionary Algorithms&lt;/em&gt;, volume 170 of
&lt;em&gt;Studies in Fuzziness and Soft Computing&lt;/em&gt;. Springer, 2005.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-7"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-8"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-9"&gt;3&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Jorge J. Moré, Burton S. Garbow, and Kenneth E. Hillstrom.
&lt;em&gt;Testing unconstrained optimization software.&lt;/em&gt; ACM Transactions
on Mathematical Software, 7(1):17–41, März 1981.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-10"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution – a simple
and efficient heuristic for global optimization over continuous
spaces. &lt;em&gt;Journal of Global Optimization&lt;/em&gt;, 11(4):341–359, Dezember 1997.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-11"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution – a simple
and efficient adaptive scheme for global optimization over
continuous spaces. Technical Report TR-95-012, International
Computer Science Institute (ICSI), März 1995.
&lt;a class="reference external" href="ftp://ftp.icsi.berkeley.edu/pub/techreports/1995/tr-95-012.pdf"&gt;Verfügbar beim the International Computer Science Institute&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-12"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Kenneth V. Price, Rainer M. Storn, and Jouni A. Lampinen.
&lt;em&gt;Differential Evolution: A Practical Approach to Global Optimization.&lt;/em&gt;
Springer, Berlin, Heidelberg, 2005.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-9" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2023/01/06/#footnote-reference-2"&gt;9&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;David E. Goldberg, Kalyanmoy Deb, and James H. Clark. Genetic
algorithms, noise, and the sizing of populations. &lt;em&gt;Complex
Systems&lt;/em&gt;, 6(4):333–362, 1992. &lt;a class="reference external" href="https://wpmedia.wolfram.com/uploads/sites/13/2018/02/06-4-3.pdf"&gt;Verfügbar von Complex Systems&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;</description><category>deutsch</category><category>documentation</category><category>genetic algorithms</category><category>howto</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2023/01/06/</guid><pubDate>Fri, 06 Jan 2023 17:45:00 GMT</pubDate></item><item><title>Proportionale Selection (Roulette-Rad) in Genetischen Algorithmen</title><link>https://blog.runtux.com/de/posts/2022/12/03/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;p&gt;Einige Leser hier wissen dass ich &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGApack&lt;/a&gt;, ein Paket für Genetische
Algorithmen, zusammen mit &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGApy&lt;/a&gt; einer Python Bibliothek pflege
(maintaine). Vor kurzem kam die Frage auf, warum &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGApack&lt;/a&gt; wenn eine
Selektionsmethode verwendet wird die proportional zur Fitness selektiert
(&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Fitness_proportionate_selection"&gt;Fitness Proportionate Selection&lt;/a&gt;), im englischen auch als Roulette-Rad
Selektion bezeichnet, mit einem Fehler aussteigt weil es einen
Fitness-Wert &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/issues/7"&gt;nicht normalisieren kann&lt;/a&gt;. Im folgenden werde ich kurz
von proportionaler Selektion schreiben.&lt;/p&gt;
&lt;p&gt;In &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGApack&lt;/a&gt; definieren wir als Anwenderin  eine Reelle
Bewertungsfunktion (die für jedes Individuum aufgerufen wird). Ausserdem
definieren wir ob diese Bewertung minimiert oder maximiert wird (wir
legen die Optimierungsrichtung fest).&lt;/p&gt;
&lt;p&gt;Bei proportionaler Selektion muss diese Bewertung auf positive Werte
abgebildet werden so dass jeder Bewertung ein Teil des Roulette-Rades
zugewiesen wird. Wenn &lt;em&gt;minimiert&lt;/em&gt; wird sind kleine Werte besser und
müssen einen &lt;em&gt;größeren&lt;/em&gt; Bereich des Roulette-Rades bekommen so dass die
Wahrscheinlichkeit der Selektion höher ist. Wir müssen also die
Bewertungsfunktion auf eine nicht-negative monoton steigende &lt;em&gt;Fitness&lt;/em&gt;
abbilden. Bei einem &lt;em&gt;Minimierungsproblem&lt;/em&gt; berechnen wir die maximale
(schlechteste) Bewertung und bilden dann die Differenz dieses Maximums
mit der Bewertung des Individuums (nach einer Skalierung des Maximums so
dass kein Fitnesswert negativ wird):&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
F = E_{max} - E
\end{equation*}
&lt;/div&gt;
&lt;p&gt;wobei &lt;span class="math"&gt;\(F\)&lt;/span&gt; die Fitness des aktuellen Individuums ist,
&lt;span class="math"&gt;\(E_{max}\)&lt;/span&gt; das Maximum aller Bewertungen der aktuellen Generation
und &lt;span class="math"&gt;\(E\)&lt;/span&gt; die Bewertung des Individuums.&lt;/p&gt;
&lt;p&gt;Wenn sich nun die Bewertungen um mehrere Größenordnungen unterscheiden
kann es vorkommen, dass die Fitness zu &lt;span class="math"&gt;\(E_{max}\)&lt;/span&gt; wird, für viele
(unterschiedliche) Individuen. Ich nenne das einen Überlauf
(overflow), vielleicht nicht der beste Name dafür.&lt;/p&gt;
&lt;p&gt;Der Überlauf passiert wenn &lt;span class="math"&gt;\(E_{max}\)&lt;/span&gt; groß ist verglichen mit der
aktuellen Bewertung &lt;span class="math"&gt;\(E\)&lt;/span&gt; so dass die obige Differenz
&lt;span class="math"&gt;\(E_{max}\)&lt;/span&gt; wird (die Subtraktion von &lt;span class="math"&gt;\(E\)&lt;/span&gt; also keine Wirkung hat)
Im Code checken wir diese Bedingung:&lt;/p&gt;
&lt;pre class="literal-block"&gt;if (cmax == cmax - evalue &amp;amp;&amp;amp; evalue != 0)&lt;/pre&gt;
&lt;p&gt;Die Bedingung ist erfüllt wenn die Subtraktion von &lt;span class="math"&gt;\(E\)&lt;/span&gt; von
&lt;span class="math"&gt;\(E_{max}\)&lt;/span&gt; &lt;span class="math"&gt;\(E_{max}\)&lt;/span&gt; nicht verändert obwohl &lt;span class="math"&gt;\(E\)&lt;/span&gt;
ungleich Null ist. &lt;span class="math"&gt;\(E\)&lt;/span&gt; ist so klein gegenüber &lt;span class="math"&gt;\(E_{max}\)&lt;/span&gt; dass
der Datentyp &lt;code class="docutils literal"&gt;double&lt;/code&gt; den Unterschied nicht repräsentieren kann.
Das passiert wenn die &lt;em&gt;Einheit der letzten Stelle&lt;/em&gt; (&lt;em&gt;units in the last
place&lt;/em&gt; von Goldberg (nicht dem Goldberg der das &lt;em&gt;Genetische Algorithmen&lt;/em&gt;
Buch geschrieben hat soweit ich weiss) auch &lt;em&gt;ulps&lt;/em&gt; genannt) der &lt;a class="reference external" href="https://de.wikipedia.org/wiki/Mantisse"&gt;Mantisse&lt;/a&gt;
größer ist als der Wert der subtrahiert wird &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In unserem Beispiel &lt;span class="math"&gt;\(E_{max} = 1.077688 * 10^{22}\)&lt;/span&gt; und die
Bewertung bei der das schiefging war &lt;span class="math"&gt;\(E = 10000\)&lt;/span&gt;. Ein IEEE 754
Fließkomma-Wert doppelter Genauigkeit (&lt;code class="docutils literal"&gt;double&lt;/code&gt;) hat 53 bit &lt;a class="reference external" href="https://de.wikipedia.org/wiki/Mantisse"&gt;Mantisse&lt;/a&gt;
die damit Zahlen bis &lt;span class="math"&gt;\(2^{54} - 1 = 18014398509481983\)&lt;/span&gt; darstellen
kann, also etwa &lt;span class="math"&gt;\(1.8 * 10^{16}\)&lt;/span&gt;. Man sieht dass die Zahl 10000
gerade unterhalb des oben erwähnten &lt;em&gt;ulps&lt;/em&gt; ist. Wir können das in Python
ausprobieren (das für Fließkommazahlen &lt;code class="docutils literal"&gt;double&lt;/code&gt; verwendet):&lt;/p&gt;
&lt;pre class="literal-block"&gt;&amp;gt;&amp;gt;&amp;gt; 1.077688e22 - 10000 == 1.077688e22
True&lt;/pre&gt;
&lt;p&gt;Warum machen wir diesen Check im Programm? Würde die Suche bei einem
solchen Überlauf (oder wie auch immer wir das nennen wollen)
weiterlaufen, würde der Algorithmus viele verschiedene Bewertungen auf
die gleiche Fitness abbilden. Der Genetische Algorithmus könnte also
diese Individuen nicht unterscheiden.&lt;/p&gt;
&lt;p&gt;Was können wir tun wenn dieser Fehler auftritt?&lt;/p&gt;
&lt;p&gt;Die kurze Antwort: Einen anderen Selektionsmechanismus verwenden. Es
gibt einen Grund, warum proportionale Selektion &lt;em&gt;nicht&lt;/em&gt; die
Standardeinstellung in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGApack&lt;/a&gt; ist.&lt;/p&gt;
&lt;p&gt;Proportionale Selektion (&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Fitness_proportionate_selection"&gt;Fitness proportionate selection&lt;/a&gt;) hat noch
andere Probleme. Sie hat zu großen Selektionsdruck am Anfang zu wenig
gegen Ende der Optimierung (auch erwähnt im obigen Wikipedia Artikel,
aber Vorsicht, ich habe Teile davon geschrieben).&lt;/p&gt;
&lt;p&gt;Blickle and Thiele &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-2" id="footnote-reference-2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; haben eine mathematische Analyse von
unterschiedlichen Selektions-Algorithmen publiziert und gezeigt dass
proportionale Selektion typischerweise keine gute Idee ist
(proportionale Selektion war historisch der erste Selektionsmechanismus
in der Literatur und war ausführlich in Goldbergs (der andere Goldberg)
Buch &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-3" id="footnote-reference-3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; beschrieben und ist vielleicht deshalb heute noch manchmal in
Verwendung). Es sei darauf hingewiese dass Blickle und Thiele in einem
früheren Report &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-4" id="footnote-reference-4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; direkter waren was die Beurteilung von
proportionaler Selektion betrifft (meine Übersetzung): "Alle
unerwünschten Eigenschaften zusammen führten uns zu dem Schluss dass
proportionale Selektion ein sehr ungeeigneter Selektionsmechanismus ist.
Informell könnten wir sagen dass der einzige Vorteil von proportionaler
Selektion ist, dass es so schwierig ist die Nachteile zu beweisen"
(&lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-4" id="footnote-reference-5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, S. 42), in der Endfassung im veröffentlichten Artikel waren sie
dann nicht mehr so deutlich :-)&lt;/p&gt;
&lt;p&gt;Wir sehen in obigem Beispiel: Wir haben sehr große Unterschiede zwischen
guten und schlechten Bewertungen (eben so groß dass die Fitness nicht
eindeutig berechnet werden kann, s.o.). Wenn man dafür proportionale
Selektion verwendet, werden sehr gute Individuen mit zu großer
Wahrscheinlichkeit selektiert was zu verfrühter Konvergenz (&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Premature_convergence"&gt;premature
convergence&lt;/a&gt;) führt.&lt;/p&gt;
&lt;p&gt;Zum Schluss all dieser Ausführungen: Wenn wir Optimierungen mit
Fließkomma-Repräsentationen durchführen (diese werden durch &lt;code class="docutils literal"&gt;double&lt;/code&gt;
Datentypen in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGApack&lt;/a&gt; repräsentiert) sollten wir Differential Evolution
ausprobieren &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-5" id="footnote-reference-6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-6" id="footnote-reference-7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-7" id="footnote-reference-8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Zumindest in meinen Experimenten mit
Antennen-Optimierung &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-8" id="footnote-reference-9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;8&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; sind die Resultate damit deutlich besser als
mit standard Genetischen Algorithmen was auch von verschiedenen
Praktikern bestätigt wird &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-7" id="footnote-reference-10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Beispiele dazu finden sich in
&lt;code class="docutils literal"&gt;examples/deb/optimize.c&lt;/code&gt; oder &lt;code class="docutils literal"&gt;examples/mgh/testprogde.c&lt;/code&gt; in
&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGApack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Der Parameter &lt;code class="docutils literal"&gt;PGASetDECrossoverProb&lt;/code&gt; ist kritisch. Für Probleme wo
die Dimensionen nicht einzeln optimierbar sind, sollte der Wert nahe
bei, aber nicht gleich 1 sein.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="footnote-1" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;David Goldberg. What every computer scientist should know
about floating-point arithmetic. ACM Computing Surveys,
23(1):5–48, 1991.
&lt;a class="reference external" href="https://dl.acm.org/doi/pdf/10.1145/103162.103163"&gt;ACM macht es frei verfügbar&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Blickle, Tobias; Thiele, Lothar (1996). "A Comparison of Selection
Schemes Used in Evolutionary Algorithms". Evolutionary Computation.
4 (4): 361–394. &lt;a class="reference external" href="https://dl.acm.org/doi/pdf/10.1162/evco.1996.4.4.361"&gt;Verfügbar bei ACM&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;David E. Goldberg. Genetic Algorithms in Search, Optimization &amp;amp;
Machine Learning. Addison Wesley, October 1989.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-4"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-5"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Tobias Blickle and Lothar Thiele. A comparison of selection
schemes used in genetic algorithms. TIK-Report 11 Version 2,
Computer Engineering and Communications Lab (TIK), December 1995.
&lt;a class="reference external" href="https://tik-old.ee.ethz.ch/file/6c0e384dceb283cd4301339a895b72b8/TIK-Report11.pdf"&gt;Verfügbar bei der ETH&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-6"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution – a simple
and efficient heuristic for global optimization over continuous
spaces. Journal of Global Optimization, 11(4):341–359, December 1997.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-7"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution – a simple
and efficient adaptive scheme for global optimization over
continuous spaces. Technical Report TR-95-012, International
Computer Science Institute (ICSI), March 1995.
&lt;a class="reference external" href="ftp://ftp.icsi.berkeley.edu/pub/techreports/1995/tr-95-012.pdf"&gt;Verfügbar beim International Computer Science Institute&lt;/a&gt;&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-8"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-10"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Kenneth V. Price, Rainer M. Storn, and Jouni A. Lampinen.
Differential Evolution: A Practical Approach to Global Optimization.
Springer, Berlin, Heidelberg, 2005.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-8" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/12/03/#footnote-reference-9"&gt;8&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Ralf Schlatterbeck. &lt;a class="reference external" href="https://blog.runtux.com/de/posts/2021/12/27/"&gt;Antennen Optimierung mit mehreren Kriterien&lt;/a&gt;.
Blogeintrag, Open Source Consulting, Dezember 2021.&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;</description><category>documentation</category><category>genetic algorithms</category><category>german</category><category>howto</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2022/12/03/</guid><pubDate>Sat, 03 Dec 2022 15:28:00 GMT</pubDate></item><item><title>Optimierung mit Epsilon-Randbedingungen</title><link>https://blog.runtux.com/de/posts/2022/08/29/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;p&gt;[Änderung 2022-10-18: Ersetze epsilon durch delta in der Beschreibung
von Beispiel 7 in pgapack]&lt;/p&gt;
&lt;p&gt;Viele Optimierungsprobleme beinhalten Randbedingungen die von gültigen
Lösungen erfüllt sein müssen. Ein
&lt;a class="reference internal" href="https://blog.runtux.com/de/posts/2022/08/29/#optimierungsproblem-mit-randbedingungen"&gt;Optimierungsproblem mit Randbedingungen&lt;/a&gt; wird typischerweise als
nichtlineares Programmierungs-Problem formuliert &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="math" id="optimierungsproblem-mit-randbedingungen"&gt;
\begin{align*}
\hbox{Minimiere}   \; &amp;amp; f_i(\vec{x}),            &amp;amp; i &amp;amp;= 1, \ldots, I \\
\hbox{Unter den Bedingungen} \;
                      &amp;amp; g_j(\vec{x}) \le 0,      &amp;amp; j &amp;amp;= 1, \ldots, J \\
                     &amp;amp; h_k(\vec{x}) = 0,        &amp;amp; k &amp;amp;= 1, \ldots, K \\
                     &amp;amp; x_m^l \le x_m \le x_m^u, &amp;amp; m &amp;amp;= 1, \ldots, M \\
\end{align*}
&lt;/div&gt;
&lt;p&gt;In diesem Problem gibt es &lt;span class="math"&gt;\(n\)&lt;/span&gt; Variablen (der Vektor
&lt;span class="math"&gt;\(\vec{x}\)&lt;/span&gt; hat die Länge &lt;span class="math"&gt;\(n\)&lt;/span&gt;), &lt;span class="math"&gt;\(J\)&lt;/span&gt; Ungleich-Bedingungen,
&lt;span class="math"&gt;\(K\)&lt;/span&gt; Gleichheits-Bedingungen und die Variable &lt;span class="math"&gt;\(x_m\)&lt;/span&gt; muss im
Bereich &lt;span class="math"&gt;\(|x_m^l, x_m^u|\)&lt;/span&gt; sein (als Box-Bedingung bezeichnet). Die
Funktionen &lt;span class="math"&gt;\(f_i\)&lt;/span&gt; heissen Zielfunktionen. Probleme mit mehreren
Zielfunktionen habe ich schon früher in diesem Blog &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-2" id="footnote-reference-2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; beschrieben.
Im folgenden werde ich einige Begriffe ohne weitere Erklärung verwenden
die in diesem früheren Blogbeitrag eingeführt wurden.&lt;/p&gt;
&lt;p&gt;Die Zielfunktionen werden nicht notwendigerweise minimiert (wie in der
Formel angegeben) sondern können auch maximiert werden wenn das Problem
dies verlangt. Die Ungleich-Bedingungen werden auch oft mit einem
&lt;span class="math"&gt;\(\ge\)&lt;/span&gt; Zeichen formuliert, die Formal kann einfach umgestellt
werden (z.B. durch Multiplikation mit -1) um ein &lt;span class="math"&gt;\(\le\)&lt;/span&gt; Zeichen zu
verwenden.&lt;/p&gt;
&lt;p&gt;Nachdem es recht schwer ist, Gleichheits-Bedingungen zu erfüllen,
besonders wenn diese in nichtlinearen Funktionen der Eingabevariablen
auftreten, werden Gleichheits-Bedingungen oft in Ungleich-Bedingungen
umgewandelt unter Verwendung einer δ‑Umgebung:&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
-\delta \le h_k(\vec{x}) \le \delta
\end{equation*}
&lt;/div&gt;
&lt;p&gt;Wobei δ so gewählt wird dass die Lösung gut genug für das zu
lösende Problem ist.&lt;/p&gt;
&lt;p&gt;Eine sehr erfolgreiche Methode zur Lösung von Problemen mit
Randbedingungen verwendet eine lexicographische Ordnung von
Randbedingungen und Zielfunktion(en). Lösungskandidaten des Problems
werden zuerst nach verletzten Randbedingungen sortiert (typischerweise
der Summe der Verletzung von Randbedingungen) und dann nach dem Wert der
Zielfunktion(en) &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-1" id="footnote-reference-3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Beim Vergleich von zwei Individuen während der
Selektionsphase des Genetischen Algorithmus gibt es drei Fälle: Wenn
beide Individuen die Randbedingungen verletzen gewinnt das Individuum
mit der kleineren Verletzung der Bedingungen. Wenn ein Individuum keine
Bedingung verletzt, das andere aber schon, gewinnt das Individuum ohne
Verletzung von Randbedingungen. Im letzten Fall dass keines der
Individuen die Bedingungen verletzt, findet ein normaler Vergleich der
Zielfunktionen statt (was vom verwendeten Algorithmus abhängt und ob
maximiert oder minimiert wird). Diese Methode, ursprünglich von Deb &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-1" id="footnote-reference-4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
vorgeschlagen ist in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; und im Python Wrapper &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;PGAPy&lt;/a&gt;
implementiert.&lt;/p&gt;
&lt;p&gt;Mit diesem Algorithmus zur Behandlung von Randbedingungen, werden zuerst
Lösungskandidaten gefunden die keine Randbedingung verletzen bevor der
Algorithmus die Zielfunktionen überhaupt "anschaut". Daher passiert es
dann oft, dass die Suche in einer Region endet wo es keine guten
Lösungen gibt (aber dafür keine Randbedingungen verletzt sind).
Schwierige Probleme, bei welchen dies auftritt, sind oft Probleme mit
Gleichheits-Bedingungen aber es gibt auch andere "schwierige"
Randbedingungen. In einem früheren Blog Post &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-2" id="footnote-reference-5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; zur
Antennen-Optimierung habe ich geschrieben: "dass der
Optimierungs-Algorithmus Schwierigkeiten hat, überhaupt sinnvolle
Lösungen für die Direktor-Variante zu finden. Nur bei einer handvoll
Experimente war es überhaupt möglich, die obige Pareto-Front zu finden."&lt;/p&gt;
&lt;p&gt;In diesem Experiment habe ich 50 Optimierungsläufe durchgeführt und nur
5 davon sind &lt;em&gt;nicht&lt;/em&gt; in einem lokalen Optimum steckengeblieben. Etwas
ähnliches passiert bei Problem 7 in Deb's Artikel &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-1" id="footnote-reference-6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; wo
Gleichheits-Bedingungen verwendet werden. Ich habe dieses als
&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/blob/master/examples/deb/deb7.c"&gt;Beispiel 7&lt;/a&gt; in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; implementiert. Es wird nur eine Lösung nahe dem
(bekannten) Optimum gefunden wenn &lt;span class="math"&gt;\(\delta \ge 10^{-2}\)&lt;/span&gt; für
alle Gleichheits-Bedingungen ist (ich habe nicht mit verschiedenen
Anfangswerten für den Zufallszahlengenerator experimentiert, es könnte
sein dass man mit einem anderen Startwert bessere Lösungen findet). Im
Artikel &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-1" id="footnote-reference-7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; verwendet Deb &lt;span class="math"&gt;\(\delta = 10^{-3}\)&lt;/span&gt; aus dem selben
Grund.&lt;/p&gt;
&lt;p&gt;Eine Methode, um dieses Problem zu verbessern, war attraktiv, weil sie
sowohl einfach zu verstehen als auch zu implementieren ist: Takahama und
Sakai haben zuerst mit einer Methode experimentiert um unter gelockerten
Randbedingungen in der Frühphase der Optimierung zu arbeiten, sie
nannten dies einen Genetischen Algorithmus mit α‑Randbedingungen &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-3" id="footnote-reference-8" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Die Methode wurde später vereinfacht und als
Optimierung mit ε‑Randbedingungen bezeichnet. Sie kann für
verschiedene Optimierungsalgorithmen verwendet werden, nicht nur für
Genetische Algorithmen und Varianten &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-4" id="footnote-reference-9" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Von speziellem Interesse in
diesem Zusammenhang ist die Anwendung der Methode für Differential
Evolution &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-5" id="footnote-reference-10" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-6" id="footnote-reference-11" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, aber natürlich kann sie auch für andere Formen von
Genetischen Algorithmen verwendet werden.&lt;/p&gt;
&lt;p&gt;Das ε im Namen dieser Methode &lt;em&gt;kann&lt;/em&gt; für das δ bei der
Konversion von Gleichheits-Bedingungen in Ungleich-Bedingungen verwendet
werden, ist aber nicht auf diesen Anwendungsfall eingeschränkt.&lt;/p&gt;
&lt;p&gt;Während des Optimimierungslaufes wird in jeder Generation ein neuer Wert
für ε berechnet. Der Vergleich von Individuen wie oben skizziert
wird so modifiziert, dass ein Individuum so behandelt wird als verletze
es keine Randbedingung wenn die Verletzung der Randbedingungen kleiner
ist als ε. Wenn also beide Individuen die Randbedingungen um
mehr als ε verletzen gewinnt das Individuum mit der kleineren
Verletzung. Wenn ein Individuum die Bedingungen um weniger als ε
verletzt, das andere aber mehr, gewinnt das erste. Und schließlich wenn
die Verletzung der Randbedingungen bei beiden Individuen kleiner ist als
ε findet der normale Zielfunktions-Vergleich statt.&lt;/p&gt;
&lt;p&gt;Dieser letzte Fall ist der Schlüssel zum Erfolg des Algorithmus: Obwohl
die Suche in eine Richtung zu weniger Verletzung der Randbedingungen
fortschreitet, wird &lt;em&gt;gleichzeitig&lt;/em&gt; eine gute Lösung bezogen auf die
Zielfunktionenen gefunden.&lt;/p&gt;
&lt;p&gt;Der Algorithmus startet mit der Initialisierung von
&lt;span class="math"&gt;\(\varepsilon_0\)&lt;/span&gt; mit der Summe der Verletzung der Randbedingungen
des Individuums mit dem Index &lt;span class="math"&gt;\(\theta\)&lt;/span&gt; der nach Verletzung der
Randbedingungen sortierten initialen Population. Dabei ist
&lt;span class="math"&gt;\(\theta\)&lt;/span&gt; ein Parameter des Algorithmus zwischen 1 und der
Populationsgröße, ein guter Wert ist etwa 20% der Populationsgröße,
was auch der Standardwert in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; ist. In jeder Generation &lt;span class="math"&gt;\(t\)&lt;/span&gt;
wird &lt;span class="math"&gt;\(\varepsilon_t\)&lt;/span&gt; berechnet zu:&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
\varepsilon_t = \varepsilon_0 \left(1-\frac{t}{T_c}\right)^{cp}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;bis zur Generation &lt;span class="math"&gt;\(T_c\)&lt;/span&gt;. Nach dieser Generation wird ε
auf 0 gesetzt. Der Exponent &lt;span class="math"&gt;\(cp\)&lt;/span&gt; ist zwischen 2 und 10. Der
Artikel von 2010 &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-6" id="footnote-reference-12" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; empfiehlt zur Generation
&lt;span class="math"&gt;\(T_\lambda = 0.95 T_c\)&lt;/span&gt; den Wert &lt;span class="math"&gt;\(cp = 0.3 cp + 0.7 cp_\min\)&lt;/span&gt;
zu setzen, wobei &lt;span class="math"&gt;\(cp_\min\)&lt;/span&gt; der fixe Wert 3 ist. Der Anfangswert
von &lt;span class="math"&gt;\(cp\)&lt;/span&gt; wird so gewählt dass zur Generation &lt;span class="math"&gt;\(T_\lambda\)&lt;/span&gt;
&lt;span class="math"&gt;\(\varepsilon_\lambda=10^{-5}\)&lt;/span&gt; ist ausser &lt;span class="math"&gt;\(cp\)&lt;/span&gt; wäre kleiner,
dann wird es auf &lt;span class="math"&gt;\(cp_\min\)&lt;/span&gt; gesetzt. &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;PGAPack&lt;/a&gt; implementiert diese
Empfehlung für &lt;span class="math"&gt;\(cp\)&lt;/span&gt; als Standard-Einstellung, erlaubt aber das
Setzen von &lt;span class="math"&gt;\(cp\)&lt;/span&gt; zu Beginn und während der Laufzeit der
Optimierung. Es ist also einfach möglich, andere Änderungen von
&lt;span class="math"&gt;\(cp\)&lt;/span&gt; zu implementieren – die Standard-Einstellung funktioniert
jedoch recht gut.&lt;/p&gt;
&lt;p&gt;Durch Optimierung mit ε Randbedingungen konnten in meinen
Experimenten die Gleichheits-Bedingungen in Beispiel 7 von Deb &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-1" id="footnote-reference-13" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; mit
einer Genauigkeit von &lt;span class="math"&gt;\(10^{-6}\)&lt;/span&gt; approximiert werden, siehe die
Variable &lt;code class="docutils literal"&gt;epsilon_generation&lt;/code&gt; im &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack/blob/master/examples/deb/optimize.c"&gt;optimizer Beispiel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Wird der &lt;a class="reference external" href="https://github.com/schlatterbeck/antenna-optimizer"&gt;antenna-optimizer&lt;/a&gt; mit ε‑generation 50 gestartet
(das ist der &lt;span class="math"&gt;\(T_c\)&lt;/span&gt; aus obigem Algorithmus) bleibt der Algorithmus
nur in einem einzigen Fall im lokalen Optimum stecken, alle anderen
Fälle finden gute Lösungen:&lt;/p&gt;
&lt;iframe class="iframe-embed" width="640" height="480" scrolling="no" frameborder="no" src="https://blog.runtux.com/content/2022/plot-50.html"&gt;
&lt;/iframe&gt;&lt;p&gt;In dieser Grafik sind alle Lösungen von einem Optimierungslauf die von
den Lösungen eines anderen Laufs dominiert werden in Schwarz
eingezeichnet. Wir sehen dass die Daten von Lauf 16 keine
nicht-dominierte Lösung beigetragen haben (auf der rechten Seite in der
Legende fehlt die Nummer 16). In der Grafik kann man die dominierten
Lösungen aus der Anzeige nehmen indem man auf den schwarzen Kreis in der
Legende klickt.&lt;/p&gt;
&lt;p&gt;Wenn der Parameter ε‑generation für den Lauf der im lokalen
Optimum geendet hat auf 60 erhöht wird, findet auch der Lauf mit
Zufallszahlen-Startwert 16 eine Lösung:&lt;/p&gt;
&lt;iframe class="iframe-embed" width="640" height="480" scrolling="no" frameborder="no" src="https://blog.runtux.com/content/2022/plot-50+60.html"&gt;
&lt;/iframe&gt;&lt;p&gt;Es ist auch sichtbar dass die Lösungen für alle Experimente ziemlich gut
(weil nahe an der Pareto-Front) sind. Der schwarze "Schatten" der
dominierten Lösungen ist ziemlich nahe an der wirklichen Pareto-Front
und ist gut genug um mit einem einzigen Optimierungslauf ausreichend
gute Lösungen zu finden.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="footnote-1" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-1"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-3"&gt;2&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-4"&gt;3&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-6"&gt;4&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-7"&gt;5&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-13"&gt;6&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Kalyanmoy Deb. An efficient constraint handling method for
genetic algorithms. Computer Methods in Applied Mechanics and
Engineering, 186(2–4):311–338, June 2000.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-2"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-5"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Ralf Schlatterbeck. &lt;a class="reference external" href="https://blog.runtux.com/posts/2021/12/27/"&gt;Multi-objective antenna optimization&lt;/a&gt;.
Blog post, Open Source Consulting, December 2021.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-8"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Tetsuyuki Takahama and Setsuko Sakai. Constrained optimization
by α constrained genetic algorithm (αGA). Systems
and Computers in Japan, 35(5):11–22, May 2004.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-9"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Tetsuyuki Takahama and Setsuko Sakai. Constrained optimization
by ε constrained particle swarm optimizer with ε‑level control. In Abraham et al., editors, Soft Computing as
Transdisciplinary Science and Technology, volume 29 of Advances
in Soft Computing, pages 1019–1029. Springer, 2005.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-10"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Tetsuyuki Takahama and Setsuko Sakai. Constrained optimization by
the ε constrained differential evolution with gradient-based
mutation and feasible elites. In IEEE International Conference on
Evolutionary Computation (CEC). Vancouver, BC, Canada, July 2006.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="backrefs"&gt;(&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-11"&gt;1&lt;/a&gt;,&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2022/08/29/#footnote-reference-12"&gt;2&lt;/a&gt;)&lt;/span&gt;
&lt;p&gt;Tetsuyuki Takahama and Setsuko Sakai. Constrained optimization by
the ε constrained differential evolution with an archive and
gradient-based mutation. In IEEE Congress on Evolutionary Computation
(CEC), Barcelona, Spain, July 2010.&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;</description><category>documentation</category><category>genetic algorithms</category><category>german</category><category>hamradio</category><category>hardware</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2022/08/29/</guid><pubDate>Mon, 29 Aug 2022 16:00:00 GMT</pubDate></item><item><title>Antennen Optimierung mit mehreren Kriterien</title><link>https://blog.runtux.com/de/posts/2021/12/27/</link><dc:creator>Ralf Schlatterbeck</dc:creator><description>&lt;p&gt;Seit einiger Zeit optimiere ich Antennen mit Genetischen Algorithmen.
Ich verwende dafür das Paket für parallele Genetische Algorithmen,
&lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;pgapack&lt;/a&gt; das ursprünglich von David Levine vom Argonne National
Laboratory entwickelt wurde und das ich pflege (wie übersetze ich
"maintain"?). Noch länger als die Pflege von &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;pgapack&lt;/a&gt; entwickle ich
eine &lt;a class="reference external" href="https://python.org"&gt;Python&lt;/a&gt; Bibliothek für &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;pgapack&lt;/a&gt; namens &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;pgapy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Für die Antennensimulation verwende ich Tim Molteno's &lt;a class="reference external" href="https://github.com/tmolteno/python-necpp"&gt;PyNEC&lt;/a&gt; Paket, eine
Bibliothek in &lt;a class="reference external" href="https://python.org"&gt;Python&lt;/a&gt; für ein Paket zur elektromagnetischen Simulation
namens "Numerical Electromagnetics Code (NEC) Version 2", geschrieben in
C++ (auch bekannt als NEC++).&lt;/p&gt;
&lt;p&gt;Mit diesen Paketen habe ich ein kleines Open Source Framework für die
Antennen-Optimierung namens &lt;a class="reference external" href="https://github.com/schlatterbeck/antenna-optimizer"&gt;antenna-optimizer&lt;/a&gt; geschrieben. Dieses
kann traditionelle Genetische Algorithmen mit Bit-Strings als Genen als
auch Fließkomma-Repräsentationen mit dafür geeigneten Operatoren
verwenden.&lt;/p&gt;
&lt;p&gt;Das "Parallel" in &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;pgapack&lt;/a&gt; sagt uns, dass die Evaluierungsfunktion des
Genetischen Algorithmus parallelisiert werden kann. Bei der Optimierung
von Antennen simulieren wir für jede Paramter-Kombination die einen
Antenne darstellt diese mit &lt;a class="reference external" href="https://github.com/tmolteno/python-necpp"&gt;PyNEC&lt;/a&gt;. Antennensimulation ist nach wie vor
(der ursprüngliche NEC Code ist aus den 80er Jahren und wurde im
Zeitalter von Lochkarten entwickelt) ein CPU-instensives Unterfangen.
So ist es eine gute Nachricht, dass wir mit &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;pgapack&lt;/a&gt; viele Simulationen
parallel mit dem Message Passing Interface (MPI) Standard &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
durchführen können.&lt;/p&gt;
&lt;p&gt;Für &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;pgapack&lt;/a&gt; – und damit auch für &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapy"&gt;pgapy&lt;/a&gt; – habe ich in letzter
Zeit einige bewährte klassische Algorithmen implementiert:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Differential Evolution &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-2" id="footnote-reference-2" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;2&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-3" id="footnote-reference-3" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;3&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;, &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-4" id="footnote-reference-4" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;4&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; ist ein erfolgreicher
Optimierungs-Algorithmus für Fließkomma-Gene der für
elektromagnetische Aufgaben sehr interessant ist.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Der "elitist Nondominated Sorting Genetic Algorithm" NSGA-II &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-5" id="footnote-reference-5" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;5&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;
erlaubt es in einem einzigen Optimierungslauf mehrere Zielfunktionen
zu optimieren&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wir können Wertebeschränkungen im Zielbereich einer Funktion
definieren die minimiert werden, sogenannte "Constraints" &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-6" id="footnote-reference-6" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;6&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;. Damit
eine Lösung gültig ist, müssen alle Constraints 0 oder negativ sein.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Traditionell ist mit Genetischen Algorithmen nur eine
Evaluierungsfunktion, die sogenannte Zielfunktion möglich. Mit NSGA-II
können mehrere Zielfunktionen oder Kriterien verwendet werden. Das
Englische nennt solche Algorithmen "Multi-Objective Optimization"
(Optimierung mehrerer Ziele).&lt;/p&gt;
&lt;p&gt;Für die Antennensimulation heisst dass, wir müssen nicht mehrere
Kriterien für eine gute Antenne wie Gewinn, Vorwärts/Rückwärtsverhältnis
und Stehwellenverhältnis (SWV) in einer einzigen Evaluierungsfunktion
zusammenfassen, was ich bisher im &lt;a class="reference external" href="https://github.com/schlatterbeck/antenna-optimizer"&gt;antenna-optimizer&lt;/a&gt; gemacht habe,
sondern können sie separat definieren und dem Genetischen Algorithmus
die Optimierung überlassen.&lt;/p&gt;
&lt;p&gt;Mit mehreren Zielfunktionen ist es allerdings typischerweise so, dass
die Verbesserung bei einem Ziel eine Verschlechterung bei einem anderen
Ziel zur Folge hat und umgekehrt. Wir suchen also Lösungen die strikt
besser sind als andere Lösungen. Eine Lösung &lt;em&gt;dominiert&lt;/em&gt; eine andere
Lösung wenn sie in einem Kriterium &lt;em&gt;besser&lt;/em&gt; aber in keinem der anderen
Kriterien &lt;em&gt;schlechter&lt;/em&gt; ist als die andere Lösung. Alle Lösungen die
dieser Definition entsprechen heissen &lt;a class="reference external" href="https://de.wikipedia.org/wiki/Pareto-Optimum"&gt;Pareto-Optimal&lt;/a&gt; nach dem
Italienischen Wissenschaftler &lt;a class="reference external" href="https://de.wikipedia.org/wiki/Vilfredo_Pareto"&gt;Vilfredo Pareto&lt;/a&gt; der das Konzept von
Pareto-Optimalität zuerst definiert hat. Alle Lösungen die dieses
Optimalitäts-Kriterium erfüllen, liegen auf einer sogenannten
&lt;em&gt;Pareto-Front&lt;/em&gt;. Wenn wir nur zwei Zielfunktionen haben, können wir die
Pareto-Front gut mit einem Scatterplot (Streudiagramm) darstellen, wie
wir weiter unten sehen werden.&lt;/p&gt;
&lt;p&gt;Weil &lt;a class="reference external" href="https://github.com/schlatterbeck/pgapack"&gt;pgapack&lt;/a&gt; einen Ansatz verfolgt, der die freie Kombination von
Algorithmen unterstützt, können wir verschiedene erfolgreiche Strategien
für unterschiedliche Teile des Genetischen Algorithmus kombinieren:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Für den Mutation/Crossover Teil können wir Differential Evolution (DE)
verwenden&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DE wiederum kann für mehrere Zielfunktionen mit der (Generations-)
Ersetzungsstrategie von NSGA-II kombiniert werden&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wir können einige der Zielfunktionen als Beschränkungen (Constraints)
definieren. Für unser Problem ist es sinnvoll nur Antennen zu erlauben
die ein bestimmtes Stehwellenverhältnis (SWV) nicht überschreiten. Wir
erlauben also keine Antenne mit einem SWV &amp;gt; 1.8. Die zugehörige
Zielfunktion ist &lt;span class="math"&gt;\(S - 1.8 \le 0\)&lt;/span&gt; wobei &lt;span class="math"&gt;\(S\)&lt;/span&gt; das SWV ist.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mit dieser Kombination können wir erfolgreich Antennen für das 70cm
Amaterufunkband (430 MHz - 440 MHz) berechnen. Die Antenne verwendet
einen sogenannten Faltdipol (das Ding mit den Rundungen in der Grafik)
und ein gerades Element. Die Messlinien in der Grafik repräsentieren die
vom Genetischen Algorithmus optimierten Längen. Die zwei Punkte in der
Mitte des Faltdipols zeigen den Punkt wo die Speiseleitung angeschlossen
wird.&lt;/p&gt;
&lt;img alt="/images/2ele.png" src="https://blog.runtux.com/images/2ele.png"&gt;
&lt;p&gt;Ein erstes Beispiel simuliert Antennenparameter für die höchste,
niedrigste und mittlere Frequenz. Der Gewinn und das
Vorwärts/Rückwärtsverhältnis (Forward/Backward ratio in der Grafik)
werden nur für die mittlere Frequenz berechnet:&lt;/p&gt;
&lt;img alt="/images/twoele-v1.png" src="https://blog.runtux.com/images/twoele-v1.png"&gt;
&lt;p&gt;In dieser Grafik (ein Scatterplot) wird die erste Zielfunktion (der
Gewinn) gegen die zweite Zielfunktion, das Vorwärts/Rückwärtsverhältnis
aufgetragen. Alle Zahlen sind für die mittlere Frequenz. Jeder Punkt in
der Grafik repräsentiert eine Antenne. Alle Antennen haben ein SWV
kleiner als 1.8 auf der kleinsten, mittleren und höchsten Frequenz.&lt;/p&gt;
&lt;p&gt;Nach diesem Erfolg habe ich dann angefangen, mit unterschiedlichen
Einstellungen für die Parameter des Differential Evolution (DE) Algorithmus
zu experimentieren. Es ist in der Literatur zu DE bekannt dass
für "zerlegbare" (decomposable) Probleme eine niedrige Crossover-Rate
besser ist, für nicht-zerlegbare eine höhere. Ein zerlegbares Problem
zeichnet sich dadurch aus, dass die unterschiedlichen Dimensionen
getrennt voneinander optimierbar sind, dies wurde zuerst von Salomon
1996 &lt;a class="brackets" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-7" id="footnote-reference-7" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;7&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt; beobachtet. Ursprünglich hatte ich eine Crossover-Rate von 0.2
eingestellt und meine Hoffnung war, dass die Optimierung mit einer
höheren Rate besser und schneller funktionieren würde. Das Experiment
unten verwendet eine Crossover-Rate von 0.9.&lt;/p&gt;
&lt;p&gt;Zusätzlich habe ich mit "Dither" für den Skalierungsfaktor &lt;span class="math"&gt;\(F\)&lt;/span&gt; von
Differential Evolution (könnte vielleicht mit einem leichten "Zittern"
Skalierung übersetzen) experimentiert. Mit diesem Faktor wird die
Differenz von zwei Vektoren der Input-Parameter bei der Anwendung von DE
multipliziert. In der ersten Implementierung hatte ich &lt;em&gt;Dither&lt;/em&gt; auf 0
gesetzt, jetzt hatte ich 0.2 eingestellt. Ich war dann sehr überrascht
dass ich mit diesen Einstellungen eine neue Pareto-Front als Lösung
gefunden habe:&lt;/p&gt;
&lt;img alt="/images/twoele-v2.png" src="https://blog.runtux.com/images/twoele-v2.png"&gt;
&lt;p&gt;Damit man besser sieht, dass die zweite Front komplett die zuerst
gefundene Front dominiert habe ich beide in einer Grafik geplottet:&lt;/p&gt;
&lt;img alt="/images/twoele-v3.png" src="https://blog.runtux.com/images/twoele-v3.png"&gt;
&lt;p&gt;Weil diese zweite Front (über den gesamten Frequenzbereich) für eine
Zwei-Elemente Antenne zu gut ausschaut um wahr zu sein schauen wir uns
das im Folgenden genauer an. Zuerst schauen wir auf die Orientierung der
Antenne und des berechneten Gewinn-Diagramms für eine der Antennen in
der Mitte der unteren Front:&lt;/p&gt;
&lt;img alt="/images/middle-lower-antenna.png" src="https://blog.runtux.com/images/middle-lower-antenna.png" style="width: 45%;"&gt;
&lt;img alt="/images/middle-lower-pattern.png" src="https://blog.runtux.com/images/middle-lower-pattern.png" style="width: 45%;"&gt;
&lt;p&gt;Die Antenne hat – wie schon aus der ersten Pareto-Front Grafik zu
entnehmen – einen Gewinn von etwa 6.6 dBi und ein
Vorwärts/Rückwärtsverhältnis von etwa 11 dB in der Mitte des Bandes
bei 435 MHz. Die Einfärbung der Antenne deutet die Ströme in der
Antennenstruktur an.
Wer sich das selbst anschauen möchte: Hier ist ein Link zur
&lt;a class="reference external" href="https://blog.runtux.com/content/2021/middle-lower.nec"&gt;NEC Input Datei für Antenne 1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vergleichen wir diese Antenne mit einer aus der Mitte der "orangen
Front" wo wir deutlich bessere Ergebnisse bekommen:&lt;/p&gt;
&lt;img alt="/images/middle-higher-antenna.png" src="https://blog.runtux.com/images/middle-higher-antenna.png" style="width: 45%;"&gt;
&lt;img alt="/images/middle-higher-pattern.png" src="https://blog.runtux.com/images/middle-higher-pattern.png" style="width: 45%;"&gt;
&lt;p&gt;Diese Antenne ist aus der Mitte der oberen Pareto-Front und hat einen
Gewinn von etwa 6.7 dBi sowie ein Vorwärts/Rückwärtsverhältnis von
etwa 16 dB in der Mitte des Bandes bei 435 MHz. Wer entdeckt den
Unterschied zur vorherigen Antenne? Ja: der maximale Gewinn liegt in der
Gegenrichtung der ersten Antenne. Wir sagen dass bei der ersten Antenne
das gerade Element ein &lt;em&gt;Reflektor&lt;/em&gt; ist, während bei der zweiten Antenne
das gerade Element als &lt;em&gt;Direktor&lt;/em&gt; arbeitet.
Auch hier ist ein Link zur &lt;a class="reference external" href="https://blog.runtux.com/content/2021/middle-higher.nec"&gt;NEC Input Datei für Antenne 2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nun schauen wir uns über die ganze Frequenz den Gewinn und das
Vorwärts/Rückwärtsverhältnis an. Die linke Grafik ist für die erste
Antenne (die mit dem &lt;em&gt;Reflektor&lt;/em&gt;-Element), die rechte für die zweite
Antenne wo das gerade Element als &lt;em&gt;Direktor&lt;/em&gt; arbeitet.&lt;/p&gt;
&lt;img alt="/images/middle-lower-fplot.png" src="https://blog.runtux.com/images/middle-lower-fplot.png" style="width: 45%;"&gt;
&lt;img alt="/images/middle-higher-fplot.png" src="https://blog.runtux.com/images/middle-higher-fplot.png" style="width: 45%;"&gt;
&lt;p&gt;Wir sehen dass sich das Vorwärts/Rückwärtsverhältnis bei der &lt;em&gt;Direktor&lt;/em&gt;
Antenne von etwas mehr als 10 dB bis zu über 25 dB bewegt,
während es für das &lt;em&gt;Reflektor&lt;/em&gt;-Design von 9.3 dB bis 11.75 dB
geht. Der Minimalgewinn ist beim Reflektor-Design etwas besser
(6.35-6.85 dBi bzw. 6.3-7.05 dBi). Also brauchen wir weitere
Experimente. Wenn man die Lösungen auf ein &lt;em&gt;Reflektor&lt;/em&gt;-Design beschränkt
und fordert dass der &lt;em&gt;Minimalgewinn&lt;/em&gt; und das &lt;em&gt;minimale&lt;/em&gt;
Vorwärts/Rückwärtsverhältnis an den drei Stellen (untere, mittlere,
obere Frequenz) genommen wird bekommen wir:&lt;/p&gt;
&lt;img alt="/images/twoele-reflector.png" src="https://blog.runtux.com/images/twoele-reflector.png"&gt;
&lt;p&gt;Für das gleiche bei einem &lt;em&gt;Direktor&lt;/em&gt; Design (auch mit &lt;em&gt;minimalem&lt;/em&gt; Gewinn
und Vorwärts/Rückwärtsverhältnis bei allen drei Frequenzen (untere,
mittlere, obere Frequenz) bekommen wir:&lt;/p&gt;
&lt;img alt="/images/twoele-director.png" src="https://blog.runtux.com/images/twoele-director.png"&gt;
&lt;p&gt;Mit diesen Resultaten ist der &lt;a class="reference external" href="https://de.wikipedia.org/wiki/Sweet_Spot"&gt;Sweet Spot&lt;/a&gt; für eine Antenne die man
wirklich bauen will wahrscheinlich bei etwa 10 dB
Vorwärts/Rückwärtsverhältnis oder darüber und bei einem Gewinn von etwa
6.2 dBi. Ein paar zehntel-dB mehr Gewinn rauszuholen und dabei
mehrere dB Vorwärts/Rückwärtsverhältnis zu verlieren scheint nicht sehr
sinnvoll. Beim Vergleich des Direktor mit dem Reflektor-Design fällt auf
(was zumindest &lt;em&gt;meiner&lt;/em&gt; Intuition widerspricht) dass das Direktor-Design
ein besseres Vorwärts/Rückwärtsverhältnis über den gesamten
Frequenzbereich hat. Wenn allerdings die Antenne für
Relais-Kommunikation Verwendung finden soll wo die Sendefrequenz (die
Relais-Eingabe) im unteren Teil des Frequenzbandes liegt und die
Relais-Ausgabe (unsere Empfangsfrequenz) in der oberen Hälfte, würden
wir vermutlich ein &lt;em&gt;Reflektor&lt;/em&gt;-Design realisieren weil der Gewinn beim
Senden besser ist und das Vorwärts/Rückwärtsverhältnis beim Empfang
besser ist (vergleiche die beiden vorherigen Grafiken zu Gewinn und
Vorwärts/Rückwärtsverhältnis).&lt;/p&gt;
&lt;p&gt;Man beachte auch, dass der Optimierungs-Algorithmus Schwierigkeiten hat,
überhaupt sinnvolle Lösungen für die Direktor-Variante zu finden. Nur bei
einer handvoll Experimente war es überhaupt möglich, die obige
Pareto-Front zu finden. Das Direktor-Design ist schmalbandiger als das
Reflektor-Design und da das Stehwellenverhältnis ein Beschränkung
(Constraint) ist, werden oft nur lokale Optima gefunden. Der größere
Unterschied im Wertebereich von Gewinn- und Vorwärts/Rückwärtsverhältnis
für das Direktor Design sagt uns ausserdem dass es schwieriger zu
realisieren sein wird: Wenn die Dimensionen nicht exakt richtig
getroffen werden wird die Antenne wohl weiter von den vorhergesagten
Simulationsergebnissen abweichen. Das Reflektor-Design ist etwas
toleranter in dieser Beziehung.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="footnote-1" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-reference-1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;MPI: A message-passing interface standard, version 4.0.
Standard, &lt;a class="reference external" href="https://www.mpi-forum.org/"&gt;Message Passing Interface Forum&lt;/a&gt;, June 2021.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-2" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-reference-2"&gt;2&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution – a simple
and efficient adaptive scheme for global optimization over
continuous spaces. Technical Report TR-95-012, International
Computer Science Institute (ICSI), March 1995.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-3" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-reference-3"&gt;3&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Rainer Storn and Kenneth Price. Differential evolution – a simple
and efficient heuristic for global optimization over continuous spaces.
Journal of Global Optimization, 11(4):341–359, December 1997.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-4" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-reference-4"&gt;4&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Kenneth V. Price, Rainer M. Storn, and Jouni A. Lampinen.
Differential Evolution: A Practical Approach to Global
Optimization.  Springer, Berlin, Heidelberg, 2005.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-5" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-reference-5"&gt;5&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Kalyanmoy Deb, Amrit Pratap, Sameer Agarwal, and T. Meyarivan.
A fast and elitist multiobjective genetic algorithm: NSGA-II.
IEEE Transactions on Evolutionary Computation, 6(2):182–197,
April 2002.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-6" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-reference-6"&gt;6&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Kalyanmoy Deb. An efficient constraint handling method for genetic
algorithms. Computer Methods in Applied Mechanics and Engineering,
186(2–4):311–338, June 2000.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="footnote brackets" id="footnote-7" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://blog.runtux.com/de/posts/2021/12/27/#footnote-reference-7"&gt;7&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;Ralf Salomon. Re-evaluating genetic algorithm performance under
coordinate rotation of benchmark functions. a survey of some
theoretical and practical aspects of genetic algorithms.
Biosystems, 39(3):263–278, 1996.&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;</description><category>documentation</category><category>genetic algorithms</category><category>german</category><category>hamradio</category><category>hardware</category><category>howto</category><category>open source</category><category>optimization</category><guid>https://blog.runtux.com/de/posts/2021/12/27/</guid><pubDate>Mon, 27 Dec 2021 17:05:00 GMT</pubDate></item></channel></rss>