Get index of a Term's argument in Prolog - prolog

I need to get the index of a term's argument in Prolog. Predicate arg/3 seems to do the opposite of what I need:
arg(Index, Term, Value).
arg/3 fails if Index is a variable, so it's not possible to get the index of a given value and term. You guys know any other way to achieve this (I can't use external libraries)?
An example of the expected behaviour would be:
?- arg_(Index, regs(a,b,c), c).
Index = 3

Not all Prolog implementations seem to behave like SWI-Prolog does when the index is a variable. Its behavior might be an extension to the standard.
Here is what GNU Prolog 1.4.5 does:
| ?- arg(Index,s(a,b,c,d),V).
uncaught exception: error(instantiation_error,arg/3)
| ?- arg(Index,regs(a,b,c),c).
uncaught exception: error(instantiation_error,arg/3)
So you'll have to backtrack over the valid indices yourself. You can use functor/3 to find out how many arguments there are:
| ?- Term = regs(a,b,c), functor(Term, _Functor, Arity).
Arity = 3
Term = regs(a,b,c)
yes
And many Prologs (including GNU Prolog) have a between/3 predicate for enumerating integers in a range:
| ?- between(1, 4, N).
N = 1 ? ;
N = 2 ? ;
N = 3 ? ;
N = 4
(1 ms) yes
So overall you can do:
| ?- Term = regs(a,b,c), functor(Term, _Functor, Arity), between(1, Arity, Index), arg(Index, Term, Value).
Arity = 3
Index = 1
Term = regs(a,b,c)
Value = a ? ;
Arity = 3
Index = 2
Term = regs(a,b,c)
Value = b ? ;
Arity = 3
Index = 3
Term = regs(a,b,c)
Value = c
yes

Related

anonymous variables - prolog - a few queries

Can you help me understand the engine of answering the next queries?
?- _ = _.
?- _ = 1.
?- A = _, B = _, C = A + B + 1.
And some extra query (not related to anonymous variables):
?- B = A + 1, A = C, C = B - 1.
I know the answers to above queries, but I want to understand how prolog find those answers :)
Thanks!
_ is called the _anonymous variable. Each occurrence of _ is a different variable. You can observe it easily by using the standard write_canonical/1 built-in predicate. For example:
| ?- write_canonical(_ = _).
=(_279,_280)
yes
A variable can be unified with any term, including other variable, as you observe in your queries. Note that the standard =/2 built-in predicate performs unification, not equality or arithmetic expression evaluation. Unification takes two terms and succeeds if the two terms are the same or can be made the same by unifying any variables in the terms. For example:
| ?- A + 1 = 2 + B.
A = 2
B = 1
(1 ms) yes
A query such as:
| ?- write_canonical(B = A + 1), nl, B = A + 1, write_canonical(B).
=(_279,+(_280,1))
+(_280,1)
B = A+1
yes
unifies the variable B with the compound term +(A,1). _279 and _280 are the internal variable representation for, respectively, B and A. Different Prolog systems print these internal representation differently. For example, using SWI-Prolog:
?- write_canonical(B = A + 1), nl, B = A + 1, write_canonical(B).
=(_,+(_,1))
+(_,1)
B = A+1.
Regarding your extra query, B = A + 1, A = C, C = B - 1, it creates cyclic terms. Consider the simpler query:
| ?- X = f(X).
The result and consequent variable binding report by the Prolog top-level depends on a specific Prolog system handles cyclic terms. For example, in GNU Prolog you will get:
| ?- X = f(X).
cannot display cyclic term for X
yes
while SICStus Prolog reports:
| ?- X = f(X).
X = f(f(f(f(f(f(f(f(f(f(...)))))))))) ?
Cyclic terms are useful for some applications, e.g. coinductive logic programming. But the handling of cyclic terms is not standardized and varies among Prolog systems. The ISO Prolog standard provides a built-in predicate, unify_with_occurs_check/2, that checks if unification will create a cyclic term, preventing it. For example:
| ?- unify_with_occurs_check(X, f(X)).
no
| ?- unify_with_occurs_check(X, Y).
Y = X
(1 ms) yes

Single clause with if-the-else vs multiple clause predicates

