我有以下事实数据库:
actor(jonny, depp, gender(male)).
actor(bruce, willis, gender(male)).
...
movie(year(1999), title([american,beauty]), cast([actor(kevin, spacey), actor(annette,bening), actor(wes,bentley)])).
movie(year(2001), title([lord,of,the,rings]), cast([actor(orlando, bloom), actor(sean, bean)])).
...
我需要写一个prolog查询来回答问题what movies were released in or after 1999
我尝试了movie(Y, M, C), member(Y, [_|year]).
,但它只列出了数据库中的所有电影。如何更改它,以便只列出1999年或之后发布的电影?
答案 0 :(得分:2)
由于您可以使用库(列表)作为成员/ 2,您也可以使用库(clpfd):
?- use_module(library(clpfd)).
然后你可以查询:
?- Y#>=1999, movie(year(Y), M, C).
C = cast([actor(kevin,spacey),actor(annette,bening),actor(wes,bentley)]),
M = title([american,beauty]),
Y = 1999 ? ;
C = cast([actor(orlando,bloom),actor(sean,bean)]),
M = title([lord,of,the,rings]),
Y = 2001
当然,对于您的示例(年份> = 1999,数据库中只有两部电影),您还可以获得整个数据库作为答案。如果你在晚些时候尝试:
?- Y#>=2000, movie(year(Y), M, C).
C = cast([actor(orlando,bloom),actor(sean,bean)]),
M = title([lord,of,the,rings]),
Y = 2001
如果仔细查看原始查询?- movie(Y, M, C), member(Y, [_|year]).
,很明显为什么要获取整个数据库:您试图将自由变量Y
与匿名变量{{1}匹配总是成功。
如果另一方面你有一个匹配的年份列表而不是一年的时间来查找所有电影,会员/ 2确实是你查询的好选择:
_
请注意,变量?- member(Y,[1999,2000,2001]), movie(year(Y), M, C).
C = cast([actor(kevin,spacey),actor(annette,bening),actor(wes,bentley)]),
M = title([american,beauty]),
Y = 1999 ? ;
C = cast([actor(orlando,bloom),actor(sean,bean)]),
M = title([lord,of,the,rings]),
Y = 2001 ? ;
no
必须是术语Y
的一部分才能匹配年份或您使用的列表作为成员/ 2的第二个参数
必须包含year(Y)
形式的年份:
year(Y)
另请注意,在这些示例中,目标#> = / 2和成员/ 2出现在目标影片/ 3的前面。这两个目标都用作约束:在电影数据库中搜索匹配的年份而不是匹配所有电影,然后检查匹配的年份。首先放置廉价约束可能会产生很大的不同,例如当你想要查询的实际谓词产生无限多的结果时。