Convex hulls of random walks in higher dimensions: A large deviation study

Die Frage wie groß das Revier eines Tieres ist, ist in konkreten Fällen für Biologen interessant und dank GPS-Sendern kann man es heutzutage sogar empirisch untersuchen. Aus der Punktwolke der besuchten Orte kann man eine Fläche abschätzen — im einfachsten Fall indem man die konvexe Hülle um alle besuchten Orte zeichnet.

Als Physiker sind mir echte Tiere zu kompliziert, sodass ich stattdessen annehme, dass sie punktförmig sind und ihre Bewegung ein Random Walk in einer isotropen Umgebung ist. Also springen meine idealisierten Tiere unabhängig von ihren bisherigen Handlungen zu ihrem nächsten Aufenthaltsort — der Abstand vom aktuellen Punkt ist dabei in jeder Dimension unabhängig und normalverteilt.

In jeder Dimension? Ja, genau! Wir wollen schließlich auch das Revierverhalten von vierdimensionalen Space Whales untersuchen.

Möbius Dick, Futurama Möbius Dick, Futurama (2011)

Spaß beiseite, in dieser Veröffentlichung geht es natürlich eher um fundamentale Eigenschaften von Random Walks — einer der einfachsten und deshalb am besten untersuchten Markow-Prozesse. Und zwar im Hinblick auf Large Deviations, die extrem unwahrscheinlichen Ereignisse, die weit jenseits der Möglichkeiten von konventionellen Sampling-Methoden liegen. Details hierzu sind am besten direkt im Artikel oder mit einer Menge Hintergrundinformationen und ausführlicher als für ein Blog angemessen in dem entsprechenden Kapitel und Anhang meiner Dissertation nachzulesen. Insbesondere ist dort auch beschrieben wie die geometrischen Unterprobleme effizient gelöst werden können, auf die wir im Verlauf dieses Blogposts stoßen werden.

Das Problem eine konvexe Hülle zu finden ist einerseits einfach zu begreifen, schön geometrisch und sehr gut untersucht. Dadurch sind überraschend viele Algorithmen bekannt, die unterschiedliche Vor- und Nachteile haben.

Im Folgenden möchte ich deshalb ein paar Methoden vorstellen, wie man effizient die konvexe Hülle einer Punktmenge bestimmen kann, und dies mit animierten gifs von Punkten und Strichen visualisieren. Der Code zur Erstellung der Visualisierungen ist übrigens in Rust geschrieben und auf GitHub zu finden.

Andrew’s Monotone Chain

In zwei Dimensionen kann man ausnutzen, dass die konvexe Hülle ein Polygon ist, das man durch die Reihenfolge der Eckpunkte definieren kann. Die grundlegende Idee ist also die Punkte im Uhrzeigersinn zu sortieren, in dieser Reihenfolge, mit dem Punkt ganz links startend, alle zu einem Polygon hinzuzufügen und dabei darauf zu achten, dass die drei neusten Punkte des Polygons ein negativ orientiertes Dreieck bilden, also dass sie im “Uhrzeigersinn drehen”. Wenn das nicht der Fall ist, wird der mittlere Punkt entfernt.

Sechs Schritte von Andrew's Monotone Chain -- oder Graham Scan

Dies ist übrigens die ursprüngliche Variante, der Graham Scan. Andrew verbesserte diesen Algorithmus dadurch, dass nicht im Uhrzeigersinn sortiert werden muss, sondern man lexikographisch nach horizontaler Koordinate (bei Gleichstand entscheidet die vertikale Koordinate) sortiert. Dann bildet dieser Algorithmus die obere Hälfte der Hülle und wenn man ihn rückwärts auf die sortierten Punkte anwendet, die untere Hälfte.

Andrew's Monotone Chain

Die Komplexität für \(n\) Punkte ist somit \(\mathcal{O}(n \ln n)\) limitiert durch das Sortieren.

Jarvis March: Gift Wrapping

Ein Geschenk einzupacken ist ein relativ intuitiver Prozess: Wir bewegen das Papier so lange herunter, bis wir auf einen Punkt des Geschenkes treffen, wo es hängen bleibt Dann wickeln wir weiter, bis wir auf den nächsten Punkt stoßen. Dabei streben wir an die konvexe Hülle zu finden, denn sie ist das Optimum möglichst wenig Papier zu verbrauchen während wir die Punktwolke einhüllen, die wir verschenken wollen. Und offenbar klappt das auch in drei Dimensionen!

In einem Computer ist es allerdings einfacher das Geschenkpapier von innen aus der Punktwolke heraus nach außen zu falten. Für jede Facette testen wir also jeden der \(n\) Punkte in der Punktwolke darauf, ob er links von unserem Stück Geschenkpapier liegt. Wenn ja, falten wir das Papier weiter. Sobald wir alle \(n\) Punkte ausprobiert haben, wissen wir, dass das Geschenkpapier an der richtigen Stelle liegt, sodass anfangen können die nächste Facette mit dem Geschenkpapier zu bilden indem wir von innen alle Punkte durchtesten.

Jarvis March: Gift Wrapping

Interessanterweise müssen wir also für jeden der \(h\) Punkte, die zur Hülle gehören \(\mathcal{O}(n)\) Punkte prüfen, sodass die Komplexität abhängig ist vom Ergebnis: \(\mathcal{O}(n h)\)

Chan’s Algorithm

Wir haben also einen \(\mathcal{O}(n \ln n)\) und einen \(\mathcal{O}(n h)\) Algorithmus kennen gelernt, aber können wir noch besser werden? Ja! \(\mathcal{O}(n \ln h)\) ist die theoretische untere Komplexitätsgrenze für 2D konvexe Hüllen. Beispielsweise Chans Algorithmus erreicht diese Komplexität mit einem trickreichen zweistufigen Prozess.

Zuerst teilt man die Punktwolke in zufällige Untermengen mit jeweils etwa \(m\) Punkten ein. Für jede berechnet man die konvexe Hülle, bspw. mit Andrews Algorithmus. Dann benutzt man Jarvis March, um die Hülle zu konstruieren, dabei muss man allerdings nicht mehr alle Punkte durchprobieren, sondern nur noch die Tangenten, die in der Animation mit grünen Strichen gekennzeichnet sind. Die Tangenten kann man für jede der \(k = \lceil \frac{n}{m} \rceil\) Sub-Hüllen effizient in \(\mathcal{O}(m)\) bestimmen. Dazu benutzt man einem Algorithmus, der an eine Binärsuche erinnert. Zusammen hat dies also eine Komplexität von \(\mathcal{O}((n+kh) \ln m)\).

Aber ich hatte \(\mathcal{O}(n \ln h)\) versprochen. Nun, um das zu erreichen, müssen wir einfach nur \(m \approx h\) wählen. Aber wie kommen wir an \(h\) bevor wir die Hülle berechnet haben? Der Trick ist, mit einem niedrigen \(m\) zu starten, dann nur \(m\) Schritte des Jarvis-Teils des Algorithmus durchzuführen und wenn die Hülle dann noch nicht fertig ist \(m\) zu erhöhen und es wieder von vorne zu beginnen. Damit dieser iterative Teil des Algorithmus nicht unsere Komplexität erhöht, muss \(m\) schnell genug wachsen, was in der Regel durch Quadrieren des alten Werten erreicht wird.

Chan's Algorithm

QuickHull

Zuletzt möchte ich hier noch QuickHull vorstellen, weil dieser Algorithmus meiner Meinung nach einen sehr hübschen rekursiven divide and conquer Ansatz verfolgt — ein bisschen wie QuickSort. In zwei Dimensionen starten wir mit dem Punkt ganz links \(A\) und ganz rechts \(B\). Dann finden wir den Punkt \(C\) der am weitesten entfernt ist von der Strecke \(\overline{AB}\) und links von der Strecke ist. Diesen Schritt wiederholen wir rekursiv auf den Strecken \(\overline{AC}\) und \(\overline{CB}\) (und \(\overline{BA}\) für die untere Hälfte.)

