如何检查名称是否在谓词中由其类似术语识别的列表中?

时间:2017-04-02 12:24:41

标签: prolog

假设,我有一个prolog谓词,如:

name(music,[jazz,blues,classical]).

我想要的是检查爵士乐的会员资格,如果在音乐中,请回复我吗?

到目前为止,我做到了这一点:

ismember(X,Y):-imember(X,name(Y,Z)),write(Z).
imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).

但它不起作用。

?- ismember(jazz,music).
false.

它并没有写write(Z)部分。

3 个答案:

答案 0 :(得分:4)

在以下片段的可见部分中存在错误。您的程序不仅会失败,而且以下泛化也会失败:

:- op(950, fy, *).
*(_).

ismember(X,Y):-
   imember(_/*X*/,name(_/*Y*/,Z)).

imember(X,[_|Tail]):-
   * imember(X,Tail).
imember(X,[_/*X*/|_]).

?- ismember(X, Y).

通过用_替换某些变量,并用*删除一个目标,获得了泛化。它尽可能概括 。也就是说,任何进一步的概括都会使目标成功。并且有一个很好的属性(纯粹的,单调的)Prolog:

如果泛化失败(对于特定查询),则原始程序也会失败(对于同一查询)。

这是一个很好的属性,它以某种方式确定了通用片段和原始程序之间的因果关系。如果要删除错误,则必须更改通用程序中的某些内容。或者相反:如果您进行的更改仍然允许进行泛化,那么您还没有修复错误。

考虑到这一点,在搜索这样的片段时,不需要“理解”实际的程序。只要这是可能的,只要盲目地猜测和概括就足够了。

现在,如果我们看一下那个概括性说明 ismember/2的论点完全被忽略了!

答案 1 :(得分:2)

问题是,您在name(Y,Z)谓词中传递的imember/2不是列表。你可以简单地写:

ismember(X,Y):-name(Y,Z),imember(X,Z),write(Z).

imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).

示例:

?- ismember(jazz,music).
[jazz,blues,classical]
true.

答案 2 :(得分:0)

ismember / 2谓词第二个参数是一个列表,而您没有传递列表

这是一个跟踪

[trace]  ?- ismember(jazz,music).
   Call: (8) ismember(jazz, music) ? creep
   Call: (9) imember(jazz, name(music, _6828)) ? creep
   Fail: (9) imember(jazz, name(music, _6828)) ? creep
   Fail: (8) ismember(jazz, music) ? creep
false.

@coder答案是正确的方法

或者你可以简单地使用member / 2谓词,如下所示:

首先在数据库中定义您的列表:

  

music([jazz,blues,classical]).

现在我们有了音乐类型列表,接下来我们写了规则

  

ismusicmember(X) :- music(L) , member(X,L),write(L).

music(L)将变量L指定给我们的音乐列表

member(X,L)成员/ 2谓词检查X是否在列表中

并运行查询

?- ismusicmember(jazz).
[jazz,blues,classical]
true .
  

追踪:

    [trace]  ?- ismusicmember(jazz).
   Call: (8) ismusicmember(jazz) ? creep
   Call: (9) music(_7376) ? creep
   Exit: (9) music([jazz, blues, classical]) ? creep
   Call: (9) lists:member(jazz, [jazz, blues, classical]) ? creep
   Exit: (9) lists:member(jazz, [jazz, blues, classical]) ? creep
   Call: (9) write([jazz, blues, classical]) ? creep
[jazz,blues,classical]
   Exit: (9) write([jazz, blues, classical]) ? creep
   Exit: (8) ismusicmember(jazz) ? creep
true .