Prolog中带有= ..运算符的谓词

时间:2019-01-17 11:45:55

标签: prolog

我上次了解= ..可以将列表翻译成术语和相反术语。 我有3个谓词,第一个是将列表翻译成术语的谓词。我想出了这样的东西:

list_to_term(List, Functor, Term) :-
    Term =.. [Functor | List].

好吗?足够?还是我想念什么?

元素A的另一个谓词是count(A,T,N),条件T中的元素N为N,如果N是元素T中元素A的数量,则为真。 ?

 ?- count(a,f(a),N).
 N = 1
 ?- count(a,f(a,g(b,a),N).
 N = 2.
 ?- count(a,f(a,g(X,a),N).
 N = 2.

3 个答案:

答案 0 :(得分:1)

看看the answer of this post,您可以重用谓词flatten_term/2,并对其进行一些修改以处理自由变量,以解决问题。这是基本解决方案的代码:

flatten_term(Term,[Term]):-
    (atomic(Term);var(Term)),!.
flatten_term(Term,Flat):-
    Term =.. TermList,
    flatten_term_list(TermList,Flat),!.

flatten_term_list([],[]):-!.
flatten_term_list([H|T],List):-
    flatten_term(H,HList),
    flatten_term_list(T,TList),
    append(HList,TList,List),!.

occurrences(_,[],N,N):-!.
occurrences(A,[H|T],N,Tot):-
    A \== H,!,
    occurrences(A,T,N,Tot).
occurrences(A,[H|T],N,Tot):-
    A == H,!,
    N1 is N+1,
    occurrences(A,T,N1,Tot).

count(A,Term,N):-
    flatten_term(Term,Flatten),
    occurrences(A,Flatten,0,N).

?- count(a,f(a,g(X,a),d),T).
T = 2.

?- count(X,f(a,g(X,a),d),T).
T = 1

首先,您使用flatten_term/2将术语展平。然后只需使用occurrences/4计算要查找的元素的出现次数即可。您可以根据需要修改flatten_term/2以避免使用occurrences/4,因此只扫描术语(列表)一次...类似flatten_term(Term,Flatten,ElementToFind,Counter,Total)

答案 1 :(得分:1)

首先解决一个更普遍的问题,即对列表中的项进行计数。毕竟,处理术语是处理包含该术语的单例列表:

count(A,T,N):- count(A, [T|Z],Z, 0,N).

count(_, [],  [], C,N):- N is C, !.
count(A, [T|B],Z, C,N):- ?=(A,T), A=T, !, count(A, B,Z, C+1,N).
count(A, [T|B],Z, C,N):- ?=(A,T), T=..[_|S], !, append(S,Y,Z), count(A, B,Y, C,N).
count(A, [_|B],Z, C,N):- count(A, B,Z, C,N).

这将依次打开 list 中的每个主术语,并将其自变量项附加到该 list ,从而将其用作 queue 。 ..因此以 breadth-first 的方式处理谓词的第二个自变量T

这假设A参数是一个原子,而?=用于避免实例化我们可能遇到的自由变量,而是跳过它们,如您的示例所示。

答案 2 :(得分:0)

  

好吗?足够?还是我想念什么?

Prolog的=../2 predicate [swi-doc]可以“打包”和“解包”一个列表,该列表包含术语中的函子名称及其参数,反之亦然。因此,可以使用它来构造一个术语,或分析一个术语。例如:

?- f(a,g(b,a)) =.. L.
L = [f, a, g(b, a)].

此处f是函子名称,ag(b, a)是自变量。这些参数也可以是术语,因此我们需要进一步解开这些参数。

例如,我们可以使用以下方法获得一个术语的所有子术语:

subterms(T, T) :-
    \+ var(T).
subterms(T, ST) :-
    \+ var(T),
    T =.. [_|As],
    member(A, As),
    subterms(A, ST).

例如:

?- subterms(f(a,g(X,a)),N).
N = f(a, g(X, a)) ;
N = a ;
N = g(X, a) ;
N = a ;
false.

现在我们获得了所有(子)项,我们可以将谓词略微重写为 count 匹配的元素数:

subterm_query(Q, T) :-
    Q == T.
subterm_query(Q, T) :-
    \+ var(T),
    T =.. [_|As],
    member(A, As),
    subterm_query(Q, A).

这样我们就可以查询a

?- subterm_query(a, f(a,g(X,a))).
true ;
true ;
false.

如果我们可以使用aggregate library,则可以利用aggregate_all/3 predicate来计数谓词成功的次数:

?- aggregate_all(count, subterm_query(a, f(a,g(X,a))), Count).
Count = 2.

如果不是,则需要实现一种机制,该机制返回1进行匹配,然后递归地总结子项的匹配。我将其保留为练习。