考虑以下简单的程序:
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是如何一次生成一对的嵌套对结构的。然后第二个目标,即您的原始谓词,是为该对生成 a
和 b
的所有可能组合。然后 h/2 回溯到pairs/2 产生的下一个对。等等。
关于prolog - Prolog 中的析取之间交替,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37233110/