Python过渡:如何将FSM的所有可能过渡映射到图形

时间:2017-11-07 08:20:22

标签: python graphviz transitions fsm pygraphviz

我无法在我的Windows 10系统上安装pygraphviz,因此我尝试将FSM的状态和转换存储在单独的图形中。例如:

from transitions import Machine
from graphviz import Digraph

class Matter(object):
    pass

# The states
states=['hungry', 'satisfied', 'full', 'sick']

# And some transitions between states. 
transitions = [
     { 'trigger': 'eat', 'source': 'hungry', 'dest': 'satisfied' },
     { 'trigger': 'eat', 'source': 'satisfied', 'dest': 'full' },
     { 'trigger': 'eat', 'source': 'full', 'dest': 'sick' },
     { 'trigger': 'rest', 'source': ['satisfied', 'full', 'sick'], 'dest': 
      'hungry' }]


# Initialize
machine = Matter()
fsm = Machine(machine, states=states, transitions=transitions, initial=states[0])
dot = Digraph(comment='FSM')

src = machine.state

for event in transitions:
    machine.trigger(event['trigger'])
    dst = machine.state
    dot.edge(src,dst,event['trigger'])
    src = dst

print (dot)

这里我的图表不包括所有可能的转换,仅包括顺序转换。

输出:

digraph {
    hungry -> satisfied [label=eat]
    satisfied -> full [label=eat]
    full -> sick [label=eat]
    sick -> hungry [label=rest]
}

如您所见,图中不存在多个状态转换。有没有办法可以触发所有过渡并将其存储在图表中,或者我是否必须为所有这些过程编写自定义代码。

1 个答案:

答案 0 :(得分:1)

transitions组织事件转换。 Event可能包含多个转换,再次在字典中组织。为了实现您的需求,首先迭代事件字典(键是触发器名称,值是Event本身)以获取事件。然后,迭代Event.transitions(键是源状态,值是适用的Transition对象列表)以获取转换列表。现在,遍历此列表以获取每个转换的源和目标。如果您愿意,可以使用触发器名称作为标签:

from transitions import Machine
from graphviz import Digraph


class Matter(object):
    pass


# The states
states = ['hungry', 'satisfied', 'full', 'sick']

# And some transitions between states.
transitions = [{'trigger': 'eat', 'source': 'hungry', 'dest': 'satisfied'},
               {'trigger': 'eat', 'source': 'satisfied', 'dest': 'full'},
               {'trigger': 'eat', 'source': 'full', 'dest': 'sick'},
               {'trigger': 'rest', 'source': ['satisfied', 'full', 'sick'],
                'dest': 'hungry'}]


# Initialize
machine = Matter()
fsm = Machine(machine, states=states, transitions=transitions, initial=states[0],
              auto_transitions=False)
dot = Digraph(comment='FSM')

for label, event in fsm.events.items():
    for event_transitions in event.transitions.values():
        for transition in event_transitions:
            dot.edge(transition.source, transition.dest, label)
print(dot)

输出:

// FSM
digraph {
    hungry -> satisfied [label=eat]
    satisfied -> full [label=eat]
    full -> sick [label=eat]
    satisfied -> hungry [label=rest]
    full -> hungry [label=rest]
    sick -> hungry [label=rest]
}

我还在auto_transitions=False添加了Machine。这种方式transitions不会生成自动转换(to_<state_name>),否则会使图形混乱。当然,您可以修改auto_transitions=True或尝试按照transitions'diagrams extension中的操作过滤图表中的自动转换。