In the following five posts, I will cover all aspects of agent-based models (ABM) and how to create and use ABM in InsightMaker (www.insightmaker.com). This post focus is to expose to the basics of ABM and to create a basic model that depicts the famous game of life model (https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life).
Before we’ll start, several words about ABM. ABM is a powerful modeling tool. It enables one to depict one or more agent behavior based on data, state, and logic that use data to change internal states. The interaction can be between agents of one “type” or agents from different “types”. The model can also use or create data because of the interaction between agents.
Agents are a generic name for people, groups, departments or any other entities. Agents can change state, move or connect to others via links. After defining agents, their data and interactions, we can define any size of agent population per agent type and run the simulation for the number of interactions that you can define.
First, if you don’t have an account on InsightMaker, Follow the instructions on www.insightmaker.com and create an account. Once you have an account login and click “Create new Insight” on the top right of the web page (image 1).
You’ll see the default page. Click the “Click me to clear this demo model” button. It’s the yellow one on the top right side of the page.
Now we can start working.
I’ll make an assumption you didn’t watch my videos on creating causal loop diagrams (https://galaxiez.com/2019/10/07/converting-causal-loop-diagrams-cld-into-stocks-and-flows-diagram/) or Stock and flows (https://galaxiez.com/2019/09/30/using-insightmaker-to-create-stocks-flows-diagram-and-run-a-simulation/). So we will start from an empty canvas.
You can add primitive to the canvas in two ways. One is using the “Add primitive” button or Ctl+Right Click (on Mac). We can use all the primitives in agent-based modeling, but the most common ones are Agent Population, Variable, State and Action. I’ll explain and show how to use each one of them later.
Before starting to create a model, we need to understand how the tool will use the model when we’ll run simulations. There are two layers of execution. One is per agent in the population of agents that we are going to run. The second is for every cycle of the simulation (we’ll define it later). Every primitive that will run per agent should be within a folder (we’ll cover it later), every primitive on the canvas and outside of a folder will be used by the tool every run cycle.
The model we will create is very simple. It contains one agent with two states (Alive, dead) and simple logic that will change agent state based on the 8 agents around her. Let’s start by adding two states. We’ll add the first one from Add primitive button.
Next step is to change the state name to Alive. We can do it by double-clicking on the state primitive or in the property window on the right side (Image 4).
Let’s add the second state by using control & right-click (on Mac). Press control and right-click below the Alive state, select “create state”, and change the name to Dead. Control & right-click gives you more control on where to add the new primitive. You should have two states (Dead & Alive).
Now we are going to add a folder. We can add a folder just if one or more primitive selected. Adding the folder tells the tool to use those states per agent. Select both of the states (left click and move the mouse) and choose “make folder” from Add primitive or “create folder” from control & right-click. A dotted rectangle should surround the two states.
If you click the Folder or the States, different property windows should appear on the left side of the screen.
The next step is to define the border color of each state. The tool will use this color to define the color of an agent state during the simulation. Control & right-click on “Alive”, select line, and choose green. Repeat the same states for “Dead” and select red.
Click on the folder. Change the name to Agent. locate the Behaviour property, and change it from None to Agent. Without this change, the system won’t treat the folder as an agent. Let’s click now above the top right side of the agent and select Create agent population.
We are going to do the following changes to the Agent Population properties:
- Change the agent base to “Agent”. This drop-down will show all folders that were set to be agents. All the other properties and behavior will be applicable to the selected folder (or agent type).
- We’ll change “Agent population” from 100 to 200. That means that the tool will create 200 agents when we’ll run the simulation.
- We’ll change the Placement method to Grid. That will create a grid with 200 cells with an agent in each cell. As you can see, there are other ways to organize agents. We’ll use them in the next posts.
Run the simulation (The button is in the top bar). You should see this Graph.
Click configuration in the simulation window. Select “Agent Map” and add “Agent Population” to the Data property. It should look like this.
Select apply and rerun the model. You should see a grid with 200 agents. (Image 12)
Now we can set the initial state of the 200 agents when the simulation starts. We want to start with a random number and positions of alive and dead agents. To do that, we will define a variable that will define probability and use this variable to define the state of each agent.
Control & right-click outside of the folder above the “Alive” status and select “create variable”. Change the Variable name to Probability. Change the value/equation property to 0.2 (20%).
InsightMaker enables you to use primitives in other primitives by linking them together. To link two primitives, you need to make sure that the Links option is selected in the top toolbar.
Hoovering over Probability and you’ll see an arrow displaying. You need to click on the arrow and drag the mouse to the target primitive. In our case, we want to connect Probability to “Alive” state.
After we linked the Probability variable and the Alive state, we can use Probability to set up randomly which agents will be alive. To do that, we need to select the Alive state and select the “Start Active” property. After selecting “Start Active” property drop-down a new window will pop up. This window enables you to write formulas and code to define the value of the property. This window has all linked primitive under reference and all build-in functions categories below reference. (Image 16)
We will use random boolean so expand the ”Random number functions” and select “Binary distribution”. You’ll see the function in the text box after the equal sign. Cleare the default probability text and scroll up to reference. Select probability. Your text box should be looked like that:
Select Apply. Now we want to set the default value of Dead state. We will do it by defining “Dead” every agent that is not defined as Alive. To do that, we need to connect Alive to Dead. Hoover over Alive and drag the arrow to Dead. Open the editor for “Start Active” and change the value to ! (not) [Alive] by typing “!” and use Alive from references.
Select apply and run the simulation. You should see the Agents with basic states fit the Probability value we selected. If you’ll change Probability value (let’s try 0.5) and rerun simulation, you should see different results. Change the value of probability back to 0.2.
Now we are going to define the logic that the tool will implement any cycle for any agent. The logic is simple: If the agent is in Dead state and there are 3 Alive agents around him, he will change his state to Alive. If the agent is alive and there are less than 2 or over 3 alive agents around him, he will change is state to dead.
To implement the above logic we want to find out how many alive agents we have around any agents. To do that, we will use a variable and a function that will provide us with this data. Click on the folder and increase its size. Select the two states and move them to the bottom of the folder, leaving space for a new variable on top of them. Use Control & right-click and add a new Variable. Change the name for neighbors and link “Agent population” and “Alive” state to neighbors variable. After linking the two, click on neighbors Variable and open the Value/Equation editor box. (Image 21)
We are going to use a function to return all the neighbors around an agent and filter it to the number of Agents with Alive state. Expand “Agent functions” locate “Find Nearby” and click on the question mark beside the text. You can see the explanation and the need for Agent Population. So, let’s scroll up and select “Agent population” from references and scroll back to Find Nearby and click it. We have a duplicated agent population just because we didn’t change the default name of the population. So, let’s remove the duplication. (Image 20)
The target should be replaced with “Self”, which is a reference to the current Agent. The count should be 8. [Agent Population].FindNearest(Self, 8). This will return the agents from the 8 cells around the current agent. We want to return just the neighbors that are in Alive state, so we will use the Find State function (under Agents functions) to filter the returned agents. Once you click this function, you should remove the default “[Agent Population]” since the FindNearest already returned a list of agents. Next, we want to change the state that we are looking for to “Alive” by using the “Alive” reference. The formula should be like that: [Agent Population].FindNearest(Self, 8).FindState([Alive]). All we need is actually the count, so we can add .count() or .length() and that will return the number of agents around a given one that are alive.
Apply the changes. We will now use the transition lines to change the state of each state primitive. The first thing we need to do is to change the state in the toolbar from “Links” to “Flows/Transitions”. If we won’t do it, we’ll create links.
We need to hover on top of each one of the states and drag the line image to the other one. To make the model clearer, select a line, click on the blue dot in the middle and drag each line to the left or to the right. (Image 23)
Change the “Triggered by” property of those two lines from Timeout to Condition. Make sure that you’ve done this change.
The next step is to link the neighbors variable to each transition line. Switch back to links and connect Neighbors to each line. You’ll see that the line will cross other lines. To fix that, select one of the links, use Shift & click to add new adjusting dot (blue) and use this new dot to change the line so it won’t cross others.
Now we are ready to apply the logic defined above. Select the arrow that transforms Alive to Dead and open the editor for Value. Following the logic above, all we need to do is to use Neighbors to create this logic: [Neighbors] < 2 or [Neighbors] > 3. Apply it and select the line that transforms Dead to Alive. Change the Value to the depict the logic above: [Neighbors] = 3.
That’s all. Now you can run the model. Before doing that, let increase the number of cycles the simulation will run. Click “Settings” from the Tool Bar. Change “Simulation Length” to 50. Apply and run the simulation. Use the right blow arrow at the top of the property window to collapse it and then expand it. You should see the Init Function set to 0.2. Change it to 0.1 and rerun the model.