【问题标题】:Using a self-created list in prolog在 prolog 中使用自创列表
【发布时间】:2014-06-13 14:00:19
【问题描述】:

我对 Prolog 很陌生,不要对我太苛刻。无论如何,我在 Prolog 中遇到了下一个问题:

我创建了一个小型演员“数据库”,由以下人员定义:

actor(ID, Name).

电影、演员、导演也是如此,定义者:

movie(ID,Name, Director, Category).
director(ID,Name).
cast(MovieID, ActorID).

现在我需要编写一个程序 people(Movie, List) 来定义电影名称与参与电影的所有人的姓名列表之间的关系 - 导演和演员(以任何顺序)。

所以我开始了:

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,[]).

所以上面的内容是回答给定列表是否在那部电影中扮演[或导演]。 [但它也有一个问题,因为不包含所有演员的列表仍然会得到“真实”。]

无论如何,我对我的解决方案进行了更多思考,并且我认为从逻辑上讲这不是解决该问题的完美方法[这就是我没有完成它的原因]。

我想过尝试另一种方法,而且是通过逻辑地问:我实际上需要回答什么?

而答案是:有没有一个名单,所以把电影中的演员名单加上导演[只有一个]就等于它了。

但现在我几乎被困住了。我如何在 Prolog 中使用自己创建的列表?获取演员列表很简单,只需这样做:

  cast(MovieID,_).

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

【问题讨论】:

    标签: prolog prolog-setof


    【解决方案1】:

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

    【讨论】:

    • 太棒了,你真的帮助我理解了。
    【解决方案2】:

    这样的事情应该做你想做的事:

    % 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 那样。它带有程序性思维的味道。

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

    【讨论】:

    • findall/3 和 !使您的定义使用起来非常脆弱。
    猜你喜欢
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多