基本上,我的知识库中有关于PopStars及其最成功年份的一系列事实(见下文)。
popStar('Jackson',1987,1991).
popStar('Jackson',1992,1996).
popStar('Michaels',1996,2000).
popStar('Newcastle',2000,2007).
popStar('Bowie',2008,2010).
如果识别出popStar的名称,我需要创建一个带有单个参数的谓词,如果使用变量,它将产生回溯,没有任何重复。最初我开始时非常简单(见下文)。
ispopStar ().
ispopStar (H) :- popStar (H,_,_).
但后来发现任何回溯都会包括重复(杰克逊'提到过两次)。因此,希望使用findall / 3创建一个列表,然后使用member来检查popStar是否是有效的。
但是,每当我尝试使用我从事实中创建的列表中的成员谓词时,它总会导致一个不停止的,不断扩展的列表。我认为这很可能是一个菜鸟错误,因为我才开始学习prolog。如果有人可以查看我下面的代码并且可以看到我做错了什么,真的很感激。
感谢。
的FindAll / 3
findall(V,popStar(V,B,N),X)
结果
X = ['Jackson', 'Jackson', 'Michaels', 'Newcastle', 'Bowie']
成员/ 2
member('Newcastle',X).
结果
339 ?- member('Newcastle',X).
X = ['Newcastle'|_G2881] ;
X = [_G2880, 'Newcastle'|_G2884] ;
X = [_G2880, _G2883, 'Newcastle'|_G2887] ;
X = [_G2880, _G2883, _G2886, 'Newcastle'|_G2890] ;
X = [_G2880, _G2883, _G2886, _G2889, 'Newcastle'|_G2893]
更新
我玩过一次但仍然很困难。我使用下面的以下谓词来创建唯一条目列表;
setof(Name,X^Y^popStar(Name),Names)
然后使用以下谓词表示元素的存在(下面的例子)。
setof(Name,popStar(Name),Names), member('Jackson',Names).
从上面的谓词中,它返回一个值;
Names = ['Jackson'].
但实际上,我希望它能够恢复正常,因为'会员'证明特定元素是否在列表中。此外,当我尝试将变量插入成员(以便它回溯所有可用的popStars时,我收到以下消息)。
setof(Name,popStar(Name),Names), member(X,Names).
Names = ['$VAR'('X')].
通过向我展示在这个例子中做什么,真的很感激一些帮助。我真的被卡住了所以非常感激。
答案 0 :(得分:3)
您的方法还有其他更微妙的问题,但首先是明显的问题。
顶级的查询彼此之间不共享变量。每个新查询都有新变量,即使它们使用相同的名称!
?- X = foo.
X = foo.
?- X = bar.
X = bar.
?- X = 3.
X = 3.
?- X == 3.
false.
你需要制作一个连接的子目标!
?- L = [a,b,c,b], member(a, L).
L = [a, b, c, b] ;
false.
?- L = [a,b,c,b], member(b, L).
L = [a, b, c, b] ;
L = [a, b, c, b].
正如你所看到的,这仍然不是你所追求的....如果一个列表有一个元素出现两次,member/2
成功两次,这正是你不想要的。
您可以考虑使用memberchk/2
代替。如果您比较member/2
和memberchk/2
上的文档,您应该看到它们在语义和预期用途上的区别。简而言之,如果您已经有一个不包含任何变量的列表,并且您只想检查该列表是否包含某个元素,那么可以使用memberchk/2
:
?- L = [a,b,c,b], memberchk(a, L).
L = [a, b, c, b].
?- L = [a,b,c,b], memberchk(b, L).
L = [a, b, c, b].
如果memberchk/2
的两个参数中的任何一个都没有根据,那么这会变得更加毛茸茸。看看这个:
?- memberchk(X, [a,b,c]).
X = a. % No more solutions!
所以,这不是解决问题的好方法。
最好使用setof/3
代替findall/3
。为简化一点,假设您有一个表foo/1
,它看起来像上面示例中的列表:
?- listing(foo).
foo(a).
foo(b).
foo(c).
foo(b).
true.
?- findall(X, foo(X), Xs).
Xs = [a, b, c, b].
然后:
?- setof(X, foo(X), Xs), member(Y, Xs).
Xs = [a, b, c],
Y = a ;
Xs = [a, b, c],
Y = b ;
Xs = [a, b, c],
Y = c.
?- setof(X, foo(X), Xs), member(b, Xs).
Xs = [a, b, c] ;
false.
当你使用pop_star/3
时,你可能不得不告诉Prolog不要将第二个和第三个参数绑定到setof/3
,所以它会像setof(Name, X^Y^pop_star(Name, X, Y), Names)
一样。