谓词来获取遗漏的事实

时间:2014-05-13 11:51:56

标签: prolog

我有很多事实。

f(1, John).
f(2, Peter).
f(3, Gordon).
f(4, Bono).
f(5, Carl).
f(6, Mick).

check([], []) .
check([f(X, Y)|L1] , [f(X, Y)|L2] ) :-  f(X, Y), check(L1,L2).

如果我运行检查谓词

check([ f(1, John), f(3, Gordon), f(2, Peter), _, f(6, Mick), f(5, Carl)], Group).

应打印。

Group = [ f(1, John), f(3, Gordon), f(2, Peter), f(4, Bono), f(6, Mick), f(5, Carl)].

黑色空间充满了缺失的事实。但是我的程序正在打印。

Group = [ f(1, John), f(3, Gordon), f(2, Peter), f(1, John), f(6, Mick), f(5, Carl)].

它取得了第一个事实。如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

你混淆了两件事:回溯和迭代列表(通过尾递归)。

此外,您有"事实"数据库变量(JohnPeter等)当你真正想要原子时? (例如johnpeter,或者,如果您想要首都,'John''Peter')。你应该看到一堆"单例变量"如果您尝试编译此警告。除此之外,

查询

?- f(X, Y).

会通过回溯

给你
X = 1, Y = john;
X = 2, Y = peter

等等。

您编写的谓词check/2遍历您给出的谓词,每一步实际上做的是检查是否存在符合f(X, Y)的事实X您提供的{1}}和Y。 (同样,由于你的第二个参数目前是变量,这也不完全正确,但对于这个解释并不重要。)

由于f(1, John)是第一个定义的事实,因此这是匹配的事实。如果你回溯,你应该在同一地点看到所有其他事实。

但是你实际上想要达到的目标对我来说并不是很清楚。

编辑:

你想要达到的目标非常奇怪。你怎么知道你有多少空白?你必须知道所有事实才能知道。你是想对你的事实进行排列吗?

答案 1 :(得分:0)

这是在previous form of the question之前解决的。以下是该解决方案的简单改编:

f(1,john).
f(2,peter).
f(3,gordon).
f(4,bono).
f(5,carl).
f(6,mick).

check(L, C) :-
    check(L, [], C).

check([], _, []).
check([f(X,Name)|T], A, [f(X,Name)|C]) :-
    f(X, Name),
    \+ member(f(X, Name), A),
    check(T, [f(X,Name)|A], C).

这里的关键是你必须随身携带你到目前为止所发现的内容(A),因为每次向check发送新查询时,f的查询都会重新开始“并从数据库的开头搜索。这不是一个回溯。但是当我们检查成员身份并发现元素成员时,我们会回溯到f查询以获取下一个查询,直到我们找到一个不是该成员的成员。到目前为止我们累积的清单。

试运行:

| ?- check([f(1,john), f(3,gordon), f(2,peter), _, f(6,mick), f(5,carl)], Group).

Group = [f(1,john),f(3,gordon),f(2,peter),f(4,bono),f(6,mick),f(5,carl)] ? a

no
| ?-

如我链接的其他答案所示,此技术可以使用多个空白。

您也可以在没有“结果”列表参数的情况下执行此操作,并在原始列表中实例化自由变量:

check(L) :-
    check(L, []).

check([], _).
check([f(X,Name)|T], A) :-
    f(X, Name),
    \+ member(f(X, Name), A),
    check(T, [f(X,Name)|A]).

| ?- X = [f(1,john), _, f(2,peter), _, f(6,mick), f(5,carl)], check(X).

X = [f(1,john),f(3,gordon),f(2,peter),f(4,bono),f(6,mick),f(5,carl)] ? a

X = [f(1,john),f(4,bono),f(2,peter),f(3,gordon),f(6,mick),f(5,carl)]

(1 ms) no
| ?-

请注意,如果您想使用大小写的名称,可以将它们用单引号括起来,这样它们就是原子而不是变量。例如,f(1, 'John')