我正在使用跃迁,并发现需要有几个与其他状态无关的状态,使用非确定性状态机进行建模非常有意义,这在数学上是等价的。
我想要以下的东西
from transitions import Machine
from transitions import EventData
class Matter(object):
def __init__(self):
transitions1 = [
{'trigger': 'heat', 'source': 'solid', 'dest': 'liquid'},
{'trigger': 'heat', 'source': 'liquid', 'dest': 'gas'},
{'trigger': 'cool', 'source': 'gas', 'dest': 'liquid'},
{'trigger': 'cool', 'source': 'liquid', 'dest': 'solid'}
]
transitions2 = [
{'trigger': 'turn_on', 'source': 'off', 'dest': 'on'},
{'trigger': 'turn_off', 'source': 'on', 'dest': 'off'},
]
self.machine = Machine(
model=self,
states=[['solid', 'liquid', 'gas'], ['on', 'off']],
transitions=[transitions1, transitions2],
initial=['solid', 'off'],
send_event=True
)
def on_enter_gas(self, event: EventData):
print(f"entering gas from {event.transition.source}")
def on_enter_liquid(self, event: EventData):
print(f"entering liquid from {event.transition.source}")
def on_enter_solid(self, event: EventData):
print(f"entering solid from {event.transition.source}")
def on_enter_on(self, event: EventData):
print(f"entering on from {event.transition.source}")
def on_enter_off(self, event: EventData):
print(f"entering off from {event.transition.source}")我可以定义一个新的状态集为states=itertools.product(states1, states2),然后定义所有的转换,如等价定理所示。
我想知道库中是否支持这种行为,如果是的话,如何实现它。
我有超过2组(大部分)独立国家。真的,我有一堆开关偶尔有互动,但大多是独立的。
发布于 2021-07-12 08:42:48
..。拥有几个与其他状态无关的状态,并且使用非确定性状态机进行建模非常有意义。
对我来说,这听起来像是你要寻找的不一定是非决定论,而是分级/复合状态和并发/并行。
您可以使用转换层次状态机扩展,该扩展还具有并发性:
from transitions.extensions import HierarchicalMachine
states1 = ['solid', 'liquid', 'gas']
states2 = ['on', 'off']
transitions1 = [
{'trigger': 'heat', 'source': 'solid', 'dest': 'liquid'},
{'trigger': 'heat', 'source': 'liquid', 'dest': 'gas'},
{'trigger': 'cool', 'source': 'gas', 'dest': 'liquid'},
{'trigger': 'cool', 'source': 'liquid', 'dest': 'solid'}
]
transitions2 = [
{'trigger': 'turn_on', 'source': 'off', 'dest': 'on'},
{'trigger': 'turn_off', 'source': 'on', 'dest': 'off'},
]
combined_states = [
{"name": "running", "parallel":
[
dict(name="component1", states=states1, transitions=transitions1, initial=states1[0]),
dict(name="component2", states=states2, transitions=transitions2, initial=states2[0])
]
}
]
m = HierarchicalMachine(states=combined_states, auto_transitions=False, initial="running")
print(m.state) # >>> ['running_component1_solid', 'running_component2_on']
m.turn_off()
print(m.state) # >>> ['running_component1_solid', 'running_component2_off']然而,HSM比简单的Machines要复杂得多。文档提到了考虑命名约定和嵌套/初始化配置需要遵循的几个限制。
这就是为什么我通常试图为我的FSM架构找到最简单的解决方案。现在,您的嵌套是相当平坦的,它也可以通过一组模型和Machines来实现。转换的“规则簿”方法使得在不同状态下仅使用一台机器管理多个模型和它的“分派”方法相当容易:
from transitions import Machine
class Model:
pass
class MultiMachine(Machine):
def __init__(self, configurations):
# Initialize the machine blank, no states, no transitions and
# no initial states. Disable auto_transitions since there shouldn't
# be the possibility to transition e.g. from 'on' to 'liquid'.
# Furthermore, ignore_invalid_triggers so that events not considered
# by a model will not throw an exception.
super().__init__(model=None, states=[], transitions=[], initial=None, auto_transitions=False,
ignore_invalid_triggers=True)
# create a model for each configuration
for states, transitions, initial in configurations:
self.add_states(states)
self.add_transitions(transitions)
self.add_model(Model(), initial=initial)
@property
def state(self):
return [model.state for model in self.models]
m = MultiMachine([(states1, transitions1, 'solid'), (states2, transitions2, 'off')])
assert m.state == ['solid', 'off']
m.dispatch("turn_on")
assert m.state == ['solid', 'on']
m.dispatch("heat")
assert m.state == ['liquid', 'on']根据你的评论:
如何根据另一个子机中的状态在一个子计算机中添加一个条件转换?例如,热只应使固体变成气体的情况下?HSMs,也许在这种情况下更好。
这可以通过仅在源状态on_*上定义on_*事件来用HSM来解决。然而,如果有许多这些因变量,嵌套就会变得相当复杂。相反,可以将对另一台机器的is_<state>方便函数的引用添加到所有相关转换的条件列表中。这可以在初始化之后完成,如果引导是一个问题:
from transitions import Machine
from transitions.core import Condition
states1 = ['solid', 'liquid', 'gas']
states2 = ['off', 'on']
m1 = Machine(states=states1, initial=states1[0],
transitions=[{'trigger': 'heat', 'source': 'solid', 'dest': 'liquid'},
{'trigger': 'heat', 'source': 'liquid', 'dest': 'gas'},
{'trigger': 'cool', 'source': 'gas', 'dest': 'liquid'},
{'trigger': 'cool', 'source': 'liquid', 'dest': 'solid'}])
m2 = Machine(states=states2, initial=states2[0],
transitions=[{'trigger': 'turn_on', 'source': 'off', 'dest': 'on'},
{'trigger': 'turn_off', 'source': 'on', 'dest': 'off'}])
# get all heat transitions and add the condition that they may only be valid when m2.is_on returns True
for trans in m1.get_transitions("heat"):
trans.conditions.append(Condition(func=m2.is_on))
# if you want to add an 'unless' statement pass `target=False`
# to the condition. e.g. "heat unless m2 is off"
# trans.conditions.append(Condition(func=m2.is_off, target=False))
assert m1.is_solid()
assert m2.is_off()
assert not m1.heat()
assert m1.is_solid()
assert m2.turn_on()
assert m1.heat()
assert m1.is_liquid()https://stackoverflow.com/questions/68336228
复制相似问题