I am writing a module which uses term_expansion/2 to process a prolog source file. While doing so, I deconstruct predicates using =.. or project to its name using functor/3.
For example:
?- functor(pred(foo, bar), N, _).
N = pred.
?- pred(foo, bar) =.. L.
L = [pred, foo, bar].
Now I want to change the name of pred to (for example) pred_expanded and make it a term again, so that pred(foo, bar) becomes pred_expanded(foo, bar).
I tried append(pred, "_expanded", F) and append(pred, '_expanded', F) without success.
change_functor(Term,NewFunctor,NewTerm) :-
Term =.. [_|Args],
NewTerm =.. [NewFunctor|Args].
term_expansion(Term,ExpandedTerm) :-
functor(Term,pred,2),
change_functor(Term,pred_expanded,ExpandedTerm).
For example:
?- term_expansion(pred(foo,bar),T).
T = pred_expanded(foo, bar).
Illustrates how to use the "univ" predefined predicate. However, this is the best solution:
term_expansion(pred(A,B),pred_expanded(A,B)).
If you need to translate any functor, use atom_concat/3 as stated before:
term_expansion(Term,ExpandedTerm) :-
functor(Term,F,_),
atom_concat(F,'_expanded',NewF),
change_functor(Term,NewF,ExpandedTerm).
Example:
?- term_expansion(kk(1,2,3),N).
N = kk_expanded(1, 2, 3).
Related
Last time I learnt about =.. that can translate a list to term and opposite.
I have 3 predicates to do, first one is the one that translates a list to a term. I came up with sth like this:
list_to_term(List, Functor, Term) :-
Term =.. [Functor | List].
Is it okey? Enough? Or I miss something?
The other predicate is count(A,T,N) for element A, in term T with number N that is true if N is a count of elements A in term T... Can anyone help me with this one or how to start?
?- 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.
Looking at the answer of this post you can reuse the predicate flatten_term/2, a little bit modified to handle free variables, to sove your problem. Here is the code for a basic solution:
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
First of all you flatten the term using flatten_term/2. Then simply count the occurrences of the element you want to find using occurrences/4. You can, if you want, modify flatten_term/2 to avoid the usage of occurrences/4 and so scan the term (list) only one time... Something like: flatten_term(Term,Flatten,ElementToFind,Counter,Total).
Start by solving a more general problem of counting the terms in a list. Processing a term is processing a singleton list containing that term, after all:
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).
This opens up each head term in a list in succession and appends its argument terms to that list thus using it as a queue... thus processing the predicate's second argument T in a breadth-first manner.
This assumes A argument is an atom, and ?= is used to avoid instantiating the free variables we might encounter, and instead to skip over them, as your examples seem to indicate.
Is it okey? Enough? Or I miss something?
Prolog's =../2 predicate [swi-doc] can "pack" and "unpack" a list that contains the functor name and its arguments in a term and vice versa. So one can use this to construct a term, or to analyze a term. For example:
?- f(a,g(b,a)) =.. L.
L = [f, a, g(b, a)].
Here f is the functor name, and a and g(b, a) are the arguments. These arguments can be terms as well, and then we thus need to unpack these arguments further.
We can for example obtain all the subterms of a term with:
subterms(T, T) :-
\+ var(T).
subterms(T, ST) :-
\+ var(T),
T =.. [_|As],
member(A, As),
subterms(A, ST).
For example:
?- subterms(f(a,g(X,a)),N).
N = f(a, g(X, a)) ;
N = a ;
N = g(X, a) ;
N = a ;
false.
Now that we obtained all (sub)terms, we can slightly rewrite the predicate to count the number of elements that match:
subterm_query(Q, T) :-
Q == T.
subterm_query(Q, T) :-
\+ var(T),
T =.. [_|As],
member(A, As),
subterm_query(Q, A).
so we obtain if we query for a:
?- subterm_query(a, f(a,g(X,a))).
true ;
true ;
false.
If we can use the aggregate library, we can make use of the aggregate_all/3 predicate to count the number of times, the predicate was succesful:
?- aggregate_all(count, subterm_query(a, f(a,g(X,a))), Count).
Count = 2.
If not, you need to implement a mechanism that returns 1 for a match, and sums up recursively the matches of the child terms. I leave this as an exercise.
This answer by Jan Burse shows one of the simplest implementations of a metainterpreter in Prolog:
solve(true) :- !.
solve((A,B)) :- !, solve(A), solve(B).
solve(H) :- clause(H,B), solve(B).
I would like to extend this interpreter so that it can call builtins. The vanilla one isn't able to handle calls such as solve(member(X, [1,2,3,4])). Is this possible using ISO predicates? If not, is it possible using SWI-Prolog predicates?
I think predicate_property/2 may be useful for your task.
As the name already implies, this predicate relates a predicate (head) to one ore more properties.
For example:
?- predicate_property((A,B), P).
P = interpreted ;
P = visible ;
P = built_in ;
P = static ;
P = imported_from(system) ;
etc.
From such properties, you can deduce whether a predicate is built-in, and the call it directly.
It is also available in SICStus.
Beware though: Not all built-in predicates retain their semantics when called directly. I think discussing what they are and how to interpret them would be well worth its own question.
Stackoverflow is refusing to accept my answer :) that was
Just call/1 them
Edit
For instance
?- [user].
solve(true) :- !.
|: solve((A,B)) :- !, solve(A), solve(B).
|: solve(H) :- clause(H,B), solve(B).
|: solve(T) :- call(T).
|: ^Dtrue.
?- solve(member(X, [1,2,3,4])).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4.
The only addition: solve(T) :- call(T).
d_edge(a, b, 5).
e_edge(a, c, 6).
f_edge(b, c, 8).
% I will have a list of rules for the graph point
% from source to destination with weight.
list2pair([T], [A,B], [(T,A,B)]).
list2pair([T1|Tt], [A1,A2|T], Result) :-
list2pair(Tt, [A1|T], R1),
append([(T1,A1,A2)], R1, Result).
I want to come up with the result like
[d_edge(a,b), f_edge(b,c)]
my 1st arg will be the list of names [d_edge,f_edge]
my 2nd arg will be the list of vertexes [a,b,c].
My current code generates [(d_edge,a,b),(f_edge,b,c)].
Whenever I try to update the predicate from (T1,A1,A2) to T1(,A1,A2)
I get an error saying that it is not valid predicate.
I understand why I am getting the error. But I couldn't find a way around it.
First things first: T1(,A1,A2) is syntactically incorrect.
Here's how you could proceed using the built-in predicate (=..)/2 (a.k.a. "univ"):
list2pair([T], [A1,A2], [X]) :-
X =.. [T,A1,A2].
list2pair([T1|Tt], [A1,A2|T], [X|Xs]) :-
X =.. [T1,A1,A2],
list2pair(Tt, [A2|T], Xs).
Sample query using SICStus Prolog 4.3.2:
| ?- list2pair([d_edge,f_edge], [a,b,c], Xs).
Xs = [d_edge(a,b),f_edge(b,c)] ? ; % expected result
no
Note that the above only "constructs" these compound terms—it does not ensure that suitable facts d_edge/3, f_edge/3 etc really do exist.
Wondering how to do this in SWIProlog, e.g., convert term
[elvis, [was, dead]]
into
[A, [B, C]]
How to do this with arbitrary data structures?
For example, convert term
ty(simple, _)
into
ty(A, _)
and convert term
ty(ty(complex, _), _)
into
ty(ty(A, ), _)
Your examples suggest that you want a term template constructed from a term. As a bound term can be depicted as a tree, the construction of the term template can be seen as replacing the bound tree leaves with fresh variables. Therefore, a solution is to traverse the tree and do the necessary transformation to its leaves. This can be accomplished by using the standard functor/3 and =../2 predicates. For example:
% template(#term, -term)
template(Term, Template) :-
( var(Term) ->
true
; Term = [_| _] ->
template_arguments(Term, Template)
; functor(Term, Functor, Arity),
functor(Template, Functor, Arity),
Term =.. [Functor| Arguments],
Template =.. [Functor| TemplateArguments],
template_arguments(Arguments, TemplateArguments)
).
template_arguments([], []).
template_arguments([Argument| Arguments], [TemplateArgument| TemplateArguments]) :-
( compound(Argument) ->
template(Argument, TemplateArgument)
; % variables and atomic terms
true
),
template(Arguments, TemplateArguments).
Some queries:
?- template(ty(ty(complex, _), _), Template).
Template = ty(ty(_G1211, _G1212), _G1191).
?- template([elvis, [was, dead]], Template).
Template = [_G1196, [_G1202, _G1205]].
?- template([elvis, [was, dead]| _], Template).
Template = [_G1199, [_G1205, _G1208]|_G1117].
Maybe you can adapt this solution to solve your problem?
I've got this work to do and my teacher gave me a prolog file with the following facts:
vowel(a).
vowel(e).
vowel(i).
vowel(o).
vowel(u).
consonant(b).
consonant(c).
consonant(d).
consonant(f).
consonant(g).
consonant(h).
consonant(j).
consonant(k).
consonant(l).
consonant(m).
consonant(n).
consonant(p).
consonant(q).
consonant(r).
consonant(s).
consonant(t).
consonant(v).
consonant(w).
consonant(x).
consonant(y).
consonant(z).
And I need to create a rule that is able to return the vowels. How can I do that?
The output would be something like this:
blafoo([s,a,r,a], X).
X = [a].
I can't use any prolog predicate.
If you are mentioning both vowel/1 and consonant/1, you might be expected to write a pure, monotonic version. After all, why do you mention consonant/1?
word_vowels([], []).
word_vowels([C|Xs], Vs) :-
consonant(C),
word_vowels(Xs, Vs).
word_vowels([V|Xs], [V|Vs]) :-
vowel(V),
word_vowels(Xs, Vs).
?- word_vowels([a,m,a,z,o,n],Vs).
Vs = [a,a,o]
; false.
Alternatively using tfilter/3:
vowel_truth(C,true) :-
vowel(C).
vowel_truth(V,false) :-
consonant(V).
?- tfilter(vowel_truth,[a,m,a,z,o,n],Vs).
Vs = [a,a,o]
; false.
setof/3 could be a good choice here:
?- setof(X,(member(X,[a,m,a,z,o,n]),vowel(X)),L).
L = [a, o].
If your Prolog implements it, I would go with standard ISO sub_atom/5
?- W = amazon, sub_atom(W, _,1,_, C).
W = amazon,
C = a ;
W = amazon,
C = m ;
...
then
blafoo(Word, Wovel) :- sub_atom(Word, _,1,_, Wovel), vowel(Wovel).
edit after comment
Prolog doesn't 'returns' things, but you could always use a more appropriate naming and implementation for the relation, for instance like
word_vowels(Word, Wovels) :-
findall(Wovel, (sub_atom(Word, _,1,_, Wovel), vowel(Wovel)), Wovels).