如何在状态机中做出决定

时间:2019-09-03 19:32:49

标签: python transition state-machine

我正在基于transitions构建状态机,但可能是一个通用的状态机问题。我正在努力建立一个简单的决策树。

简化的状态机应该看起来像

[state:new] --- generateXYZ ---> [state:generation_successful]
                            ---> [state:generation_failed]

我知道我可以创建两个过渡并对其进行保护,但这并不是理想的解决方案-也许您在那个过渡上纠正了我。

理想情况下,我想运行一些代码,它要么返回true(=成功),要么返回false(= failed)。

期待任何建议,也许我是从错误的角度来看待这个问题。谢谢!

1 个答案:

答案 0 :(得分:0)

欢迎堆栈溢出!

  

建立一个简单的决策树。

我认为您对generating状态不感兴趣。如果生成可能要花一些时间,那么在状态为“忙”的情况下,添加这种状态可能有助于调整模型/机器的行为。

  

我知道我可以创建两个过渡并对其进行保护

我猜最终两个不同的目的地必须导致两次转换。但是,使用transitions时,您可以在过渡定义中使用conditions,还可以包装过渡创建内容,以提供更多便利。我用GraphMachine来说明结果:

from transitions.extensions.diagrams import GraphMachine as Machine
import random


class Model:

    def __init__(self):
        self.machine = Machine(self, states=['A', 'B', 'C', 'D', 'AF', 'BF', 'F'], initial='A', show_conditions=True)
        # decision trees are easier to read top to bottom
        # configure graphviz accordingly 
        self.machine.machine_attributes['rankdir'] = 'TB'
        self._generated = False

    def add_decision(self, trigger, source, execute, check, on_success, on_fail):
        # this transition will be evaluated first, when execute returns true it will be used
        self.machine.add_transition(trigger, source, on_success, prepare=execute, conditions=check)
        # if this transition is evaluated, we know that a) execute has been called and b) it returned False
        # thus, we could omit 'unless'
        self.machine.add_transition(trigger, source, on_fail, unless=check)

    def generate(self):
        self._generated = bool(random.getrandbits(1))  # returns True of False randomly

    def generated(self):
        return self._generated


model = Model()
model.add_decision('execute', 'A', execute='generate', check='generated', on_success='B', on_fail='AF')
model.add_decision('execute', 'B', execute='generate', check='generated', on_success='C', on_fail='BF')
model.add_decision('execute', 'AF', execute='generate', check='generated', on_success='C', on_fail='F')
model.add_decision('execute', 'C', execute='generate', check='generated', on_success='D', on_fail='F')

# call execute twice
model.execute()
model.execute()

# let's see where we ended up
model.get_graph().draw('graph.png', prog='dot')

这将导致如下结果:

State Machine Graph

就我而言,生成在第一次运行中成功,而在第二次运行中失败。您可以通过以下方式精简此代码:a)不使用GraphMachine,b)使generate返回FalseTrue并将其直接传递给条件:

# ... Model.add_decision
        self.machine.add_transition(trigger, source, on_success, conditions=execute)
        self.machine.add_transition(trigger, source, on_fail)
# ...
    def generate(self):
        return bool(random.getrandbits(1))  # returns True of False randomly
# ...
model.add_decision('execute', 'A', execute='generate', on_success='B', on_fail='AF')

代码和图形的易懂性可能会受到影响。