Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

State Transition Table #691

Open
laniakea opened this issue Dec 9, 2024 · 2 comments
Open

State Transition Table #691

laniakea opened this issue Dec 9, 2024 · 2 comments
Assignees

Comments

@laniakea
Copy link

laniakea commented Dec 9, 2024

Is it possible to fetch a state transition table in a matrix format? I was unable to find anything regarding this.

@aleneum
Copy link
Member

aleneum commented Dec 12, 2024

Hi @laniakea,

Option A: Iterate over machine.events

transitions sorts Events by their 'trigger'.
Each Event has a list of Transitions that are sorted by source.
Each Transition has a dest attribute that contains the name of the destination state.
(Optional: A Transition also contains the conditions that must be met for a it to happen. Just in case your use case is more complex)

If you iterate over events and transition you could collect a dictionary of trigger dictionaries.
This data structure could be used to create a representation that suits your needs.
I used pandas in the example below out of lazyness:

from transitions import Machine
from collections import defaultdict
from pprint import pprint
from pandas import DataFrame

states = ["A", "B", "C"]
transitions = [["go", "A", "B"], ["go", "B", "C"], ["reset", "*", "A"]]
data = defaultdict(lambda: defaultdict(list))
machine = Machine(states=states, transitions=transitions, initial="A")

for trigger, event in machine.events.items():
    for source, trans in event.transitions.items():
        for tran in trans:
            data[source][tran.dest].append(trigger)

pprint(data)  # [1]

print(DataFrame([[", ".join(data[source][dest]) for dest in states] for source in states],
                columns=states, index=states))  # [2]

pprint [1]

defaultdict(<function <lambda> at 0x100b923e0>,
            {'A': defaultdict(<class 'list'>,
                              {'A': ['to_A', 'reset'],
                               'B': ['to_B', 'go'],
                               'C': ['to_C']}),
             'B': defaultdict(<class 'list'>,
                              {'A': ['to_A', 'reset'],
                               'B': ['to_B'],
                               'C': ['to_C', 'go']}),
             'C': defaultdict(<class 'list'>,
                              {'A': ['to_A', 'reset'],
                               'B': ['to_B'],
                               'C': ['to_C']})})

Pandas [2]

             A         B         C
A  to_A, reset  to_B, go      to_C
B  to_A, reset      to_B  to_C, go
C  to_A, reset      to_B      to_C

Option B: Iterate over pygraphviz.AGraph

Alternatively, you could use a graph created by the diagram extension. If you use the pygraphviz backend, you can iterate over all edges and nodes and get a similar result but with conditions:

from transitions.extensions import GraphMachine
from collections import defaultdict
from pygraphviz import AGraph
from pandas import DataFrame

states = ["A", "B", "C"]
transitions = [["go", "A", "B"], ["go", "B", "C"], ["reset", "*", "A"]]
data = defaultdict(lambda: defaultdict(lambda: "-"))
machine = GraphMachine(states=states, transitions=transitions, initial="A", show_auto_transitions=False,
                       show_conditions=True, graph_engine="pygraphviz")
machine.add_transition("go", "C", "B", conditions="is_it_friday")
machine.add_transition("go", "C", "A")
machine.add_transition("stop", "C", "C", unless="not_done")

graph: AGraph = machine.get_graph()
for source in states:
    for edge in graph.edges_iter(source):
        if edge[0] == source:
            data[source][edge[1]] = edge.attr["label"]

print(DataFrame([[data[source][dest] for dest in states] for source in states],
                columns=states, index=states))  # [3]

Pandas [3]

            A                  B                 C
A       reset                 go                 -
B       reset                  -                go
C  go | reset  go [is_it_friday]  stop [!not_done]

@abdolreza-sh
Copy link

Many thanks for the comprehensive answer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants