Stock
system dynamics, bptk, bptk-py, python, business prototyping
Stock
Stock in a SD DSL model.
A stock is what a system remembers. Its value at any instant cannot be read off the rest of the system: it is the accumulation of everything that has flowed in and out since the start, which is why it needs both an initial value and an equation.
Create one through the model rather than directly: model.stock("population").
Stock Constructor
Stock(model, name)
Create the stock.
Stock.equation
property equation
The net change per timestep, not the value — usually the inflows minus the outflows. Read, it returns the equation as originally set - an SD DSL Element or Operator.
population.equation = births - deathsWriting the equation replaces the flow lists below. A non-negative stock refuses it: its equation comes from its lists.
Stock.inflows
property inflows
The flows into the stock, as a list. Setting it, or outflows, writes the equation as the inflows minus the outflows - the way XMILE describes a stock:
population.inflows = [births, immigration]
population.outflows = [deaths]
# population.equation is now births + immigration - deathsA list takes flows and biflows. A flow leaves one stock only, so naming a flow among the outflows of a second stock raises ElementError.
Stock.initial_value
property initial_value
The value the stock holds at starttime, before any flow has acted on it. Set it to a number, to a Constant — which is what lets a scenario override it — or to any expression:
population = model.stock("population")
population.initial_value = 80000000.0
# or computed, from constants, converters or a user-defined function
births = model.constant("births")
births.equation = 800000.0
population.initial_value = births * 100The expression is evaluated once, before the run, with t at the start time. A boolean is refused, and so is anything that is not a number or a model expression; the error names the stock.
A scenario cannot set the stock itself as a constant - that would replace its equation and the stock would not move. It raises ValueError naming the stock; set the constant its initial value refers to instead.
Stock.non_negative
property non_negative
True keeps the stock from falling below zero, as Stella does. The outflows are cut back, not the stock: in each timestep they may take, together, what the stock holds plus what flows in during the step, and the first outflow in the list is served first.
store.inflows = [delivery] # 3 per day
store.outflows = [sales, scrap] # want 8 and 9 per day
store.non_negative = True
# With 10 in store and dt = 1: sales gets 8, scrap gets the remaining 5, the store is emptyThe flows report what they actually took - scrap reads 5, not 9 - so nothing leaves the stock that it did not hold. An arrayed stock is cut back cell by cell; its outflows have its shape.
Three rules come with it:
- The stock needs its flow lists. A stock whose equation was written directly raises
ElementErrorwhen it is made non-negative. - An outflow that depends on another outflow of the same stock comes after it in the list. The other way round raises
ElementErrornaming both, when the lists are set or at the start of the run. - An inflow that depends on one of the stock’s outflows is not counted towards what the outflows may take; only the stock’s content is.
A biflow is cut back while it drains the stock and left alone while it fills it. Among the outflows it is served at its place in the list; among the inflows it drains the stock when it runs backwards, and is then served after every outflow. Filling, it counts towards what the outflows may take, from either list. A flow is cut back by one stock only.
A non-negative stock runs on the Python engine only for now; backend="rust" raises RustBackendError naming the stock.
Stock.outflows
property outflows
The flows out of the stock, as a list. For a non-negative stock the order is the priority in which they are served.
Inherited from Element
Everything else — equation, function_string, plot() and the arrayed-element API — comes from Element, where it is documented once for all element types.