In diesem Beitrag werde ich den Algorithmus zur prozeduralen Erzeugung von Ebenen eines zweidimensionalen Dungeons mit einer vorgegebenen Struktur beschreiben. Im ersten Teil wird eine allgemeine Beschreibung und im zweiten Teil die Implementierung des Algorithmus vorgestellt.
EinfĂŒhrung
Der Algorithmus wurde im Rahmen
einer Bachelorarbeit geschrieben und basiert auf einem Artikel von
Ma et al. (2014) . Ziel der Arbeit war es, den Algorithmus zu beschleunigen und durch neue Funktionen zu ergĂ€nzen. Ich bin sehr zufrieden mit dem Ergebnis, da wir den Algorithmus schnell genug gemacht haben, um ihn wĂ€hrend der AusfĂŒhrung des Spiels zu verwenden. Nachdem wir die Bachelorarbeit abgeschlossen hatten, beschlossen wir, sie in
einen Artikel umzuwandeln und an die Game-ON 2018-Konferenz zu senden.
Algorithmus
Um ein Spiellevel zu erstellen, erhĂ€lt der Algorithmus als Eingabe einen Satz polygonaler Bausteine ââund ein Diagramm der Level-KonnektivitĂ€t (Level-Topologie). Die Knoten des Diagramms geben die RĂ€ume an, und die Kanten bestimmen die Verbindungen zwischen ihnen. Der Zweck des Algorithmus besteht darin, jedem Knoten des Diagramms die Form und Position des Raums zuzuweisen, so dass sich keine zwei Raumformen schneiden und jedes Paar benachbarter RĂ€ume durch TĂŒren verbunden werden kann.
(a)
(b)
(c)
(d)
Die Abbildungen (c) und (d) zeigen die Diagramme, die aus dem Eingabegraphen (a) und den Bausteinen (b) erzeugt wurden.
Mithilfe des KonnektivitĂ€tsdiagramms kann ein Spieledesigner den Spielfluss einfach steuern. Benötigen Sie einen gemeinsamen Weg zum Chefraum mit mehreren optionalen Seitenwegen? Beginnen Sie einfach mit dem Pfaddiagramm und geben Sie dann einige Knoten an, in denen der Spieler wĂ€hlen kann: Gehen Sie entweder den Hauptpfad entlang oder erkunden Sie den Nebenpfad, wobei mögliche SchĂ€tze und / oder Monster darauf warten. MĂŒssen Sie den Weg abschneiden? WĂ€hlen Sie einfach die beiden Knoten im Diagramm aus und fĂŒgen Sie eine kurze StraĂe hinzu, die sie verbindet. Die Möglichkeiten dieses Schemas sind endlos.
Beispiele fĂŒr Eingabediagramme. Der Hauptpfad ist rot dargestellt, die Hilfspfade sind blau, der kurze Pfad ist orange.Der Algorithmus ermöglicht es Spieldesignern nicht nur, die Struktur der generierten Karten auf hoher Ebene zu verwalten, sondern bietet auch die Möglichkeit, das Erscheinungsbild einzelner RĂ€ume zu steuern und sie miteinander zu verbinden.
Unterschiedliche Formen fĂŒr unterschiedliche RĂ€ume
Ich erwĂ€hnte den Chefraum am Ende des Levels. Wir wollen nicht, dass der Chefraum wie ein anderer gewöhnlicher Raum aussieht, oder? Mit dem Algorithmus können Sie Formulare fĂŒr jeden Raum festlegen. Zum Beispiel können wir einen Raum am Anfang des Levels und einen Chefraum erstellen, der ihre eigenen SĂ€tze von Raumformen haben sollte, und einen gemeinsamen Satz fĂŒr alle anderen RĂ€ume.
Zwei aus dem Eingangsgraphen erzeugte Schaltkreise, in denen der Raumnummer 8 eine spezielle Form von RĂ€umen zugeordnet ist.
Explizit angegebene TĂŒrpositionen
Stellen Sie sich vor, Sie haben ein hochwertiges Boss-Meeting-Skript und der Spieler muss den Raum des Chefs von einem bestimmten PlĂ€ttchen aus betreten. Oder wir haben eine Raumvorlage, in der einige Fliesen fĂŒr WĂ€nde und andere Hindernisse reserviert sind. Mit dem Algorithmus können Designer mögliche TĂŒrpositionen fĂŒr einzelne Raumformen explizit festlegen.
Aber manchmal kann das Ziel das Gegenteil sein. Wir können Raumvorlagen so erstellen, dass die TĂŒren zu ihnen fast ĂŒberall sein können. Aus diesem Grund legen wir dem Algorithmus weniger EinschrĂ€nkungen auf, daher lĂ€uft er hĂ€ufig schneller und die erzeugten Schaltkreise wirken möglicherweise weniger eintönig und organischer. In solchen Situationen kann einfach die LĂ€nge der TĂŒren angegeben werden und wie weit sie von den Ecken entfernt sein sollten. Der Abstand von den Ecken ist eine Art Kompromiss zwischen der manuellen Anordnung aller TĂŒren und dem Vorhandensein von TĂŒren ĂŒberall.
(a)
(b)
Abbildung (a) zeigt die verschiedenen Arten der TĂŒrplatzierung: Ein quadratischer Raum hat 8 klar definierte TĂŒrpositionen, und ein rechteckiger Raum verwendet LĂ€nge und Abstand von den Ecken. Abbildung (b) zeigt ein einfaches generiertes Diagramm mit den Formen der RĂ€ume in Abbildung (a).
Korridore zwischen den Zimmern
Wenn wir ĂŒber Dungeonebenen sprechen, stellen wir uns oft RĂ€ume vor, die durch enge Korridore verbunden sind. Ich wĂŒrde gerne annehmen, dass die Verbindungen im Eingabediagramm die Korridore anzeigen, aber sie sind es nicht. Sie garantieren einfach, dass alle benachbarten Knoten direkt durch TĂŒren verbunden werden. Wenn wir möchten, dass die RĂ€ume durch Korridore verbunden sind, mĂŒssen wir einen neuen Knoten zwischen allen benachbarten Raumpaaren einfĂŒgen und so tun, als wĂ€ren dies KorridorrĂ€ume (mit bestimmten Raumformen und bestimmten TĂŒrpositionen).
(a)
(b)
Eine Illustration, wie wir das Eingabediagramm Ă€ndern können, um Korridore zwischen RĂ€umen hinzuzufĂŒgen. Abbildung (a) zeigt das Eingabediagramm vor dem HinzufĂŒgen der KorridorrĂ€ume. Abbildung (b) zeigt das aus (a) erstellte Eingabediagramm, indem neue RĂ€ume zwischen allen benachbarten RĂ€umen des ursprĂŒnglichen Diagramms hinzugefĂŒgt werden.
Leider erschwert dies die Aufgabe des Algorithmus erheblich, da sich die Anzahl der Knoten hĂ€ufig verdoppelt. Aus diesem Grund habe ich eine Version des Algorithmus implementiert, die Korridore berĂŒcksichtigt und es ermöglicht, den Leistungsabfall beim Anordnen von KorridorrĂ€umen zu verringern. Im Moment unterstĂŒtzt der Algorithmus entweder Korridore zwischen allen RĂ€umen oder das völlige Fehlen von Korridoren, aber in Zukunft plane ich, ihn flexibler zu gestalten.
Beispiele
Mehrere Schemata, die aus verschiedenen BausteinsĂ€tzen und mit aktivierten Korridoren generiert wurden.Mehrere Schemata, die aus verschiedenen BausteinsĂ€tzen mit ein- und ausgeschalteten Korridoren generiert wurden.Im zweiten Teil des Beitrags werde ich ĂŒber die interne Funktionsweise des Algorithmus sprechen.
Ich arbeite auch an einem Unity-Plugin fĂŒr die prozedurale Dungeon-Generierung, das diesen Algorithmus enthalten wird. Ich mache das, weil trotz der Möglichkeit, diesen Algorithmus direkt in Unity zu verwenden (er ist in C # geschrieben), die Bequemlichkeit, damit zu arbeiten, alles andere als ideal ist. Das Erstellen von Raumvorlagen ohne GUI nimmt viel Zeit in Anspruch, und es wird viel Code benötigt, um die Ausgabe des Algorithmus in die im Spiel verwendete Darstellung zu konvertieren.
Da ich selbst kein Spieleentwickler bin, ist es mein Ziel, das Plugin so gut zu machen, dass andere es verwenden können. Wenn alles gut geht, werde ich versuchen, Updates zu veröffentlichen, wenn ich etwas Interessantes zu sagen habe. Ich habe bereits einige Ideen zum Generator selbst und zum Testen seiner FÀhigkeiten.
Screenshots des Unity-Plugins (das Projekt befindet sich in der Entwicklung)Teil 2. Implementierung des Algorithmus
In diesem Teil werde ich ĂŒber die Grundideen sprechen, die in der Grundlage des im ersten Teil des Beitrags beschriebenen Algorithmus festgelegt wurden. ZunĂ€chst wollte ich die grundlegenden Konzepte sowie die wichtigsten Verbesserungen beschreiben, die erforderlich sind, damit der Algorithmus schnell genug ist. Wie sich jedoch herausstellte, sind selbst die Grundkonzepte fĂŒr diesen Beitrag mehr als ausreichend. Aus diesem Grund habe ich beschlossen, Leistungsverbesserungen in einem zukĂŒnftigen Artikel aufzuzeigen.
Motivation
Bevor ich zur Implementierung ĂŒbergehe, möchte ich das Ergebnis dessen zeigen, was wir tun werden. Das folgende Video zeigt 30 verschiedene Schaltkreise, die aus einem Eingangsgraphen und einem Satz von Bausteinen generiert wurden. Der Algorithmus stoppt nach dem Erzeugen der Schaltung immer fĂŒr 500 ms und versucht dann, die nĂ€chste zu erzeugen.
Wie funktioniert es?
Der Zweck des Algorithmus besteht darin, jedem Knoten im Diagramm die Form und Position des Raums zuzuweisen, sodass sich keine zwei RĂ€ume schneiden und benachbarte RĂ€ume durch TĂŒren verbunden sind.
Eine Möglichkeit, dies zu erreichen, besteht darin, alle möglichen Kombinationen von Raumformen und deren Positionen auszuprobieren. Wie Sie vielleicht erraten haben, wird dies jedoch sehr ineffizient sein, und wir werden wahrscheinlich keine Schaltungen erzeugen können, selbst wenn sehr einfache Eingabegraphen verwendet werden.
Anstatt nach allen möglichen Kombinationen zu suchen, berechnet der Algorithmus, wie alle einzelnen RĂ€ume (die sogenannten KonfigurationsrĂ€ume) korrekt verbunden werden, und verwendet diese Informationen, um die Suche zu steuern. Leider ist es trotz dieser Informationen immer noch schwierig, das richtige Schema zu finden. FĂŒr eine effektive Untersuchung des Suchraums verwenden wir daher eine probabilistische Optimierungstechnik (in diesem Fall eine Tempersimulation). Zur weiteren Beschleunigung der Optimierung teilen wir die Eingabeaufgabe in kleinere und einfacher zu lösende Unteraufgaben auf. Dies erfolgt durch Aufteilen des Diagramms in kleinere Teile (als Ketten bezeichnet) mit anschlieĂender Erstellung von Schemata fĂŒr jeden von ihnen in der angegebenen Reihenfolge.
Konfigurationsbereiche
FĂŒr ein Paar von Polygonen, in denen eines an Ort und Stelle fixiert ist und das andere sich frei bewegen kann, ist der Konfigurationsraum die Menge der Positionen eines freien Polygons, an denen sich zwei Polygone nicht schneiden und durch TĂŒren verbunden werden können. Bei der Arbeit mit Polygonen kann jeder Konfigurationsraum als möglicherweise leerer Satz von Linien dargestellt und mit einfachen geometrischen Werkzeugen berechnet werden.
(a)
(b)
Raumkonfigurationen. Abbildung (a) zeigt den Konfigurationsraum (rote Linien) eines freien Rechtecks âârelativ zu einem festen L-förmigen Polygon. Es bestimmt alle Positionen der Mitte des Quadrats, an denen sich die beiden Blöcke nicht schneiden und berĂŒhren. Abbildung (b) zeigt den Schnittpunkt (gelbe Punkte) der KonfigurationsrĂ€ume eines sich bewegenden Quadrats in Bezug auf zwei feste Rechtecke.
Der folgende Algorithmus wird verwendet, um den Konfigurationsraum eines festen und eines freien Blocks zu berechnen. Wir wĂ€hlen einen Referenzpunkt auf dem beweglichen Block aus und berĂŒcksichtigen alle Positionen in
, so dass sich beim Verschieben des Polygons so, dass sich sein Referenzpunkt an dieser Stelle befindet, sowohl der bewegliche als auch der feste Block berĂŒhren, sich jedoch nicht schneiden. Die Menge all dieser Punkte bildet den Konfigurationsraum von zwei Blöcken (Abbildung (a) oben). Um den Konfigurationsraum des sich bewegenden Blocks relativ zu zwei oder mehr festen Blöcken zu erhalten, wird der Schnittpunkt der einzelnen KonfigurationsrĂ€ume berechnet (Abbildung (b) oben).
Der Algorithmus verwendet KonfigurationsrĂ€ume auf zwei Arten. Anstatt die zufĂ€lligen Positionen einzelner RĂ€ume auszuprobieren, verwenden wir zunĂ€chst KonfigurationsrĂ€ume, um nach Positionen zu suchen, die zu einer möglichst groĂen Anzahl benachbarter RĂ€ume fĂŒhren, die durch die TĂŒren verbunden sind. Dazu mĂŒssen wir den maximalen nicht leeren Schnittpunkt der KonfigurationsrĂ€ume der Nachbarn erhalten. Zweitens verwenden wir KonfigurationsrĂ€ume, um zu prĂŒfen, ob alle Paare benachbarter RĂ€ume mit TĂŒren verbunden werden können. Dies erfolgt durch ĂberprĂŒfen, ob sich die Position des Raums innerhalb des Konfigurationsraums aller seiner Nachbarn befindet.
Da sich die Formen der RĂ€ume wĂ€hrend der AusfĂŒhrung des Spiels nicht Ă€ndern, können wir die KonfigurationsrĂ€ume aller Paare von Raumformen vor dem Start des Algorithmus vorberechnen. Dadurch wird der gesamte Algorithmus erheblich beschleunigt.
Inkrementelles Schema
Bei der Lösung eines komplexen Problems besteht einer der möglichen AnsĂ€tze darin, es in kleinere und einfachere Teilaufgaben zu unterteilen und diese bereits zu lösen. Genau das tun wir mit der Aufgabe, einzelne RĂ€ume zu platzieren. Anstatt alle RĂ€ume gleichzeitig anzuordnen, teilen wir das Eingabediagramm in kleinere Untergraphen auf und versuchen, daraus nacheinander Diagramme zu erstellen. Die Autoren des ursprĂŒnglichen Algorithmus nennen diese Untergraphen aufgrund des Prinzips dieser Graphen, in denen jeder Knoten nicht mehr als zwei Nachbarn hat, "Ketten", und daher ist es recht einfach, ihr Schema zu erstellen.
Die endgĂŒltige Ausgangsschaltung ist immer eine verbundene Komponente, daher ist es nicht sinnvoll, die einzelnen Komponenten in die Schaltung einzubinden und dann zu versuchen, sie zu kombinieren, da der Kombinationsprozess sehr kompliziert sein kann. Daher ist nach dem Platzieren der Kette die nĂ€chste verbundene Kette immer diejenige, die mit den Scheitelpunkten verbunden ist, die bereits in der Schaltung aufgereiht sind.
Layout GenerateLayout(inputGraph) { var emptyLayout = new Layout(); var stack = new Stack<Layout>(); stack.Push(emptyLayout); while(!stack.Empty()) { var layout = stack.Pop(); var nextChain = GetNextChain(layout, inputGraph); Layout[] partialLayouts = AddChain(layout, nextChain); if (!partialLayouts.Empty()) { if (IsFullLayout(partialLayouts[0])) { return partialLayouts[0]; } else { stack.Push(partialLayouts); } } } return null; }
Pseudocode, der einen inkrementellen Ansatz zum Finden des richtigen Schemas zeigt.Der oben gezeigte Pseudocode demonstriert die Implementierung eines inkrementellen Schemas. Bei jeder Iteration des Algorithmus (Zeilen 6 - 18) nehmen wir zuerst die letzte Schaltung aus dem Stapel (Zeile 7) und berechnen, welche Kette als nĂ€chstes hinzugefĂŒgt werden soll (Zeile 8). Dies kann durch einfaches Speichern der Nummer der letzten Schaltung erfolgen, die zu jeder Teilschaltung hinzugefĂŒgt wurde. Im nĂ€chsten Schritt fĂŒgen wir der Schaltung (Zeile 9) die folgende Kette hinzu, erzeugen mehrere detaillierte Schaltungen und speichern sie. Wenn die Erweiterungsphase fehlschlĂ€gt, dem Stapel jedoch keine neuen Teilschemata hinzugefĂŒgt werden und der Algorithmus mit dem zuletzt gespeicherten Teilschema fortfahren muss. Wir nennen diese Situation eine RĂŒckgabesuche, da der Algorithmus das aktuelle Teilschema nicht erweitern kann und zurĂŒckgehen und mit einem anderen gespeicherten Schema fortfahren muss. Dies ist normalerweise erforderlich, wenn nicht genĂŒgend Platz vorhanden ist, um zusĂ€tzliche Schaltungen mit den bereits in der Schaltung zusammengesetzten Scheitelpunkten zu verbinden. Eine RĂŒckgabesuche ist auch der Grund, warum wir immer versuchen, mehrere erweiterte Schemata zu generieren (Zeile 9). Andernfalls hĂ€tten wir nichts, worauf wir zurĂŒckkommen könnten. Der Prozess endet, wenn wir eine vollstĂ€ndige Schaltung erzeugen oder der Stapel leer ist.

(a) Eingabediagramm
(b) Teildiagramm
(c) Teildiagramm
(d) VollstĂ€ndiger Ăberblick
(e) VollstÀndige Gliederung
Inkrementelles Schema. Die Abbildungen (b) und (c) zeigen zwei Teildiagramme nach der Planung der ersten Schaltung. Fig. (D) zeigt die vollstÀndige Schaltung nach der Erweiterung (b) um eine zweite Schaltung. Fig. (E) zeigt die vollstÀndige Schaltung nach der Erweiterung (c) um eine zweite Schaltung.
Um das Diagramm in Teile zu unterteilen, mĂŒssen Sie eine flache Einbettung des Eingabediagramms finden, dh eine Zeichnung in der Ebene, in der sich die Kanten nur an den Endpunkten schneiden. Dieser Anhang wird dann verwendet, um alle FlĂ€chen des Diagramms abzurufen. Die Hauptidee der Zerlegung besteht darin, dass es schwieriger ist, eine Schaltung aus Zyklen zu erstellen, da ihre Knoten mehr EinschrĂ€nkungen aufweisen. Daher versuchen wir, die Zyklen zu Beginn der Zerlegung so anzuordnen, dass sie so frĂŒh wie möglich verarbeitet werden und die Wahrscheinlichkeit verringert wird, dass in nachfolgenden Phasen zurĂŒckgegangen werden muss. Die erste Zerlegungskette wird durch die kleinste FlĂ€che des Anhangs gebildet, und nachfolgende FlĂ€chen werden dann in der Reihenfolge der Breitensuche hinzugefĂŒgt. Wenn andere FlĂ€chen ausgewĂ€hlt werden können, wird die kleinste verwendet. Wenn keine FlĂ€chen mehr vorhanden sind, werden die verbleibenden nichtzyklischen Komponenten hinzugefĂŒgt. Fig. 4 zeigt ein Beispiel der Zersetzung in einer Kette, die gemÀà diesen Schritten erhalten wurde.

(a)
(b)
Zersetzung in Ketten. Abbildung (b) zeigt ein Beispiel fĂŒr die Anordnung von Abbildung (a) auf einer Schaltung. Jede Farbe reprĂ€sentiert eine separate Kette. Zahlen geben die Reihenfolge an, in der die Ketten erstellt werden.
(c) Gutes Teildesign
(d) VollstĂ€ndiger Ăberblick
(a) Eingabediagramm
(b) Schlechter Teilgraph
Suche mit RĂŒckgabe. Abbildung (b) zeigt ein Beispiel fĂŒr eine schlechte Teilschaltung, da nicht genĂŒgend Platz vorhanden ist, um die Knoten 0 und 9 zu verbinden. Um die vollstĂ€ndige Schaltung (d) zu erzeugen, ist eine RĂŒckkehr zu einer anderen Teilschaltung (c) erforderlich.
Simuliertes GlĂŒhen
Der Tempersimulationsalgorithmus ist eine probabilistische Optimierungstechnik, deren Zweck darin besteht, den Raum möglicher Schaltungen zu untersuchen. Es wurde von den Autoren des Originalartikels ausgewĂ€hlt, weil es sich in der Vergangenheit in Ă€hnlichen Situationen als nĂŒtzlich erwiesen hat. Bei der Implementierung des Algorithmus habe ich mich fĂŒr dieselbe Methode entschieden, weil ich mit dem beginnen wollte, was sich bereits als wirksam bei der Lösung dieses Problems erwiesen hat. Ich denke jedoch, dass es durch eine andere Methode ersetzt werden kann und meine Bibliothek so geschrieben ist, dass das Ersetzen der Methode recht einfach ist.
Der Tempersimulationsalgorithmus wertet iterativ kleine Ănderungen in der aktuellen Konfiguration oder Schaltung aus. Dies bedeutet, dass wir eine neue Konfiguration erstellen, indem wir zufĂ€llig einen Knoten auswĂ€hlen und seine Position oder Form Ă€ndern. Wenn die neue Konfiguration die Energiefunktion verbessert, wird sie immer akzeptiert. Andernfalls besteht ohnehin nur eine geringe Chance, die Konfiguration zu akzeptieren. Die Wahrscheinlichkeit, schlechtere Entscheidungen zu treffen, nimmt mit der Zeit ab. Die Energiefunktion ist so ausgelegt, dass sich kreuzende Knoten und benachbarte Knoten, die sich nicht berĂŒhren, mit hohen BuĂgeldern belegt werden.
A ist die gesamte SchnittflĂ€che zwischen allen Blockpaaren im Diagramm. D ist die Summe der Quadrate der AbstĂ€nde zwischen den Mittelpunkten der Blockpaare im Eingabediagramm, die Nachbarn sind, sich aber nicht berĂŒhren. Wert
beeinflusst die Wahrscheinlichkeit, dass simuliertes Tempern in die schlechteste Konfiguration gelangen darf; Dieser Parameter wird aus der durchschnittlichen FlĂ€che der Bausteine ââberechnet.
Nachdem Sie einen zu Ă€ndernden Knoten ausgewĂ€hlt haben, Ă€ndern wir entweder seine Form oder Position. Wie wĂ€hlen wir eine neue Position? Sie können es zufĂ€llig auswĂ€hlen, aber dies verschlechtert hĂ€ufig die Energiefunktion und der Algorithmus konvergiert sehr langsam. Können wir eine Position wĂ€hlen, die die Energiefunktion eher erhöht? Sehen Sie, wohin ich fĂŒhre? Wir verwenden KonfigurationsrĂ€ume, um eine Position auszuwĂ€hlen, die die Grenzen der gröĂten Anzahl benachbarter RĂ€ume erfĂŒllt.
Um die Form zu Ă€ndern, wĂ€hlen Sie einfach eine der verfĂŒgbaren Raumformen aus. Der Algorithmus versucht zwar nicht zu entscheiden, welche Form uns am wahrscheinlichsten zum richtigen Schema fĂŒhrt. Es wĂ€re jedoch interessant, diese Funktion auszuprobieren und zu prĂŒfen, ob sie den Algorithmus beschleunigt.
List<Layout> AddChain(chain, layout) { var currentLayout = GetInitialLayout(layout, chain); var generatedLayouts = new List<Layout>(); for (int i = 1; i <= n, i++) { if () { break; } for (int j = 1; j <= m, j++) { var newLayout = PerturbLayout(currentLayout, chain); if (IsValid(newLayout)) { if (DifferentEnough(newLayout, generatedLayouts)) { generatedLayouts.Add(newLayout); } } if () { currentLayout = newLayout; } else if () { currentLayout = newLayout; } } } return generatedLayouts; }
Dies ist der Pseudocode des Verfahrens, das fĂŒr die Erzeugung einer separaten Schaltungsschaltung durch Simulation des Temperns verantwortlich ist.
Um den gesamten Prozess zu beschleunigen, werden wir versuchen, die anfĂ€ngliche Niedrigenergiekonfiguration zu finden. Zu diesem Zweck ordnen wir die Knoten in der aktuellen Kette fĂŒr eine Breitensuche an, beginnend mit denen, die an die bereits im Schema enthaltenen Knoten angrenzen. Dann werden die geordneten Knoten einzeln platziert und fĂŒr sie wird die Position mit der niedrigsten Energie aus dem Konfigurationsraum ausgewĂ€hlt. Hier machen wir kein Backtracking - dies ist ein einfacher gieriger Prozess.
Bonus Video
Das folgende Video zeigt die Diagramme, die aus demselben Eingabediagramm wie im ersten Video erstellt wurden. Diesmal wird jedoch ein inkrementeller Ansatz gezeigt. Möglicherweise stellen Sie fest, dass der Algorithmus nacheinander Knotenketten hinzufĂŒgt. Es ist auch ersichtlich, dass es manchmal zwei aufeinanderfolgende Teilschaltungen mit der gleichen Anzahl von Knoten gibt. Dies geschieht, wenn der Algorithmus zurĂŒckkehrt. Wenn die ersten Versuche, der ersten Teilschaltung eine weitere Schaltung hinzuzufĂŒgen, fehlschlagen, versucht der Algorithmus eine andere Teilschaltung.
Herunterladbare Materialien
Die Implementierung des Algorithmus in .NET finden Sie in
meinem Github . Das Repository enthÀlt die .NET-DLL und die WinForms-GUI-Anwendung, die von YAML-Konfigurationsdateien gesteuert werden.