transentis consulting

Einführung in das Business Prototyping Toolkit

Die Schlüsselkomponenten des Business Prototyping Toolkit und die Erstellung von System Dynamics Modellen, agentenbasierten Modellen und hybriden Modellen anhand eines einfachen Beispiels.
  • Oliver Grasl
    Oliver Grasl
    Tuesday, August 17, 2021
Eine Vorstellung der Komponenten des Business Prototyping Toolkits und Veranschaulichung der Erstellung von System Dynamics Modellen, agentenbasierten Modellen und hybriden Modellen anhand eines einfachen Beispiels
Das Business Prototyping Toolkit (BPTK) ist ein computational Modellierungs-Framework, mit dem Sie Simulationsmodelle unter Verwendung von System Dynamics (SD) und/oder agentenbasierte Modelling (ABM) erstellen und Simulationsszenarien mühelos verwalten können.
Der Rahmen wird für die Erstellung von Modellen von Märkten, Geschäftsmodellen, Organisationen und ganzen Geschäftsökosystemen verwendet. Es kann sowohl für kleine, explorative Modelle (wie hier dargestellt) als auch für große Modelle mit Hunderttausenden von Gleichungen verwendet werden.
Das Leitprinzip des Frameworks besteht darin, dem Modellierer die Möglichkeit zu geben, sich auf die Erstellung von Simulationsmodellen zu konzentrieren, indem eine nahtlose Schnittstelle für die Verwaltung von Modelleinstellungen und Szenarien sowie für die Darstellung von Simulationsergebnissen bereitgestellt wird. Es verfolgt einen "minimalistischen" Ansatz und bietet nur die notwendigen Modellierungs- und Simulationsfunktionen. Für alles andere werden Standard-Open-Source-Pakete verwendet. Insbesondere wird auf Umgebungen wie Jupyter zurückgegriffen, um die Darstellung und interaktive Dashboards zu ermöglichen.
  • Alle Darstellungen werden mit Matplotlib vorgenommen.
  • Die Simulationsergebnisse werden als Pandas DataFrames zurückgegeben.
  • Numerik über NumPy und SciPy.
Modelleinstellungen und Szenarien werden in JSON-Dateien gespeichert. Diese Einstellungen werden bei der Initialisierung automatisch vom Framework geladen, ebenso wie die Modellklassen selbst. Dies macht die interaktive Modellierung, Codierung und Prüfung sehr einfach, insbesondere bei Verwendung der Jupyter-Notebook-Umgebung.
Neben einer Jupyter-Notebook-Version dieses Notebooks online und fortgeschrittenen Tutorials und Beispielen auf GitHub finden Sie auch eine umfangreiche Dokumentation online.

Wichtige Komponenten des Business Prototyping Toolkit

Das Toolkit ist seit 2018 verfügbar und bietet mittlerweile Modellierung in Python für agentenbasierte Modellierung (ABM), systemdynamische Modellierung (SD) und hybride Modellierung mit SD und ABM.
Es gibt auch Unterstützung für den Import von XMILE-Modellen, die mit externen Modellierungsumgebungen erstellt wurden, wie z.B. isee systems Stella Architect oder iThink Modellierungsumgebungen.
Sobald Sie ein Modell haben, können Sie verschiedene Simulationsszenarien definieren und verwalten, die Ergebnisse dieser Szenarien darstellen und interaktive Dashboards erstellen.
Das Framework bietet auch einen einfachen REST-API-Server, mit dem Sie Modelle mithilfe von Webtechnologie leicht bereitstellen und abfragen können. Sie können dann die BPTK-Widget-Bibliothek verwenden, um Web-Dashboards zu erstellen.
Sie können ein Beispiel-Dashboard zur Darstellung verschiedener COVID-Szenarien online ansehen. Die Repositories für das Dashboard und die Simulation sind auf GitHub verfügbar.

Beispielmodell: Simulation der Kundenakquise anhand des Bass-Diffusionsmodells

Um die verschiedenen Möglichkeiten der Erstellung von Simulationsmodellen mit BPTK zu veranschaulichen, werden wir ein einfaches Modell der Kundenakquisition, das sogenannte Bass-Diffusionsmodell, verwenden. Es beschreibt den Prozess, wie neue Produkte oder Dienstleistungen von den Verbrauchern angenommen werden.
Wir werden das Modell unter Verwendung der System Dynamics DSL, der agentenbasierten Modellierung, eines hybriden ABM- und SD-DSL-Modells und eines XMILE erstellen.
Die Grundstruktur des Modells ist in dem folgenden Kausalschleifendiagramm dargestellt:

Aufbau des Kundenakquisitionsmodells mit SD DSL

Auf der Grundlage des Kausalschleifendiagramms werden wir ein Bestands- und Flussmodell mit den folgenden Beständen, Flüssen, Konvertern und Konstanten implementieren:

Aufbau des Modells

Die Einrichtung des Modells mit der SD DSL ist recht einfach. Zunächst wird eine Modellklasse instanziiert, die als Container für die Modellelemente dient. Dadurch wird sichergestellt, dass Sie mehrere Modelle parallel ausführen können.
from BPTK_Py import Model from BPTK_Py import sd_functions as sd model = Model(starttime=1.0,stoptime=60.0, dt=1.0, name="Customer Acquisition SDDSL") # stocks customers = model.stock("customers") potential_customers = model.stock("potential_customers") #flows customer_acquisition=model.flow("customer_acquisition") #converters acquisition_through_advertising = model.converter("acquisition_through_advertising") acquisition_through_word_of_mouth = model.converter("acquisition_through_word_of_mouth") consumers_reached_through_advertising = model.converter("consumers_reached_through_advertising") consumers_reached_through_word_of_mouth= model.converter("consumers_reached_through_word_of_mouth") market_saturation = model.converter("market_saturation") #constants initial_customers = model.constant("initial_customers")  initial_potential_customers = model.constant("initial_potential_customers")  advertising_success = model.constant("advertising_success") consumers_reached_per_euro = model.constant("consumers_reached_per_ruro") advertising_budget = model.constant("advertising_budget") word_of_mouth_success = model.constant("word_of_mouth_success") contact_rate = model.constant("contact_rate")
Nachdem wir nun alle Modellelemente definiert haben, müssen wir die eigentlichen Gleichungen definieren. Das Schöne daran ist, dass wir diese Gleichungen direkt mit den Modellelementen schreiben können.
#equations customers.equation = customer_acquisition potential_customers.equation = -customer_acquisition customer_acquisition.equation=sd.min(potential_customers,acquisition_through_advertising+acquisition_through_word_of_mouth) acquisition_through_advertising.equation = advertising_success*consumers_reached_through_advertising consumers_reached_through_advertising.equation = consumers_reached_per_euro*advertising_budget*(1-market_saturation) market_saturation.equation = customers/(customers+potential_customers) acquisition_through_word_of_mouth.equation = word_of_mouth_success*consumers_reached_through_word_of_mouth consumers_reached_through_word_of_mouth.equation=contact_rate*customers*(1-market_saturation)
Wir müssen auch die Bestände initialisieren und die Konstanten festlegen.
#initialize model customers.initial_value=initial_customers potential_customers.initial_value=initial_potential_customers initial_customers.equation = 0.0 initial_potential_customers.equation = 60000.0 advertising_success.equation = 0.1 consumers_reached_per_euro.equation = 100.0 advertising_budget.equation = 100.0 word_of_mouth_success.equation = 0.01 contact_rate.equation = 10.0
Das Modell ist nun vollständig und wir können das Verhalten der Modellelemente im Laufe der Zeit direkt aufzeichnen:
customers.plot()
Natürlich können Sie auch auf den zugrunde liegenden Pandas-Datenrahmen zugreifen:
customers.plot(return_df=True)[1:10]
<div> <style scoped>     .dataframe tbody tr th:only-of-type {         vertical-align: middle;     }     .dataframe tbody tr th {         vertical-align: top;     }     .dataframe thead th {         text-align: right;     } </style> <table border="1" class="dataframe">   <thead>     <tr style="text-align: right;">       <th></th>       <th>customers</th>     </tr>   </thead>   <tbody>     <tr>       <th>1.0</th>       <td>0.000000</td>     </tr>     <tr>       <th>2.0</th>       <td>1000.000000</td>     </tr>     <tr>       <th>3.0</th>       <td>2081.666667</td>     </tr>     <tr>       <th>4.0</th>       <td>3247.916662</td>     </tr>     <tr>       <th>5.0</th>       <td>4500.994779</td>     </tr>     <tr>       <th>6.0</th>       <td>5842.312754</td>     </tr>     <tr>       <th>7.0</th>       <td>7272.284453</td>     </tr>     <tr>       <th>8.0</th>       <td>8790.164623</td>     </tr>     <tr>       <th>9.0</th>       <td>10393.900018</td>     </tr>     <tr>       <th>10.0</th>       <td>12080.003090</td>     </tr>   </tbody> </table> </div>
Zu Debugging-Zwecken kann es nützlich sein, einen Blick auf die internat-Darstellung der Modellgleichungen zu werfen - diese sind als Python-Lambda-Funktionen gespeichert.
customers.function_string     "lambda model, t : ( (model.memoize('initial_customers',t)) if (t <= model.starttime) else (model.memoize('customers',t-model.dt))+ model.dt*(model.memoize('customer_acquisition',t-model.dt)) )"
customer_acquisition.function_string     "lambda model, t : max( 0,min( model.memoize('potential_customers',t), model.memoize('acquisition_through_advertising',t)+model.memoize('acquisition_through_word_of_mouth',t)))"

Einrichten von Szenarien

Szenarien sind lediglich bestimmte Einstellungen für die Konstanten und grafischen Funktionen in Ihrem Modell, und Szenario-Manager sind eine einfache Möglichkeit, Szenarien zu gruppieren.
Sie können Szenarien direkt in Python erstellen (was wir hier tun werden), aber der einfachste Weg, sie zu pflegen, ist, sie in separaten JSON-Dateien aufzubewahren - Sie können so viele Szenario-Manager und Szenarien in einer Datei definieren, wie Sie möchten, und so viele Dateien verwenden, wie Sie möchten.
Jeder Szenario-Manager verweist auf das Modell, auf das er sich bezieht. Sie können also mehrere Simulationsmodelle in einem Notizbuch ausführen.
Alle Szenariodefinitionsdateien werden im Ordner scenarios/ aufbewahrt. Das BPTK_Py-Framework durchsucht diesen Ordner automatisch und lädt die Szenarien - einschließlich der zugrunde liegenden Simulationsmodelle - in den Speicher.
scenario_manager={     "sddsl_customer_acquisition":{         "model":model,         "base_constants":{             "initial_customers" : 0.0,             "initial_potential_customers" : 60000.0,             "advertising_success": 0.1,             "consumers_reached_per_euro" : 100.0,             "advertising_budget" : 100.0,             "word_of_mouth_success": 0.01,             "contact_rate" : 10.0         }     } }
Um die Szenarien zu verwalten, müssen Sie die Klasse bptk instanziieren - diese Klasse speichert die Szenario-Manager und Szenarien und bietet viele praktische Funktionen zum Darstellen von Daten, Exportieren von Modellergebnissen oder Importieren von Daten.
import BPTK_Py bptk = BPTK_Py.bptk() bptk.register_scenario_manager(scenario_manager)
Ein praktisches Merkmal von Szenarien ist, dass Sie nur Variablen definieren müssen, die sich ändern - im Wesentlichen übernimmt der Szenario-Manager zunächst die im Modell selbst festgelegten Konstanten und überschreibt sie dann mit den Einstellungen aus dem Szenario.
bptk.register_scenarios(          scenario_manager="sddsl_customer_acquisition",     scenarios=     {         "base":{                      },         "low_word_of_mouth":{             "constants":{                 "word_of_mouth_success":0.001             }         },         "high_word_of_mouth":{             "constants":{                 "word_of_mouth_success":0.1             }         },         "interactive_scenario":{}              }      ) bptk.plot_scenarios(     scenario_managers=["sddsl_customer_acquisition"],     scenarios=["base","low_word_of_mouth","high_word_of_mouth"],     equations=["customers"],     series_names={         "sddsl_customer_acquisition_base_customers":"Base",         "sddsl_customer_acquisition_low_word_of_mouth_customers":"Low Word of Mouth",         "sddsl_customer_acquisition_high_word_of_mouth_customers":"High Word of Mouth",     } )
bptk.get_scenario_names([],format="dict") {'xmile_customer_acquisition': ['base',       'low_word_of_mouth',       'high_word_of_mouth'],      'sddsl_customer_acquisition': ['base',       'low_word_of_mouth',       'high_word_of_mouth',       'interactive_scenario']}

Aufbau einer interaktiven UI

Es ist einfach, interaktive Dashboards in Jupyter mit IPywidgets zu erstellen - alles, was Sie von BPTK brauchen, ist die Fähigkeit, Graphen zu zeichnen.
%matplotlib inline import matplotlib.pyplot as plt from ipywidgets import interact import ipywidgets as widgets customerTab = widgets.Output() customerAcquisitionTab = widgets.Output() scenariosTab = widgets.Output() tabs = widgets.Tab(children = [customerTab, customerAcquisitionTab,scenariosTab]) tabs.set_title(0, 'Customers') tabs.set_title(1, 'Customer Acquisition') tabs.set_title(2, 'Scenarios') display(tabs) @interact(word_of_mouth_success=widgets.FloatSlider(     value=0.01,     min=0.001,     max=0.1,     step=0.001,     continuous_update=False,     description='Word Of Mouth Success' )) def dashboardWithTabs(word_of_mouth_success):     scenario= bptk.get_scenario("sddsl_customer_acquisition","interactive_scenario")          scenario.constants["word_of_mouth_success"]=word_of_mouth_success     bptk.reset_scenario_cache(scenario_manager="sddsl_customer_acquisition",                                                              scenario="interactive_scenario")
    with customerTab: # turn of pyplot's interactive mode to ensure the plot is not created directly         plt.ioff()         # clear the widgets output ... otherwise we will end up with a long list of plots, one for each change of settings         customerTab.clear_output()         # create the plot, but don't show it yet         bptk.plot_scenarios(             scenario_managers=["sddsl_customer_acquisition"],             scenarios=["interactive_scenario"],             equations=['customers'],             title="Customers",             freq="M",             x_label="Time",             y_label="No. of Customers"             )         # show the plot         plt.show()         # turn interactive mode on again         plt.ion()     with customerAcquisitionTab:         plt.ioff()         customerAcquisitionTab.clear_output()         bptk.plot_scenarios(             scenario_managers=["sddsl_customer_acquisition"],             scenarios=["interactive_scenario"],             equations=['customer_acquisition'],             title="Customer Acquisition",             freq="M",             x_label="Time",             y_label="No. of Customers"             )         plt.show()         plt.ion()          with scenariosTab:         plt.ioff()         scenariosTab.clear_output()         bptk.plot_scenarios(             scenario_managers=["sddsl_customer_acquisition"],             scenarios=["base","low_word_of_mouth","high_word_of_mouth","interactive_scenario"],             equations=["customers"],             series_names={                 "sddsl_customer_acquisition_base_customers":"Base",                 "sddsl_customer_acquisition_interactive_scenario_customers":"Interactive",                 "sddsl_customer_acquisition_low_word_of_mouth_customers":"Low Word of Mouth",                 "sddsl_customer_acquisition_high_word_of_mouth_customers":"High Word of Mouth",         }),         plt.show()         plt.ion()
    Tab(children=(Output(), Output(), Output()), _titles={'0': 'Customers', '1': 'Customer Acquisition', '2': 'Sce...     interactive(children=(FloatSlider(value=0.01, continuous_update=False, description='Word Of Mouth Success', ma...
HINWEIS: Vor allem bei größeren Modellen ist es viel besser, das Modell und die Szenariendefinitionen in getrennten Dateien zu halten, was natürlich auch möglich ist. In der Online-Dokumentation und dem ausführlichen Tutorial finden Sie Illustrationen, wie dies gemacht werden kann.

Kundenakquise durch agentenbasierte Modellierung

Das Grundkonzept von agentenbasierten Modellen ist recht einfach: Sie bevölkern eine Umgebung (das Modell) mit einer Reihe von Agenten. Die Agenten und die Umgebung haben jeweils eine Reihe von Eigenschaften und jeder Agent muss sich immer in einem bestimmten Zustand befinden.
Agenten können Aktionen durchführen und untereinander und mit der Umgebung interagieren, indem sie sich gegenseitig Ereignisse senden - die Agenten reagieren auf diese Ereignisse, indem sie ihre Eigenschaften aktualisieren und/oder ihren Zustand ändern.
Um einen Agenten mit Python und dem BPTK-Framework zu erstellen, müssen Sie also nur Folgendes tun:
  • die relevanten Agenten zu identifizieren
  • die Eigenschaften der Agenten definieren
  • für jeden Agenten ist ein Initialisierungsprogramm zu implementieren, das den Anfangszustand des Agenten festlegt
  • die Handler für jede Art von Ereignis definieren, auf die Ihr Agent reagieren soll
  • eine Aktionsmethode zu definieren, die beschreibt, was der Agent in jedem Zeitschritt tut, z. B. interne Aufgaben ausführen und Ereignisse an andere Agenten senden
Die Definition des Modells ist noch einfacher:
  • Definition der Umgebungseigenschaften und ggf. deren Aktualisierung
  • Dem Modell mitteilen, welche Arten von Agenten es gibt
  • Um die Simulation zu konfigurieren, müssen wir dann nur noch die Anfangswerte der Eigenschaften festlegen und die ersten Agenten instanziieren. Jede einzigartige Konfiguration eines Modells wird als Szenario bezeichnet. Das BPTK-Framework hilft Ihnen, verschiedene Szenarien zu verwalten und die Ergebnisse einfach zu vergleichen.
Die Konfiguration von agentenbasierten Modellen erfolgt am besten über eine in JSON definierte Konfigurationsdatei.
Die agentenbasierte Modellierung ist ein sehr leistungsfähiger Ansatz, und Sie können mit ABM Modelle erstellen, die Sie mit SD nicht erstellen können. Diese Leistung hat jedoch ihren Preis: Da jeder Agent als individuelle Einheit modelliert wird, sind agentenbasierte Modelle recht langsam.

Das Modell einrichten

Für das Modell der Kundenakquise brauchen wir eigentlich nur zwei Agenten: das Unternehmen, das Werbeereignisse sendet, und die Verbraucher, die diese Ereignisse empfangen. Wenn ein Verbraucher zum Kunden wird, beginnt er, Mundpropaganda-Ereignisse zu senden.
Dies wird in der folgenden Graphik veranschaulicht:
Beachten Sie, dass das Werbebudget und die Kontaktrate Eigenschaften der jeweiligen Agenten sind - dies ist ein kleiner Einblick in die Möglichkeiten der agentenbasierten Modellierung, denn wir könnten problemlos individuelle Kontaktraten für die Verbraucher festlegen oder mehrere Unternehmen haben, die für konkurrierende Produkte werben. All diese Aspekte können nicht einfach mit System Dynamics modelliert werden.
from BPTK_Py import Model from BPTK_Py import sd_functions as sd from BPTK_Py import Agent from BPTK_Py import Model from BPTK_Py import Event from BPTK_Py import DataCollector from BPTK_Py import SimultaneousScheduler
Das Einrichten von Agenten ist eigentlich ganz einfach - Sie müssen lediglich Handler für die Ereignisse registrieren und die Methode `act` definieren.
class Consumer(Agent):     def initialize(self):         self.agent_type = "consumer"         self.state = "potential"        self.register_event_handler(["potential"],"advertising_event",self.handle_advertising_event)        self.register_event_handler(["potential"],"word_of_mouth_event",self.handle_word_of_mouth_event)              def handle_advertising_event(self,event):         if self.is_event_relevant(self.model.advertising_success):             self.state="customer"          def handle_word_of_mouth_event(self, event):         if self.is_event_relevant(self.model.word_of_mouth_success):             self.state="customer"                      def act(self,time,round_no,step_no):         # consumers who are customers generate word of mouth events         if self.state == "customer":             self.model.random_events(                 "consumer",
self.contact_rate,                 lambda agent_id: Event("word_of_mouth_event", self.id, agent_id)             )
Beachten Sie, dass der unten definierte Unternehmensagent auf die Eigenschaften `advertising_budget` und `consumers_reacher_per _euro` zugreift. Diese Eigenschaften werden in den Szenarien definiert und können dann "auf magische Weise" entweder als Agenteneigenschaften oder als Modelleigenschaften aufgerufen werden.
class Company(Agent):     def initialize(self):             self.agent_type="company"             self.state = "active"          def act(self,time,round_no,step_no):         self.model.random_events(             "consumer",             self.advertising_budget*self.model.consumers_reached_per_euro,             lambda agent_id: Event("advertising_event",self.id, agent_id)         )
Das Modell selbst benötigt eine Möglichkeit, Agenten zu instanziieren - dafür registrieren Sie Agentenfabriken, die einen Agenten eines bestimmten Typs zurückgeben. In ihrer einfachsten Form ist eine Agentenfabrik einfach eine Lambda-Funktion.
class CustomerAcquisitionAbm(Model):     def instantiate_model(self):         self.register_agent_factory("consumer", lambda agent_id,model,properties: Consumer(agent_id, model,properties))         self.register_agent_factory("company", lambda agent_id,model, properties: Company(agent_id, model, properties)) customer_acquisition_abm=CustomerAcquisitionAbm(1,60,dt=1,name="Customer Acquisition Agent-based Model",scheduler=SimultaneousScheduler(),data_collector=DataCollector()) customer_acquisition_abm.instantiate_model() customer_acquisition_abm_config =  {              "runspecs": {                   "starttime": 1,                   "stoptime":60,                   "dt": 1.0             },             "properties":             {                 "word_of_mouth_success":                 {                     "type":"Double",                     "value":0.01                 },                 "advertising_success":                 {                     "type":"Double",                     "value":0.1                 },                 "consumers_reached_per_euro":                 {                     "type":"Integer",                     "value":100                 }                              },             "agents":             [                 {                     "name":"company",                     "count":1,                     "properties":{                          "advertising_budget":                         {                             "type":"Integer",                             "value":100                         }                     }                 },                 {                     "name":"consumer",                     "count":60000,                     "properties":{                         "contact_rate":                         {                         "type":"Integer",                         "value":10                         }                     }                                          }             ]         } customer_acquisition_abm.configure(customer_acquisition_abm_config) HINWEIS: Die Ausführung des agentenbasierten Modells nimmt etwas Zeit in Anspruch, ca. 3 Minuten auf meinem Rechner.
customer_acquisition_abm.run() [customer_acquisition_abm.statistics().get(1.0*key) for key in range(1,5)]     [{'company': {'active': {'count': 1,         'advertising_budget': {'total': 100,          'max': 100,          'min': 100,          'mean': 100.0}}},       'consumer': {'potential': {'count': 60000,         'contact_rate': {'total': 600000, 'max': 10, 'min': 10, 'mean': 10.0}}}},      {'company': {'active': {'count': 1,         'advertising_budget': {'total': 100,          'max': 100,          'min': 100,          'mean': 100.0}}},       'consumer': {'potential': {'count': 58982,         'contact_rate': {'total': 589820, 'max': 10, 'min': 10, 'mean': 10.0}},        'customer': {'count': 1018,         'contact_rate': {'total': 10180, 'max': 10, 'min': 10, 'mean': 10.0}}}},      {'company': {'active': {'count': 1,         'advertising_budget': {'total': 100,          'max': 100,          'min': 100,          'mean': 100.0}}},       'consumer': {'potential': {'count': 57881,         'contact_rate': {'total': 578810, 'max': 10, 'min': 10, 'mean': 10.0}},        'customer': {'count': 2119,         'contact_rate': {'total': 21190, 'max': 10, 'min': 10, 'mean': 10.0}}}},      {'company': {'active': {'count': 1,         'advertising_budget': {'total': 100,          'max': 100,          'min': 100,          'mean': 100.0}}},       'consumer': {'potential': {'count': 56717,         'contact_rate': {'total': 567170, 'max': 10, 'min': 10, 'mean': 10.0}},        'customer': {'count': 3283,         'contact_rate': {'total': 32830, 'max': 10, 'min': 10, 'mean': 10.0}}}}]

Einrichten von Szenarien

Der Szenariomechanismus funktioniert für SD DSL, agentenbasierte und hybride Modelle genau gleich. Damit ist sichergestellt, dass Sie verschiedene Modelle laden und die Ergebnisse vergleichen können!
import BPTK_Py bptk = BPTK_Py.bptk() customer_acquisition_abm.reset()
abm_scenario_manager={     "abm_customer_acquisition":{         "name":"abm_customer_acquisition",         "type":"abm",         "model":customer_acquisition_abm,         "scenarios":{             "base":         {              "runspecs": {                   "starttime": 1,                   "stoptime":60,                   "dt": 1.0             },             "properties":             {                 "word_of_mouth_success":                 {                     "type":"Double",                     "value":0.01                 },                 "advertising_success":                 {                     "type":"Double",                     "value":0.1                 },                 "consumers_reached_per_euro":                 {                     "type":"Integer",                     "value":100                 }                              },             "agents":             [                 {                     "name":"company",                     "count":1,                     "properties":{                          "advertising_budget":                         {                             "type":"Integer",                             "value":100                         }                     }                 },                 {                     "name":"consumer",                     "count":60000,                     "properties":{                          "contact_rate":                          {                             "type":"Integer",                             "value":10                         }                                              }                 }             ]         }         }     }           } bptk.register_scenario_manager(abm_scenario_manager) bptk.plot_scenarios(     scenario_managers=["abm_customer_acquisition"],     scenarios=["base"],     agents=["consumer"],     agent_states=["customer"],     progress_bar=True )   
    Output()
HINWEIS: Vor allem bei größeren Modellen ist es viel besser, das Modell und die Szenariodefinitionen in getrennten Dateien zu speichern, was natürlich auch möglich ist. In der Online-Dokumentation und in einem ausführlichen Tutorial wird gezeigt, wie dies gemacht werden kann.

Das Beste aus beiden Welten: Hybride ABM- und SD-Modelle

Hybride Modelle sind agentenbasierte Modelle, die ein System Dynamics el "enthalten". Die Agenten können die Elemente des SD-Modells aufrufen. Die Elemente des SD-Modells können auch Eigenschaften des agentenbasierten Modells über benutzerdefinierte SD-Funktionen aufrufen.

Einrichten vom Modell

from BPTK_Py import Model from BPTK_Py import sd_functions as sd
from BPTK_Py import Agent from BPTK_Py import Model from BPTK_Py import Event from BPTK_Py import DataCollector from BPTK_Py import SimultaneousScheduler class Customer(Agent):     def initialize(self):         self.agent_type = "customer"         self.state = "active"
Der folgende Code veranschaulicht, wie man ein System Dynamics Modell als Python-Klasse einrichtet.
class CustomerAcquisitionSD():     def __init__(self,model):         self.model = model                  # stocks         self.customers = model.stock("customers")                  #flows         self.customer_acquisition=model.flow("customer_acquisition")                  #converters         self.acquisition_through_advertising = model.converter("acquisition_through_advertising")         self.acquisition_through_word_of_mouth = model.converter("acquisition_through_word_of_mouth")         self.consumers_reached_through_advertising = model.converter("consumers_reached_through_advertising")         self.consumers_reached_through_word_of_mouth= model.converter("consumers_reached_through_word_of_mouth")         self.market_saturation = model.converter("market_saturation")                  #constants         self.initial_customers = model.constant("initial_customers")          self.target_market= model.constant("target_market")         self.advertising_success = model.constant("advertising_success")         self.consumers_reached_per_euro = model.constant("consumers_reached_per_ruro")         self.advertising_budget = model.constant("advertising_budget")         self.word_of_mouth_success = model.constant("word_of_mouth_success")         self.contact_rate = model.constant("contact_rate")                  #equations         self.customers.equation = self.customer_acquisition        self.customer_acquisition.equation=self.acquisition_through_advertising+self.acquisition_through_word_of_mouth         self.acquisition_through_advertising.equation = self.advertising_success*self.consumers_reached_through_advertising         self.consumers_reached_through_advertising.equation = self.consumers_reached_per_euro*self.advertising_budget*(1-self.market_saturation)         self.market_saturation.equation = self.customers/self.target_market         self.acquisition_through_word_of_mouth.equation = self.word_of_mouth_success*self.consumers_reached_through_word_of_mouth        self.consumers_reached_through_word_of_mouth.equation=self.contact_rate*self.customers*(1-self.market_saturation)
#initialize model         self.customers.initial_value=self.initial_customers         self.initial_customers.equation = 0.0         self.target_market.equation = 60000.0         self.advertising_success.equation = 0.1         self.consumers_reached_per_euro.equation = 1.0         self.advertising_budget.equation = 100.0         self.word_of_mouth_success.equation = 0.01         self.contact_rate.equation = 1.0          class CustomerAcquisitionHybrid(Model):     def instantiate_model(self):         super().instantiate_model()         # register agent factories         self.register_agent_factory("customer", lambda agent_id,model,properties: Customer(agent_id, model,properties))                  # set up the sd model - keep it in its own class so we can use the SD DSL                   self.sd_model = CustomerAcquisitionSD(self)            def configure(self,config):         super().configure(config)                  ## the config sets the model properties, which we need to set the initial values of the sd model         self.sd_model.target_market.equation = self.target_market         self.sd_model.advertising_success.equation = self.advertising_success         self.sd_model.consumers_reached_per_euro.equation = self.consumers_reached_per_euro         self.sd_model.advertising_budget.equation = self.advertising_budget         self.sd_model.word_of_mouth_success.equation = self.word_of_mouth_success         self.sd_model.contact_rate.equation = self.contact_rate                       def begin_round(self, time, sim_round, step):         # at the beginning of each round we check to see how many customers we should have according to the         # SD model and then create the right number of agents.                  required_num_customers = int(self.evaluate_equation("customers",time))         current_num_customers = self.agent_count("customer")         agents_needed = required_num_customers-current_num_customers         self.create_agents({"name":"customer","count":agents_needed})                     customer_acquisition_hybrid=CustomerAcquisitionHybrid(1,60,dt=1,name="Customer Acquisition Hybrid",scheduler=SimultaneousScheduler(),data_collector=DataCollector()) customer_acquisition_hybrid.instantiate_model() customer_acquisition_hybrid_config =  {              "runspecs": {                   "starttime": 1,                   "stoptime":60,                   "dt": 1.0             },             "properties":             {                  "word_of_mouth_success":                 {                     "type":"Double",                     "value":0.01                 },                 "advertising_success":                 {                     "type":"Double",                     "value":0.1                 },                 "consumers_reached_per_euro":                 {                     "type":"Double",                     "value":100.0                 },                 "advertising_budget":                 {                     "type":"Double",                     "value":100.0                 },                 "contact_rate":                 {                     "type":"Double",                     "value":10.0                 },                 "target_market":                 {                     "type":"Double",                     "value":60000.0                 }                              },             "agents":             [                 {                     "name":"customer",                     "count":0                 }             ]         } customer_acquisition_hybrid.configure(customer_acquisition_hybrid_config) customer_acquisition_hybrid.run() [customer_acquisition_hybrid.statistics().get(1.0*key) for key in range(2,10)]     [{'customer': {'active': {'count': 1000}}},      {'customer': {'active': {'count': 2081}}},      {'customer': {'active': {'count': 3247}}},      {'customer': {'active': {'count': 4500}}},      {'customer': {'active': {'count': 5842}}},      {'customer': {'active': {'count': 7272}}},      {'customer': {'active': {'count': 8790}}},      {'customer': {'active': {'count': 10393}}}]

Einrichten von Szenarien

import BPTK_Py bptk = BPTK_Py.bptk() customer_acquisition_hybrid.reset() hybrid_scenario_manager={     "hybrid_customer_acquisition":{         "name":"hybrid_customer_acquisition",         "type":"abm",         "model":customer_acquisition_hybrid,         "scenarios":{             "base":            {              "runspecs": {                   "starttime": 1,                   "stoptime":60,                   "dt": 1.0             },             "properties":             {                  "word_of_mouth_success":                 {                     "type":"Double",                     "value":0.01                 },                 "advertising_success":                 {                     "type":"Double",                     "value":0.1                 },                 "consumers_reached_per_euro":                 {                     "type":"Double",                     "value":100.0                 },                 "advertising_budget":                 {                     "type":"Double",                     "value":100.0                 },                 "contact_rate":                 {                     "type":"Double",                     "value":10.0                 },                 "target_market":                 {                     "type":"Double",                     "value":60000.0                 }                              },             "agents":             [                 {                     "name":"customer",                     "count":0                 }                              ]         }         }     }    } bptk.register_scenario_manager(hybrid_scenario_manager) bptk.plot_scenarios(     scenario_managers=["hybrid_customer_acquisition"],     scenarios=["base"],     agents=["customer"],     agent_states=["active"],     progress_bar=True )   
 Output()
HINWEIS: Vor allem bei größeren Modellen ist es viel besser, das Modell und die Szenariodefinitionen in getrennten Dateien zu speichern, was natürlich auch möglich ist. In der Online-Dokumentation und in einem ausführlichen Tutorial wird gezeigt, wie dies gemacht werden kann.

XMILE-Modell

Viele Modellierer ziehen es vor, Modelle mit visuellen Modellierungsumgebungen und nicht direkt im Code zu erstellen. Eine solche Umgebung ist Stella Architect. Mit Stella Architect können Sie System Dynamics Modelle visuell erstellen. Sie können sie dann mit BPTK in Python importieren und mit ihnen arbeiten, wie mit jedem anderen Modell auch.
Das Framework überträgt das XMILE-Modell automatisch neu, wenn Änderungen in der visuellen Modellierungsumgebung vorgenommen werden. Sie können also in Stella Architect modellieren und in Jupyter mit Szenarien experimentieren.
Transpilierte Modelle arbeiten eigenständig, so dass Sie sie unabhängig von der Modellierungsumgebung überall ausführen können.

Einrichten von Modell

So sieht unser Kundenakquisitionsmodell in Stella Architect aus:

Einrichten von Szenarien

Um mit XMILE-Modellen zu arbeiten, müssen wir lediglich eine Szenariodatei im Ordner scenarios einrichten.
Die Szenariodatei teilt dem Framework mit, wo das XMILE-Modell zu finden ist und welche Szenarien eingerichtet werden sollen.
In unserem Fall sieht die Datei wie folgt aus - der einzige Unterschied zur SD DSL-Szenariodefinition ist die Einbeziehung der XMILE-Quelle.
{     "xmile_customer_acquisition":     {         "source":"simulation_models/customer_acquisition_xmile.stmx",         "model":"simulation_models/customer_acquisition_xmile",         "scenarios":         {           "base": { },                    "low_word_of_mouth":{             "constants":{                 "wordOfMouthSuccess":0.001             }         },         "high_word_of_mouth":{             "constants":{                 "wordOfMouthSuccess":0.1             }         }         }     } }
Sobald wir bptk instanziieren, sucht das Framework automatisch im Ordner scenarios nach Szenarien und lädt diese.
import BPTK_Py bptk = BPTK_Py.bptk()
Wir wollen alle Szenarien und Gleichungen auflisten, die der Rahmen findet.
bptk.list_equations(scenario_managers=["xmile_customer_acquisition"],scenarios=[]) Available Equations:          Scenario Manager: xmile_customer_acquisition     Scenario: base     --------------------------     stock:               customers     flow:                customerAcquisition     converter:      acquisitionThroughAdvertising     converter:      acquisitionThroughWordOfMouth     converter:      advertisingBudget     converter:      advertisingSuccess     converter:      consumersReachedPerEuro     converter:      consumersReachedThroughAdvertising     converter:      consumersReachedThroughWordOfMouth     converter:      contactRate     converter:      initialCustomers     converter:      marketSaturation     converter:      targetMarket     converter:      wordOfMouthSuccess           Scenario: low_word_of_mouth     --------------------------     stock:               customers     flow:                customerAcquisition     converter:      acquisitionThroughAdvertising     converter:      acquisitionThroughWordOfMouth     converter:      advertisingBudget     converter:      advertisingSuccess     converter:      consumersReachedPerEuro     converter:      consumersReachedThroughAdvertising     converter:      consumersReachedThroughWordOfMouth     converter:      contactRate     converter:      initialCustomers     converter:      marketSaturation     converter:      targetMarket     converter:      wordOfMouthSuccess           Scenario: high_word_of_mouth     --------------------------     stock:               customers     flow:                customerAcquisition     converter:      acquisitionThroughAdvertising     converter:      acquisitionThroughWordOfMouth     converter:      advertisingBudget     converter:      advertisingSuccess     converter:      consumersReachedPerEuro     converter:      consumersReachedThroughAdvertising     converter:      consumersReachedThroughWordOfMouth     converter:      contactRate     converter:      initialCustomers     converter:      marketSaturation     converter:      targetMarket     converter:      wordOfMouthSuccess
Wir stellen die Szenarien direkt dar:
bptk.plot_scenarios(     scenario_managers=["xmile_customer_acquisition"],     scenarios=["base","high_word_of_mouth","low_word_of_mouth"],     equations=["customers"],     series_names={                 "xmile_customer_acquisition_base_customers":"Base",                 "xmile_customer_acquisition_low_word_of_mouth_customers":"Low Word of Mouth",                 "xmile_customer_acquisition_high_word_of_mouth_customers":"High Word of Mouth",         } )   
HINWEIS: Sobald die XMILE-Datei in ein Python-Modell umgewandelt wurde, ist das Framework unabhängig von der XMILE-Datei. Die gesamte Simulation wird in Python durchgeführt. Die Software, die zur Erstellung der XMILE-Datei verwendet wurde, wird vom BPTK-Framework nicht benötigt.

Weitere Beispiele

Wenn Sie mehr über das BPTK-Framework erfahren möchten, finden Sie online eine ausführliche Dokumentation sowie ein detailliertes Tutorial auf GitHub.
Sie können auch fortgeschrittenere Beispiele auf GitHub finden:
  • Covid Simulation. Jupyter-Notebooks und Dashboards zur Veranschaulichung des SIR-Modells.
  • Covid Simulation Dashboard. Ein webbasiertes Simulations-Dashboard für die COVID-Simulation, das mit unserer BPTK-Widgets-Bibliothek für Javascript erstellt wurde. Sehen Sie sich eine Live-Version des Dashboards online an.
  • Beer Distribution Game. Eingehende Analyse des Beer Ga unter Verwendung von System Dynamics und agentenbasierter Simulation. Enthält eine Illustration, wie BPTK in Verbindung mit Reinforcement Learning eingesetzt werden kann, um Agenten zu trainieren, das Beer Game autonom zu spielen.

Kontaktieren Sie uns

Bitte lassen Sie uns wissen, wenn Sie Hilfe bei den ersten Schritten benötigen, wenn Sie einen Fehler finden oder wichtige Funktionen vermissen.
Ein guter Ort, um mit uns in Kontakt zu treten, ist unsere Meetup Gruppe, die sich monatlich online trifft. Hier können Sie BPTK in Aktion sehen, Fragen stellen und neue Funktionen vorschlagen.
Sie können uns auch per E-Mail unter support@transentis.com erreichen.
Upcoming Events

Training AI to Play The Beer Distribution Game

2 hours - 2021-10-27

Mastering The Complexity of Digital Transformation

2 hours - 2021-10-28

Modeling Growth Strategies For Professional Service Firms

2 hours - 2021-11-18

Go to event overview

Recent Blogposts

Meetup: Agile Transformation Tools

Olga Medvedeva - 2021-09-27

Meetup: Understanding The Beer Distribution Game

Olga Medvedeva - 2021-09-01

Introduction to The Business Prototyping Toolkit

Oliver Grasl - 2021-08-17

Go to blog overview

Email newsletter

Subscribe to our newsletter and stay up to date about the latest trends and news.

Name
Email
Subscribe to our newsletter and stay up to date about the latest trends and news.
  • transentis
Contact us

transentis consulting

Geisbergstraße 9

10777 Berlin


+49 30 9203833320

info@transentis.com