prolog - 控制 Prolog 变量值选择

标签 prolog evaluation prolog-defaulty

灵感来自 an earlier question我试图实现一些可以枚举 bool 表达式可能性的东西。但是,我在变量选择方面遇到了麻烦。这是我的预期结果:

?- eval(X^Y, R).
R = 0^0;
R = 0^1;
R = 1^0;
R = 1^1;
no.

这是我的代码:

:- op(200, yfx, ^).

split(V, R) :- var(V), R = 0.
split(V, R) :- var(V), R = 1.
split(X ^ Y, XP ^ YP) :- split(X, XP), split(Y, YP).

即使对于这个简单的案例,这也没有达到我想要的效果:

?- split(Y, R).
R = 0 ;
R = 1 ;
Y = _G269^_G270,
R = 0^0 ;
Y = _G269^_G270,
R = 0^1 ;
Y = _G269^ (_G275^_G276),
R = 0^ (0^0) ;
Y = _G269^ (_G275^_G276),
R = 0^ (0^1) ;
Y = _G269^ (_G275^ (_G281^_G282)),
R = 0^ (0^ (0^0)) .

所以,我可以看出这里的问题是什么,在通过 split(Y, YP) 的过程中,Prolog 已经用完了前两个子句,所以它在 中结束split(X^Y, ...) 再次将我的 YX'^Y' 统一起来,本质上。我只是不确定我需要做什么来关闭这条路径,除了一开始我有结构 ^/2

我也希望它能处理嵌套结构,所以我不能只消除分支的递归处理。

编辑:没有运算符

如果 op/3 困扰您,请考虑以下公式:

eval(and(X,Y), R).
R = and(0,0);
R = and(0,1);
R = and(1,0);
R = and(1,1);
no.

这将是这种情况下的代码:

split(V, R) :- var(V), R = 0.
split(V, R) :- var(V), R = 1.
split(and(X,Y), and(XP,YP)) :- split(X, XP), split(Y, YP).

请记住,我仍然希望它能够使用递归公式,例如 and(and(X,Y),and(Y,Z)) 等。

最佳答案

主要问题:默认表示

本例中的核心问题是您用来表示 bool 表达式的默认表示

“默认”是指您无法通过模式匹配清楚地区分情况:在您的情况下,变量 V 可能表示任一个

  • 命题常数 01 之一,
  • A^B 形式的复合表达式。

由于这个缺点,您无法在程序中清晰地表达“变量 X 仅代表两个命题常数之一”形式的约束。


出路:清洁表示

声明式的出路是使用干净的表示代替

例如,假设我们任意使用v/1来区分只表示命题常数的变量,那么我们有:

  • v(X) 表示命题变量X
  • A^B 表示一个复合表达式

显然,由于主仿函数和元数不同(v/1(^)/2),我们可以仅通过模式匹配来区分情况。

有了这个新的表示,您的代码片段就变成了:

split(v(V), V) :- V = 0.
split(v(V), V) :- V = 1.
split(X^Y, XP ^ YP) :-
        split(X, XP),
        split(Y, YP).

示例查询:

?- split(v(X)^v(Y), R).
X = Y, Y = 0,
R = 0^0 ;
X = 0,
Y = 1,
R = 0^1 ;
X = 1,
Y = 0,
R = 1^0 ;
X = Y, Y = 1,
R = 1^1.

请注意,这仍然适用于所有方向,在最一般的情况中也是如此:

?- split(Expr, R).
Expr = v(0),
R = 0 ;
Expr = v(1),
R = 1 ;
Expr = v(0)^v(0),
R = 0^0 ;
Expr = v(0)^v(1),
R = 0^1 ;
etc.

根据经验,一旦您必须在代码中使用像 var/1 这样的逻辑外谓词,就很难保持其逻辑纯度和单调性。以干净的表示为目标以保留这些属性。

有时,使用默认表示是不可避免的,例如,因为您想让用户更轻松地输入。在这种情况下,目标是在开始实际推理之前快速将它们转换为干净的。

关于prolog - 控制 Prolog 变量值选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41621414/

相关文章:

prolog - 在 Prolog 中使用广度优先搜索 (BFS) 解决食人族/传教士问题?

Prolog 删除一个元素到给定列表中

evaluation - 按名称调用与通过宏扩展调用

Prolog - 替换和评估

prolog - 将结果标记为列表?

algorithm - Prolog中信息检索的性能优化

math - 我如何评估对数字的整合?

performance - 为什么严格长度函数的执行速度明显更快?

Prolog:如何做 "check(a++b++c++d equals d++a++c++b) -> yes"