Présentation
La simulation est une méthode permettant de mener des expériences, le système réel étudié est remplacé par un modèle. Dans un tel modèle, vous pouvez perdre à la fois des situations individuelles et beaucoup d'entre elles. Les statistiques collectées peuvent aider à tirer des conclusions sur les processus dans le système, ainsi qu'à définir les chemins d'optimisation.
La simulation est souvent considérée comme une sorte de tests expérimentaux, mais en même temps, elle est moins coûteuse, elle permet de modifier rapidement les paramètres et d'observer le système simulé en dynamique.
Déjà environ un demi-siècle dans la modélisation par simulation, des modèles informatiques ont été utilisés. De nombreux programmes et frameworks différents ont été créés pour leur développement, parmi lesquels, à mon avis, les plus développés sont les outils de modélisation des systèmes de files d'attente (QS). L'un des programmes les plus connus et les plus simples pour la simulation de QS - GPSS World (General Purpose Simulation System - un système de modélisation à usage général), peut être trouvé plus en détail dans les liens
[1] ,
[2] .
Le concept de ce programme a été la base du cadre de simulation sur Go.
Simulation dans GPSS
Un modèle dans GPSS est une séquence de blocs (commandes) décrivant les objets simulés entre lesquels les transactions se déplacent. Lorsqu'une transaction entre dans le bloc, des événements sont générés qui conduisent soit à une modification de l'état de l'objet modélisé, soit à une modification de l'état / des paramètres de la transaction.
Les principaux blocs de l'ordre de dix: GÉNÉRER, TERMINER, ATTRIBUER, SAISIR, LIBÉRER, QUEUE, AVANCE, DÉPART, DÉMARRER. Il y a environ trois douzaines de blocs au total. Les blocs ont des paramètres, qui peuvent être des nombres, des noms de fonctions, des étiquettes dans le programme de simulation, des noms de variables. Vous trouverez plus de détails sur les blocs, par exemple,
ici .
Les objets dans GPSS ont un ensemble d'attributs numériques standard (NAV) et d'attributs logiques standard (ALS). Par exemple, pour une file d'attente, l'un des NAV est la longueur actuelle et un exemple d'ALS pour certains équipements sera libre (TRUE) ou occupé (FALSE).
Dans certaines versions de GPSS, il existe une visualisation du processus de modélisation, mais le plus souvent elle est absente. Sur la base des résultats de la simulation, un rapport est généré dans GPSS, indiquant la NAV et l'ALS pour tous les objets.
Mise en œuvre Go
L'implémentation dans Go est le développement d'un ensemble d'objets similaires en fonction aux blocs GPSS. Le premier a été créé Pipeline - l'objet dans lequel la simulation est effectuée.
Basé sur une
map
contenant une liste de composants pour décrire le système simulé. Comme, lors de la simulation, les transactions doivent passer par une séquence de blocs dans un ordre strict, dans la méthode d'ajout de composants
Append
, la procédure d'ajout avec indication simultanée des adresses des transactions de ceux-ci a été mise en place. Le nom du composant est utilisé comme clé de
map
, donc chaque composant doit avoir un nom unique.
Après avoir ajouté tous les composants, vous pouvez démarrer la simulation à l'aide de la méthode
Start
. A l'intérieur, un bypass cyclique de tous les composants est implémenté pour un temps de simulation donné. À la fin de la simulation, vous pouvez imprimer un rapport contenant NAV et ALS.
Le deuxième élément important est les composants réels pour décrire la simulation. Les éléments suivants ont été mis en œuvre: Generator - génère des transactions, Advance - crée des retards sur le chemin de la transaction, Queue - files d'attente de transactions, Facility - un périphérique qui est exclusivement capturé par la transaction pendant un certain temps, Hole - un «trou» dans lequel les transactions échouent à la fin du chemin. Bien sûr, un tel ensemble n'est pas suffisant pour créer des modèles de simulation complexes, mais suffisant pour élaborer la solution et comparer avec les résultats GPSS. Tous les composants implémentent l'interface IBaseObj, qui couvre la fonctionnalité minimale requise.
Chaque composant a une file d'attente de transactions. Directement en tant que file d'attente, il est utilisé uniquement dans la file d'attente, pour les autres composants, il s'agit simplement d'un référentiel. La file d'attente est implémentée sur la base de la
map
. Dans le processus de modélisation, les composants passent à tour de rôle et vérifient l'état de préparation (réalisation d'une certaine condition) de la transaction pour la transmission au composant suivant. Le transfert est effectué via la méthode
AppendTransact
du composant suivant. Si le transfert réussit, la transaction est supprimée de la file d'attente, respectivement, le composant suivant la reprend à son tour. Puisque plusieurs destinataires sont définis pour chaque composant, alors s'il n'était pas possible d'envoyer une transaction à un destinataire, nous essayons de l'envoyer à un autre.
Pour générer des variables aléatoires lors de la détermination de l'heure d'apparition de la transaction et de la création de retards, les fonctions PRNG de Go sont utilisées.
Étant donné que lors de la modélisation, en même temps, de nombreuses transactions peuvent se déplacer entre différents composants, l'idée est venue d'utiliser des goroutines à l'intérieur des composants. Le pipeline, en passant par les composants, démarre le gestionnaire
HandleTransacts
pour chacun d'eux, à l'intérieur duquel le goroutine est créé. Une fois tous les goroutines terminés, le compteur de temps du modèle est incrémenté et
HandleTransacts
est de
HandleTransacts
appelé.
Le dernier objet clé est la transaction elle-même. Il dispose d'un identifiant, de l'heure de naissance et de décès, du propriétaire (dans quelle composante il se trouve désormais), d'un certain nombre de paramètres de calcul de la VNI et de la VNI.
Dans la fig. 1 est un diagramme structurel de l'interaction des principaux objets du cadre lors de la modélisation.
Fig. 1. Schéma structurel généralisé de l'interaction des principaux objets dans la simulationExemple de simulation
Supposons que vous deviez simuler le travail d'un coiffeur. Ceci est un exemple célèbre de GPSS. Les visiteurs se rendent au hasard, avec une fréquence de 18 ± 6 minutes, leur nombre n'est pas connu à l'avance. Nous avons un coiffeur, il passe 16 ± 4 minutes sur une coupe de cheveux. Alors, combien de personnes va-t-il couper pour une journée de travail? Combien de personnes seront en ligne? Quel est le temps moyen nécessaire pour une coupe de cheveux et combien de temps les gens attendent-ils en ligne? Beaucoup de questions et une simulation simple. Le schéma de principe de la Fig. 2.
Fig. 2. Le schéma structurel de la modélisation d'un coiffeurLe code de construction du modèle sera le suivant.
barbershop := NewPipeline("Barbershop", true)
Les résultats de la simulation peuvent être trouvés ici.Nom du pipeline "Barbershop"
Temps de simulation 480
Nom de l'objet "Chairs"
Contenu max 1
Total des inscriptions 26
Zéro entrée 11
Entrées zéro persistantes 42,31%
En file d'attente 0
Temps moyen / trans 2,58
Temps moyen / trans sans aucune entrée 4.47
Nom de l'objet "Clients"
Généré 26
Nom de l'objet "Master"
Avance moyenne 16,46
Utilisation moyenne 89,17
Entrées numériques 26,00
Transact 26 dans l'installation
Nom de l'objet "Out"
25 tués
Avance moyenne 16,56
Durée de vie moyenne 19,44
Au service de 25 clients, le 26 au moment de l'achèvement de la simulation était toujours dans le fauteuil du maître. La file d'attente n'était pas supérieure à 1 personne, 11 personnes n'ont pas attendu (passe zéro) et sont immédiatement allées se faire couper les cheveux. En moyenne, les gens ont passé 2,58 minutes dans la file d'attente, et parmi ceux qui attendaient (pas un zéro), 4,47 minutes. 89,17% de son temps, un coiffeur, tondait intensément.
Bien sûr, si vous effectuez une autre simulation, les résultats changeront. Mais au cours d'une série de simulations, le niveau global de la charge du maître et le nombre de clients servis seront visibles. Une simulation similaire dans GPSS produit des résultats similaires.
Un autre exemple. Il y a un bureau, il a 10 employés et une toilette. Les gens veulent aller aux toilettes toutes les 90 ± 60 minutes, aller aux toilettes pendant 5 ± 3 minutes, prendre des toilettes pendant 15 ± 10 minutes, retourner au bureau pendant 5 ± 3 minutes. Nous réaliserons la simulation pendant 9 heures (8 heures de travail + 1 heure de déjeuner), fig. 3 est un schéma structurel.
Fig. 3. Schéma structurel du modèle d'emploi des toilettes: à gauche avec une toilette, à droite avec deuxÀ gauche, un modèle avec une toilette, à droite avec deux. Voici le code du modèle.
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()
Les résultats de la simulation sont les suivants.Nom du pipeline "Water Closet Simulation"
Temps de simulation 540
Nom de l'objet "Office"
Généré 10
Nom de l'objet "Path from WC"
Avance moyenne 5,77
Nom de l'objet "Path to WC"
Avance moyenne 5,22
Nom de l'objet "Queue to the WC"
Contenu max 4
Total des inscriptions 36
Zéro entrée 8
Entrées zéro persistantes 22,22%
Contenu actuel 4
Contenu moyen 1,78
Temps moyen / trans 24.11
Temps moyen / trans sans aucune entrée 31,00
Nom de l'objet "WC"
Avance moyenne 14,69
Utilisation moyenne 87,04
Entrées numériques 32,00
Transact 2 dans l'installation
Nom de l'objet "Voulait utiliser les toilettes"
Avance moyenne 95,85
Il y avait jusqu'à 4 personnes en ligne, 8 fois une personne immédiatement entrée dans les toilettes, pendant la journée de travail, les toilettes étaient utilisées à 87,04%. Le plus important, à mon avis, est que les gens attendent environ une demi-heure (31 minutes) en ligne pour aller aux toilettes. Cela est peut-être dû au fait qu'il n'y a qu'une seule toilette, et peut-être au fait qu'en moyenne, les gens y restent pendant 14,69 minutes.
Après avoir ajouté une autre toilette, j'ai vu que la file d'attente était réduite à 3 personnes, 29 fois les gens sont immédiatement entrés dans les toilettes. Mais surtout, l'attente a diminué presque trois fois.
Conclusion
Le cadre créé sur le genou est assez simple et toujours limité. Prévoit d'augmenter sa fonctionnalité au niveau de GPSS. La valeur pratique du cadre est la capacité d'assembler rapidement et facilement un modèle de simulation sur Go et d'obtenir des résultats.
Le code est publié sur GitHub .