Let's say I want to implement a predicate that 'returns' a list of all elements shared by a list of lists.
I can implement it as a one clause (looks bit ugly for logic programing):
shared_members(Members, Lists) :-
Lists = [] ->
Members = []
; findall(M, (maplist(member(M), Lists)), Members).
or as a set of clauses:
shared_members([], []). % possibly adding cut here to increase effciency
shared_members(Members, Lists) :-
findall(M, (maplist(member(M), Lists)), Members).
Which implementation is considered to be more efficient?
I know it depends on the Prolog implementation but maybe there is a general stand about efficiency of these cases.
In this case, you don't even need the first clause shared_member([], []). The findall/3 call will result in Members = [] if Lists = [].
The question is still interesting, though, and so we'll ignore this for now. You could run some stats to determine time-efficiency. Memory efficiency difference is negligible. The second approach given, however, is considered to be the canonical approach in Prolog. But they are also not equivalent in their behavior. The "if-else" in Prolog, as represented by p1 -> p2 ; p3 cuts removes the choice point after evaluation of p1. It's equivalent to p1, !, p2 ; p3.
Here's why this matters. I'll use a contrived example (which also does not require both clauses, but illustrates the point). I'll define a len/2 predicate that is true if the first argument is the length of the second:
len(0, []).
len(N, L) :- length(L, N).
Obviously, as in the case of the original problem, the first clause here is redundant, but it is important for this illustration. If I run this query, I get the following results:
| ?- len(N, [a,b,c]).
N = 3
yes
| ?- len(3, L).
L = [_,_,_]
yes
| ?- len(N, L).
L = []
N = 0 ? ;
L = []
N = 0 ? ;
L = [_]
N = 1 ? ;
L = [_,_]
N = 2 ? ;
L = [_,_,_]
N = 3 ?
Note that if both arguments are variable, it enumerates solutions. (Also, due to the redundant first clause, one of the solutions appears twice.)
Let's rewrite this predicate using "if-else":
len(N, L) :-
( L = []
-> N = 0
; length(L, N)
).
And we'll run it:
| ?- len(N, [a,b,c]).
N = 3
yes
So far, so good. But...
| ?- len(3, L).
no
| ?- len(N, L).
L = []
N = 0
yes
| ?-
Yikes! This is quite different. What happened?
In the second approach, ( L = [] -> N = 0 ; length(L, N) ) first attempts to unify L and []. If L is a variable, this succeeds with L = []. Since it succeeded, Prolog then attempts to unify N = 0. But with the query len(3, L), N is already bound to 3. So N = 0 fails and the entire clause fails.
Using the -> ; construct then, in this case, greatly reduces the generality of the implementation and yields incorrect results in some of the call scenarios.

Create successor numbers from natural numbers

I want to create successor Numbers from natural numbers in Prolog.
nat2s(0, s(0)).
nat2s(NaturalNumber, SNumber) :-
N is NaturalNumber - 1,
nat2s(N, s(SNumber)).
The output should be like this:
nat2s(3, X).
X = s(s(s(0))).
Actually it's an infinitive loop. I don't how to end the loop without only getting true as result.
I suggest a slightly different approach, namely the use of library(clpfd). First let's pick a more declarative name for the predicate. Since in your post the natural number and the number in s(X)-notation are the first and second argument respectively, let's call it nat_sx/2. Then the predicate can be defined like so:
:- use_module(library(clpfd)).
nat_sx(0,0).
nat_sx(N,s(X)) :-
N #> 0,
N0 #= N-1,
nat_sx(N0,X).
This yields the desired result in your post:
?- nat_sx(3,X).
X = s(s(s(0))) ? ;
no
To see why the use of clpfd is beneficial let's incorporate the suggested corrections from the comments into your code and compare both versions.
nat2s(0, 0).
nat2s(NaturalNumber, s(SNumber)) :-
NaturalNumber > 0,
N is NaturalNumber - 1,
nat2s(N, SNumber).
The above query works with this version as well:
?- nat2s(3,S).
S = s(s(s(0))) ? ;
no
However, it would be nice to be able to use the predicate in the other direction as well. So let's ask which natural number corresponds to s(s(0)):
?- nat_sx(N,s(s(0))).
N = 2 ? ;
no
?- nat2s(N,s(s(0))).
ERROR at clause 2 of user:nat2s/2 !!
INSTANTIATION ERROR- =:=/2: expected bound value
The reason for the instantiation error is the fact that is/2 expects a variable-free expression on the right side:
?- X is 3-1.
X = 2
?- 2 is X-1.
ERROR!!
INSTANTIATION ERROR- in arithmetic: expected bound value
?- 2 is 3-X.
ERROR!!
INSTANTIATION ERROR- in arithmetic: expected bound value
This is also the reason why the most general query of nat2s/2 has an instantiation error after the first solution...
?- nat2s(N,S).
N = S = 0 ? ;
ERROR at clause 2 of user:nat2s/2 !!
INSTANTIATION ERROR- =:=/2: expected bound value
... while nat_sx/2 keeps generating solutions:
?- nat_sx(N,S).
N = S = 0 ? ;
N = 1,
S = s(0) ? ;
N = 2,
S = s(s(0)) ? ;
...