QuickHull

Mehr Dimensionen

Aber ich hatte Space Whales versprochen, also können wir uns nicht mit 2D zufrieden geben! Tatsächlich müssen wir schon beim Verallgemeinern auf 3D aufpassen. Schließlich konnten wir für 2D die konvexe Hülle als Sequenz von Punkten repräsentieren. Für höhere Dimensionen müssen wir sie allerdings als Menge von Facetten repräsentieren. Glücklicherweise tauchen für noch höhere Dimensionen dann keine weiteren Schwierigkeiten mehr auf — abgesehen von der Grundsätzlichen Schwierigkeit, dass höherdimensionale Gebilde deutlich größere Oberflächen haben und somit die konvexe Hülle aus deutlich mehr Facetten besteht, sodass die untere Schranke für die Komplexität für Dimension \(d\) durch \(\mathcal{O}(n^{\lfloor d / 2 \rfloor})\) gegeben ist.

Bevor ich hier QuickHull für \(d=3\) beschreibe, möchte ich darauf hinweisen, dass es die qhull Implementierung gibt, die sich bspw. auch um die subtilen numerischen Fehler kümmert, die sich bei sehr spitzen Winkeln einschleichen können.

Grundsätzlich bleibt das Vorgehen gleich: Wir starten mit einem \(d\)-dimensionalen Simplex, also für \(d=3\) mit einem Tetraeder, dessen Eckpunkte zur konvexen Hülle gehören. Dann führen wir für jede Facette den rekursiven Schritt durch: Finde den Punkt, der am weitesten vor der Facette (also außerhalb des Tetraeders) ist. Diesen Punkt nennt man Eye-Point. Denn es reicht jetzt im Gegensatz zum 2D Fall nicht mehr einfach neue Facetten aus den Rändern und dem neuen Punkt zu bilden. Stattdessen müssen wir alle Facetten, deren Vorderseite (also Außenseite) wir vom Eye-Point aus sehen können entfernen und neue Facetten mit dem Horizont und dem Eye-Point bilden. In der Animation unten sind der Eye-Point sowie die Facetten, die er sieht, rot dargestellt. Der Horizont ist mit schwarzen Strichen gekennzeichnet.

Wird dieser Schritt rekursiv auf alle neu hinzugefügten Facetten angewendet, resultiert die konvexe Hülle. Und genauso, wenn auch deutlich schwieriger darstellbar, funktioniert es auch für alle höheren Dimensionen.

QuickHull

Eine wichtige Anwendung für 3D konvexe Hüllen ist übrigens die Delaunay-Triangulation einer planaren Punktmenge. Die wiederum kann für eine effiziente Berechnung des Relative-Neighborhood-Graphs aus diesem Post genutzt werden.

Fira Code

Fira ist eine humanist Sans-Serif Schriftart, die für FirefoxOS entwickelt wurde, und wird zur Zeit für die Sans-Serif Typen, wie die Überschriften, in diesem Blog genutzt. Aber eigentlich geht es mir hier um Fira Mono die dicktengleiche Variante, die später mit Ligaturen (und mehr) zu Fira Code erweitert wurde. Ich sehe wie in genau diesem Moment im Geist des Lesers die Frage “Ligaturen in einer dicktengleichen Schrift?!” auftaucht. Beziehungsweise “Ist da ein Tippfehler in dickengleich?” oder “Was sind Ligaturen?” falls der Leser kein Hobby-Typographie-Nerd ist.

Für letztere klären wir erstmal kurz die beiden Fragen:

Die Dickte bezeichnet die Breite der Metall-Lettern im klassischen Buchdruck; wenn sie für alle Glyphen gleich ist, stehen die Buchstaben immer in perfekt ausgerichteten Spalten untereinander, was von vielen für das Schreiben von Code bevorzugt wird. Die meisten Schreibmaschinen haben ebenfalls solche Schrifttypen verwendet.

