检查谓词是不同的

时间:2017-10-12 03:41:27

标签: prolog

我有一个SWI-Prolog代码:

class(c1, 'Vehicle').
class(c2, 'Car').
class(c3, 'Motorcycle').
class(c4, 'Company').
class(c5, 'RentalStation').
class(c6, 'Person').

我想写一条规则来检查类的所有谓词是否都有不同的名称(第二个参数)。我应该怎么写这条规则?

2 个答案:

答案 0 :(得分:2)

另一种可能性是使用bagof / 3和maplist / 2。要获得所有名称,您可以像这样使用bagof / 3:

?- bagof(Y,X^class(X,Y),List).
List = ['Vehicle', 'Car', 'Motorcycle', 'Company', 'RentalStation', 'Person'].

要获得所有ID,您可以像这样使用bagof / 3:

?- bagof(X,Y^class(X,Y),List).
List = [c1, c2, c3, c4, c5, c6].

您可以使用maplist / 2来定义描述具有唯一元素的列表的谓词,让我们将其称为uniques / 1,如下所示:

:- use_module(library(apply)).   % for maplist/2

uniques([]).
uniques([X|Xs]) :-
   maplist(dif(X),Xs),
   uniques(Xs).

您可以查询此谓词,以确定它确实描述了您想要的内容:

?- uniques([]).
true.

?- uniques([a,b,c]).
true.

?- uniques([a,b,c,a]).
false.

在此基础上,您可以检查名称或ID是否如此唯一:

?- bagof(Y,X^class(X,Y),List), uniques(List).
List = ['Vehicle', 'Car', 'Motorcycle', 'Company', 'RentalStation', 'Person'].

?- bagof(X,Y^class(X,Y),List), uniques(List).
List = [c1, c2, c3, c4, c5, c6].

如果你想得到一个答案,显示列表中的重复,你可以像这样定义一个谓词list_reps / 2:

:- use_module(library(lists)).          % for append/3

list_reps([],[]).
list_reps([X|Xs],Ds1) :-
   x_reps_others_fromlist(X,Ds,Os,Xs),
   list_reps(Os,Ds0),
   append(Ds,Ds0,Ds1).

x_reps_others_fromlist(_X,[],[],[]).
x_reps_others_fromlist(X,[X|Ds],Os,[X|Ys]) :-
   x_reps_others_fromlist(X,Ds,Os,Ys).
x_reps_others_fromlist(X,Ds,[Y|Os],[Y|Ys]) :-
   dif(Y,X),
   x_reps_others_fromlist(X,Ds,Os,Ys).

现在让我们看看这个谓词在起作用:

?- list_reps([],R).
R = [].

?- list_reps([a,b,c],R).
R = [] ;
false.

?- list_reps([a,b,c,a],R).
R = [a] ;
false.

?- list_reps([a,b,c,a,b],R).
R = [a, b] ;
false.

?- list_reps([a,b,c,a,b,a],R).
R = [a, a, b] ;
false.

如您所见,元素在重复显示时会在第二个列表中显示。使用您提供的事实类/ 2,既没有重复的名称也没有重复的ID:

?- bagof(Y,X^class(X,Y),List), list_reps(List,R).
List = ['Vehicle', 'Car', 'Motorcycle', 'Company', 'RentalStation', 'Person'],
R = [] ;
false.

?- bagof(X,Y^class(X,Y),List), list_reps(List,R).
List = [c1, c2, c3, c4, c5, c6],
R = [] ;
false.

要看到两个反例,我们再添加两个事实:

class(c1, 'Vehicle').
class(c2, 'Car').
class(c3, 'Motorcycle').
class(c4, 'Company').
class(c5, 'RentalStation').
class(c6, 'Person').
class(c6, 'Person').          % <- new
class(c7, 'Person').          % <- new

现在上述查询告诉您名称'Person'重复两次,ID c6重复一次:

?- bagof(Y,X^class(X,Y),List), list_reps(List,R).
List = ['Vehicle', 'Car', 'Motorcycle', 'Company', 'RentalStation', 'Person', 'Person', 'Person'],
R = ['Person', 'Person'] ;
false.

?- bagof(X,Y^class(X,Y),List), list_reps(List,R).
List = [c1, c2, c3, c4, c5, c6, c6, c7],
R = [c6] ;
false.

出于比较原因:上面进一步检查名称或ID是否唯一的两个查询都失败并附加了其他事实:

?- bagof(Y,X^class(X,Y),List), uniques(List).
false.

?- bagof(X,Y^class(X,Y),List), uniques(List).
false.

答案 1 :(得分:0)

您可以先使用findall / 3谓词来获取所有类名的列表,然后只需检查该列表是否没有重复元素,例如:

 if(v<10)
   {
     if(v>20)
        System.out.println("20 IF");
   }
 // now the following else statement will be of ""if(v<10)"" and not 
 //                                                     ""if(v>20)""
 else
   {
      System.out.println("20 ELSE");  // its not of (20 ELSE)
   }

这里我们首先将所有名称都放入Names变量中,然后使用一些&#34;技巧&#34;检查所有元素是否唯一,即我们使用sort / 2谓词,它不仅排序,而且删除重复(与msort / 2不同)。之后,我们只是比较原始列表和重复数据删除列表的长度。

更新:如果您需要检查每个特定ID的唯一性,您可以使用另一个findall / 3调用来获取所有ID的列表,然后将maplist / 2和上面的解决方案结合起来检查每个id的唯一性。将所有内容组合在一起,我们得到:

findall(Name, class(_, Name), Names),
sort(Names, Unique),
length(Names, X),
length(Unique, X).