pytransitions / transitions

A lightweight, object-oriented finite state machine implementation in Python with many extensions
MIT License
5.52k stars 525 forks source link

Support for parallel states? #371

Closed fkromer closed 4 years ago

fkromer commented 4 years ago

Does transitions support something equivalent to Qt for Python's Parallel States (exemplary graphical reprensentation)?

psheltz commented 4 years ago

I have been contemplating this question as well. Could we build a statechart like structure from HierarchicalGraphMachine and a new NestedState that establishes regions?

fkromer commented 4 years ago

I've tried some things using HierarchicalGraphMachine and NestedState without beeing successful. It seems like it's not possible to define several initial states as part of initial. And it seems like transitions is not able to handle states in parallel. Whenever I called machine.state I got one state only but expected several.

psheltz commented 4 years ago

I have not perused the tranisitions core to trace how initials and state transitions are handled. I imagine adding state chart like functionality would be non-trivial, since you have more book keeping on the states and transitions within each region.

I have looked as sismic, which is a full state chart library. Might work better for you if you are in a hurry.

fkromer commented 4 years ago

I have not perused the tranisitions core to trace how initials and state transitions are handled. I imagine adding state chart like functionality would be non-trivial, since you have more book keeping on the states and transitions within each region.

I agree.

I have looked as sismic, which is a full state chart library. Might work better for you if you are in a hurry.

I stumbled over sismic some time ago but it was not on my radar this time. It's a cool project cause you can define statecharts in YAML, load the model for execution into code, visualize and test the model easily. sismic supports parallel states. But I've a workaround already which works good enough for me. I created a class which inherits from HierarchicalGraphMachine, defined my states + transitions and added private instance variables to keep track of in which parallel states the class is. Add some rather complex conditions + unless + before/after callbacks to the mixture and you've your workaround :smile:

aleneum commented 4 years ago

Hi @fkromer,

as of version 0.8.0, transitions supports parallel states (see ReadMe.md for more details):

from transitions.extensions import HierarchicalMachine
states = ['A',
          {'name': 'B',
           'parallel': [
               {'name': '1', 'parallel': [
                   {'name': 'a', 'children': ['x', 'y', 'z'], 'initial': 'z'},
                   {'name': 'b', 'children': ['x', 'y', 'z'], 'initial': 'y'}
               ]},
               {'name': '2', 'children': ['a', 'b', 'c'], 'initial': 'a'},
           ]}]

m = HierarchicalMachine(states=states, initial='A')
assert m.is_A()
m.to_B()
assert [['B_1_a_z', 'B_1_b_y'], 'B_2_a'] == m.state
m.to_A()
assert 'A' == m.state

As this required some major changes in the codebase it should be considered experimental. If you have any feedback or bugs to report, feel free to open new issues.

fkromer commented 4 years ago

@aleneum Cool, thanks a lot!