Creating multidimensional SD Models

Description and overview how vector-valued and matrix-valued SD Models can bet setup and worked with
Keywords

system dynamics, systemdynamics, sd dsl, bptk, bptk-py, python, business simulation

Multidimensional SD Models

This document illustrates how vector- or matrix-valued SD Models can be defined.

We start with some boilerplate to get a BPTK project up and running:

This is already enough to define arrayed components.

How to define arrayed components

There are two options for arrayed components:

  • Vectors (one dimensional arrays)
  • Matrices (two dimensional arrays)

Moreover, both types of arrays - Vectors and Matrices - can be setup:

  • using numerical indices
  • using string-valued indices (named arrays)

Lets have a look at some examples:

As can be seen, we need two parameters for setting up a Vector using numerical indices. Moreover, there is one optional parameter.

Parameter Type Meaning
size Integer Defines the length of the Vector
values List of Float/Integer Defines the values of the Vector elements
set_stack_equation Boolean (optional) If the element is a stock, the initial value is set (False) or the equation is set (True). Default is False.

And we need one parameter (+ one optional parameter) for setting up a Vector using string indices:

Parameter Type Meaning
values Dictionary Defines the string-values indices and their values
set_stack_equation Boolean (optional) If the element is a stock, the initial value is set (False) or the equation is set (True). Default is False.

For matrices, we can proceed completely similar.

As can be seen, we need two parameters (+ one optional parameter) for setting up a Matrix using numerical indices:

Parameter Type Meaning
size List (tuple) of Integer Defines the size of the Matrix
values List of Lists of Float/Integer Defines the values of the Matrix elements
set_stack_equation Boolean (optional) If the element is a stock, the initial value is set (False) or the equation is set (True). Default is False.

And we need one parameter (+ one optional parameter) for setting up a Matrix using string-valued indices:

Parameter Type Meaning
values Dictionary Defines the string-values indices and their values
set_stack_equation Boolean (optional) If the element is a stock, the initial value is set (False) or the equation is set (True). Default is False.

Math-Operations for arrayed Components

The standard Operations (+, -, *, %) can be used for arrayed Components. Moreover some array-specific Operations are provided.

Standard Operations

It is possible to use the standard Operations (+, -, *, %) for:

Operand 1 Operand 2
Arrayed Element Arrayed Element
Arrayed Element Float/Integer
Float/Integer Arrayed Element

⚠️ If both operands are arrayed elements, they must have the same numerical/string-valued indices.

That means it is not possible to have operand 1 = vector with numerical indices and operand 2 = vector with string-valued indicies, even if they have the same size.

It is also not possible to have operand 1 = vector and operand 2 = matrix or vice versa.

