在 prolog 中使用自创建列表 [英] Using a self-created list in prolog

查看:42
本文介绍了在 prolog 中使用自创建列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm pretty new to Prolog, Don't be too hard on me. Anyhow, I've got the next problem in Prolog:

我创建了一个小型的演员数据库",定义为:

I've created a small 'database' of actors, defined by:

actor(ID, Name).

电影、演员、导演也是如此,由以下定义:

Same goes for movies,cast,Director, Defined by:

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

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

Now i need to Write a procedure people(Movie, List) that defines the relation between movie name and list of names of all people participated in the movie - director and actors (in any order).

所以我已经开始了:

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- 的列表,演员仍然会得到 'true'.]

So what the above does is answering whether a given list is acting [or Directing] in that movie. [But it has a problem as well, Since a list which doesn't contain -all- the actors will still get 'true'.]

无论如何,我对我的解决方案思考了更多,而且我认为这在逻辑上不是解决这个问题的完美方法[这就是我没有完成它的原因].

Anyhow, I thought a bit more about my solution, And I think that it's logically not the perfect approach to that question [That's why i didn't finish it].

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

I thought about trying another approach, And it's by logically asking: What do i actually need to answer about?

答案是:是否有一个列表,以便将电影中的演员列表与导演 [只有一个] 相同.

And the answer is: Is there a list so that appending the list of actors in the movie with the director [There's only one] equals to it.

但现在我几乎被卡住了.如何在 Prolog 中使用自创建列表?获取演员列表很容易,只需执行以下操作:

But now I'm pretty much stuck. How can i use a self-created lists in Prolog? Getting the list of actors is easy and it's by doing:

  cast(MovieID,_).

但是我如何使用函数定义的答案?[我什至可以这样做吗?] 还是我应该再次尝试改变我的方法?

But how can i use the answer defined by the function? [Can i even do that?] Or shall i try to change my approach again?

推荐答案

关系 people(Move, Persons) 给定您的数据库,不再是单调关系.因为,您是否将事实添加到 actor/2cast/2,关系 people/2 现在将成功用于更长且不同的列表人.

The relation people(Move, Persons) is, given your database, no longer a monotonic relation. For, would you add facts to actor/2 and cast/2, the relation people/2 would now succeed for a longer and different list of Persons.

因此,鉴于此,您可以使用 setof/3 定义 helper/2.实际上,为此您需要 setof/3 或其他一些非单调结构:

So, given that, you can define helper/2 with setof/3. In fact, you need setof/3 or some other non-monotonic construct to that end:

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

或者,您可以将所有这些都放在一个大目标中.请注意,在这种情况下,必须声明所有存在变量:

Alternatively, you might put all of it into one big goal. Be aware that in such a situation all existential variables have to be declared:

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) 隐式处理此类变量.这对匿名变量特别有用:

It is very easily possible to forget a variable or two, so you might also use library(lambda) to handle such variables implicitly. This is particularly useful for anonymous variables:

helper(MovID, Ys) :-
   setof(Y, {MovID,Y}+\
              ( move(MovID,_,DirID,_,_), director(DirId,Y)
              ; cast(MovID, ActID), actor(ActId, Y)
              ),
         Ys).

这篇关于在 prolog 中使用自创建列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