是否可以将布尔表达式表示为有限状态机,以便FSM接受与布尔表达式匹配的输入?
是否有可能合并多个此类FSM,并在接受时,知道哪个原始FSM匹配?
背景:我正在尝试一次评估很多布尔表达式。我认为用正确的表示法,也许DFA可以超级有效地做到这一点(即优于O(n),其中n =表达式数。)
答案 0 :(得分:0)
我知道这是一个非常老的问题,但我确实发现自己处于类似情况,并且我认为在某些情况下,FSM可能会为复杂的布尔逻辑提供帮助。
我在blog post of mine中概述了一个示例,其中描述了在遍历(循环)简单字符串的令牌时使用状态机的情况。
在这种情况下的优点是,解析过程中的每个令牌都没有专用的布尔标志,而语法树中的其他路径需要防范,我可以将每个令牌作为事件提供给FSM并让机器陷入不同的状态。在处理状态时,我使用Statechart操作来构建少量操作码,然后最终根据最终状态放弃或继续编译生成的操作码。
您必须阅读这篇文章,才能获得我上面所说的内容。但要点是,在某些情况下,可以将一系列布尔值转换为事件名称,然后传递给FSM进行处理。在另一个示例中,我不得不根据一组压倒性的布尔逻辑来选择需要呈现的UI状态。
由于某些标志优先于其他标志,因此生成的逻辑树如下所示:
图1 —示例UML活动图
产生的代码看起来像这样:
图2 —复杂的布尔逻辑代码let presenterFlags = {
showSpecialTypeTab: model.type === 'special',
showDefaultWarning: (model.type === 'special' && model.isDefault && !settings.enforced),
showDefaultInBrokenStateWarning: (model.type === 'special' && model.isDefault && settings.enforce),
disableSaveButton: (model.type === 'special' && model.isDefault && !settings.enforce) || !model.canWrite,
disableCancelButton: (model.type === 'special' && model.isDefault && !settings.enforce) || !model.canWrite,
disableDeleteButton: (model.type === 'special' && model.isDefault) || !model.canWrite,
disableEnforcementToggle: (model.type === 'special' && model.isDefault && !settings.enforced) || !model.canWrite,
disableAnotherToggle: (model.type === 'special' && model.isDefault) || !model.canWrite,
};
对我来说,我的大脑承受不了太多。因此,我依靠使用FSM生成了如下状态图:
图3 —示例UML状态图
使用XState的代码可能看起来像这样:
图4 — XState机器示例let booleanMachine = Machine({
id: 'ExamplePresentationFlags',
strict: true,
initial: 'conditional',
context: {},
states: {
conditional: {
on: {
'EVALUATE': [
{ target: 'SpecialExample', cond: 'isSpecialExample' },
{ target: 'GenaricExample' },
],
},
},
GenaricExample: {
initial: 'conditional',
states: {
conditional: {
on: {
'': [
{ target: 'ReadOnly', cond: 'canNotWrite' },
{ target: 'Default', cond: 'isDefault' },
{ target: 'Writable' },
],
},
},
Writable: {},
Default: {},
ReadOnly: {
meta: {
disableSaveButton: true,
disableCancelButton: true,
disableDeleteButton: true,
},
},
},
},
SpecialExample: {
initial: 'conditional',
meta: { showSpecialTypeTab: true },
states: {
conditional: {
on: {
'': [
{ target: 'ReadOnly', cond: 'canNotWrite' },
{ target: 'Default', cond: 'isDefault' },
{ target: 'Writable' },
],
},
},
Writable: {},
ReadOnly: {
meta: {
disableSaveButton: true,
disableCancelButton: true,
disableDeleteButton: true,
disableAnotherToggle: true,
},
},
Default: {
initial: 'conditional',
states: {
conditional: {
on: {
'': [
{ target: 'Enforced', cond: 'isEnforced' },
{ target: 'Unenforced' },
],
},
},
Unenforced: {
meta: {
exampleWarning: 'default-read-only',
disableSaveButton: true,
disableCancelButton: true,
disableDeleteButton: true,
disableAnotherToggle: true,
},
},
Enforced: {
meta: {
exampleWarning: 'special-default-broken-enforce-state',
disableSaveButton: false,
disableCancelButton: false,
disableDeleteButton: true,
disableAnotherToggle: true,
},
},
},
},
},
},
},
}, {
guards: {
isSpecialExample: (ctx) => ctx.exampleType === 'special',
canNotWrite: (ctx) => !ctx.canWrite,
isEnforced: (ctx) => ctx.isEnforced,
isDefault: (ctx) => ctx.isDefault,
isNotDefault: (ctx) => !ctx.isDefault,
},
});
具有类似reducer的功能:
图5 — XState reducer函数示例function presentorFlags({ canWrite, model, settings }) {
let machine = booleanMachine.withContext({
canWrite,
exampleType: model.type,
isEnforced: settings.enforced,
isDefault: model.isDefault,
});
let { meta } = machine.transition(machine.initialState, 'EVALUATE');
return Object.keys(meta)
.reduce((acc, key) => ({ ...acc, ...meta[key] }), {});
}
理解我同意这个例子是非常规的,而且也更大。它的确为我提供了理解逻辑的能力,尤其是借助手头的可视化工具(即图3)。当时,它使我可以概念化所有边缘情况状态,而不必担心就视图代码而言,UI的每个状态意味着什么。相反,我可以专注于状态本身以及什么逻辑可使计算机进入该状态。然后,我给了reducer实际的布尔值,然后让机器完成了工作。我得到的只是一组易于放置在模板中的UI标志。
再次,也许这不是更好,或者也许是。关键是使用状态机来表达布尔逻辑是可能的。