在 prolog 中使用自创建列表 [英] Using a self-created list in 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/2
和 cast/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屋!