fi Ligaturen sind Kontraktionen von mehreren Glyphen in eine Glyphe. Die typischen Ligaturen sind fi oder fl (allerdings nicht in der Schriftart, in der diese Zeilen geschrieben sind, weshalb ich hier ein Bild der fi Ligatur in Computer Modern zeige). Ein paar Ligaturen haben sich mittlerweile zu eigenen Symbolen entwickelt, wie das Kaufmannsund &, das ursprünglich eine Ligatur von et war (Latein für und). Aber dieses Konzept beißt sich anscheinend mit einer dicktengleichen Schrift, in der jeder Buchstabe die gleiche Breite haben soll. Der Clou an der Sache ist, dass Fira Code Ligaturen für übliche Ausdrücke für mathematische Symbole in Programmiersprachen wie >=, != und -> hat, die wie folgt dargestellt werden: >=, !=, ->. Nur zu, kopiert diese Symbole in einen Editor eurer Wahl, um zu sehen, wie sie sich wieder in ihre Bestandteile zerlegen

Nur eine Spielerei? Möglicherweise. Aber ich bin begeistert davon, und verwende Fira Code in allen Editoren, die Ligaturen unterstützen. Der Fairness halber sollte gesagt werden, dass Fira Code nicht als erstes Projekt diese Idee hatte. Hasklig beispielsweise hatte ihr erstes Release 2 Jahre vor der Veröffentlichung von Fira Code im Jahr 2014. Und mittlerweile sind Code-Ligaturen so ziemlich im Mainstream angekommen, seitdem JetBrains Mono im letzten Jahr von dem gleichnamigen IDE-Entwickler veröffentlicht wurde.

Zum Schluss möchte ich noch auf eine Kleinigkeit aufmerksam machen, die wohl nur die wenigsten Nutzer von Fira Code bewusst bemerken würden, die aber zweifellos demonstriert wie durchdacht diese Schrift ist. Denn Fira Code passt die Position von arithmetischen Symbolen an die benachbarten Glyphen an: ein + zwischen zwei Großbuchstaben ist höher als eines zwischen zwei Kleinbuchstaben.

A+A a+a, die Plus-Zeichen haben unterschiedliche vertikale Positionen

Ich persönlich weiß solche Details sehr wertzuschätzen. Es ist ein Beispiel dafür, dass alle Aspekte unserer modernen Gesellschaft, so wenige Gedanken wir uns auch darum machen und für wie trivial wir sie halten, zahllose Stunden Design und Entwicklung gekostet haben und ständig verbessert werden. Typographie — und um das klarzustellen, ich bin beileibe kein Experte — fasziniert mich. Schriften sind exakt, mit klar definierter Funktion, aber obwohl wir sie seit Jahrtausenden benutzen, ist ihre Entwicklung noch lange nicht abgeschlossen. Mit jedem neuen Medium gibt es neue Anforderungen. Marken haben steten Bedarf an individuellen Schrifttypen als Teil ihres Brandings. Für jede neue Anwendung gibt es andere Optimierungskriterien.

Und jedes Mal wenn in meinem Code = und > wieder zu => verschmelzen, freue ich mich erneut über die Magie.

Noch mehr Fraktale

Seit meinem ersten Eintrag über meinen Fraktal-tweetenden Bot @AFractalADay, habe ich selbigen noch um ein paar Fraktale erweitert, die ich hier kurz festhalten möchte. Der ganze Code ist auf Github.

Chaotic Maps

Eine Quadratic Map ist eine Rekursionsgleichung mit einem quadratischen Term, also beispielsweise

$$x_{i+1} = a_0 x^2 + a_1 x + a_2.$$

Das berühmteste Mitglied dieser Familie ist die Logistic-Map mit \(a_0=1, a_1=r, a_2=0\), die chaotisches Verhalten für \(3.56995 < r < 4\) zeigt. Aber leider ist sie nur eindimensional und ihr Attraktor deshalb nicht besonders hübsch.

