自动更新事实的专家/规则引擎?
Posted
技术标签:
【中文标题】自动更新事实的专家/规则引擎?【英文标题】:Expert/Rule Engine that updates facts atomically? 【发布时间】:2013-12-24 09:58:03 【问题描述】:Atomically 可能不是正确的词。在对元胞自动机或神经网络进行建模时,通常您有两个系统状态副本。一个是当前状态,一个是您正在更新的下一步的状态。这确保了一致性,即在运行所有规则以确定下一步时,整个系统的状态保持不变。例如,如果您为一个细胞/神经元运行规则以确定下一步的状态,然后为下一个细胞运行规则,它是邻居,您希望将当前状态用作这些规则的输入相邻单元格的状态,而不是其更新状态。
这可能看起来效率低下,因为每个步骤都需要您在更新它们之前将所有当前步骤状态复制到下一步状态,但是这样做很重要,因为它可以像所有细胞/神经元一样准确地模拟系统实际上是同时处理的,因此规则/触发函数的所有输入都是当前状态。
在为专家系统设计规则时困扰我的事情是如何运行一条规则,更新一些应该触发其他规则运行的事实,并且您可能有 100 条规则排队等待运行以响应,但使用了显着性作为一种脆弱的方式来确保真正重要的人首先运行。随着这些规则的运行,系统会发生更多变化。事实的状态一直在变化,因此当您处理第 100 条规则时,系统的状态自从它真正响应第一个事实变化时被添加到队列以来已经发生了显着变化。它可能已经发生了如此巨大的变化,以至于规则没有机会在它真正应该有的时候对系统的原始状态做出反应。通常作为一种解决方法,您会仔细调整其显着性,但随后会将其他规则移至列表下方,您会遇到先有鸡还是先有蛋的问题。其他解决方法包括添加“处理标志”事实,作为锁定机制来抑制某些规则,直到其他规则处理。这些都感觉像是 hack,并导致规则包含超出核心域模型的标准。
如果您构建了一个非常复杂的系统来准确地建模问题,那么您确实希望将事实的更改暂存到一个单独的“更新”队列中,该队列在规则队列为空之前不会影响当前的事实。因此,假设您进行了一项事实更改,该更改填充了规则队列以运行 100 条规则。所有这些规则都会运行,但它们都不会更新当前事实列表中的事实,它们所做的任何更改都会排队到更改列表中,这样可以确保在当前批处理正在处理时没有其他规则被激活。处理完所有规则后,事实更改将立即应用于当前事实列表,然后触发更多规则被激活。冲洗重复。所以它变得很像神经网络或元胞自动机的处理方式。 针对不变的当前状态运行所有规则,队列更改,在运行所有规则后将更改应用到当前状态。
这种操作模式是专家系统学术界存在的概念吗?我想知道它是否有一个术语。
Drools 是否有能力以允许所有规则运行而不影响当前事实的方式运行,并且将事实更改单独排队,直到所有规则都运行?如果是,怎么写?我不希望你为我写代码,只是一些它叫什么的关键字或API中的关键字,一些帮助我搜索的起点。
是否有其他专家/规则引擎具有此功能?
请注意,在这种情况下,运行的订单规则不再重要,因为所有排队运行的规则都只会看到当前状态。因此,随着规则队列的运行和清除,没有一个规则可以看到其他规则所做的任何更改,因为它们都是针对当前的一组事实运行的。 因此顺序变得无关紧要,管理规则执行顺序的复杂性消失了。 所有事实更改都处于待处理状态,并且在所有规则都从队列中清除之前不会应用于当前状态。然后立即应用所有这些更改,从而导致相关规则再次排队。所以我的目标不是更好地控制规则运行的顺序,而是通过使用模拟同时规则执行的引擎来完全避免规则执行顺序的问题。
【问题讨论】:
您描述的内容在我看来更像是复杂事件处理。否则,如果您正在寻找更强大的机制来强制执行规则能够运行的顺序,那么 Drools 提供了诸如议程组之类的工具,但我更喜欢自己设计规则以在它们可以激活时强制执行。对于一个典型的模式,看看这里的“标记事实”:engage.redhat.com/forms/rule-design-patterns 理论上,拥有一个不知道 Drools 的核心域模型会很棒。尽管如此,在实践中,drools 可能变得如此复杂,以至于说你的域也是 drools 是有道理的(事实上:它是由规则驱动的,所以你可以决定在某些情况下可以考虑规则方式你的域)。我有很多事实可以确保我的规则以正确的顺序处理,这是我的业务逻辑的一部分。就个人而言,我更喜欢这种妥协,而不是严重依赖显着性(使用“神奇”数字)或议程组(如果它们是从 DRL 外部触发的,则具有隐藏的含义)。 感谢您的反馈。试图避免涉及管理规则执行顺序的变通方法,请参阅更新。我确实考虑使用标记事实来模拟同时执行,将所有新事实标记为“下一个”,并且所有规则都会排除这些事实。然后,具有最低优先级的最终规则将删除“下一个”标记。因此,只有在所有规则都已执行后,“下一个”事实才会被“应用”。我还必须以类似的方式处理更改和删除的事实,而不是实际删除它们,而是延迟删除,直到所有其他规则都运行为止。 【参考方案1】:如果我理解你的描述:
您有一个由许多规则管理的事实 每个规则都应该适用于你的事实的初始值,并且无权修改事实值(不修改其他规则的执行) 然后,您将根据规则对您的事实进行的所有更新进行批处理 其他规则以类似的方式“同时”应用于此新事实值在我看来,它是一种工作单元设计模式,就像 Hibernate 实现它一样(实际上还有许多 ORM):http://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern
基本上,您将所有更改(例如在“技术”事实中)存储在内存中,然后在基于初始值的所有规则都已触发以更新事实值时执行“事务”,依此类推. Hibernate 通过它的会话来做到这一点(你修改你附加的对象,然后在需要时它在数据库上执行更新查询,并不是对 java 对象的所有修改都会在你的数据库上产生查询)。
如果更新冲突(修改了相同的事实字段值,选择哪个值?与源版本控制冲突相同),您仍然会遇到麻烦,您将必须定义一种确定性的方式来订购更新,但它只会被定义一次可用于所有规则和其他更改,它将无缝运行。
【讨论】:
【参考方案2】:根据您相当模糊的描述,此工作可能会/可能不会起作用。如果您真的担心触发进一步激活的规则,为什么不自己排队中间状态。一旦当前评估完成,将这些新事实插入工作记忆中。
您必须在插入每个事实后调用fireAllRules()
,但这可能会非常昂贵。然后在规则中,而不是直接插入事实,将它们推入队列。一旦上面的调用返回,遍历队列做同样的事情(或者在完全插入原始事实之后......)
我想这会很慢,为了加快速度,你可以有多个具有相同规则的并行工作内存,并一次评估多个事实进入多个队列等。但事情变得非常棘手......
不管怎样,对于cmets来说只是一个太长的想法......
【讨论】:
以上是关于自动更新事实的专家/规则引擎?的主要内容,如果未能解决你的问题,请参考以下文章