Prolog: comparing predicate value with constant

I have some problems with prolog, specifically I can't compare a value of a predicate with a constant.
predicate(9).
compare(X,Y) :- X<Y.
Running the program:
?-compare(predicate(X),10).
Why doesn't it work? Thank you for your answers.
Predicates don't return values in the way that a function does.
This is C:
int nine() { return 9; }
int main() {
int x = nine(); /* x is now 9 */
}
This is Prolog:
% source
nine(9).
% from the top level
?- nine(X).
X = 9.
?- nine(X), X < 10.
X = 9.
?- nine(X), compare(C1, X, 10), compare(C2, 10, X).
X = 9,
C1 = (<),
C2 = (>).
Few things (trying not to use too much Prolog lingo):
What your predicate/1 and my nine/1 does is to unify its only argument with the integer 9. If the unification succeeds, the predicate succeeds, and now the argument is bound to 9. If the unification fails, the predicate fails.
?- nine(9).
true.
?- nine(nine).
false.
?- nine(X), nine(Y).
X = Y, Y = 9.
You will also notice that there is a standard predicate compare/3 that can be used for comparison of Prolog terms. Because predicates don't have a return value in the way that functions do, it uses an extra argument to report the result of the comparison. You could have instead tried something along the lines of:
% greater_than(X, Y) : true if X is greater than Y according
% to the standard order of terms
greater_than(X, Y) :- X #> Y.
But this is just defining an alias for #>/2, which is a predicate itself (but has been declared as an operator so that you can use it in infix notation).
?- #>(a, b).
false.
?- #>(b, a).
true.
Same goes for </2, which is a predicate for comparison of arithmetic expressions:
?- 2 + 4 =< 6.
true.
?- nine(X), X > 10 - X.
X = 9.
?- nine(X), X > 10.
false.
Like #Boris said before "Predicates don't return values in the way that a function does." Here you must try to instantiate the variables in the head of your rule.
If you are trying with you predicate compare/2 to find a number X greater than Y, and at the same time this number X should be a fact predicate/1, then add both conditions to the body of your rule or predicate compare/2
predicate(9).
compare(X,Y) :- predicate(X), X<Y.
Now if you consult:
?- compare(X,10).
The answer will be
X = 9
As you can see, 9 is smaller than 10, and at the same time 9 is a fact predicate/1. And that is the return value you are looking for.
Caution
Note that the operator >/2, requires that both sides are instantiated, so in this case you won't be able ask for the value Y in your predicate
?- compare(9, Y)
</2: Arguments are not sufficiently instantiated
Maybe and if it make sense, you can try to instantiate this variable to a fact predicate/1 too.
predicate(9).
predicate(10).
compare(X,Y) :- predicate(X), predicate(Y), X<Y.
?- compare(9,Y).
Y = 10

Extracting sequences (Lists) Prolog

Given a list eg [1,2,3,7,2,5,8,9,3,4] how would I extract the sequences within the list?
A sequence is defined as an ordered list (Normally I would say n-tuple but I have been told in prolog a tuple is referred to as a sequence). So we want to cut the list at the point where the next element is smaller than the previous one.
So for the list [1,2,3,7,2,5,8,9,3,4] it should return:
[ [1,2,3,7], [2,5,8,9], [3,4] ] %ie we have cut the list at position 4 & 8.
For this exercise you CANNOT use the construct ; or ->
Many thanks in advance!
EXAMPLE RESULTS:
eg1.
?-function([1,2,3,7,2,5,8,9,3,4],X): %so we cut the list at position 4 & 9
X = [ [1,2,3,7], [2,5,8,9], [3,4] ].
eg2.
?-function([1,2,3,2,2,3,4,3],X): %so we cut the list at position 3,4 & 8
X = [ [1,2,3], [2], [2,3,4], [3] ].
Hopefully that helps clarify the problem. If you need further clarification just let me know! Thanks again in advance for any help you are able to provide.
First, let's break it down conceptually. The predicate list_ascending_rest/3 defines a relation between a list Xs, the left-most ascending sublist of maximum length Ys, and the remaining items Rest. We will use it like in the following query:
?- Xs = [1,2,3,7,2,5,8,9,3,4], list_ascending_rest(Xs,Ys,Rest).
Ys = [1,2,3,7],
Rest = [2,5,8,9,3,4] ;
false.
The straight-forward predicate definition goes like this:
:- use_module(library(clpfd)).
list_ascending_rest([],[],[]).
list_ascending_rest([A],[A],[]).
list_ascending_rest([A1,A2|As], [A1], [A2|As]) :-
A1 #>= A2.
list_ascending_rest([A1,A2|As], [A1|Bs], Cs) :-
A1 #< A2,
list_ascending_rest([A2|As], Bs,Cs).
Then, let's implement predicate list_ascendingParts/2. This predicate repeatedly uses list_ascending_rest/3 for each part until nothing is left.
list_ascendingParts([],[]).
list_ascendingParts([A|As],[Bs|Bss]) :-
list_ascending_rest([A|As],Bs,As0),
list_ascendingParts(As0,Bss).
Example queries:
?- list_ascendingParts([1,2,3,7,2,5,8,9,3,4],Xs).
Xs = [[1,2,3,7], [2,5,8,9], [3,4]] ;
false.
?- list_ascendingParts([1,2,3,2,2,3,4,3],Xs).
Xs = [[1,2,3], [2], [2,3,4], [3]] ;
false.
Edit 2015/04/05
What if the ascending parts are known but the list is unknown? Let's find out:
?- list_ascendingParts(Ls, [[3,4,5],[4],[2,7],[5,6],[6,8],[3]]).
Ls = [3,4,5,4,2,7,5,6,6,8,3] ? ;
no
And let's not forget about the most general query using list_ascendingParts/2:
?- assert(clpfd:full_answer).
yes
?- list_ascendingParts(Ls, Ps).
Ls = [], Ps = [] ? ;
Ls = [_A], Ps = [[_A]] ? ;
Ls = [_A,_B], Ps = [[_A],[_B]], _B#=<_A, _B in inf..sup, _A in inf..sup ? ...
Edit 2015-04-27
Room for improvement? Yes, definitely!
By using the meta-predicate splitlistIfAdj/3 one can "succeed deterministically" and "use non-determinism when required", depending on the situation.
splitlistIfAdj/3 is based on if_/3 as proposed by #false in this answer. So the predicate passed to it has to obey the same convention as (=)/3 and memberd_truth/3.
So let's define (#>)/3 and (#>=)/3:
#>=(X,Y,Truth) :- X #>= Y #<==> B, =(B,1,Truth).
#>( X,Y,Truth) :- X #> Y #<==> B, =(B,1,Truth).
Let's re-ask above queries, using splitlistIfAdj(#>=)
instead of list_ascendingParts:
?- splitlistIfAdj(#>=,[1,2,3,7,2,5,8,9,3,4],Pss).
Pss = [[1,2,3,7],[2,5,8,9],[3,4]]. % succeeds deterministically
?- splitlistIfAdj(#>=,[1,2,3,2,2,3,4,3],Pss).
Pss = [[1,2,3],[2],[2,3,4],[3]]. % succeeds deterministically
?- splitlistIfAdj(#>=,Ls,[[3,4,5],[4],[2,7],[5,6],[6,8],[3]]).
Ls = [3,4,5,4,2,7,5,6,6,8,3] ; % works the other way round, too
false. % universally terminates
Last, the most general query. I wonder what the answers look like:
?- splitlistIfAdj(#>=,Ls,Pss).
Ls = Pss, Pss = [] ;
Ls = [_G28], Pss = [[_G28]] ;
Ls = [_G84,_G87], Pss = [[_G84],[_G87]], _G84#>=_G87 ;
Ls = [_G45,_G48,_G41], Pss = [[_G45],[_G48],[_G41]], _G45#>=_G48, _G48#>=_G41
% and so on...
maplist/3 as suggested in the comment won't help you here because maplist/3 is good at taking a list and mapping each element into a same-size collection of something else, or establishing a relation evenly across all of the individual elements. In this problem, you are trying to gather contiguous sublists that have certain properties.
Here's a DCG solution. The idea here is to examine the list as a series of increasing sequences where, at the boundary between them, the last element of the prior sequence is less than or equal to the first element of the following sequence (as the problem statement basically indicates).
% A set of sequences is an increasing sequence ending in X
% followed by a set of sequences that starts with a value =< X
sequences([S|[[Y|T]|L]]) --> inc_seq(S, X), sequences([[Y|T]|L]), { X >= Y }.
sequences([S]) --> inc_seq(S, _).
sequences([]) --> [].
% An increasing sequence, where M is the maximum value
inc_seq([X,Y|T], M) --> [X], inc_seq([Y|T], M), { X < Y }.
inc_seq([X], X) --> [X].
partition(L, R) :- phrase(sequences(R), L).
| ?- partition([1,2,3,4,2,3,8,7], R).
R = [[1,2,3,4],[2,3,8],[7]] ? ;
(1 ms) no
| ?- partition([1,2,3,2,2,3,4,3],X).
X = [[1,2,3],[2],[2,3,4],[3]] ? ;
(1 ms) no
The only reason for the rule sequences([]) --> []. is if you want partition([], []) to be true. Otherwise, the rule isn't required.

Resources