Um visuell ansprechende Fraktale daraus zu erzeugen, brauchen wir also ein System aus zwei Rekursionsgleichungen, die wir als \(x\)- und \(y\)-Koordinaten betrachten können:

\begin{align*} x_{i+1} &= a_{0} + a_{1} x + a_{2} x^2 + a_{3} x y + a_{4} y + a_{5} y^2\\ y_{i+1} &= a_{6} + a_{7} x + a_{8} x^2 + a_{9} x y + a_{10} y + a_{11} y^2. \end{align*}

Jetzt haben wir 12 freie Parameter, die einen riesigen Parameterraum aufspannen, in dem etwa 1.6% aller Möglichkeiten chaotisches Verhalten mit einem seltsamen Attraktor zeigen.

Quadratic Map

Chaotische Differentialgleichungssysteme

Ein echter Klassiker ist das Differentialgleichungssystem, das die Chaostheorie begründet hat und nach dem der Schmetterlingseffekt benannt ist [1, 2]. Für bestimmte Paramtersätze verlaufen die Bahnkurven entlang eines seltsamen Attraktors, dessen fraktale Dimension \(\approx 2.06\) ist. Da der vollständige Attraktor somit in einer zweidimensionalen Projektion etwas langweilig aussieht, habe ich hier nur eine Trajektorie über kurze Zeit dargestellt.

Lorenz-Attraktor

Und es gibt eine ganze Menge weitere Differntialgleichungssysteme (und chaotic maps), die chaotische Attraktoren aufweisen. Deshalb zeige ich hier noch einen Rössler-Attraktor, der eine vereinfachte Version des Lorenz-Systems ist:

\begin{align*} \frac{\mathrm{d}x}{\mathrm{d}t} &= -(y+z)\\ \frac{\mathrm{d}y}{\mathrm{d}t} &= x + ay\\ \frac{\mathrm{d}z}{\mathrm{d}t} &= b + xz - cz \end{align*}

Und hier haben wir das Glück, dass auch seine Projektion sehr ansehnlich ist.

Rössler-Attraktor

Ich persönlich frage mich, nun wie der Attraktor für das Doppelpendel aussieht. Es ist anscheinend kein Fraktal, aber es sieht dennoch ganz interessant aus:

Doppelpendel

Ising model

Das Ising Modell für Ferromagnetismus wird auch als Drosophila der statistischen Physik bezeichnet: Es ist ein einfaches Modell, dass einen Phasenübergang aufweist — Eisen verliert seine magnetischen Eigenschaften oberhalb der Curie-Temperatur.

Es besteht aus magnetischen Momenten, Spins, die gerne in die gleiche Richtung zeigen wie ihre Nachbarn, aber durch hohe Temperatur gestört werden. Oder etwas formaler: Die innere Energie \(U\) wird durch den Hamiltonian \(\mathcal{H} = - \sum_{<ij>} s_i s_j\) bestimmt, wobei \(s_i = \pm 1\), je nachdem ob der Spin up oder down ist und die Summe über benachbarte Spins läuft. Das System wird immer einen Zustand anstreben, der die freie Energie \(F=U-TS\) minimiert. Das kann entweder passieren, indem \(U\) möglichst klein ist oder die Entropie \(S\) möglichst hoch. Bei großen Werten der Temperatur \(T\) bekommt der Entropie-Term ein höheres Gewicht, sodass Zustände mit hoher Entropie, also zufälligen Spinausrichtungen, bevorzugt sind, bei niedrigen Temperaturen werden Konfigurationen mit niedriger innerer Energie bevorzugt, also solche in denen alle Spins in die selbe Richtung zeigen. Die Temperatur, bei der sich beide Terme die Waage halten, nennt man kritische Temperatur. Hier bilden sich Regionen von Spins, die in die gleiche Richtung zeigen, auf allen Größenskalen. Die fraktale Dimension dieser Regionen ist 187/96, was solche kritische Konfigurationen interessant anzusehen macht. Ich empfehle auf das folgende Bild zu klicken und etwas hineinzuzoomen.

Kritisches Ising System