1

我正在使用 Python 的转换库,我发现它非常有用。在我的特定情况下,我使用 FSM 在状态内(在回调中)做出决策,并相应地根据内部逻辑调用新的转换。例如:

states = ["Begin", "CheckCondition", "MakeA", "MakeB", "End"]

transitions = [
    ["proceed", "Begin", "CheckCondition"],
    ["path_a", "CheckCondition", "MakeA"],
    ["path_b", "CheckCondition", "MakeB"],
    ["proceed", "MakeA", "End"],
    ["proceed", "MakeB", "End"]
]

class MyModel:
    def __str__(self):
        return f">>>>> STATE: {self.state}"

    def on_enter_CheckCondition(self):
        if random.randint(1, 10) > 5:
            self.path_a()
            return
        else:
            self.path_b()
            return

my_model = MyModel()

machine = HierarchicalGraphMachine(
    model=my_model,
    states=states,
    transitions=transitions,
    initial="Begin",
    ignore_invalid_triggers=False
)

while my_model.state != "End":
    my_model.proceed()

这种方法将所有逻辑保留在 FSM 中,这正是我想要的,但有两个缺点:

  • 我可能有一个无限的调用链,这会导致堆栈溢出(只有proceed()转换,while循环调用,会中断它)
  • 我必须记住return在从回调调用任何转换后手动调用

有没有更好的方法来使用转换库来实现我想要的(从回调调用转换)?

感谢帮助!

4

2 回答 2

1

transitions支持条件转换,您可以将有效性检查作为对该转换的回调传递。通过提供具有不同条件的转换列表,您可以很容易地对替代路径进行建模。请注意,转换是按照它们添加的顺序进行评估的。对于您的示例,这意味着您可以按以下方式编写它:

from transitions import Machine
import random

# we do not need 'CheckConditions' when using 'conditions' in transitions
states = ["Begin", "MakeA", "MakeB", "End"]

transitions = [
    # when 'proceed' is triggered, 'is_larger_than_5' will be evaluated. The transition is only
    # conducted when it evaluates to True.
    {"trigger": "proceed", "source": "Begin", "dest": "MakeA", "conditions": ["is_larger_than_5"]},
    # This one would be evaluated next. You could add as many checks and paths as you like.
    # {"trigger": "proceed", "source": "Begin", "dest": "MakeX", "conditions": ["condition_check"]},
    # Otherwise this transition is executed. Since it has no 'conditions' it acts as an 'else' clause.
    {"trigger": "proceed", "source": "Begin", "dest": "MakeB"},
    # You can specify multiple sources for each transition.
    ["proceed", ["MakeA", "MakeB"], "End"],
]


class MyModel:
    def __str__(self):
        return f">>>>> STATE: {self.state}"

    # our condition
    @staticmethod
    def is_larger_than_5():
        return random.randint(1, 10) > 5


my_model = MyModel()

machine = Machine(
    model=my_model,
    states=states,
    transitions=transitions,
    initial="Begin",
    ignore_invalid_triggers=False
)

while my_model.state != "End":
    my_model.proceed()
    print(my_model)

这将返回:

>>>>> STATE: MakeB
>>>>> STATE: End

或者:

>>>>> STATE: MakeA
>>>>> STATE: End
于 2021-09-03T10:28:59.550 回答
0

Transitions 支持条件转换,您可以将有效性检查作为回调传递给该转换。通过提供具有不同情况的转换列表,您可以轻松地对各种路径进行建模。转换按照它们添加的顺序进行评估。

于 2021-09-03T10:35:51.833 回答