Search for a Atom in Prolog

2019-04-15 02:21发布

I have most Compound Term, such as:

likes(a, b).
likes(c, b).
likes(a, d).
likes(b, c).
likes(c, a).
likes(a, f).
go(a, t).
go(t, d).
go(g, a).
go(f, g).
go(f, a).

I want to search Compound Tern, value of Atom is "a", value of the other Atom is any value.

The result of Prolog return:

likes(a, b).
likes(a, d).
likes(c, a).
likes(a, f).
go(a, t).
go(g, a).
go(f, a).

Please, help me

标签: prolog
2条回答
看我几分像从前
2楼-- · 2019-04-15 02:40

I've written here a generic helper. I thought that less builtins were needed...

search_facts_by_arg(Functor, Arg, C) :-
    current_functor(Functor, Arity),
    Arity >= 2, % because of 'value of the other Atom is any value.'
    length(Args, Arity),
    C =.. [Functor|Args],
    clause(C, true),
    once((arg(_, C, A), A == Arg)).

Phew...

test:

?- search_facts_by_arg(go, a, C).
C = go(a, t) ;
C = go(g, a) ;
C = go(f, a) ;
false.

edit: after @false' suggestion, the code could be simplified

search_facts_by_arg(Functor, Arg, C) :-
    functor(C, Functor, 2),
    clause(C, true),
    once((arg(_, C, A), A == Arg)).

here is the functor/3 documentation. The essential builtin is clause/2, here another simplified way, using univ to build the 'template' head:

search_facts_by_arg(Functor, Arg, C) :-
    C =.. [Functor,_,_],
    clause(C, true),
    once((arg(_, C, A), A == Arg)).
查看更多
来,给爷笑一个
3楼-- · 2019-04-15 02:41

First you need to "reify" the predicate term. Your theory becomes:

do(likes, a, b).
do(likes, c, b).
do(likes, a, d).
do(likes, b, c).
do(likes, c, a).
do(likes, a, f).
do(go, a, t).
do(go, t, d).
do(go, g, a).
do(go, f, g).
do(go, f, a).

Add the following:

has_value(X) :- do(_, X, _)
has_value(X) :- do(_, _, X)

And you're done.

You could use meta-predicates like =.. to avoid changing your theory. Personally I think that's the wrong approach. Better to have the right formalisation of the problem from the start.

查看更多
登录 后发表回答