在prolog中使用自创建的列表

时间:2014-06-13 14:00:19

标签: prolog prolog-setof

我对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,_).

但是我怎样才能使用函数定义的答案? [我甚至可以这样做吗?]或者我是否会尝试再次改变我的方法?

2 个答案:

答案 0 :(得分:3)

对于您的数据库,关系people(Move, Persons)不再是单调关系。对于,您是否会向actor/2cast/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)
      .