Quick Start Guide
This guide provides a quick introduction to StateTracker, a Python library for creating composable states with unidirectional value propagation.
Installation
Install from PyPI:
pip install statetracker
Basic Usage
All states must be created within a Manager context:
from statetracker import Manager, State
with Manager():
A = State(num_values=3, name="A")
print(list(A))
[0, 1, 2]
State Operations
Product (Cartesian Product)
Use product to create Cartesian products:
from statetracker import Manager, State, product
with Manager():
A = State(num_values=2, name="A")
B = State(num_values=3, name="B")
C = product([A, B], name="C") # 6 values
for _ in C:
C.print_states()
C=0, A=0, B=0
C=1, A=1, B=0
C=2, A=0, B=1
C=3, A=1, B=1
C=4, A=0, B=2
C=5, A=1, B=2
Stack (Disjoint Union)
Use stack to create disjoint unions where only one state is active at a
time:
from statetracker import Manager, State, stack
with Manager():
A = State(num_values=2, name="A")
B = State(num_values=3, name="B")
C = stack([A, B], name="C") # 5 values
for _ in C:
# Only one of A or B is active at a time (the other is None)
C.print_states()
C=0, A=0, B=None
C=1, A=1, B=None
C=2, A=None, B=0
C=3, A=None, B=1
C=4, A=None, B=2
Slicing
Use Python slice syntax to select subsets of values:
from statetracker import Manager, State
with Manager():
A = State(num_values=10, name="A")
B = A[2:5].named("B") # Values 2, 3, 4
C = A[::-1].named("C") # Reversed: 9, 8, 7, ..., 0
print(f"A has {A.num_values} values")
print(f"\nB (slice [2:5]) has {B.num_values} values: {list(B)}")
for _ in B:
B.print_states()
print(f"\nC (reversed) has {C.num_values} values: {list(C)}")
for _ in C:
C.print_states()
A has 10 values
B (slice [2:5]) has 3 values: [0, 1, 2]
B=0, A=2
B=1, A=3
B=2, A=4
C (reversed) has 10 values: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
C=0, A=9
C=1, A=8
C=2, A=7
C=3, A=6
C=4, A=5
C=5, A=4
C=6, A=3
C=7, A=2
C=8, A=1
C=9, A=0
Value Propagation
StateTracker uses unidirectional value propagation. Setting a child state’s value automatically updates all parent states:
from statetracker import Manager, State, product
with Manager():
A = State(num_values=2, name="A")
B = State(num_values=3, name="B")
C = product([A, B])
C.value = 5 # Set child value
print("After setting C.value = 5:")
print(f"A.value = {A.value}") # 1 (automatically updated)
print(f"B.value = {B.value}") # 2 (automatically updated)
After setting C.value = 5:
A.value = 1
B.value = 2
Inspecting States
Use get_states() and print_states() to conveniently view all state
values at once:
from statetracker import Manager, State, product
with Manager():
A = State(num_values=2, name="A")
B = State(num_values=3, name="B")
C = product([A, B], name="C")
C.value = 5
C.print_states() # Print all values in one line
values = C.get_states() # Get values as a dictionary
print(values)
C=5, A=1, B=2
{'C': 5, 'A': 1, 'B': 2}
Visualization
Use print_dag() to visualize state dependencies:
from statetracker import Manager, State, product
with Manager():
A = State(num_values=2, name="A")
B = State(num_values=3, name="B")
C = product([A, B], name="C")
C.print_dag()
C (counter, io=0, n=6)
+-- [op=Product]
+-- A (counter, io=0, n=2)
+-- B (counter, io=0, n=3)
Next Steps
See Core Concepts for a deeper understanding of state algebra
Explore the Operations reference for all available operations
Check the API Reference for detailed function documentation