CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pysd

System Dynamics modeling library for Python that integrates with data science tools

Pending
Overview
Eval results
Files

stateful-components.mddocs/

Stateful Model Components

PySD's stateful components maintain state between simulation time steps, implementing core System Dynamics structures like stocks (integrations), delays, smoothing functions, and forecasting components.

Capabilities

Base Stateful Classes

Foundation classes that provide state management capabilities for model components.

class Stateful:
    """
    Base class for stateful objects.
    
    Provides basic state management functionality including initialization,
    state updates, and memory management for model components that maintain
    state between time steps.
    """

class DynamicStateful(Stateful):
    """
    Base for dynamically updating stateful objects.
    
    Extends Stateful with capabilities for dynamic state updates,
    dependency tracking, and integration with the simulation engine.
    """

Integration Components

Core stock and flow components that perform integration over time.

class Integ(DynamicStateful):
    """
    Integration/stock elements.
    
    Implements System Dynamics stocks (levels) that accumulate flows over time.
    Performs numerical integration using specified integration method.
    
    Methods:
    - __init__(lambda_function, initial_value, lambda_init_function=None)
    - __call__(time) - Get current integrated value
    - init(time, initial_value) - Initialize with specific value
    - update(time) - Update integration state for current time step
    """

class NonNegativeInteg(Integ):
    """
    Non-negative integration.
    
    Integration component that ensures the integrated value never goes below zero,
    useful for physical quantities like population, inventory, or resources.
    
    Inherits all Integ methods with additional constraint enforcement.
    """

Usage Examples

from pysd.py_backend.statefuls import Integ, NonNegativeInteg

# Create basic integration component
def population_flows():
    return births_per_time_step - deaths_per_time_step

population = Integ(population_flows, initial_value=1000)

# Non-negative integration for physical quantities
def inventory_flows():
    return production_rate - consumption_rate

inventory = NonNegativeInteg(inventory_flows, initial_value=500)

# Access current values during simulation
current_population = population(current_time)
current_inventory = inventory(current_time)

Delay Components

Components that implement various types of delays commonly used in System Dynamics models.

class Delay(DynamicStateful):
    """
    Variable delay functions.
    
    Implements first-order variable delay where delay time can change dynamically.
    Models processes where items spend variable time in the delay.
    
    Methods:
    - __init__(delay_input, delay_time, initial_value, order=1)
    - __call__(time) - Get delayed output value
    - init(time, initial_value) - Initialize delay chain
    """

class DelayN(DynamicStateful):
    """
    Nth order delay.
    
    Implements higher-order delays by chaining multiple first-order delays.
    Provides more realistic delay behavior with gradual buildup and decay.
    
    Methods:
    - __init__(delay_input, delay_time, initial_value, order=3)
    - __call__(time) - Get delayed output value
    """

class DelayFixed(DynamicStateful):
    """
    Fixed delay.
    
    Implements pipeline delay with fixed delay time. Items enter and exit
    after exactly the specified delay time (FIFO queue behavior).
    
    Methods:  
    - __init__(delay_input, delay_time, initial_value)
    - __call__(time) - Get delayed output value
    """

Usage Examples

from pysd.py_backend.statefuls import Delay, DelayN, DelayFixed

# Variable delay for information processing
def information_input():
    return new_information_rate

def processing_time():
    return base_processing_time * complexity_factor

information_delay = Delay(
    delay_input=information_input,
    delay_time=processing_time,
    initial_value=0,
    order=1
)

# Third-order delay for material flow
material_delay = DelayN(
    delay_input=lambda: production_rate,
    delay_time=lambda: 5.0,  # 5 time units
    initial_value=100,
    order=3
)

# Fixed pipeline delay for manufacturing
manufacturing_delay = DelayFixed(
    delay_input=lambda: orders_received,
    delay_time=lambda: 7.0,  # Exactly 7 time units
    initial_value=50
)

# Get delayed values during simulation
processed_info = information_delay(current_time)
materials_out = material_delay(current_time)
finished_goods = manufacturing_delay(current_time)

Smoothing and Forecasting

Components for smoothing noisy data and generating forecasts.

class Smooth(DynamicStateful):
    """
    Smoothing functions.
    
    Implements exponential smoothing (first-order delay applied to input).
    Reduces noise and volatility in model variables.
    
    Methods:
    - __init__(smooth_input, smooth_time, initial_value)
    - __call__(time) - Get smoothed output value
    """

class Trend(DynamicStateful):
    """
    Trend calculation.
    
    Calculates the trend (rate of change) of input variable using
    exponential smoothing of the derivative.
    
    Methods:
    - __init__(trend_input, trend_time, initial_trend=0)
    - __call__(time) - Get current trend value
    """

