我对Prolog很新,不要对我太过刻薄。无论如何,我在Prolog中遇到了下一个问题:
我创建了一个小型的'数据库',由以下人员定义:
actor(ID, Name).
同样适用于电影,演员,导演,定义:
movie(ID,Name, Director, Category).
director(ID,Name).
cast(MovieID, ActorID).
现在我需要编写一个程序人(电影,列表)来定义电影名称和参与电影的所有人的名字列表之间的关系 - 导演和演员(以任何顺序)。
所以我开始:
people(Movie, List):-
movie(MovID,Movie,_,_,_), %Getting the movie ID.
helper(MovID,List).
% Either its a director.
helper(MovID,[Y|Ys]):-
director(DirID,Y),
movie(MovID,_,DirID,_,_),
helper(MovID,Ys).
% Or an actor
helper(MovID,[Y|Ys]):-
actor(ActID,Y),
cast(MovID,ActID),
helper(MovID,Ys).
% Finished when reached to an empty List.
helper(MovID,[]).
那么上面所做的就是回答一个给定的列表是否在该电影中扮演[或指挥]。 [但它也存在问题,因为一个不包含-all-的演员的名单仍然会'真'。]
无论如何,我想到了更多关于我的解决方案,而且我认为这在逻辑上不是解决这个问题的完美方法[这就是为什么我没有完成它]。
我想过尝试另一种方法,并且从逻辑上问:我实际需要回答什么?
答案是:是否有一个列表,以便在导演[只有一个]中附加电影中的演员列表等于它。
但现在我几乎陷入困境。如何在Prolog中使用自创列表?获取演员列表很简单,这样做:
cast(MovieID,_).
但是我怎样才能使用函数定义的答案? [我甚至可以这样做吗?]或者我是否会尝试再次改变我的方法?
答案 0 :(得分:3)
对于您的数据库,关系people(Move, Persons)
不再是单调关系。对于,您是否会向actor/2
和cast/2
添加事实,现在关系people/2
会成功获得更长且不同的人员列表。
因此,您可以使用helper/2
定义setof/3
。事实上,你需要setof/3
或其他一些非单调构造:
helper(MovID, Ys) :-
setof(Y, person_in(Y,MovID), Ys).
person_in(Y, MovID) :-
movie(MovID, _, DirID, _, _),
director(DirID, Y).
person_in(Y, MovID) :-
cast(MovID, ActID),
actor(ActID, Y).
或者,您可以将所有这些都放在一个大目标中。请注意,在这种情况下,必须声明所有存在变量:
helper(MovID, Ys) :-
setof(Y, Ex1^Ex2^Ex3^DirId^ActID^
( move(MovID,Ex1,DirID,Ex2,Ex3), director(DirId,Y)
; cast(MovID, ActID), actor(ActId, Y)
),
Ys).
很容易忘记一个或两个变量,因此您也可以使用library(lambda)
隐式处理这些变量。这对匿名变量特别有用:
helper(MovID, Ys) :-
setof(Y, {MovID,Y}+\
( move(MovID,_,DirID,_,_), director(DirId,Y)
; cast(MovID, ActID), actor(ActId, Y)
),
Ys).
答案 1 :(得分:0)
这样的事情应该做你想做的事情:
% movie_people/2 ----------------------------------
%
% finds all the people involved in a given movie:
% - look up the movie
% - look up the director
% - find all the actors involved in the film
%-------------------------------------------------
movie_people( Title , [directed_by(Director)|Actors] ) :-
movie(Id,Title,DirectorId,_) ,
director(DirectorId,Director) ,
findall( actor(Name) , movie_cast(Id,Name) , Actors )
.
% movie_cast ------------------------------------------------
%
% Enumerate the actors involved in a movie via backtracking.
%
%------------------------------------------------------------
movie_cast( MovieId , Name ) :-
cast(MovieID , ActorId ) ,
actor(ActorId,Name)
.
但是你的模型虽然使用了[推测数字] ID,但它看起来并不像Prolog-ish。它有程序性思维的气息。
Prolog中更典型的模型可能如下所示:
%----------------------------------------------------------------
% Title Actor Role
%----------------------------------------------------------------
cast( the_thin_man , william_powell , nick_charles ) .
cast( the_thin_man , myrna_loye , nora_charles ) .
cast( the_thin_man , maureen_o_sullivan , dorothy ) .
cast( the_thin_man , nat_pendleton , guild ) .
cast( the_thin_man , minna_gombell , mimi ) .
cast( the_thin_man , porter_hall , maccaulley ) .
cast( the_thin_man , henry_wadsworth , tommy ) .
cast( the_thin_man , william_henry , gilbertt ) .
cast( the_thin_man , harold_huber , nunheim ) .
cast( the_thin_man , cesar_romero , chris ) .
cast( the_thin_man , natalie_moorhead , julia_wolf ) .
cast( the_thin_man , edward_brophy , morelli ) .
cast( the_thin_man , edward_ellis , wynant ) .
cast( the_thin_man , cyril_thornton , tanner ) .
cast( wife_vs_secretary , clark_gable , van ) .
cast( wife_vs_secretary , jean_harlow , whitey ) .
cast( wife_vs_secretary , myrna_loy , linda ) .
cast( wife_vs_secretary , may_robson , mimi ) .
cast( wife_vs_secretary , george_barbier , underwood ) .
cast( wife_vs_secretary , james_stewart , dave ) .
cast( wife_vs_secretary , hobart_cavanaugh , joe ) .
cast( wife_vs_secretary , tom_dugan , finney ) .
cast( wife_vs_secretary , gilbert_emery , simpson ) .
cast( wife_vs_secretary , marjorie_gateson , eve_merritt ) .
cast( wife_vs_secretary , gloria_holden , joan_carstairs ) .
film( the_thin_man ) .
film( wife_vs_secretary ) .
category( the_thin_man , comedy ) .
category( the_thin_man , screwball_comedy ) .
category( the_thin_man , film_noir ) .
category( the_thin_man , mystery ) .
category( wife_vs_secretary , comedy ) .
category( wife_vs_secretary , drama ) .
category( wife_vs_secretary , romance ) .
directed_by( the_thin_man , w_s_van_dyke ) .
director_by( wife_vs_secretary , clarence_brown ) .
然后事情变得容易
演员是在电影中扮演的人
actor(X) :- cast(_,X,_) , ! .
导演是指导电影的人
director(X) :- directed_by(_,X) , ! .
查找特定演员扮演的所有电影:
films_of(X,Titles) :-
findall(Title,cast(Title,X,_),Titles) .
列出参与影片的人
movie_people( Title , Director , Cast ) :-
directed_by( Title , Director ) ,
findall(Actor,cast(Title,Actor,_),Actors)
.
等