Counting definite clause grammar recursions in Prolog - prolog

I have the following Prolog definite clause grammar:
s-->[a],s,[b].
s-->[].
This will result in words like [a,a,b,b] being accepted in opposite to words like [a,b,a,b]. To put it in a nutshell the grammar is obviously a^n b^n. Now I want to return n to the user. How can I calculate n?

s(X)-->[a],s(Y),[b],{X is Y+1}.
s(0)-->[].
One needs to give parameters to the DCG non terminals. Please take care equality doesn't work exactly like assignment of imperative programming languages so X is Y + 1 was used.
Some sample outputs:
s(X,[a,b,b,b],[]).
false.
s(X,[a,a,a,b,b,b],[]).
X = 3 ;
false.

s(N, M) --> [a], {N1 is N + 1}, s(N1, M), [b].
s(N, N) --> [].
s(N) --> s(0, N).
Usage:
?- phrase(s(N), [a,a,a,b,b,b]).
N = 3

The answers by #thequark and by #LittleBobbyTables work fine when used with ground strings.
But what if they are not bounded in length, like in the following queries?
?- phrase(s(3),_). % expected: success
% observed: no answer(s)
?- phrase(s(-10),_). % expected: failure
% observed: no answer(s)
We surely want queries like the one above to terminate universally!
Let's use clpfd and write:
:- use_module(library(clpfd)).
s(0) --> [].
s(N) --> {N#>0,N#=N0+1},[a],s(N0),[b].
Sample queries:
?- phrase(s(N),[a,a,a,a,b,b,b,b]).
N = 4 ; % works like in the other answers
false.
?- phrase(s(3),Xs).
Xs = [a,a,a,b,b,b] ; % now, this works too!
false. % (terminates universally)
?- phrase(s(-10),_). % fails, like it should
false.

Related

Function to find a list in prolog

I am new to Prolog and I am trying to write a function that finds a list that follows some rules.
More specifically, given two numbers, N and K, I want my function to find a list with K powers of two that their sum is N. The list must not contain each power but the total sum of each power. For example if N=13 and K=5, I want my list to be [2,2,1] where the first 2 means two 4, the second 2 means two 2, and the third 1 means one 1 (4+4+2+2+1=13). Consider that beginning from the end of the list each position i represents the 2^i power of 2. So I wrote this code:
sum2(List, SUM, N) :-
List = [] -> N=SUM;
List = [H|T],
length(T, L),
NewSUM is SUM + (H * 2**L),
sum2(T, NewSUM, N).
powers2(N,K,X):-
sum2(X,0,N),
sum_list(X, L),
K = L.
The problem is:
?- sum2([2,2,1],0,13).
true.
?- sum2([2,2,1],0,X).
X = 13.
?- sum2(X,0,13).
false.
?- powers2(X,5,[2,2,1]).
X = 13.
?- powers2(13,5,[2,2,1]).
true.
?- powers2(13,X,[2,2,1]).
X = 5.
?- powers2(13,5,X).
false.
In the cases, X represents the list I expected the output to be a list that follows the rules and not false. Could you help me to find how can I solve this and have a list for output in these cases?
The immediate reason for the failure of your predicate with an unbound list is due to your use of the -> construct for control flow.
Here is a simplified version of what you are trying to do, a small predicate for checking whether a list is empty or not:
empty_or_not(List, Answer) :-
( List = []
-> Answer = empty
; List = [H|T],
Answer = head_tail(H, T) ).
(Side note: The exact layout is a matter of taste, but you should always use parentheses to enclose code if you use the ; operator. I also urge you to never put ; at the end of a line but rather in a position where it really sticks out. Using ; is really an exceptional case in Prolog, and if it's formatted too similarly to ,, it can be hard to see that it's even there, and what parts of the clause it applies to.)
And this seems to work, right?
?- empty_or_not([], Answer).
Answer = empty.
?- empty_or_not([1, 2, 3], Answer).
Answer = head_tail(1, [2, 3]).
OK so far, but what if we call this with an unbound list?
?- empty_or_not(List, Answer).
List = [],
Answer = empty.
Suddenly only the empty list is accepted, although we know from above that non-empty lists are fine as well.
This is because -> cuts away any alternatives once it has found that its condition is satisfied. In the last example, List is a variable, so it is unifiable with []. The condition List = [] will succeed (binding List to []), and the alternative List = [H|T] will not be tried. It seems simple, but -> is really an advanced feature of Prolog. It should only be used by more experienced users who know that they really really will not need to explore alternatives.
The usual, and usually correct, way of implementing a disjunction in Prolog is to use separate clauses for the separate cases:
empty_or_not([], empty).
empty_or_not([H|T], head_tail(H, T)).
This now behaves logically:
?- empty_or_not([], Answer).
Answer = empty.
?- empty_or_not([1, 2, 3], Answer).
Answer = head_tail(1, [2, 3]).
?- empty_or_not(List, Answer).
List = [],
Answer = empty ;
List = [_2040|_2042],
Answer = head_tail(_2040, _2042).
And accordingly, your definition of sum2 should look more like this:
sum2([], SUM, N) :-
N = SUM.
sum2([H|T], SUM, N) :-
length(T, L),
NewSUM is SUM + (H * 2**L),
sum2(T, NewSUM, N).
This is just a small step, however:
?- sum2(X, 0, 13).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] _2416 is 0+_2428* ...
ERROR: [8] sum2([_2462],0,13) at /home/gergo/sum.pl:5
ERROR: [7] <user>
You are trying to do arithmetic on H, which has no value. If you want to use "plain" Prolog arithmetic, you will need to enumerate appropriate values that H might have before you try to do arithmetic on it. Alternatively, you could use arithmetic constraints. See possible implementations of both at Arithmetics in Prolog, represent a number using powers of 2.

