我试图了解我正在编写的程序在 AI 编程中反向和正向链接的最佳用途。谁能解释反向和正向链接的最理想用途?另外,你能举个例子吗?
2 回答
我对目前对“前向链接”和“后向链接”的理解做了一些研究。这带来了很多材料。这是一份简历。
首先是一个图表,部分基于:
- 关于逻辑、规则和逻辑编程之间关系的悲伤状态(罗伯特·科瓦尔斯基)
LHS
代表“左侧”,RHS
始终代表规则的“右侧”。
让我们将“基于规则的系统”(即基于规则进行本地计算的系统)分为三组,如下所示:
- 生产规则系统,包括老式的专家系统外壳,它们不是建立在逻辑原则上的,即“没有指导模型”。
- 逻辑规则系统,即基于逻辑形式主义的系统(通常是一阶逻辑的片段,经典的或直觉的)。这包括 Prolog。
- 重写规则系统,基于
LHS => RHS
重写规则重写一些工作内存的系统。
可能还有其他人。一组的特征可以在另一组中找到。一组系统可以部分或全部由另一组系统实现。重叠不仅是可能的,而且是确定的。
(遗憾的是,imgur 在 2020 年不接受 .svg,所以它是 .png)
- 绿色:前向链接
- 橙色:反向链接
- 黄色:序言
RuleML(一个组织)试图对现有的各种规则集进行 XML 化。他们将规则分类如下:
以上内容出现在Adrian Paschke的The RuleML Perspective on Reaction Rule Standards中。
因此,他们区分了“审议规则”和“反应规则”,这很合适。
第一个方框:“生产规则系统”
“生产规则系统”(PRS)的总体思路
- 有“
LHS->RHS
”规则和元规则,后者控制前者的应用。规则可以是“逻辑的”(类似于 Prolog Horn 子句),但它们不必如此! - PRS 有一个“工作记忆”,只要应用规则就会破坏性地改变它:可以在工作记忆中删除、添加或替换元素或事实。
- PRS 仅具有“操作语义”(它们由它们所做的定义)。
- PRS 没有“声明性语义”,这意味着没有正确的方法来推理规则集本身:它计算什么、它的固定点是什么(如果有的话)、它的不变量是什么、它是否终止等等。
- 更多功能:
- 使用局部可计算函数(即不是概率计算)对不确定性进行临时处理,如MYCIN中的模糊规则、Dempster-Shaefer 理论等。
- 强否定可以以特别的方式表达。
- 通常,不会执行僵局的回溯,必须明确实施。
- PRS 可以直接连接到其他系统:调用神经网络、调用优化器或 SAT Solver、调用传感器、调用 Prolog 等。
- 对解释和调试的特殊支持可能存在也可能不存在。
示例实现
- 古老的:
- 老式的“专家系统外壳”,通常用 LISP 编写。
- 1971 年的规划师,这是一种带有基本 (?) 前向和后向链接的语言。该语言的实现从未完成。
- 最初的 OPSx 系列,尤其是 OPS5,在其上运行R1/XCON(具有 2500 条规则的 VAX 系统配置器)。这实际上是一个前向链接实现。
- 最近的:
- CLIPS(用 C 编写):http ://www.clipsrules.net/
- Jess(用 Java 编写):https ://jess.sandia.gov/
- Drools(用“企业”Java 编写):https ://www.drools.org/
Drools 支持“向后链接”(究竟如何),但我不确定其他任何人是否支持,如果他们支持,它的外观如何)
PRS 中的“前向链接”
前向链接是 PRS“循环”的原始方法,也称为“识别-行为”循环或“数据驱动循环”,它表明了它的用途。事件-条件-动作架构是另一种常用的描述。
内部工作很简单:
- 规则
LHS
s 与工作记忆相匹配(由于RETE 算法,在每次工作记忆更新时都会发生这种情况)。 - 根据某些标准(例如优先级)选择匹配规则之一并
RHS
执行它。这种情况一直持续到不再LHS
匹配为止。
这个循环可以看作是命令式基于状态的语言的高级方法。
Robert Kowalski 指出,“前向链接”规则实际上是两种不同用途的结合:
前向链逻辑规则
这些规则将Modus Ponens反复应用于工作记忆并添加推断的事实。
例子:
“如果 X 是人,那么 X 就是凡人”
用途:
- 审议,细化陈述。
- 探索状态空间。
- 计划是否需要更多控制或空间非常宝贵(R1/XCON 是一个前向链接系统,我觉得这很令人惊讶。这显然是由于希望将资源使用保持在界限内)。
Fahiem Bacchus在使前向链接相关(1998)中写道:
前向链接规划器有两个特别有用的属性。首先,它们维护有关潜在计划生成的中间状态的完整信息。该信息可用于提供高效的搜索控制,包括域独立启发式控制和更有效的域相关控制……前向链接规划器的第二个优点是它们可以支持丰富的规划语言。例如,TLPlan 系统支持完整的 ADL 语言,包括函数和数值计算。数字和函数对于对实际规划领域的许多特征进行建模至关重要,尤其是资源和资源消耗。
以上有多少真正适用是有争议的。您始终可以编写后向链接规划器以保留更多信息或通过搜索策略选择模块对配置开放。
前向链接“反应规则”又名“刺激响应规则”
例子:
“如果你饿了,那就吃点东西”
刺激是“饥饿”(可以从传感器读取)。反应是“吃东西”(这可能意味着控制效应器)。有一个未说明的目标,即“不那么饿”,这是通过吃来实现的,但没有明确目标的审议阶段。
用途:
- 即时、非故意的代理控制:
LHS
可以是传感器输入,RHS
也可以是效应器输出。
PRS 中的“反向链接”
反向链接,也称为“目标导向搜索”,应用“目标减少规则”并运行“假设驱动循环”,这表明它的用途。
例子:
在以下情况下使用它:
- 您的问题看起来像一个“目标”,可以分解为“子目标”,可以单独解决。根据问题,这可能是不可能的。子目标有太多的相互依赖关系或太少的结构。
- 您需要按需“获取更多数据”。例如,您在
Y/N
正确分类对象之前询问用户问题,或者等价地,直到获得诊断为止。 - 当您需要计划、搜索或建立目标证明时。
可以将后向链接规则编码为前向链接规则作为编程练习。但是,应该选择最适合自己的问题的表示和计算方法。这就是为什么存在反向链接的原因。
第二个框:“逻辑规则系统”(LRS)
这些是基于一些底层逻辑的系统。系统的行为可以(至少一般地)独立于其实现来研究。
请参阅此概述:斯坦福哲学百科全书:自动推理。
我区分了“逻辑建模问题”系统和“逻辑编程”系统。两者被合并在 Prolog 的教科书中。简单的“逻辑问题”可以直接在 Prolog 中建模(即使用逻辑编程),因为语言“足够好”并且没有不匹配。但是,在某些时候,您需要专门的系统来完成您的任务,而这些系统可能与 Prolog 完全不同。有关示例,请参见Isabelle或Coq。
将自己限制为“逻辑编程”的 Prolog 系列系统:
LRS 中的“前向链接”
Prolog 系统本身不支持前向链接。
前向链逻辑规则
如果您想转发链式逻辑规则,您可以“在 Prolog 之上”编写自己的解释器。这是可能的,因为 Prolog 是通用编程语言。
这是逻辑规则前向链接的一个非常愚蠢的示例。当然,最好定义一种特定于领域的语言和适当的数据结构:
add_but_fail_if_exists(Fact,KB,[Fact|KB]) :- \+member(Fact,KB).
fwd_chain(KB,KBFinal,"forall x: man(x) -> mortal(x)") :-
member(man(X),KB),
add_but_fail_if_exists(mortal(X),KB,KB2),
!,
fwd_chain(KB2,KBFinal,_).
fwd_chain(KB,KBFinal,"forall x: man(x),woman(y),(married(x,y);married(y,x)) -> needles(y,x)") :-
member(man(X),KB),
member(woman(Y),KB),
(member(married(X,Y),KB);member(married(Y,X),KB)),
add_but_fail_if_exists(needles(Y,X),KB,KB2),
!,
fwd_chain(KB2,KBFinal,_).
fwd_chain(KB,KB,"nothing to deduce anymore").
rt(KBin,KBout) :- fwd_chain(KBin,KBout,_).
试试看:
?- rt([man(socrates),man(plato),woman(xanthippe),married(socrates,xanthippe)],KB).
KB = [needles(xanthippe, socrates), mortal(plato),
mortal(socrates), man(socrates), man(plato),
woman(xanthippe), married(socrates, xanthippe)].
已经研究了向 Prolog 添加有效前向链接的扩展,但它们似乎都已被放弃。我发现:
- 1989:向 Prolog 添加正向链接和真相维护(PDF) (Tom_Finin, Rich Fritzson, Dave Matuszek)
- 在 GitHub 上有一个积极的实现: Pfc - Prolog中的前向链接,以及SWI-Prolog 包,另请参阅此讨论。
- 1997: Efficient Support for Reactive Rules in Prolog (PDF) (Mauro Gaspari) ...作者谈到“反应式规则”,但显然是指“前向链式审议规则”。
- 1998 年:关于主动演绎数据库:Statelog 方法(Georg Lausen、Bertram Ludäscher、Wolfgang May)。
科瓦尔斯基写道:
“Zaniolo (LDL++?) 和 Statelog 使用带有框架公理的类似情况演算的表示,并将生产规则和事件-条件-动作规则简化为逻辑程序。两者都存在框架问题。”
前向链式反应规则
Prolog 并不是真正为“反应式规则”而设计的。有过一些尝试:
- LUPS : 一种用于更新逻辑程序的语言(1999) (Moniz Pereira, Halina Przymusinska, Teodor C. Przymusinski C)
“基于逻辑的生产系统”(LPS)是最近的并且相当有趣:
- 在溯因逻辑编程代理中集成逻辑编程和生产系统(Robert Kowalski,Fariba Sadri)
- 在 RR2009 上的演讲:在溯因逻辑编程代理中集成逻辑编程和生产系统
- LPS 网站
它定义了一种新语言,其中Observations导致Forward-Chaining和Backward-Chaining导致Acts。两个“孤岛”都通过溯因逻辑编程的完整性约束联系起来。
所以你可以像这样替换一个反应规则:
通过这样的东西,它有一个逻辑解释:
第三个框:“重写规则系统”(前向链接)
另请参阅:重写。
在这里,我只会提到CHR。它是一种前向链接系统,根据规则与匹配的工作存储器元素依次重写工作存储器中的元素,验证逻辑保护条件,如果逻辑保护条件成功,则删除/添加工作存储器元素。
CHR 可以理解为线性逻辑片段的应用(参见Hariolf Betz的“约束处理规则的统一分析基础” )。
SWI Prolog存在CHR 实现。它为 CHR 规则提供回溯能力,并且可以像任何其他 Prolog 目标一样调用 CHR 目标。
CHR的用法:
- 计算的通用模型(例如图灵机等)
- 自底向上解析。
- 类型检查。
- 约束逻辑编程中的约束传播。
- 任何你宁愿前向链(过程自下而上)而不是后向链(过程自上而下)的东西。
我发现从你的过程和目标开始很有用。
如果你的过程可以很容易地表达为试图通过满足子目标来满足一个目标,那么你应该考虑一个反向链接系统,比如 Prolog。这些系统通过处理可以满足目标的各种方式的规则以及应用这些方式的约束来工作。规则处理通过回溯搜索目标网络,以在满足目标的一种方式失败时尝试替代方案。
如果您的流程从一组已知信息开始并应用规则来添加信息,那么您应该考虑使用前向链接系统,例如 Ops5、CLIPS 或 JESS。这些语言将匹配应用于规则的左侧,并调用匹配成功的规则的右侧。工作记忆更好地被认为是“已知的”而不是“真实的事实”。工作记忆可以包含已知为真的信息、已知为假的信息、目标、子目标,甚至领域规则。如何使用这些信息取决于规则,而不是语言。对于这些语言来说,创造价值(推断事实)的规则、创造目标的规则、创造新领域知识的规则或改变状态的规则之间没有区别。
使用另一种方法实现其中一种方法相当容易。如果您拥有丰富的知识并希望做出贡献,但这需要以某些目标为指导,请继续使用带有规则的前向链接语言来跟踪目标。在反向链接语言中,您可以有目标来推断知识。
我建议您考虑编写规则来处理领域知识,而不是将您的领域知识直接编码到推理引擎处理的规则中。相反,工作记忆或基础子句可以包含您的领域知识,并且语言规则可以应用它们。通过在工作记忆中表示领域知识,您还可以编写规则来检查领域知识(验证数据、检查重叠范围、检查缺失值等),在规则之上添加逻辑系统(计算概率,置信值或真值)或通过提示用户输入来处理缺失值。