4

另一种提问方式是:

如何列出原子的所有属性?

例如:

movie(agora).
director(agora, 'Alejandro Amenabar')
duration(agora, '2h').

所以,我想接收所有具有agora参数的谓词。在这种情况下,它将是:movie, director, duration, 和其他参数('Alejandro Amenabar', '2h')

我发现:thisthis问题,但我不能很好地理解。

PersonInvited如果不喜欢这部电影的某些内容,我希望在“可变答案”中具有 false 的值。

我的查询将是:

answer(Answer, PersonInvited, PersonWhoMadeInvitation, Movie)

答:我不喜欢这个导演

answer(false, PersonInvited, PersonWhoMadeInvitation, Movie):-
    director(Movie, DirectorName),not(like(PersonInvited,DirectorName)).

例如,类似类型的任何属性都会发生同样的事情。

答:不喜欢这个类型

answer(false, PersonInvited, PersonWhoMadeInvitation, Movie):-
    genre(Movie, Genre), not(like(PersonInvited,Genre)).

所以,我想概括这种情况,而不是重复写每个对象的每个特征。

4

6 回答 6

3

我发现了两种解决方案,从我的角度来看,第二种更清洁,但它们是不同的。

参数

  • PredName:谓词的名称。
  • Arity:谓词的 Arity。
  • ParamValue:如果我想按一个特定参数进行过滤。
  • PosParam:谓词中参数的位置。
  • ListParam:所有可能的值参数的值(必须始终是一个变量)。

解决方案 1

filter_predicate(PredName, Arity, ParamValue,PosParam, ListParam):-
    current_predicate(PredName/Arity),
    Arity >= PosParam,
    nth(PosParam, ListParam, ParamValue),
    append([PredName], ListParam, PredList),
    GlobalArity is Arity + 1,
    length(PredList, GlobalArity),
    Predicate =.. PredList,
    Predicate.

询问

filter_predicate(PredName, Arity, agora, 1, Pm).

输出

Arity = 2                                                                              
Pm = [agora,'Alejandro Amenabar']
PredName = director ? 

yes

解决方案2

filter_predicate(PredName, Arity, ParamList):-
    current_predicate(PredName/Arity),
    append([PredName], ParamList, PredList), 
    GlobalArity is Arity + 1,
    length(PredList, GlobalArity),
    Predicate =.. PredList,
    Predicate.

查询一:

filter_predicate(PredName, Arity, [agora, X]).

输出

Arity = 2
PredName = director
X = 'Alejandro Amenabar' ? 

查询 2:

filter_predicate(PredName, Arity, [X, 'Alejandro Amenabar']).

输出

Arity = 2
PredName = director
X = agora ? 
于 2015-10-02T10:28:05.120 回答
2

这是我的尝试,使用 SWI-Prolog

?- current_predicate(so:F/N), N>0, length(As,N), Head =.. [F|As], clause(so:Head,Body), As=[A|_], A==agora.

请注意,我编码到一个名为so facts 的模块中,因此我使用模块名称来限定相关调用。此类内置函数(条款/2 和current_predicate /1)符合 ISO 标准,而模块(在 SWI-prolog 中)则不符合。所以我不确定便携性等......

Clause /2 它是一个内置的,允许轻松编写metainterprets。有关此 Prolog 历史“强度点”的精彩介绍,请参阅链接。

最后的 2 次调用(我的意思是As=[A|_], A==agora)避免了将变量作为第一个参数的匹配子句。

于 2015-09-30T12:25:58.677 回答
0

使用序言将行读入列表

您所有的谓词都在文件“my_file.pl”中。

例如 my_file.pl 包含:

movie(agora).
director(agora, 'Alejandro Amenabar').
duration(agora, '2h').

您可以使用:

getLines(File,L):-
 setup_call_cleanup(
 open(File, read, In),
 readData(In, L),
 close(In)
 ).

readData(In, L):-
  read_term(In, H, []),
  (   H == end_of_file
  ->  L = []
  ;   L = [H|T],
      readData(In,T)
  ).


