views:

118

answers:

2

I have three types of facts:

album(code, artist, title, date).

songs(code, songlist).

musicians(code, list).

Example:

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']].

I need to create these 4 rules:

together(X,Y) This succeeds if X and Y have played on the same album.

artistchain(X,Y) This succeeds if a chain of albums exists from X to Y; two musicians are linked in the chain by 'together'.

role(X,Y) This succeeds if X had role Y (e.g. guitar) ever.

song(X,Y) This succeeds if artist X recorded song Y.

Any help?

I haven't been able to come up with much but for role(X,Y) I came up with:

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).

But that doesn't work. It does work if I manually put in a list instead of musicians(_,W) like [[1,2,3],[4,5,6]].

Is there another way for me to insert the list as a variable?

As for the other rules I'm at a complete loss. Any help would really be appreciated.

+1  A: 

You have a misconception about Prolog: Answering a goal in Prolog is not the same as calling a function! E.g.: You expect that when "role(X,Y) :- prole(X,Y,musicians(_,W))." is executed, "musicians(_,W)" will be evaluated, because it is an argument to "prole". This is not how Prolog works. At each step, it attempts to unify the goal with a stored predicate, and all arguments are treaded either as variables or grounded terms. The correct way to do it is:

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

The first goal unifies L with a list of musicians, and the second goal finds the role (assuming that the rest of your code is correct).

Little Bobby Tables
A: 

Little Bobby Tables is right, you need to understand the declarative style of Prolog. Your aim is to provide a set of rules that will match against the set of facts in the database.

Very simply, imagine that I have the following database

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

Supposed I want to find out who is both a guitarist and in the Rolling Stones. I could use a rule like this

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

When a variable name is given within a rule (in this case X) it holds its value during the rule, so what we're saying is that the X which is a guitarist must also be the same X that is in a band called 'Rolling Stones'.

There are lots of possible ways for you to arrange the database. For example it might be easier if the names of the musicians were themselves a list (e.g. [guitar,[keith,brian]]).

I hope the following example for song(X,Y) is of some help. I'm using Sicstus Prolog so import the lists library to get 'member', but if you don't have that it's fairly easy to make it yourself.

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