.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/basic/example_typing_module.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_basic_example_typing_module.py: =========== Type System =========== This example demonstrates BAM Engine's type aliases for defining custom roles and components. These types hide NumPy complexity while maintaining full type safety. If you're extending BAM Engine with custom roles or events, understanding these types will make your code cleaner and more maintainable. .. GENERATED FROM PYTHON SOURCE LINES 15-26 Introduction to Type Aliases ---------------------------- BAM Engine provides four user-friendly type aliases: - ``Float``: Array of floating-point values (prices, quantities, rates) - ``Int``: Array of integer values (counts, periods, durations) - ``Bool``: Array of boolean values (flags, conditions) - ``Agent``: Array of agent IDs (references to other agents) These are all NumPy arrays under the hood, but with clear semantic meaning. .. GENERATED FROM PYTHON SOURCE LINES 26-43 .. code-block:: Python import numpy as np from bamengine import Agent, Bool, Float, Int, ops # Create arrays using standard NumPy, but type them semantically prices: Float = np.array([1.0, 1.2, 0.95, 1.1], dtype=np.float64) counts: Int = np.array([10, 5, 8, 12], dtype=np.int64) active: Bool = np.array([True, True, False, True], dtype=np.bool_) employers: Agent = np.array([0, 1, -1, 0], dtype=np.intp) # -1 = unemployed print("Type aliases map to NumPy arrays:") print(f" Float -> {prices.dtype}") print(f" Int -> {counts.dtype}") print(f" Bool -> {active.dtype}") print(f" Agent -> {employers.dtype}") .. rst-class:: sphx-glr-script-out .. code-block:: none Type aliases map to NumPy arrays: Float -> float64 Int -> int64 Bool -> bool Agent -> int64 .. GENERATED FROM PYTHON SOURCE LINES 44-48 Understanding the Underlying Types ---------------------------------- Each type alias corresponds to a specific NumPy dtype: .. GENERATED FROM PYTHON SOURCE LINES 48-59 .. code-block:: Python print("\nType mapping:") print(" Float = NDArray[np.float64] # 64-bit floating point") print(" Int = NDArray[np.int64] # 64-bit signed integer") print(" Bool = NDArray[np.bool_] # Boolean (True/False)") print(" Agent = NDArray[np.intp] # Platform-dependent integer (for indexing)") # The Agent type uses np.intp for safe array indexing # This ensures compatibility across 32-bit and 64-bit systems print(f"\nnp.intp on this system: {np.dtype(np.intp)}") .. rst-class:: sphx-glr-script-out .. code-block:: none Type mapping: Float = NDArray[np.float64] # 64-bit floating point Int = NDArray[np.int64] # 64-bit signed integer Bool = NDArray[np.bool_] # Boolean (True/False) Agent = NDArray[np.intp] # Platform-dependent integer (for indexing) np.intp on this system: int64 .. GENERATED FROM PYTHON SOURCE LINES 60-65 Defining Custom Roles with Types -------------------------------- When defining custom roles, use these types to annotate fields. This provides IDE autocomplete, type checking, and documentation. .. GENERATED FROM PYTHON SOURCE LINES 65-93 .. code-block:: Python from bamengine import role @role class Inventory: """Custom inventory tracking role for firms.""" # Float for quantities and monetary values goods_on_hand: Float # Current stock level reorder_point: Float # When to reorder unit_cost: Float # Cost per unit # Int for counts and durations days_to_delivery: Int # Days until next delivery order_count: Int # Number of pending orders # Bool for status flags needs_reorder: Bool # Whether stock is low is_backordered: Bool # Whether we're out of stock # Agent for relationships to other agents supplier_id: Agent # Which firm supplies us (-1 if none) print("Inventory role defined with typed fields:") print(f" Fields: {list(Inventory.__dataclass_fields__.keys())}") .. rst-class:: sphx-glr-script-out .. code-block:: none Inventory role defined with typed fields: Fields: ['name', 'goods_on_hand', 'reorder_point', 'unit_cost', 'days_to_delivery', 'order_count', 'needs_reorder', 'is_backordered', 'supplier_id'] .. GENERATED FROM PYTHON SOURCE LINES 94-98 Instantiating Roles with Arrays ------------------------------- When creating role instances, pass NumPy arrays of the appropriate type. .. GENERATED FROM PYTHON SOURCE LINES 98-119 .. code-block:: Python # Number of agents with this role n_firms = 5 # Create arrays for each field inventory = Inventory( goods_on_hand=np.array([100.0, 50.0, 75.0, 200.0, 30.0]), reorder_point=np.array([25.0, 20.0, 30.0, 50.0, 15.0]), unit_cost=np.array([10.0, 15.0, 12.0, 8.0, 20.0]), days_to_delivery=np.array([3, 0, 5, 2, 7], dtype=np.int64), order_count=np.array([1, 0, 2, 0, 1], dtype=np.int64), needs_reorder=np.array([False, True, False, False, True]), is_backordered=np.array([False, True, False, False, False]), supplier_id=np.array([2, 0, 4, 1, -1], dtype=np.intp), ) print("\nInventory instance:") print(f" Goods on hand: {inventory.goods_on_hand}") print(f" Needs reorder: {inventory.needs_reorder}") print(f" Supplier IDs: {inventory.supplier_id}") .. rst-class:: sphx-glr-script-out .. code-block:: none Inventory instance: Goods on hand: [100. 50. 75. 200. 30.] Needs reorder: [False True False False True] Supplier IDs: [ 2 0 4 1 -1] .. GENERATED FROM PYTHON SOURCE LINES 120-124 When to Use Each Type --------------------- Here's guidance on choosing the right type: .. GENERATED FROM PYTHON SOURCE LINES 124-156 .. code-block:: Python print( """ Type Selection Guide ==================== Float (np.float64): - Prices, costs, revenues - Quantities (production, inventory, consumption) - Rates (interest, inflation, unemployment) - Ratios and proportions - Any continuous numerical value Int (np.int64): - Counts (workers, orders, periods) - Durations (contract length, days until event) - Discrete quantities (number of items) - Period/time indices Bool (np.bool_): - Status flags (employed, bankrupt, active) - Conditions (has_inventory, needs_reorder) - Masks for filtering (unemployed_mask) - Binary states Agent (np.intp): - References to other agents (employer_id, supplier_id) - Agent indices for array lookup - Use -1 to indicate "no agent" (unemployed, no supplier) """ ) .. rst-class:: sphx-glr-script-out .. code-block:: none Type Selection Guide ==================== Float (np.float64): - Prices, costs, revenues - Quantities (production, inventory, consumption) - Rates (interest, inflation, unemployment) - Ratios and proportions - Any continuous numerical value Int (np.int64): - Counts (workers, orders, periods) - Durations (contract length, days until event) - Discrete quantities (number of items) - Period/time indices Bool (np.bool_): - Status flags (employed, bankrupt, active) - Conditions (has_inventory, needs_reorder) - Masks for filtering (unemployed_mask) - Binary states Agent (np.intp): - References to other agents (employer_id, supplier_id) - Agent indices for array lookup - Use -1 to indicate "no agent" (unemployed, no supplier) .. GENERATED FROM PYTHON SOURCE LINES 157-166 Type Checking Benefits ---------------------- Using type annotations enables: 1. **IDE Autocomplete**: Your editor knows the types 2. **Static Analysis**: mypy can catch type errors 3. **Documentation**: Types serve as inline docs 4. **Refactoring Safety**: Rename/refactor with confidence .. GENERATED FROM PYTHON SOURCE LINES 166-174 .. code-block:: Python # Example: mypy would catch this error (wrong type) # inventory.goods_on_hand = "not an array" # Type error! # Correct usage inventory.goods_on_hand = np.array([90.0, 45.0, 70.0, 195.0, 25.0]) print("Updated goods_on_hand:", inventory.goods_on_hand) .. rst-class:: sphx-glr-script-out .. code-block:: none Updated goods_on_hand: [ 90. 45. 70. 195. 25.] .. GENERATED FROM PYTHON SOURCE LINES 175-180 Working with Agent References ----------------------------- The ``Agent`` type is commonly used for relationships between entities. The convention is to use -1 to indicate "no reference". .. GENERATED FROM PYTHON SOURCE LINES 180-194 .. code-block:: Python # Example: Workers with employer references worker_employers: Agent = np.array([0, 0, 1, -1, 2, -1], dtype=np.intp) # Find employed workers employed_mask: Bool = worker_employers >= 0 print(f"Worker employers: {worker_employers}") print(f"Employed mask: {employed_mask}") print(f"Employed count: {ops.sum(employed_mask)}") # Find workers at firm 0 at_firm_0: Bool = worker_employers == 0 print(f"Workers at firm 0: {np.where(at_firm_0)[0]}") .. rst-class:: sphx-glr-script-out .. code-block:: none Worker employers: [ 0 0 1 -1 2 -1] Employed mask: [ True True True False True False] Employed count: 4.0 Workers at firm 0: [0 1] .. GENERATED FROM PYTHON SOURCE LINES 195-208 Internal vs User-Friendly Types ------------------------------- BAM Engine provides two sets of type aliases: **User-friendly (recommended for custom code):** - ``Float``, ``Int``, ``Bool``, ``Agent`` **Internal (used in bamengine source code):** - ``Float1D``, ``Int1D``, ``Bool1D``, ``Idx1D`` - ``Float2D``, ``Int2D``, ``Idx2D`` (for 2D arrays) Both work identically - use whichever you prefer. .. GENERATED FROM PYTHON SOURCE LINES 208-217 .. code-block:: Python from bamengine.typing import Float1D # These are equivalent: prices_v1: Float = np.ones(10) prices_v2: Float1D = np.ones(10) print(f"\nFloat and Float1D are equivalent: {Float is Float1D}") .. rst-class:: sphx-glr-script-out .. code-block:: none Float and Float1D are equivalent: True .. GENERATED FROM PYTHON SOURCE LINES 218-222 Practical Example: Custom Production Role ----------------------------------------- Here's a realistic example of a custom role with proper typing. .. GENERATED FROM PYTHON SOURCE LINES 222-281 .. code-block:: Python @role class AdvancedProducer: """Enhanced producer with inventory management and quality control.""" # Production metrics (Float) output: Float # Units produced this period capacity: Float # Maximum production capacity efficiency: Float # Production efficiency (0-1) unit_labor_cost: Float # Cost per unit of output # Inventory (Float) inventory: Float # Current stock inventory_target: Float # Desired stock level # Quality metrics (Float) defect_rate: Float # Fraction of defective output (0-1) quality_investment: Float # Spending on quality improvement # Workforce (Int) n_workers: Int # Number of employees n_skilled_workers: Int # Subset that are skilled # Status flags (Bool) is_operating: Bool # Currently producing has_excess_inventory: Bool # Inventory above target needs_workers: Bool # Has unfilled positions # Relationships (Agent) primary_bank: Agent # Main lender (-1 if none) main_supplier: Agent # Key input supplier (-1 if none) # Instantiate for 3 firms advanced_prod = AdvancedProducer( output=np.array([100.0, 80.0, 120.0]), capacity=np.array([150.0, 100.0, 150.0]), efficiency=np.array([0.85, 0.75, 0.90]), unit_labor_cost=np.array([5.0, 6.0, 4.5]), inventory=np.array([50.0, 20.0, 80.0]), inventory_target=np.array([40.0, 30.0, 60.0]), defect_rate=np.array([0.02, 0.05, 0.01]), quality_investment=np.array([10.0, 5.0, 15.0]), n_workers=np.array([20, 15, 25], dtype=np.int64), n_skilled_workers=np.array([8, 5, 12], dtype=np.int64), is_operating=np.array([True, True, True]), has_excess_inventory=np.array([True, False, True]), needs_workers=np.array([False, True, False]), primary_bank=np.array([0, 1, 0], dtype=np.intp), main_supplier=np.array([1, -1, 2], dtype=np.intp), ) print("\nAdvanced Producer role instantiated:") print(f" Output: {advanced_prod.output}") print(f" Efficiency: {advanced_prod.efficiency}") print(f" Operating: {advanced_prod.is_operating}") print(f" Banks: {advanced_prod.primary_bank}") .. rst-class:: sphx-glr-script-out .. code-block:: none Advanced Producer role instantiated: Output: [100. 80. 120.] Efficiency: [0.85 0.75 0.9 ] Operating: [ True True True] Banks: [0 1 0] .. GENERATED FROM PYTHON SOURCE LINES 282-291 Key Takeaways ------------- - Use ``Float`` for continuous values (prices, quantities, rates) - Use ``Int`` for discrete counts and durations - Use ``Bool`` for flags and conditions - Use ``Agent`` for references to other agents (-1 = no reference) - Type annotations enable IDE support and static analysis - Both user-friendly (Float) and internal (Float1D) types work .. _sphx_glr_download_auto_examples_basic_example_typing_module.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: example_typing_module.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: example_typing_module.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: example_typing_module.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_