stormvogel.graph

Contains the code responsible for representing the structure of a model as a graph.

Classes

NodeType

Create a collection of name/value pairs.

ModelGraph

A directed networkx graph describing the structure of a model.

Functions

node_key(→ str)

Convert a graph node to a unique, JS/JSON-safe string key.

Module Contents

stormvogel.graph.node_key(node: stormvogel.model.State | tuple[stormvogel.model.State, stormvogel.model.Action]) str

Convert a graph node to a unique, JS/JSON-safe string key.

State nodes map to their UUID string. Action (State, Action) tuple nodes map to {state_uuid}__{base64url(action_label)}.

The action label is base64url-encoded so that the result is safe for embedding inside JS/JSON double-quoted strings and free of separator collisions (the UUID hex+hyphen alphabet and the base64url alphabet never produce the __ bigram).

Parameters:

node – A state or (State, Action) tuple to convert.

Returns:

A unique string key for the node.

Raises:

TypeError – If node is not a State or (State, Action) tuple.

class stormvogel.graph.NodeType(*args, **kwds)

Bases: enum.Enum

Create a collection of name/value pairs.

Example enumeration:

>>> class Color(Enum):
...     RED = 1
...     BLUE = 2
...     GREEN = 3

Access them by:

  • attribute access:

    >>> Color.RED
    <Color.RED: 1>
    
  • value lookup:

    >>> Color(1)
    <Color.RED: 1>
    
  • name lookup:

    >>> Color['RED']
    <Color.RED: 1>
    

Enumerations can be iterated over, and know how many members they have:

>>> len(Color)
3
>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

Methods can be added to enumerations, and members can have their own attributes – see the documentation for details.

STATE = 0
ACTION = 1
UNDEFINED = 2
class stormvogel.graph.ModelGraph(incoming_graph_data=None, **attr)

Bases: networkx.DiGraph

A directed networkx graph describing the structure of a model.

States and actions (except EmptyActions) are represented as nodes in the graph. All outgoing edges of a state node describe the available actions for that state. The outgoing edges from an action describe the possible next states (possible choices) and hold the probability of each transition as a node attribute.

add_state(state: stormvogel.model.State, **attr)

Add a state node to the graph.

Parameters:
  • state – The state to add.

  • **attr – Arbitrary keyword arguments representing attributes to associate with the state node.

add_action(state: stormvogel.model.State, action: stormvogel.model.Action, **action_attr)

Add an action node to the graph and connect it to a given state.

The action node is uniquely identified and linked from the source state. The action is skipped if it is an EmptyAction.

Parameters:
  • state – The source state from which the action originates.

  • action – The action to add.

  • **action_attr – Arbitrary keyword arguments representing attributes to associate with the action node.

Raises:

AssertionError – If the source state is not already in the graph.

add_transition(state: stormvogel.model.State, action: stormvogel.model.Action, next_state: stormvogel.model.State, probability: stormvogel.model.Value, **attr) None

Add a transition to the graph with an associated probability.

For non-empty actions, this adds an edge from the action node to the target state. For EmptyAction, the edge is added directly from the source state to the target state.

Parameters:
  • state – The source state.

  • action – The action that causes the transition.

  • next_state – The target state reached by the transition.

  • probability – The probability associated with the transition.

  • **attr – Arbitrary keyword arguments representing attributes to associate with the transition edge.

Raises:

AssertionError – If the source state or target state is not in the graph, or if the action node is missing (for non-empty actions).

classmethod from_model(model: stormvogel.model.Model, state_properties: collections.abc.Callable[[stormvogel.model.State], dict[str, Any]] | None = None, action_properties: collections.abc.Callable[[stormvogel.model.State, stormvogel.model.Action], dict[str, Any]] | None = None, transition_properties: collections.abc.Callable[[stormvogel.model.State, stormvogel.model.Action, stormvogel.model.State], dict[str, Any]] | None = None) Self

Construct a directed graph representation of a model.

Initialize the graph from the provided model by adding all states, actions, and transitions. Optional callbacks allow customization of properties for states, actions, and transitions.

Parameters:
  • model – The model containing states and choices.

  • state_properties – A callable that returns a dictionary of properties for a given state.

  • action_properties – A callable that returns a dictionary of properties for a given action from a state.

  • transition_properties – A callable that returns a dictionary of properties for a transition from a source state via an action to a target state.

Returns:

An instance of the graph populated with states, actions, and transitions from the model.

>>> import stormvogel.examples as examples
>>> mdp = examples.create_lion_mdp()
>>> G = ModelGraph.from_model(mdp, state_properties = lambda s: {"labels": s.labels})
>>> G.nodes[mdp.initial_state]
{'type': <NodeType.STATE: 0>, 'labels': ['init']}