class Forecast(DynamicStateful):
    """
    Forecasting functions.
    
    Generates forecasts by extrapolating current value and trend.
    Combines exponential smoothing with trend analysis.
    
    Methods:
    - __init__(forecast_input, average_time, horizon_time, initial_trend=0)
    - __call__(time) - Get forecasted value
    """

Usage Examples

from pysd.py_backend.statefuls import Smooth, Trend, Forecast

# Smooth noisy sales data
def raw_sales():
    return daily_sales_with_noise

smoothed_sales = Smooth(
    smooth_input=raw_sales,
    smooth_time=5.0,  # 5-day smoothing
    initial_value=1000
)

# Calculate trend in market growth
def market_size():
    return current_market_size

market_trend = Trend(
    trend_input=market_size,
    trend_time=10.0,  # 10-period trend calculation
    initial_trend=0.05  # 5% initial growth rate
)

# Forecast future demand
demand_forecast = Forecast(
    forecast_input=lambda: current_demand,
    average_time=8.0,    # 8-period averaging
    horizon_time=12.0,   # 12-period forecast horizon
    initial_trend=0.02
)

# Access values during simulation
current_smooth_sales = smoothed_sales(current_time)
current_trend = market_trend(current_time)
future_demand = demand_forecast(current_time)

Sampling and Control

Components for conditional sampling and initial value handling.

class SampleIfTrue(DynamicStateful):
    """
    Conditional sampling.
    
    Samples and holds input value when condition is true, maintaining
    the last sampled value when condition is false.
    
    Methods:
    - __init__(sample_input, condition, initial_value)
    - __call__(time) - Get current sampled value (held if condition false)
    """

class Initial(Stateful):
    """
    Initial value storage.
    
    Stores and provides access to initial values of model variables.
    Used for reference and reset operations.
    
    Methods:
    - __init__(initial_function)
    - __call__(time) - Get initial value
    """

Usage Examples

from pysd.py_backend.statefuls import SampleIfTrue, Initial

# Sample price when market is open
def current_price():
    return stock_price

def market_open():
    return trading_hours_active

sampled_price = SampleIfTrue(
    sample_input=current_price,
    condition=market_open,
    initial_value=100.0
)

# Store initial population for comparison
def initial_population():
    return starting_population_value

population_initial = Initial(initial_population)

# Use during simulation
price_when_open = sampled_price(current_time)
baseline_population = population_initial(current_time)

State Management

All stateful components provide common state management functionality:

Initialization

# Components can be initialized with specific values
component.init(time=0, initial_value=500)

# Or use default initialization
component.__init__(input_function, initial_value=100)

State Updates

# Components automatically update during simulation
# Manual update if needed:
component.update(current_time)

# Access current state
current_value = component(current_time)

Memory Management

Stateful components automatically manage their internal memory:

  • Maintain necessary historical values for calculations
  • Clean up old data beyond required history
  • Handle time step changes dynamically

Integration with Models

Stateful components are typically created automatically when models are translated from Vensim/XMILE, but can also be used directly:

import pysd
from pysd.py_backend.statefuls import Integ, Smooth

# In translated models, stateful components are created automatically
model = pysd.read_vensim('model_with_stocks.mdl')
results = model.run()

# Direct usage for custom components
def custom_flow():
    return some_calculation()

custom_stock = Integ(custom_flow, initial_value=1000)

# Use in custom simulation loop
time_step = 0.25
current_time = 0

while current_time <= 50:
    stock_value = custom_stock(current_time)
    print(f"Time {current_time}: Stock = {stock_value}")
    custom_stock.update(current_time)
    current_time += time_step

Error Handling

Stateful components include robust error handling:

  • Division by zero in delay times handled gracefully
  • Negative delay times raise appropriate warnings
  • Initialization errors provide clear diagnostic messages
  • Time step consistency automatically managed
try:
    problem_delay = Delay(input_func, delay_time=lambda: -1, initial_value=0)
except ValueError as e:
    print(f"Invalid delay configuration: {e}")

Performance Considerations

Stateful components are optimized for simulation performance:

  • Efficient memory usage for long simulations
  • Vectorized operations where possible
  • Automatic caching of intermediate calculations
  • Minimal overhead for state updates

For large models with many stateful components, consider:

  • Using appropriate integration time steps
  • Monitoring memory usage for very long simulations
  • Utilizing model caching capabilities

Install with Tessl CLI

npx tessl i tessl/pypi-pysd

docs

cli-tools.md

external-data.md

functions-module.md

index.md

model-loading.md

model-simulation.md

parameter-management.md

stateful-components.md

utils-module.md

tile.json