prolog - Prolog 中的析取之间交替

标签 prolog

考虑以下简单的程序:

h(n0).
h(p(A,N)) :- (A=a, h(N)) ; (A=b , h(N)).

查询:

1 ?- h(p(A,N)).
A = a,
N = n0 ;
A = a,
N = p(a, n0) ;
A = a,
N = p(a, p(a, n0)) ;
A = a,
N = p(a, p(a, p(a, n0))) ;
A = a,
N = p(a, p(a, p(a, p(a, n0)))) ;

...

由于第一个析取 [(A=a, h(N))] 产生无限数量的答案,因此它无法显示第二个析取 [(A=b , h(N))]。

问题是:

是否可以更改代码,以便在查询时在第一个析取的解决方案和第二个析取的解决方案之间交替?

最佳答案

为了获得 h/1 结果的公平列表,您可以使用辅助谓词,例如 h2/2,它包含两个目标:1) 谓词对/1,仅描述解决方案的结构,而不描述解决方案的结构。具体值:

pairs(n0).
pairs(p(A,N)) :-
   pairs(N).

并产生以下答案:

   ?- pairs(X).
X = n0 ? ;
X = p(_A,n0) ? ;
X = p(_A,p(_B,n0)) ? ;
X = p(_A,p(_B,p(_C,n0))) ? 
...

2) 你的谓词 h/1 作为第二个目标,描述变量 _A, _B, _C,... 实际上是什么:

h2(X) :-
   pairs(X),
   h(X).

如果您查询此谓词,您将获得所需的结果:

   ?- h2(X).
X = n0 ? ;
X = p(a,n0) ? ;
X = p(b,n0) ? ;
X = p(a,p(a,n0)) ? ;
X = p(a,p(b,n0)) ? ;
X = p(b,p(a,n0)) ? ;
X = p(b,p(b,n0)) ? ;
X = p(a,p(a,p(a,n0))) ? ;
...

请注意,第一个目标pairs/2是如何一次生成一对的嵌套对结构的。然后第二个目标,即您的原始谓词,是为该对生成 ab 的所有可能组合。然后 h/2 回溯到pairs/2 产生的下一个对。等等。

关于prolog - Prolog 中的析取之间交替,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37233110/

相关文章:

prolog - 在Prolog编程中制定一些特定的规则(if-then-else之类)

prolog - 序言中前n个数字的总和

prolog - 列出转换

prolog - 评估阶乘

prolog - Prolog 是否有像 Common Lisp 那样的条件和重启系统?

list - Prolog二进制列表问题

prolog - Prolog如何指定pair打印格式

list - Prolog 从列表元素对到新列表变大

list - 列表替换中的 Prolog 元素

prolog - 递归过程解释