是否可以使用转换从 HierarchicalMachine 派生模型实例创建 HierarchicalGraphMachine

Is it possible to create HierarchicalGraphMachine from HierarchicalMachine derived model instance using transitions

我有一个模特class喜欢

class MyModel(HierarchicalMachine):
    Machine.__init__(self, states=self.states, transitions=self.transitions,  
                                                    initial='EstablishingWsConnection')
...

效果很好。

现在我想从我的模型创建一个 HierarchicalGraphMachine,例如

model = MyModel()
GraphMachine = mfact.get_predefined(graph=True, nested=True)  
grMachine =self.GraphMachine(                        
                    send_event=False, 
                    auto_transitions=False, 
                    title="BootNotificationStates",
                    show_conditions=True)  
hgm = HierarchicalGraphMachine(model, grMachine)

hgm.model.show_graph('mystate.png') 

结果 mystate.png

是否可以将我的模型实例重新用于绘图?

谢谢,

价值

GraphMachine 不是 mfact.get_predefined(graph=True, nested=True) 给你的。那将是 mfact.get_predefined(graph=True)。你这里所说的 GraphMachine 已经是 HierarchicalGraphMachine.

为了弄清楚这一点,您可以像下面的代码片段一样创建一个 HierarchicalGraphMachine

from transitions import Machine
from transitions.extensions import MachineFactory

myStates = ['walking', 'running']
myTransitions = [ { 'trigger': 'accelerate', 'source': 'walking', 'dest': 'running' } ]

graphNestedMachineClass = MachineFactory.get_predefined(
    graph=True, nested=True)
hierarchicalGraphMachine = graphNestedMachineClass(
    states=myStates, transitions=myTransitions, initial='walking')

如果您想在 HierarchicalGraphMachine 中嵌入任何类型的 Machine 并使用模型,您可以将以下代码添加到上述代码段中。

class MyModel(object):
    pass

myModel = MyModel()

moreStates = [
    'waiting',
    {'name': 'moving', 'children': hierarchicalGraphMachine }
]
moreTransitions = [
    { 'trigger': 'wait', 'source': '*', 'dest': 'waiting'},
    {'trigger': 'move', 'source': 'waiting', 'dest': 'moving_walking'}
]

parentHierarchicalGraphMachine = graphNestedMachineClass(
    model=myModel, states=moreStates, transitions=moreTransitions, initial='waiting')

现在您可以像这样在各州之间穿梭:

print myModel.state  # prints 'waiting'
myModel.move()
print myModel.state  # prints 'move_walking'
myModel.accelerate()
print myModel.state  # prints 'move_running'
myModel.wait()
print myModel.state  # prints 'waiting'

你可以使用例如myModel.graph.draw('mystate.png', prog='dot') 生成如下图所示的状态图。

有关详细信息,请考虑查看转换 factory.py 的源代码,位于转换存储库的 transition/extension 路径中。并且还可以在同一个存储库的顶级目录中查看非常好的 README.md

转换存储库可通过 GitHub 在 https://github.com/tyarkoni/transitions 获得。

As answer already states, the recommended solution is to nest your HierarchicalStateMachine into a HierarchicalGraphMachine. Right now transitions contains a bug 这会影响嵌套状态的解析方式。这就是为什么它看起来有点奇怪。这将很快得到解决!最终,这个:

解决方案 1:嵌套

from transitions.extensions import MachineFactory as factory

HSM = factory.get_predefined(nested=True)
GraphHSM = factory.get_predefined(nested=True, graph=True)

class MyModel(HSM):
    def __init__(self):
        self.states = ['A', 'B', 'C']
        self.transitions = [['go', 'A', 'B'],
                            ['go', 'B', 'C'],
                            ['go', 'C', 'A']]
        super(MyModel, self).__init__(self, states=self.states,       
                                      transitions=self.transitions,
                                      auto_transitions=False, initial='A')

mymodel = MyModel()

# define the nesting for the new machine
states = [{'name': 'mymodel', 'children': mymodel}]
# set the initial state to A of mymodel. Replace the underscore
# with the seperatore you are using
graph_machine = GraphHSM(states=states, auto_transitions=False,
                         title="Reused Machine", initial="mymodel_A")
graph_machine.graph.draw('reuse.png', prog='dot')

结果应该是这样的:

同样,这是推荐的方式。但是,如果您 真的 需要在新创建的机器的根级别拥有您的状态,您可以修补两台机器的内部结构,然后通过猴子补丁来获得荣耀。 transitions 在两个集合中管理它的中心部分:一个带有 states 的列表和一个带有 events 的字典(其中包含状态转换)。第二件要知道的事情是,转换将在有效时更新图形。 NestedTransition 类型的对象不知道该怎么做。所以这就是你可以做的:

解决方案 2:修补

# Create a new graph_machine which is initialized in mymodel's  state
graph_machine = GraphHSM(mymodel, title="Patched Machine",
                         states=[mymodel.state],
                         initial=mymodel.state)
# shallow copy the core parts to the new machine
graph_machine.events = mymodel.events
graph_machine.states = mymodel.states
# reinitialize the graph with the new configuration
mymodel.get_graph(force_new=True)

# 'upcast' the transitions to be of the type NestedGraphTransition
from transitions.extensions.factory import NestedGraphTransition
for event in mymodel.events.values():
    event.machine = graph_machine
    for lists in event.transitions.values():
        for transition in lists:
            transition.__class__ = NestedGraphTransition
# use the machine and test if the graph has been updated
mymodel.go()
mymodel.graph.draw('patching.png', prog='dot')

结果你会得到这个:

我不知道第二种解决方案的防弹性能如何,但我想把它留在这里作为 扩展 文档 transitions 如何操作...当然,我很好奇它是否真的有效;P.