pred_arg_file(Pred,Argue,File):-
  getLines(File,L),
  member(M,L),
  M=..List,
  member(Argue,List),
  List=[Pred|_].

然后可以查询:

 ?-pred_arg_file(Pred,agora,'my_file.pl').
 Pred = movie ;
 Pred = director ;
 Pred = duration ;
 false

或者

?- findall(Pred,pred_arg_file(Pred,agora,'my_file.pl'),Preds).
Preds = [movie,director,duration].

如果要返回属性,请返回整个 List 而不仅仅是头部。

pred_arg_file(List,Argue,File):-
  getLines(File,L),
  member(M,L),
  M=..List,
  member(Argue,List).
于 2015-09-30T11:59:52.610 回答
0

根据我的理解,您应该更改数据表示,以便查询关系。正如其他答案所指出的那样,因此使用三元组,您可以轻松编写代码将所有关系更改为这种形式。然后,您需要弄清楚存储喜欢或不喜欢的最佳方式是什么。这将影响否定的工作方式。在这个例子中:

relation(starwars,is,movie).
relation(lucas, directs,starwars).
relation(agora, is,movie).
relation('Alejandro Amenabar', directs, agora).
relation(agora, duration, '2h').

like(ma,'Alejandro Amenabar').
like(ma,movie).
like(ma,'2h').

ma_does_not_want_to_go(Film):-
  relation(Film,is,movie),
  relation(Film,_,Test), \+like(ma,Test).
ma_does_not_want_to_go(Film):-
  relation(Film,is,movie),
  relation(Test,_,Film), \+like(ma,Test).

ma_wants_to_go(Film):-
  relation(Film,is,movie),
  \+ma_does_not_want_to_go(Film).

sa_invites_ma(Film,true):-
  ma_wants_to_go(Film).

sa_invites_ma(Film,false):-
  ma_does_not_want_to_go(Film).
于 2015-10-01T12:09:32.790 回答
0

使用 Logtalk 和 GNU Prolog 作为后端编译器的解决方案草案:

% a movie protocol
:- protocol(movie).

    :- public([
        director/1,
        duration/1,
        genre/1
    ]).

:- end_protocol.


% a real movie
:- object('Agora',
    implements(movie)).

    director('Alejandro Amenabar').
    duration(120).
    genre(drama).

:- end_object.


% another real movie
:- object('The Terminator',
    implements(movie)).

    director('James Cameron').
    duration(112).
    genre(syfy).

:- end_object.


% a prototype person
:- object(person).

    :- public([
        likes_director/1,
        likes_genre/1
    ]).

    :- public(likes/1).
    likes(Movie) :-
        conforms_to_protocol(Movie, movie),
        (   Movie::genre(Genre),
            ::likes_genre(Genre) ->
            true
        ;   Movie::director(Director),
            ::likes_director(Director) ->
            true
        ;   fail
        ).

:- end_object.


% a real person
:- object(mauricio,
    extends(person)).

    likes_director('Ridlye Scott').

    likes_genre(drama).
    likes_genre(syfy).

:- end_object.

一些示例查询:

$ gplgt
...

| ?- {movies}.
...

(5 ms) yes
| ?- mauricio::likes('Agora').

true ? 

yes
| ?- mauricio::likes(Movie).  

Movie = 'Agora' ? ;

Movie = 'The Terminator' ? ;

no

| ?- 'The Terminator'::director(Director).

Director = 'James Cameron'

yes

可以通过多种方式改进代码,但足以让您清楚地了解评估此解决方案。

于 2015-10-01T14:56:56.010 回答
0

如果我正确理解了您的问题,我建议如下:

如果您更改架构或遵循这个想法,您可以制作一个模拟相同事物的方法。

class(movie, agora).
property(director, agora, 'Alejandro Amenabar').
property(duration, agora, '2h').

如果你想要 agora 的类型,查询将是:

class(Type, agora)

如果你想要 agora 的所有属性,那就是:

property( PropertyName, agora, Value).
于 2015-10-01T08:26:56.567 回答