How to get predicate values - prolog

For example I have:
pos(10, 20).
How can i write the predicate which returns the first pos term(10).
get_pos_x(Pos) :- % should return the first pos param(10).
Example of work:
get_pos_x(pos(10,20)) :- % should write 10.

There is a difference between a predicate pos(10, 20). and a term pos(10, 20).
For the predicate, this would be the code:
pos(10, 20).
And this would be the execution of the code:
:- pos(X, 20), write(X), nl.
For the term, this would be the code:
get_pos_x(pos(X, _)) :-
write(X), nl.
And this would be the execution of the code:
:- get_pos_x(pos(10, 20)).

Related

Calculating syntactic complexity of a prolog predicate

Currently working on an exercise where, given some predicate, the syntactic complexity has to be calculated. The syntactic complexity of some predicate is calculated as follows:
If the predicate is atomic or a function, its complexity is 2.
If the predicate is a variable, its complexity is 1.
For example, the syntactic complexity of loyalty(father(bob, Y), X) is worked out as follows:
loyalty = 2 (function)
father = 2 (function)
bob = 2 (atom)
Y = 1 (variable)
X = 1 (variable)
Total = 8
The approach taken was calculating such complexity if the predicate was in the form of a nested list, i.e. loyalty(father(bob, Y), X) = [loyalty, father, bob, Y, X], as follows:
complexity([], 0).
complexity([H|L], C) :- atomic(H), complexity(L, C1), C is C1+2.
complexity([H|L], C) :- var(H), complexity(L, C1), C is C1+1.
The remaining issue is converting the predicate to a flat list, as shown above. The ..= is useful, but its output is not complete, that is:
loyalty(father(bob, Y), X) ..= ["loyalty", "father(bob, Y)", "X"]
Any help would be appreciated.
You must apply =.. recursively as follows:
% term_to_list(+Term, -List)
term_to_list(Term, [Term]) :- var(Term), !.
term_to_list(Term, [Term]) :- atomic(Term), !.
term_to_list(Term, List) :-
compound(Term),
Term =.. Components,
maplist(term_to_list, Components, ListOfLists),
flatten(ListOfLists, List).
Example:
?- term_to_list(loyalty(father(bob, Y), X), L).
L = [loyalty, father, bob, Y, X].
Alternatively, you can define complexity/2 as follows:
% complexity(+Term, -Complexity)
complexity(Term, 1) :- var(Term), !.
complexity(Term, 2) :- atomic(Term), !.
complexity(Term, Complexity) :-
compound(Term),
Term =.. Components,
maplist(complexity, Components, Complexities),
sum_list(Complexities, Complexity).
Example:
?- complexity(loyalty(father(bob, Y), X), L).
L = 8.
Remark SWI-Prolog defines maplist/3 and sum_list/2 as follows:
maplist(Goal, List1, List2) :-
maplist_(List1, List2, Goal).
maplist_([], [], _).
maplist_([Elem1|Tail1], [Elem2|Tail2], Goal) :-
call(Goal, Elem1, Elem2),
maplist_(Tail1, Tail2, Goal).
sum_list(Xs, Sum) :-
sum_list(Xs, 0, Sum).
sum_list([], Sum, Sum).
sum_list([X|Xs], Sum0, Sum) :-
Sum1 is Sum0 + X,
sum_list(Xs, Sum1, Sum).

Prolog remove parenthesis when transforming list in polynomial

Basically when I try to transform a list into a polynomial or vice-versa, it always shows up with parenthesis (in case of the polynomials). Here is the code, the function not working is the poly2list, the other one are just to define what a monomial/polinomial is.
pvars([x,y,z]).
pvar(X):-pvars(V),member(X,V).
polinomial(X) :- monomial(X).
polinomial(P+M) :- monomial(M), polinomial(P).
monomial(X) :- pvar(X).
monomial(N) :- number(N).
monomial(X) :- power(X),!.
monomial(K*X) :- coefficient(K), power(X),!.
coefficient(N) :- number(N).
power(X) :- pvar(X),!.
power(X^Y) :- pvar(X), integer(Y), Y>1,!.
poly2list(X,[X]) :- monomial(X),!.
poly2list(X+P,[X|Y]) :- monomial(X), poly2list(P,Y).
For example, when i ask:
poly2list(X,[2*x^2,3,y]).
The result is:
X = 2*x^2+(3+y)
And I'm trying to get:
X = 2*x^2+3+y
Thanks in advance :)

Use "univ" Prolog predicate with a Logtalk object method as parameter

How to use the 'Univ' ( =../2 ) prolog predicate with a Logtalk object method as parameter ?
Consider this code :
baz(foo(X)) :-
write(predicate), write(X), nl.
run :-
Term =.. [baz, foo(testfoo)],
write(Term), nl, Term,nl,
TermLgt =.. [bar::baz, foo(testfoo2)],
write(TermLgt), nl, Term,nl.
:- object(bar).
:- public(baz/1).
baz(foo(X)) :-
write(method), write(X), nl.
:- end_object.
:- object(main).
:- public(run/0).
run :-
Term =.. [baz, foo(testfoo)],
write(Term), nl, Term,nl,
TermLgt =.. [bar::baz, foo(testfoo2)],
write(TermLgt), nl, Term,nl.
:- end_object.
I'll obtain :
?- {myfile}.
% (0 warnings)
true.
?- run.
baz(foo(testfoo))
predicatetestfoo
ERROR: =../2: Type error: `atom' expected, found `bar::baz' (a compound)
?- main::run.
baz(foo(testfoo))
ERROR: Undefined procedure: baz/1
ERROR: However, there are definitions for:
ERROR: baz/1
What workaround to use for a good interpretation / compilation ? It seems issue is the same with swi-prolog building predicate like predsort/3 (predsort/3 doc).
The standard =../2 predicate expects, when constructing a term from a list, that the first list argument be an atom but bar::baz is a compound term with functor ::/2 (which is both defined as a predicate - for top-level queries - and as an operator when Logtalk is loaded). The solution is to write instead:
baz(foo(X)) :-
write(predicate), write(X), nl.
run :-
Term =.. [baz, foo(testfoo)],
write(Term), nl, call(Term), nl,
TermLgt =.. [::, bar, Term],
write(TermLgt), nl, call(Term), nl.
:- object(bar).
:- public(baz/1).
baz(foo(X)) :-
write(method), write(X), nl.
:- end_object.
:- object(main).
:- public(run/0).
run :-
Term =.. [baz, foo(testfoo)],
write(Term), nl, Term,nl,
TermLgt =.. [::, bar, Term],
write(TermLgt), nl, Term,nl.
:- end_object.
With this changes, you get:
?- {univ}.
% [ /Users/pmoura/Desktop/univ.lgt loaded ]
% (0 warnings)
true.
?- run.
baz(foo(testfoo))
predicatetestfoo
bar::baz(foo(testfoo))
predicatetestfoo
true.

Prolog: script doesn't halt

I'm currently trying to learn prolog. I hope you can help..
I have three rules:
reverse - retrieves the reverse of a list
startswith - checks if the second list is a prefix of the first list
suffix - checks if the first list is a suffix of the second list
reverse([H|T], Y) :- append(Z, [H], Y), reverse(T, Z).
reverse([], Y) :- Y = [].
startswith(_, []).
startswith([Xh|Xt], [Yh|Yt]) :- Xh=Yh, startswith(Xt, Yt).
suffix(X, Y) :- reverse(X, XR), reverse(Y, YR), startswith(YR,XR).
reverse and startswith seem to work as they should.
But suffix doesn't stop calculating. I cannot understand why?
In general, it's a bad idea to pass variables that have yet to be unified to predicates that you will unify later. Essentially, append(Z,[H],Y) is spiraling off into prolog never-never land because it's unifying Z over and over based on your version of Prolog's append.
Change
reverse([H|T], Y) :- append(Z, [H], Y), reverse(T, Z).
To
reverse([H|T], Y) :- reverse(T, Z), append(Z, [H], Y).
So that you unify Z before you pass it to append

Prolog: converting atom to new atom

I have a problem with predicate which works in that way that it takes list of atoms:
nopolfont([to,jest,tekśćik,'!'],L).
and in result
L = [to,jest,tekscik,'!'].
I have problem with make_swap and swap predicates. So far I have:
k(ś,s).
k(ą,a).
% etc.
swap(X,W) :- name(X,P), k(P,Y), !, name(Y,W).
swap(X,X).
make_swap(A,W)
:- atom(A),!,
name(A,L),
swap(L,NL),
name(W,NL).
nopolfont([],[]).
nopolfont([H|T],[NH|S]) :- make_swap(H,NH), nopolfont(T,S).
Is there any elegant way to do this?
This is also quite elegant:
polish_char_replacer(X, Y) :-
k(X, Y),
!.
polish_char_replacer(X, X).
nopolfont(Atoms1, Atoms2) :-
maplist(replace(polish_char_replacer), Atoms1, Atoms2).
replace(Goal, Atom1, Atom2) :-
atom_chars(Atom1, Chars1),
maplist(Goal, Chars1, Chars2),
atom_chars(Atom2, Chars2).
Probably as elegant as it can get:
k(ś,s).
k(ą,a).
swap(X,W) :- name(P,[X]), k(P,Y), !, name(Y,[W]).
swap(X,X).
list_swap([], []).
list_swap([H|T], [W|S]) :-
swap(H, W),
list_swap(T, S).
atom_swap(A,W) :-
atom(A), !,
name(A, L),
list_swap(L,S),
name(W, S).
nopolfont([],[]).
nopolfont([H|T],[NH|S]) :-
atom_swap(H,NH),
nopolfont(T,S).
Also, obviously define this, to get the expected result, but I assume this is in the % etc
k(ć, c).

Resources