Creating multidimensional SD Models
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: