1

I've been experimenting with the HierarchicalGraphMachine class to help visualise the machine structures as I edit them.

from transitions.extensions import HierarchicalGraphMachine as Machine

count_states = ['1', '2', '3', 'done']
count_trans = [
    ['increase', '1', '2'],
    ['increase', '2', '3'],
    ['decrease', '3', '2'],
    ['decrease', '2', '1'],
    ['done', '3', 'done'],
    ['reset', '*', '1']
]
counter = Machine(states=count_states, transitions=count_trans, initial='1')

states = ['waiting', 'collecting', {'name': 'counting', 'children': counter, 'initial': '1'}]

transitions = [
    ['collect', '*', 'collecting'],
    ['wait', '*', 'waiting'],
    ['count', 'collecting', 'counting']
]

collector = Machine(states=states, transitions=transitions, initial='waiting')
collector.get_graph(show_roi=False).draw('count1.png', prog='dot')

This generates the expected graphic showing both the parent and nested states in full (I'm not yet authorised to upload the graphics). Is there a way to generate a the full parent state machine graphic without expanding the nested states? For example reducing the nested states to an empty box.

I've tried "show_roi=True", but this only shows the current transition event, and removes all other states.

4

1 回答 1

0

根据您使用的是pygraphviz(默认为 0.8.8 及之前的版本)还是graphviz后端,get_graph可能会返回pygraphiv.AGraph对象或自定义transitions.Graph. 一个AGraph更容易操作,而第二个基本上是点中的纯图形符号。但是,您可以根据需要对两者进行操作。例如,您可以从中过滤边和节点AGraph并重建它的“平面”版本:

# your code here ...

collector.collect()

graph = collector.get_graph()

# iterate over all edges; We know that parent and child states are connected
# with an underscore. We just collect the root element of each source
# and target element of each edge. Furthermore, we collect the edge color,
# and the label which is stored either in 'label', 'taillabel' or 'headlabel' 
new_edges = [(edge[0].split('_')[0],
              edge[1].split('_')[0],
              edge.attr['color'],
              edge.attr['label']
              or edge.attr['taillabel']
              or edge.attr['headlabel']) for edge in graph.edges()]

# States with children are noted as subgraphs. We collect their name and their
# current color.
new_nodes = [(sgraph.graph_attr['label'], sgraph.graph_attr['color'])
             for sgraph in graph.subgraphs()]
# We add all states that have no children and also do not contain an
# underscore in their name. An underscore would suggest that this node/state
# is a child/substate.
new_nodes += [(node.name, node.attr['color'])
              for node in graph.nodes() if '_' not in node.name]

# remove everything from the graph obeject
graph.clear()

# and add nodes and edges again
for name, color in new_nodes:
    graph.add_node(name, color=color)

for start, target, color, label in new_edges:
    if label:
        graph.add_edge(start, target, color=color, label=label)

graph.draw('agraph.png', prog='dot')

结果如下图:

HSM 图

您会看到,我还收集了边缘和节点颜色以可视化最后的过渡,但graph.clear()删除了所有“默认”样式属性。它们也可以被复制和恢复,或者我们只能删除节点、边和子图。这取决于您愿意与 (py)graphviz 混淆多少。

于 2021-06-30T22:12:12.593 回答