Other standard Operations (**, //, %, …) are not supported yet.

Standard Operations are always performed element-wise. Lets have a look at some examples:

Addition (\(+\))

\[\begin{equation*} \begin{pmatrix} 1.1 \\ 2.2 \end{pmatrix} + \begin{pmatrix} 3.1 \\ 4.2 \end{pmatrix} = \begin{pmatrix} 4.2 \\ 6.4 \end{pmatrix} \end{equation*}\]

[ 4.2 , 6.4 ]

\[\begin{equation*} \begin{pmatrix} 3.1 \\ 4.2 \end{pmatrix} +1.0 = \begin{pmatrix} 4.1 \\ 5.2 \end{pmatrix} \end{equation*}\]

[ 4.1 , 5.2 ]

Subtraction (\(-\))

\[\begin{equation*} \begin{pmatrix} 1.1 & 2.2 \\ 3.3 & 4.4 \end{pmatrix} - \begin{pmatrix} 5.5 & 7.7 \\ 3.3 & 14.4 \end{pmatrix} = \begin{pmatrix} -4.4 & -5.5\\ 0.0 & -10.0 \end{pmatrix} \end{equation*}\]

[ [-4.4 , -5.5]
  [0.0 , -10.0] ]

\[\begin{equation*} \begin{pmatrix} 5.5 & 7.7 \\ 3.3 & 14.4 \end{pmatrix} -1.0 = \begin{pmatrix} 4.5 & 6.7\\ 2.3 & 13.4 \end{pmatrix} \end{equation*}\]

[ [4.5 , 6.7]
  [2.3 , 13.4] ]

Multiplication (\(*\))

\[\begin{equation*} \begin{pmatrix} 4.0\\ 5.0 \end{pmatrix} \odot \begin{pmatrix} 6.0\\ 7.0 \end{pmatrix} = \begin{pmatrix} 24.0\\ 35.0 \end{pmatrix} \end{equation*}\]

[ 24.0 , 35.0 ]

\[\begin{equation*} \begin{pmatrix} 6.0\\ 7.0 \end{pmatrix} \cdot 3.0 = \begin{pmatrix} 18.0\\ 21.0 \end{pmatrix} \end{equation*}\]

[ 18.0 , 21.0 ]

The case “- arrayed element” is a special case since it is interpreted as “(-1) \(\cdot\) element”:

\[\begin{equation*} - \begin{pmatrix} 6.0\\ 7.0 \end{pmatrix} = \begin{pmatrix} -6.0\\ -7.0 \end{pmatrix} \end{equation*}\]

[ -6.0 , -7.0 ]

Division (\(/\))

\[\begin{equation*} \begin{pmatrix} 2.0 & 4.0\\ 8.0 & 16.0 \end{pmatrix} \oslash \begin{pmatrix} 2.0 & 1.0\\ 0.5 & 0.25 \end{pmatrix} = \begin{pmatrix} 1.0 & 4.0\\ 16.0 & 64.0 \end{pmatrix} \end{equation*}\]

[ [1.0 , 4.0]
  [16.0 , 64.0] ]

\[\begin{equation*} \begin{pmatrix} 2.0 & 1.0\\ 0.5 & 0.25 \end{pmatrix} / \text{ } 5.0 = \begin{pmatrix} 0.4 & 0.2\\ 0.1 & 0.05 \end{pmatrix} \end{equation*}\]

[ [0.4 , 0.2]
  [0.1 , 0.05] ]

Array-specific Operations

Array Sum

Calculates the element-wise sum of an array.

\[\begin{equation*} \text{sum} \begin{pmatrix} 1.0 \\ 2.0\\ 3.0 \end{pmatrix} = 1.0 + 2.0 + 3.0 = 6.0 \end{equation*}\]

6.0

Array Product

Calculates the element-wise product of an array.

\[\begin{equation*} \text{prod} \begin{pmatrix} 2.0 & 3.0 & 4.0 \\ 5.0 & 6.0 & 7.0 \end{pmatrix} = 2.0 \cdot 3.0 \cdot 4.0 \cdot 5.0 \cdot 6.0 \cdot 7.0 = 5040.0 \end{equation*}\]

5040.0

Array Rank

Calculates the \(n\)-th highest element of an array. \(n\) is given by a parameter.

For \(n=-1\) the lowest element of the array will be returned.

\[\begin{equation*} \text{rank} \left( \begin{pmatrix} -2.0\\ -0.1\\ 3.1\\ 5.2\\ 11.1 \end{pmatrix} , 1 \right) = 11.1 \end{equation*}\]

11.1

\[\begin{equation*} \text{rank} \left( \begin{pmatrix} -2.0\\ -0.1\\ 3.1\\ 5.2\\ 11.1 \end{pmatrix} , 4 \right) = -0.1 \end{equation*}\]

-0.1

\[\begin{equation*} \text{rank} \left( \begin{pmatrix} -2.0\\ -0.1\\ 3.1\\ 5.2\\ 11.1 \end{pmatrix} , -1 \right) = -2.0 \end{equation*}\]

-2.0

Array Mean

Calculates the element-wise mean of an array.

\[\begin{equation*} \text{mean} \begin{pmatrix} 2.0 & 4.0\\ 6.0 & 8.0\\ 10.0 & 12.0 \end{pmatrix} = \frac{2.0 + 4.0 + 6.0 + 8.0 + 10.0 +12.0}{6} = 7.0 \end{equation*}\]

7.0

Array Median

Calculates the element-wise median of an array.

\[\begin{equation*} \text{median} \begin{pmatrix} -2.0\\ -0.1\\ 3.1\\ 5.2\\ 11.1 \end{pmatrix} = 3.1 \end{equation*}\]

3.1

\[\begin{equation*} \text{median} \begin{pmatrix} -2.0\\ -0.1\\ 3.1\\ 5.2\\ \end{pmatrix} = \frac{-0.1+3.1}{2}=1.5 \end{equation*}\]

1.5

Array Standdarddeviation

Calculates the element-wise standard deviation of an array.

\[\begin{equation*} \sigma \begin{pmatrix} 1.0 & 3.0\\ 3.0 & 1.0 \end{pmatrix} = \sqrt{ \frac{1}{4} \cdot \left( (1-2)^2 + (3-2)^2 + (3-2)^2 + (1-2)^2 \right) } = 1 \end{equation*}\]

1.0

Array Size

Calculates the size of an array.

For a vector, the length will be returned. For a matrix, the size of the highest level will be returned (for example 2 for a \(2 \times 3\) matrix).

\[\begin{equation*} \text{len} \begin{pmatrix} 1.0\\ 1.0\\ 1.0\\ 1.0\\ 1.0\\ 1.0\\ \end{pmatrix} = 6 \end{equation*}\]

6

\[\begin{equation*} \text{len} \begin{pmatrix} 1.0 & 1.0 & 1.0\\ 1.0 & 1.0 & 1.0 \end{pmatrix} = 2 \end{equation*}\]

2

\[\begin{equation*} \text{len} \begin{pmatrix} 1.0 & 1.0 & 1.0\\ 1.0 & 1.0 & 1.0\\ 1.0 & 1.0 & 1.0\\ 1.0 & 1.0 & 1.0 \end{pmatrix} = 4 \end{equation*}\]

4

Array Dot

The Dot function provides the classical vector/matrix-multiplication logic. That means, the following can be calculated:

Factor 1 Factor 2 Result
Vector of size \(m\) Constant Vector of size \(m\)
Constant Vector of size \(m\) Vector of size \(m\)
Matrix of size \(m \times n\) Constant Matrix of size \(m \times n\)
Constant Matrix of size \(m \times n\) Matrix of size \(m \times n\)
Vector of size \(m\) Vector of size \(m\) Value (Scalar Product)
Vector of size \(m\) Matrix of size \(m \times n\) Vector of size \(n\)
Matrix of size \(m \times n\) Vector of size \(n\) Vector of size \(m\)
Matrix of size \(m \times n\) Matrix of size \(n \times p\) Matrix of size \(m \times p\)

❗ Using the Dot function for an array and a constant yields the same result as using the \(*\)-Operator for the array and the value of the constant.

If the dimensions of the arrays to which the dot function is applied do not allow for a valid array multiplication, an exception is thrown.

⚠️ The Dot function is currently supported for not-named arrays only!

Lets have a look at some examples:

\[\begin{equation*} 2.0 \cdot \begin{pmatrix} 1.0 \\ 2.0 \\ 3.0 \end{pmatrix} = \begin{pmatrix} 2.0 \\ 4.0 \\ 6.0 \end{pmatrix}\end{equation*}\]

[2.0 , 4.0 , 6.0]

\[\begin{equation*} \begin{pmatrix} 4.0 \\ 5.0 \\ 6.0 \end{pmatrix} \cdot 2.0 = \begin{pmatrix} 8.0 \\ 10.0 \\ 12.0 \end{pmatrix}\end{equation*}\]

[8.0 , 10.0 , 12.0]

\[\begin{equation*} \begin{pmatrix} 1.0 & 2.0 \\ 3.0 & 4.0 \\ 5.0 & 6.0 \end{pmatrix} \cdot 2.0 = \begin{pmatrix} 2.0 & 4.0 \\ 6.0 & 8.0 \\ 10.0 & 12.0 \end{pmatrix}\end{equation*}\]

[ [2.0 , 4.0]
  [6.0 , 8.0]
  [10.0 , 12.0] ]

\[\begin{equation*} 2.0 \cdot \begin{pmatrix} -1.0 & -2.0 & -3.0 \\ -4.0 & -5.0 & -6.0 \\ \end{pmatrix} = \begin{pmatrix} -2.0 & -4.0 & -6.0 \\ -8.0 & -10.0 & -12.0 \\ \end{pmatrix}\end{equation*}\]

[ [-2.0 , -4.0 , -6.0]
  [-8.0 , -10.0 , -12.0] ]

\[\begin{equation*} \left\langle \begin{pmatrix} 1.0 \\ 2.0 \\ 3.0 \end{pmatrix}, \begin{pmatrix} 4.0 \\ 5.0 \\ 6.0 \end{pmatrix} \right\rangle = 1.0 \cdot 4.0 + 2.0 \cdot 5.0 + 3.0 \cdot 6.0 = 32.0 \end{equation*}\]

32.0

\[\begin{equation*} \begin{pmatrix} 1.0 & 2.0 & 3.0 \\ \end{pmatrix} \cdot \begin{pmatrix} 1.0 & 2.0 \\ 3.0 & 4.0 \\ 5.0 & 6.0 \\ \end{pmatrix} = \begin{pmatrix} 1.0 \cdot 1.0 + 2.0 \cdot 3.0 + 3.0 \cdot 5.0 \\ 1.0 \cdot 2.0 + 2.0 \cdot 4.0 + 3.0 \cdot 6.0 \\ \end{pmatrix} = \begin{pmatrix} 22.0 & 28.0 \end{pmatrix} \end{equation*}\]

[22.0 , 28.0]

\[\begin{equation*} \begin{pmatrix} -1.0 & -2.0 & -3.0 \\ -4.0 & -5.0 & -6.0 \\ \end{pmatrix} \cdot \begin{pmatrix} 4.0 \\ 5.0 \\ 6.0 \\ \end{pmatrix} = \begin{pmatrix} -1.0 \cdot 4.0 + (-2.0) \cdot 5.0 + (-3.0) \cdot 6.0 \\ -4.0 \cdot 4.0 + (-5.0) \cdot 5.0 + (-6.0) \cdot 6.0 \\ \end{pmatrix} = \begin{pmatrix} -32.0 \\ -77.0 \end{pmatrix} \end{equation*}\]

[-32.0 , -77.0]

\[\begin{equation*} \begin{aligned} \begin{pmatrix} 1.0 & 2.0 \\ 3.0 & 4.0 \\ \end{pmatrix} \cdot \begin{pmatrix} -1.0 & -2.0 \\ -4.0 & -5.0 \\ \end{pmatrix} &= \begin{pmatrix} 1.0 \cdot (-1.0) + 2.0 \cdot (-4.0) & 1.0 \cdot (-2.0) + 2.0 \cdot (-5.0) \\ 3.0 \cdot (-1.0) + 4.0 \cdot (-4.0) & 3.0 \cdot (-2.0) + 4.0 \cdot (-5.0) \\ 5.0 \cdot (-1.0) + 6.0 \cdot (-4.0) & 5.0 \cdot (-2.0) + 6.0 \cdot (-5.0) \\ \end{pmatrix}\\ &= \begin{pmatrix} -9 & -12 \\ -19 & -26\\ \end{pmatrix} \end{aligned} \end{equation*}\]

[ [-9.0 , -12.0]
  [-19.0 , -26.0] ]

Plotting arrayed Components

Similar to one-dimensional SD DSL elements, we can also plot these elements. Lets have a look:

As can be seen, both elements of the Vector are plotted.

If you want to plot the values of the Matrix, you need to specify the first index.

A simple Example

Lets have a look on a concrete example, how a multidimensional SD Model can look like.

Consider an investment depot with two accounts:

  • bank account
  • depot account

Both accounts will have different deposit rates and different interest rates each year. We want to investigate the value development of the bank account, the depot account and the whole investment depot.

Lets set up the model:

As always we define a scenario manager and scenarios:

And plot the results:

As always we can compare different scenarios with each other by plotting them simultaneously: