Einführung
Die Simulation ist eine Methode zur Durchführung von Experimenten. Das untersuchte reale System wird durch ein Modell ersetzt. In einem solchen Modell können Sie sowohl einzelne als auch viele Situationen verlieren. Die gesammelten Statistiken können helfen, Schlussfolgerungen über die Prozesse im System zu ziehen und Optimierungspfade zu skizzieren.
Die Simulation wird oft als eine Art experimenteller Test betrachtet, ist aber gleichzeitig kostengünstiger und ermöglicht es Ihnen, die Parameter schnell zu ändern und das simulierte System in der Dynamik zu beobachten.
Bereits seit etwa einem halben Jahrhundert werden in der Simulationsmodellierung Computermodelle verwendet. Für ihre Entwicklung wurden viele verschiedene Programme und Frameworks erstellt, von denen meiner Meinung nach die Tools zur Modellierung von Warteschlangensystemen (QS) am weitesten entwickelt sind. Eines der bekanntesten und einfachsten Programme zur Simulation von QS - GPSS World (General Purpose Simulation System - ein Allzweckmodellierungssystem) - finden Sie unter den Links
[1] ,
[2] .
Das Konzept dieses Programms war die Grundlage des Simulationsframeworks auf Go.
Simulation in GPSS
Ein Modell in GPSS ist eine Folge von Blöcken (Befehlen), die die simulierten Objekte beschreiben, zwischen denen sich Transaktionen bewegen. Wenn eine Transaktion in den Block eintritt, werden Ereignisse generiert, die entweder zu einer Änderung des Status des modellierten Objekts oder zu einer Änderung des Status / der Parameter der Transaktion führen.
Die Hauptblöcke in der Größenordnung von zehn: GENERATE, TERMINATE, ASSIGN, SEIZE, RELEASE, QUEUE, ADVANCE, DEPART, START. Insgesamt gibt es ungefähr drei Dutzend Blöcke. Blöcke haben Parameter, die Zahlen, Funktionsnamen, Beschriftungen im Simulationsprogramm und Variablennamen sein können. Weitere Details zu den Blöcken finden Sie beispielsweise
hier .
Objekte in GPSS verfügen über eine Reihe von numerischen Standardattributen (NAV) und logischen Standardattributen (ALS). Beispielsweise ist für eine Warteschlange einer der NAV die aktuelle Länge, und ein Beispiel für einen ALS für einige Geräte ist TRUE oder beschäftigt (FALSE).
In einigen Versionen von GPSS gibt es eine Visualisierung des Modellierungsprozesses, die jedoch meistens fehlt. Basierend auf den Simulationsergebnissen wird in GPSS ein Bericht erstellt, der den NAV und ALS für alle Objekte angibt.
Gehen Sie zur Implementierung
Die Implementierung in Go ist die Entwicklung einer Reihe von Objekten, deren Funktion GPSS-Blöcken ähnelt. Die erste wurde Pipeline erstellt - das Objekt, in dem die Simulation durchgeführt wird.
Basierend auf einer
map
mit einer Liste von Komponenten zur Beschreibung des simulierten Systems. Da Transaktionen während der Simulation eine Folge von Blöcken in einer strengen Reihenfolge durchlaufen müssen, wurde beim Hinzufügen von
Append
Komponenten das Verfahren zum Hinzufügen mit gleichzeitiger Angabe von Transaktionszielen von diesen implementiert. Der Name der Komponente wird als
map
, daher muss jede Komponente einen eindeutigen Namen haben.
Nachdem Sie alle Komponenten hinzugefügt haben, können Sie die Simulation mit der
Start
Methode
Start
. Darin wird für eine bestimmte Simulationszeit ein zyklischer Bypass aller Komponenten implementiert. Am Ende der Simulation können Sie einen Bericht mit NAV und ALS drucken.
Das zweite wichtige Element sind die eigentlichen Komponenten zur Beschreibung der Simulation. Wurden implementiert: Generator - generiert Transaktionen, Advance - erzeugt Verzögerungen auf dem Pfad der Transaktion, Queue - Warteschlangen von Transaktionen, Facility - ein Gerät, das für eine Weile ausschließlich von der Transaktion erfasst wird, Hole - ein "Loch", in dem Transaktionen am Ende des Pfads fehlschlagen. Natürlich reicht ein solcher Satz nicht aus, um komplexe Simulationsmodelle zu erstellen, sondern um die Lösung zu erarbeiten und mit den GPSS-Ergebnissen zu vergleichen. Alle Komponenten implementieren die IBaseObj-Schnittstelle, die die minimal erforderliche Funktionalität abdeckt.
Jede Komponente verfügt über eine Transaktionswarteschlange. Direkt als Warteschlange wird es nur in der Warteschlange verwendet, für andere Komponenten ist es nur ein Repository. Die Warteschlange wird basierend auf der
map
implementiert. Während des Modellierungsprozesses durchlaufen die Komponenten der Reihe nach und überprüfen die Bereitschaft (Erfüllung einer bestimmten Bedingung) der Transaktion für die Übertragung an die nächste Komponente. Die Übertragung erfolgt über die
AppendTransact
Methode der nächsten Komponente. Wenn die Übertragung erfolgreich ist, wird die Transaktion aus der Warteschlange entfernt, und die nächste Komponente nimmt sie der Reihe nach. Da für jede Komponente mehrere Empfänger definiert sind, versuchen wir, eine Transaktion an einen anderen Empfänger zu senden, wenn es nicht möglich war, eine Transaktion an einen Empfänger zu senden.
Um Zufallsvariablen zu generieren, wenn der Zeitpunkt des Auftretens der Transaktion bestimmt und Verzögerungen erzeugt werden, werden die PRNG-Funktionen in Go verwendet.
Da beim Modellieren gleichzeitig viele Transaktionen zwischen verschiedenen Komponenten verschoben werden können, entstand die Idee, Goroutinen innerhalb der Komponenten zu verwenden. Die Pipeline, die die Komponenten durchläuft, startet den
HandleTransacts
Handler für jede von ihnen, in dem die Goroutine erstellt wird. Nachdem alle Goroutinen abgeschlossen sind, wird der
HandleTransacts
erhöht und
HandleTransacts
aufgerufen.
Das letzte Schlüsselobjekt ist die Transaktion selbst. Er hat eine Kennung, eine Geburts- und Todeszeit, den Eigentümer (in welcher Komponente er sich jetzt befindet), eine Reihe von Parametern für die Berechnung von SCA und SCHL.
In Abb. 1 ist ein Strukturdiagramm der Interaktion der Hauptobjekte des Frameworks während der Modellierung.
Abb. 1. Verallgemeinertes Strukturdiagramm der Interaktion der Hauptobjekte in der SimulationSimulationsbeispiel
Angenommen, Sie müssen die Arbeit eines Friseurs simulieren. Dies ist ein berühmtes Beispiel von GPSS. Besucher gehen zufällig mit einer Häufigkeit von 18 ± 6 Minuten, ihre Anzahl ist nicht im Voraus bekannt. Wir haben einen Friseur, er verbringt 16 ± 4 Minuten mit einem Haarschnitt. Also, wie viele Leute wird er für einen Arbeitstag schneiden? Wie viele Leute werden in der Schlange stehen? Was ist die durchschnittliche Zeit für einen Haarschnitt und wie viel Zeit warten die Leute in der Schlange? Viele Fragen und eine einfache Simulation. Das Blockschaltbild in Abb. 2.
Abb. 2. Das Strukturschema der Modellierung eines FriseursDer Code zum Erstellen des Modells lautet wie folgt.
barbershop := NewPipeline("Barbershop", true)
Die Simulationsergebnisse finden Sie hier.Pipeline-Name "Barbershop"
Simulationszeit 480
Objektname "Stühle"
Maximaler Inhalt 1
Gesamtzahl der Einträge 26
Null Einträge 11
Persent Null Einträge 42,31%
In Warteschlange 0
Durchschnittliche Zeit / Trans 2,58
Durchschnittliche Zeit / Trans ohne Null-Einträge 4.47
Objektname "Clients"
Generiert 26
Objektname "Master"
Durchschnittlicher Vorschuss 16.46
Durchschnittliche Auslastung 89.17
Nummerneinträge 26.00
Transaktion 26 in der Einrichtung
Objektname "Out"
25 getötet
Durchschnittlicher Vorschuss 16.56
Durchschnittliche Lebensdauer 19.44
25 Kunden betreut, war der 26. zum Zeitpunkt des Abschlusses der Simulation noch auf dem Stuhl des Masters. Die Warteschlange bestand aus nicht mehr als 1 Person, 11 Personen warteten nicht (Nullpass) und machten sofort einen Haarschnitt. Im Durchschnitt verbrachten die Leute 2,58 Minuten in der Warteschlange und von denen, die warteten (kein Nullpass), 4,47 Minuten. 89,17% seiner Zeit, ein Friseur, intensiv geschert.
Wenn Sie eine andere Simulation durchführen, ändern sich natürlich die Ergebnisse. Während einer Reihe von Simulationen werden jedoch die Gesamtlast des Masters und die Anzahl der bedienten Clients sichtbar. Eine ähnliche Simulation in GPSS liefert ähnliche Ergebnisse.
Ein weiteres Beispiel. Es gibt ein Büro mit 10 Mitarbeitern und einer Toilette. Die Leute wollen alle 90 ± 60 Minuten auf die Toilette gehen, 5 ± 3 Minuten auf die Toilette gehen, 15 ± 10 Minuten auf die Toilette gehen, 5 ± 3 Minuten zurück ins Büro. Wir werden die Simulation für 9 Stunden (8 Stunden Arbeit + 1 Stunde Mittagessen) durchführen, in Abb. 3 ist ein Strukturdiagramm.
Abb. 3. Strukturdiagramm des Toilettenbeschäftigungsmodells: links mit einer Toilette, rechts mit zweiLinks ist ein Modell mit einer Toilette, rechts mit zwei. Das Folgende ist der Modellcode.
waterclosetsim := NewPipeline("Water Closet Simulation", false) office := NewGenerator("Office", 0, 0, 0, 10, nil) wantToToilet:= NewAdvance("Wanted to use the toilet", 90, 60) pathToWC := NewAdvance("Path to WC", 5, 3) queue := NewQueue("Queue to the WC") pathFromWC := NewAdvance("Path from WC", 5, 3) wc := NewFacility("WC", 15, 10) pathToOffice:= NewAdvance("Path from WC", 5, 3) waterclosetsim.Append(office, wantToToilet) waterclosetsim.Append(wantToToilet, pathToWC) waterclosetsim.Append(pathToWC, queue) waterclosetsim.Append(queue, wc) waterclosetsim.Append(wc, pathFromWC) waterclosetsim.Append(pathFromWC, wantToToilet) waterclosetsim.Start(540) <-waterclosetsim.Done waterclosetsim.PrintReport()
Die Simulationsergebnisse sind wie folgt.Pipeline-Name "Water Closet Simulation"
Simulationszeit 540
Objektname "Office"
Generiert 10
Objektname "Pfad vom WC"
Durchschnittlicher Vorschuss 5.77
Objektname "Pfad zum WC"
Durchschnittlicher Vorschuss 5.22
Objektname "Warteschlange zum WC"
Maximaler Inhalt 4
Gesamtzahl der Einträge 36
Null Einträge 8
Persent Null Einträge 22,22%
Aktueller Inhalt 4
Durchschnittlicher Inhalt 1.78
Durchschnittliche Zeit / Trans 24.11
Durchschnittliche Zeit / Trans ohne Nulleinträge 31.00
Objektname "WC"
Durchschnittlicher Vorschuss 14.69
Durchschnittliche Auslastung 87.04
Nummerneinträge 32.00
Transaktion 2 in der Einrichtung
Objektname "Wollte die Toilette benutzen"
Durchschnittlicher Vorschuss 95,85
Es waren bis zu 4 Personen in der Schlange, 8 Mal kam eine Person sofort in die Toilette, während des Arbeitstages wurde die Toilette zu 87,04% benutzt. Das Wichtigste ist meiner Meinung nach, dass die Leute ungefähr eine halbe Stunde (31 Minuten) in der Schlange auf die Toilette warten. Vielleicht liegt das daran, dass es nur eine Toilette gibt, und vielleicht daran, dass durchschnittlich 14,69 Minuten darin sitzen.
Nachdem ich eine weitere Toilette hinzugefügt hatte, sah ich, dass die Warteschlange auf 3 Personen reduziert war, 29 Mal kamen sofort Personen in die Toilette. Vor allem aber ging die Erwartung fast dreimal zurück.
Fazit
Der am Knie erstellte Rahmen ist recht einfach und immer noch begrenzt. Pläne, seine Funktionalität auf das Niveau von GPSS zu erhöhen. Der praktische Wert des Frameworks ist die Fähigkeit, schnell und einfach ein Simulationsmodell auf Go zusammenzustellen und Ergebnisse zu erhalten.
Der Code wird auf GitHub veröffentlicht .