Element
system dynamics, bptk, bptk-py, python, business prototyping
Element
Element Constructor
Element(model, name, function_string=None)
Generic element in a SD DSL model.
Concrete elements are Biflows, Flows, Constants and Converters.
In general elements are created via an instance of the Model class, using the appropriate methods.
Parameters
Model – Model. The model the element belongs to.
Name – String. The name of the model.
Function_string – String (Default=None) The function string of the element. This is set by the framework.
Element.equation
property equation()
Returns the equation as originally set.
Returns
The equation, either a SD DSL Element or Operator.
Element.function_string
property function_string()
Returns a string representation of the underlying function. Useful for debugging purposes.
Element.plot
plot(starttime=None, stoptime=None, dt=None, return_df=False, format=‘plot’, matplotlib_rc_settings=None)
Plot the equation or return a dataframe with the simulated data.
Parameters
starttime – Integer (Default None). The timestep where to begin the plot. If set to None the plot starts at the Models starttime.
stoptime – Integer (Default None) The timestep when to end the plot.
dt – Fraction of 1 (Default None) The timestep to plot. If set to None, then the plot uses the Models dt.
return_df – Boolean (Default False). Whether to plot the equation or return the underlying dataframe. Equivalent to format=‘df’, which it overrides when set.
format – String (Default ‘plot’). What to return: ‘plot’ draws the diagram and returns nothing, ‘axes’ returns the matplotlib Axes, ‘df’ returns the underlying dataframe. ‘plot’ relies on the notebook displaying the figure as a side effect, which only Jupyter’s inline backend does — in marimo, and in a plain script, use ‘axes’. Every example in this documentation does.
matplotlib_rc_settings – Dict (Default None). matplotlib settings for this one plot, laid over the central plotting configuration rather than replacing it. The central configuration is left alone, so the next plot is styled centrally again.
Returns
Nothing for format=‘plot’, the matplotlib Axes for format=‘axes’, or a Pandas dataframe for format=‘df’ (or return_df=True).
Arrayed elements
Any element can hold a vector or a matrix instead of a scalar. The Multidimensional SD DSL chapter works through this in depth; these are the methods it uses.
Setting an element up as an array
setup_vector(size, default_value=0.0, set_stack_equation=False)
Turn the element into a vector of size entries, each initialised to default_value. Pass a list as default_value to give the entries different values.
setup_matrix(size, default_value=0.0, set_stack_equation=False)
The same for a matrix. size is a two-element list, [rows, columns].
setup_named_vector(values, set_stack_equation=False)
A vector whose entries are addressed by name rather than by index, from a dict {name: value}. Subscripting then reads element["young"] instead of element[0].
setup_named_matrix(names, set_stack_equation=False)
The same for a matrix, from a nested dict.
set_stack_equation governs whether the element’s own equation is built from its entries. Leave it at False when you set the equation yourself.
An array needs at least one entry: a size of 0, or an empty dict, raises ValueError.
Parts of an array
Square brackets take a range or a pair of keys as well as a single one. Positions count from 0, and a range includes its end, as in Stella; a range reaching beyond the array stops at its edge. Labels select by name, and : alone takes a whole dimension.
salaries[0:2] # the first three entries
salaries["x1":"x3"] # by label, x3 included
matrix[1, 0] # one cell
matrix["boston", :] # a row
matrix[:, "b"] # a columnA part of an array is an expression like any other: it can be computed with, aggregated, or given to an arrayed element of the same size. Arrays combined in one equation need the same labels.
Element.transpose
transpose()
The matrix with its rows and columns swapped, as an expression: b.equation = a.transpose() gives b[j][i] = a[i][j]. Only a matrix can be transposed.
Aggregating over an array
Each of these returns an expression, so it can be used inside another equation. They work on an arrayed element and on any expression that is an array, such as (a * b).arr_sum() or a[0:2].arr_mean().
| Method | Returns |
|---|---|
| arr_sum(dimension=‘*’, over=None) | The sum |
| arr_mean(over=None) | The arithmetic mean |
| arr_median(over=None) | The median |
| arr_prod(dimension=‘*’, over=None) | The product |
| arr_stddev(over=None) | The standard deviation |
| arr_max(over=None) | The largest entry |
| arr_min(over=None) | The smallest entry |
| arr_size(over=None) | The number of entries |
| arr_rank(rank) | The entry of the given rank, counted from the largest |
| dot(other) | The dot product with another arrayed element |
Without over an aggregation takes every entry and returns one number. With over it aggregates a matrix along one dimension and returns a vector: over=1 one value per row, over=0 one value per column - XMILE’s SUM(A[M, *]).
dimension on arr_sum and arr_prod accepts '*' or the array’s full depth, which both aggregate every entry. arr_rank is the SD DSL’s own; XMILE’s RANK - the position of the r-th smallest entry - is sd.rank. The aggregations, the parts of arrays and transpose run on the Rust engine as well - they become engine-side functions over the sub-elements. See Execution Backends.