Vectors (Arrays)

Vectors are a powerful tool that play a key role in agent-based modeling. Vectors are also very useful in System Dynamics modeling allowing you to easily extend a model to represent different categories or classes of behavior.

For example, imagine you wanted to create a population model of North America. You could build the model using a single stock representing the population for the entire continent. Once you completed this model, you may decide that you now want to track the populations for Mexico, Canada and the United States separately. One way to do this would be to duplicate your model structure for each of these three countries. Though workable, this process would be laborious and prone to error. With vectors, you can achieve the same effect as duplicating the model structure just by adjusting your model equations slightly.

In this section, we will introduce vectors to you and show you how to use them to keep track of different categories in your model. As an example, here is that North America population model implemented using vectors:

What is a Vector

A vector is just an ordered list of numbers surrounded by curly braces. This is a vector of the squares of the numbers one, two, and three :

{1, 4, 9}

You can do mathematical operations on vectors like you would with regular numbers. For example:

sqrt({1, 4, 9}) # = {1, 2, 3}
5+{1, 4, 9} # = {6, 9, 14}
{0, 1, 2} * {1, 4, 9} # = {0, 4, 18}

Note: element-wise operations are carried out, including for multiplication of vectors or matrices. See Macros and Globals if you need matrix multiplication.

In addition to regular vectors, Insight Maker also has named vectors. In named vectors each element of the vector has a name (which is case-insensitive). For example:

{cats: 1, dogs: 3, birds: 9}

You can apply mathematical operations to named vectors just like you would for regular vectors. For example:

2 * {cats: 1, dogs: 3} # = {cats: 2, dogs: 6}
{cats: 1, dogs: 3} + {dogs: 4, cats: -1 } # = {cats: 0, dogs: 7}

Vectors are sometimes referred to as "arrays" or "lists" in other languages and named vectors are sometimes referred to as "associative arrays" or "dictionaries".

Vectorizing your Model

Imagine we wanted to extend Insight Maker's standard rabbit growth model to keep track of male and female rabbits separately. We could do this either by duplicating the entire model structure, or more simply by using vectors.

To take the vector approach, we simply need to replace the values of the primitives in our model with named vectors. For example, replace the Rabbit stock's initial value ("200") with:

{Males: 200, Females: 100}

That equation tells Insight Maker that the stock contains a vector with 200 "Males" and 100 "Females". Now run the model. Insight Maker will automatically vectorize its calculations and track the two distinct populations of rabbits without any additional configuration. The before and after results of the vectorization are shown below:

Now, edit the Birth Rate variable to be:

{Males: 0.1, Females: 0.2}

Again run the model and everything will work automatically. Your "Males" and "Females" populations of rabbits will have different initial population sizes and birth rates. Insight Maker keeps track of everything for you and automatically applies the correct vectorization.

Multidimensional Vectors (Matrices)

A matrix in Insight Maker is simply a vector of vectors. For instance to define a 2x2 matrix you could use the following:

{ {1, 4}, {9, 16} }

You can do the same with named vectors. Say for instance we wanted to track rabbits by both gender and country, we could use something like:

{Canada: {Males: 200, Females: 100}, USA: {Males: 150, Females: 50} }

If you put this is the initial value for the stock, you will now be simulating four distinct rabbit populations.

In this case, for the birth rate equation, Insight Maker will work correctly either with one number (all the populations have the same birth rate), or a vector for the genders (each gender has a different birth rate), or a vector for the countries (each country has a different birth rate), or a matrix of countries and genders (each country and gender has a different birth rate). Insight Maker will do the right thing for you in each case.

Multidimensional vectors can start to become clunky if you type them in manually. If you have the same values for some of the elements (such as all the countries have the same population sizes) you can use other vector functions to help construct the vector. For instance the "Repeat" function is quite useful:

Repeat({Males: 200, Females: 100}, {"Canada", "USA", "Mexico", "France", "Germany"})
# = {Canada: {Males: 200, Females: 100}, USA: {Males: 200, Females: 100}, ...... }

Selecting Elements and Collapsing Matrices

You can select an element from a vector like so:

{1, 4, 9}{2} # = 4

You can do the same with named vectors:

{Males: 200, Females: 100}{"Males"} # = 200

For named vectors you can also use a shorthand notation "." to select single elements:

{Males: 200, Females: 100}.Males # = 200

You can also use vectors in your selections to select multiple elements at a time:

{1, 4, 9}{ {2, 1} } # = {4, 1}
{Males: 200, Females: 100}{ {"Females", "Males"}} } # = {Females: 100, Males: 200}

For matrices, you list your selectors sequentially dimension by dimension. For example, you can do something like the following:

[Rabbits] <- {Canada: {Males: 200, Females: 100}, USA: {Males: 150, Females: 50} }

[Rabbits]{"Canada", "Males"} # = 200
[Rabbits].Canada.Males # = 200

If you use a "*" instead of an element name, Insight Maker returns the whole vector along that dimension:

[Rabbits]{"Canada", *} # = {Males: 200, Females: 100}

[Rabbits]{*, "Males"} # = {Canada: 200, USA: 150}

You can also collapse or summarize elements from a matrix by using the name of a function in the selection. The function is used to aggregate elements along that dimension. For example, to get the total number of rabbits by country:

[Rabbits]{*, sum} # = {Canada: 300, USA: 200}

To get the average number of males and females in the countries:

[Rabbits]{mean, *} # = {Males: 175, Females: 75}

All standard Insight Maker vector functions (Mean, Median, StdDev, etc...) can be used in this way. Additionally, you can also write and use custom functions.

Wildcards

"*" in vectors is a wildcard and will match missing elements. For instance if we wanted the birth rates of Canada and USA to be 0.1, but for all other countries to be 0.2, we could use:

{USA: 0.1, Canada: 0.1, *: 0.2}

Multi-word Names

If you have a name that contains spaces, you need to quote it when you declare the vector:

{USA: 0.1, Canada: 0.3, "Great Britain": 0.2}