如何在状态机中做出决定

How to take decision in a state-machine

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

简化的状态机应该是这样的

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

我知道我可以创建两个转换并保护它们,但这并不是理想的解决方案 - 也许你会纠正我的那个。

理想情况下,我想 运行 一些代码,它返回真(=成功)或假(=失败)。

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

欢迎来到 Stack Overflow!

build a simple decision tree.

我假设您对 generating 状态不感兴趣。如果生成可能需要一段时间,添加这样的状态可能有助于调整 model/machine 行为,以防它是 'busy'.

I understand that I could create two transitions and guard them

我猜最终两个不同的目的地必须导致两个转换。但是,使用 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')

这将导致如下结果:

在我的例子中,生成在第一个 运行 中成功,在第二个 运行 中失败。您可以通过 a) 不使用 GraphMachine、b) 使 generate return 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')

代码和图形的可理解性可能会受到影响。