Use of redundant goals in queries

(Upon the suggestion of #repeat) Consider a query of a pure program1 ?- G_0. What use if any would the query ?- G_0, G_0. have?
Footnotes
1 No tabling (to be safe), constraints are OK.
Previous post on the subject.
The query ?- G_0, G_0. helps to identify redundant answers of ?- G_0.
To do so it suffices to compare the number of answers of ?- G_0. with the number of answers of ?- G_0, G_0.. No need to store those answers (which is a frequent source of errors anyway). Just two integers suffice! If they are equal, then there is no redundancy. But if ?- G_0, G_0. has more answers, then there is some redundancy. Here is an example:
p(f(_,a)).
p(f(b,_)).
?- p(X).
X = f(_A, a)
; X = f(b, _A). % two answers
?- p(X), p(X).
X = f(_A, a)
; X = f(b, a)
; X = f(b, a)
; X = f(b, _A). % four answers
% thus p(X) contains redundancies
... and now let's fix this:
p(f(B,a)) :-
dif(B, b).
p(f(b,_)).
?- p(X).
X = f(_A, a), dif(_A, b)
; X = f(b, _A).
?- p(X), p(X).
X = f(_A, a), dif(_A, b), dif(_A, b).
; X = f(b, _A). % again two answers, thus no redundancy
No need to manually inspect the constraints involved.
This can be further extended when we are explicitly searching for redundant answers only using call_nth/2.
?- G_0, call_nth(G_0, 2).
Consider a query of a pure program1 ?- G_0. What use if any would the query ?- G_0, G_0. have?
I see no usefulness of the second goal, especially when tail recursion optimization (last call optimization) is ON.
I could realize an GC issue (stack/heap overflow) when the query is resources-greedy and above options are OFF (e.g. when debugging).
I think the second call is redundant (for pure program) and should be eliminated by the compiler.

Prolog - Backtracking through a set of dynamic options

I'm trying to trigger backtracking on a goal but in a dynamic way, if it's possible. To better exemplify my issue let's say we have the following PROLOG code:
num(1).
num(2).
num(3).
num(4).
num(5).
Then I head to SWI-Prolog and call: num(X). This triggers backtracking looking for all solutions, by typing ; .
What I would like is to remove those facts (num(1),num(2), etc) and replace that code with something thata generates those facts dynamically. Is there any way in which I can achieve this? Someting of the sorts,maybe?
num(X):- for X in 1..5
that yields the same solutions as the code above?
As far as I know, the findall predicate returns a list, which is not what I'm looking for. I would like to backtrack through all answers and look through them using ; in the console.
Yes there is, and you were already very close!
:- use_module(library(clpfd)).
num(X) :-
X in 1..5.
?- num(X).
X in 1..5.
?- num(X), X #>3.
X in 4..5.
?- num(X), labeling([], [X]).
X = 1
; X = 2
; X = 3
; X = 4
; X = 5.
SWI-Prolog has the (non-ISO) predicate between/3 for that:
num(X) :- between(1, 5, X).
You can implement the predicate (for other Prologs and for further tweaking) like this:
between2(A, A, A) :- !. % green cut
between2(A, B, A) :- A < B.
between2(A, B, C) :-
A < B,
A1 is A + 1,
between2(A1, B, C).
The signature for both between/3 and between2/3 is (+From,+To,?X). It means that the From and To must be bound and X can be either bound or not. Also note that From and To must be integers such that From <= To. (Oh, and these integers must be written using Arabic numerals with an optional plus or minus sign before. And using ASCII. Is something non-obvious still missed? And the integers must not be too large or too small, although SWI-Prolog is usually compiled with unbounded integer support, so both between(1, 100000000000000000000000000000000000000000000, X) and between2(1, 100000000000000000000000000000000000000000000, X) usually work.)

Why do I get duplicate results in my `length/2` implementation in prolog?

I'm working through exercises in Prolog. I've implemented a predicate similar to length/2 (called ue_length here) like this:
%%
% ue_length/2
%%
% not a list predicate
\+(T) :- call(T), !, fail.
\+(_).
% target case
ue_length(List, Length) :- \+(is_list(List)), !, fail.
ue_length(List, Length) :- ue_length(List, 0, Length).
% standard cases
ue_length([], Length, Length).
ue_length([X], Part, Length) :- ue_length([], [Part], Length).
ue_length([X| Rest], Part, Length) :- ue_length(Rest, [Part], Length).
The result is supposed to be a term rather than a number: 0 for [], [0] for a list of length one and [...[0]...] (n brackets) for a list of length n.
When I query Prolog (SWI-Prolog 6) with e.g. [1,2,3,4,5] I get the correct result twice.
?- ue_length([1,2,3,4,5], X).
X = [[[[[0]]]]]
X = [[[[[0]]]]].
I'm new to Prolog. Can someone explain why I get a redundant result?
Minimize the problematic query
As a first step, reduce the size of your query. The same problem (redundant solutions) can be observed already with ue_length([1], X). alone.
But there is something else which is much more problematic:
Is your definition a relation?
?- ue_length(L,N).
false.
So your definition succeeds with a list [1] but fails with a variable in its place? This does not make any sense at all! Even looping would be a better behavior.
Another problematic case is
?- ue_length(L,0).
false.
Here, your definition should give L = [] as answer.
The culprit for this is the test using is_list/1. Simply drop the rule
ue_length(List, Length) :- \+(is_list(List)), !, fail. % incorrect!
Now your definition can also be used to ask the most general query which contains distinct variables in the arguments.
?- ue_length(L,N).
L = [], N = 0
; L = [_A], N = [0]
; L = [_A], N = [0]
; L = [_A, _B], N = [[0]]
...
This is one of the very nice properties of Prolog: You do not need to type in concrete data for your test cases. Just enter the most general query like a pro, and Prolog will do the rest for you.
Localize with false
To localize this redundancy, first think of how that could have happened. One simple possibility is that some clause in your program is redundant and can thus be deleted.
Let's say it's the last one. So I will insert a goal false into the last clause. And I try again the most general query. Alas ...
ue_length(List, Length) :- ue_length(List, 0, Length).
% standard cases
ue_length([], Length, Length).
ue_length([_X], Part, Length) :-
ue_length([], [Part], Length).
ue_length([_X| Rest], Part, Length) :-
false,
ue_length(Rest, [Part], Length).
?- ue_length(L,N).
L = [], N = 0
; L = [_A], N = [0]
; false.
That rule must be quite important, for now we get only answers for lists of length zero and one. So my guess was wrong. But my point is that you can see this very easily by simply using the most general query. The actual redundant clause is the other one. And don't forget to ask the most general query such that you can be sure you get all your answers!

Implement a Prolog predicate that say if an element belong to a list. Problems with not numerical lists

I am studying Prolog for an university exam and I have problems with this exercise:
Implement the predicate not_member(X,L) that is TRUE if the element X does not belong to the list L.
If my reasoning is correct, I have found a solution:
% FACT (BASE CASE): It is TRUE that X is not in the list if the list is empty.
not_member(_,[]).
% RULE (GENERAL CASE): If the list is non-empty, I can divide it in its Head
% element and the sublist Tail. X does not belong to the list if it is different
% from the current Head element and if it does not belong to the sublist Tail.
not_member(X,[Head|Tail]) :-
X =\= Head,
not_member(X,Tail).
This code works well with lists of numbers, as the following queries show:
2 ?- not_member(4, [1,2,3]).
true.
3 ?- not_member(1, [1,2,3]).
false.
With lists having some non-numerical elements, however,
it does not work and reports an error:
4 ?- not_member(a, [a,b,c]).
ERROR: =\=/2: Arithmetic: `a/0' is not a function
Why?
Let's check the documentation!
(=\=)/2 is an arithmetic operator.
+Expr1 =\= +Expr2
True if expression Expr1 evaluates to a number non-equal to Expr2.
You have to use (\=)/2 to compare two generic terms:
not_member(_, []) :- !.
not_member(X, [Head|Tail]) :-
X \= Head,
not_member(X, Tail).
and:
?- not_member(d, [a,b,c]).
true.
Use prolog-dif to get logically sound answers—for both ground and non-ground cases!
Just like in this answer, we define non_member(E,Xs) as maplist(dif(E),Xs).
Let's put maplist(dif(E),Xs) and not_member(E,Xs) by #Haile to the test!
?- not_member(E,[1,2,3]).
false. % wrong! What about `E=4`?
?- maplist(dif(E),[1,2,3]).
dif(E,1), dif(E,2), dif(E,3). % success with pending goals
Is it steadfast? (For more info on this important issue, read
this, this, this, and this answer.)
?- E=d, not_member(E,[a,b,c]).
E = d.
?- not_member(E,[a,b,c]), E=d.
false. % not steadfast
?- E=d, maplist(dif(E),[a,b,c]).
E = d.
?- maplist(dif(E),[a,b,c]), E=d. % steadfast
E = d.
Let's not forget about the most general use!
?- not_member(E,Xs).
Xs = []. % a lot of solutions are missing!
?- maplist(dif(E),Xs).
Xs = []
; Xs = [_A] , dif(E,_A)
; Xs = [_A,_B] , dif(E,_A), dif(E,_B)
; Xs = [_A,_B,_C], dif(E,_A), dif(E,_B), dif(E,_C)
...

Resources