Prolog程序的录音数据库

时间:2010-04-04 03:53:13

标签: list prolog

我有三种类型的事实:

album(code, artist, title, date).

songs(code, songlist).

musicians(code, list).

示例:

album(123, 'Rolling Stones', 'Beggars Banquet', 1968).

songs(123, ['Sympathy for the Devil', 'Street Fighting Man']).

musicians(123, [[vocals, 'Mick Jagger'], [guitar, 'Keith Richards', 'Brian Jones']].

我需要创建这4条规则:

在一起(X,Y)如果X和Y在同一张专辑中播放,则成功。

artistchain(X,Y)如果从X到Y存在一系列专辑,则会成功;                     两个音乐家通过'在一起'链接在链中。

角色(X,Y)如果X有角色Y(例如吉他),这就成功了。

歌曲(X,Y)如果艺术家X录制了歌曲Y,则成功。

任何帮助?

我无法提出太多但是我想出了角色(X,Y):

role(X,Y) :- prole(X,Y,musicians(_,W)).

prole(X,Y,[[Y|[X|T]]|Z]).
prole(X,Y,[[Y|[H|T]]|Z]) :- prole(X,Y,[[Y|T]|Z]).
prole(X,Y,[A|Z]) :- prole(X,Y,Z).

但这不起作用。如果我手动输入列表而不是音乐家(_,W),如[[1,2,3],[4,5,6]],它确实有效。

我是否有另一种方法可以将列表作为变量插入?

至于其他规则,我完全失败了。任何帮助都会非常感激。

2 个答案:

答案 0 :(得分:1)

你对Prolog有一种误解:在Prolog中回答一个目标与调用一个函数不同! 例如:你期望“角色(X,Y): - prole(X,Y,音乐家(_,W))。”执行时,“musicians(_,W)”将被评估,因为它是“prole”的参数。这不是Prolog的工作方式。在每一步中,它都尝试用存储的谓词统一目标,并且所有参数都被作为变量或基础术语处理。 正确的方法是:

role(X,Y) :- musicians(_, L), prole(X,Y,L).

第一个目标将L与音乐家列表统一起来,第二个目标找到角色(假设您的其余代码是正确的)。

答案 1 :(得分:0)

Little Bobby Tables是对的,你需要了解Prolog的声明风格。您的目标是提供一组与数据库中的事实相匹配的规则。

很简单,想象一下我有以下数据库

guitarist(keith).
guitarist(jim).
in_band('Rolling Stones', keith).
in_band('Rolling Stones', mick).

假设我想知道滚石乐队中谁是吉他手。我可以使用像这样的规则

stones_guitarist(X):-
     guitarist(X),
     in_band('Rolling Stones', X).

当一个规则中给出一个变量名(在这种情况下为X)时,它在规则期间保持其值,所以我们所说的是作为吉他手的X也必须是同一个X中的X.乐队名为“滚石乐队”。

您可以通过多种方式安排数据库。例如,如果音乐家的名字本身就是一个列表可能会更容易(例如[guitar,[keith,brian]])。

我希望歌曲(X,Y)的以下示例有所帮助。我正在使用Sicstus Prolog,所以导入列表库以获得'成员',但是如果你没有,那么你自己很容易做到。

:- use_module(library(lists)).
song(ARTIST,SONG):-
    album(CODE,ARTIST,_,_),
    songs(CODE,TRACKS),
    member(SONG,TRACKS).