Prolog membership predicate without dif or when - prolog

The following prolog logic
memberd(X, [X|_T]).
memberd(X, [Y| T]) :- dif(X,Y), memberd(X, T).
will produce
?- memberd(a, [a, b, a]).
true
?- memberd(X, [a, b, a]).
X = a ;
X = b ;
false.
?- memberd(X, [a, b, a, c, a, d, b]).
X = a ;
X = b ;
X = c ;
X = d ;
false.
is there prolog logic that can be used to produce the same result without using when() or dif() function or anything from a loaded prolog library. Just using pure logic?

To answer your question literally, just use:
?- setof(t, member(X, [a,b,a]), _).
X = a
; X = b.
However, some answers will be suboptimal:
?- setof(t,member(a,[a,X]),_).
true
; X = a. % redundant
... whereas memberd/2 answers in perfection:
?- memberd(a,[a,X]).
true
; false.
In fact, if you use library(reif) with
memberd(E, [X|Xs]) :-
if_(E = X, true, memberd(E, Xs) ).
you get the best answer possible:
?- memberd(a,[a,X]).
true.

Related

How to program in Prolog a function that does operations on lists

How can I make a program in Prolog that contains n numbers of a and n numbers of b, it's important to note here that the number of a and b in the list must be equal, also the list must always start with a and finish with b, otherwise it's false. Example : [a,b] is true, [a,a,a,b,b,b] is true, [a,a,a,a] is false and [a,a,a,b,b] is also false.
Here is what I tried to do :
langageB([b]).
langageB([b| S]):- langageB(S).
language([]).
langage([a,b]).
langage([a | S]):- langage(S).
langage([a| S]):- langageB(S).
But it does not work as I want it to.
Using DCG notation, the desired language can be defined as:
langage --> [a,b].
langage --> [a], langage, [b]. % For each a at the beginning of the list
% there must be a corresponding b at the end
langage(List) :- phrase(langage, List).
Examples:
?- langage([a,a,a,b,b,b]).
true .
?- langage([a,a,b,b,b]).
false.
?- langage(L).
L = [a, b] ;
L = [a, a, b, b] ;
L = [a, a, a, b, b, b] ;
L = [a, a, a, a, b, b, b, b] .
If you want to see how to define the predicate directly using difference lists, you can list the clauses of the predicate langage/2:
?- listing(langage).
langage([a, b|A], A).
langage([a|A], B) :-
langage(A, C),
C=[b|B].
So, an alternative solution is:
langage(List) :-
langage(List, []).
langage([a, b|A], A).
langage([a|A], B) :-
langage(A, C),
C = [b|B].
langage --> [a], ( [] | langage ) , [b].
?- phrase(langage, Xs).
Xs = "ab"
; Xs = "aabb"
; Xs = "aaabbb"
; Xs = "aaaabbbb"
; Xs = "aaaaabbbbb"
; ... .
Assuming e.g. [a, b, a, b] is an acceptable list:
go :-
findnsols(20, ABs, ab_list(ABs), ABsLst), !,
writeln(ABsLst).
ab_list(ABsWrapped) :-
length(ABs, Len),
ab_list_(Len, 0, [], ABs),
append([[a], ABs, [b]], ABsWrapped).
ab_list_(0, 0, ABs, ABs) :- !.
ab_list_(CharsToAdd, Bal, SoFar, ABs) :-
succ(CharsToAdd0, CharsToAdd),
add_char(Char, Inc),
Bal1 is Bal + Inc,
% Ensure that the balance can be zero for the complete list
CharsToAdd0 >= abs(Bal1),
ab_list_(CharsToAdd0, Bal1, [Char|SoFar], ABs).
add_char(b, -1).
add_char(a, 1).
Results:
?- time(go).
[[a,b],[a,a,b,b],[a,b,a,b],[a,a,a,b,b,b],[a,a,b,a,b,b],[a,b,a,a,b,b],[a,a,b,b,a,b],[a,b,a,b,a,b],[a,b,b,a,a,b],[a,a,a,a,b,b,b,b],[a,a,a,b,a,b,b,b],[a,a,b,a,a,b,b,b],[a,b,a,a,a,b,b,b],[a,a,a,b,b,a,b,b],[a,a,b,a,b,a,b,b],[a,b,a,a,b,a,b,b],[a,a,b,b,a,a,b,b],[a,b,a,b,a,a,b,b],[a,b,b,a,a,a,b,b],[a,a,a,b,b,b,a,b]]
% 935 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 1419728 Lips)
Original: Here's a (very inefficient) solution as a one-liner in swi-prolog:
length(As, 2), same_length(As, Bs), maplist(=(a), As), maplist(=(b), Bs), append([As, Bs], ABs), distinct(ABsPerm, permutation(ABs, ABsPerm)), append([[a], ABsPerm, [b]], Final).

bagof/3 is unpredictable

I am baffled by the following results. I am using SWI-Prolog.
?- bagof(Q, (Q=A, (A=[a,_] ; A=[_,b])), X).
A = [_G16898, b],
X = [[_G16898, b]] ;
A = [a, _G16892],
X = [[a, _G16892]].
Notice that [a,_] and [_,b] are not unified to produce an answer A = [a,b], X=[[a,b],[a,b]].
Now, lets try the same with arithmetic constraints:
?- bagof(Q, (Q=A, (A in 1..5 ; A in 3..8)), X).
X = [A, A],
A in 3..5.
Strangely, this time the arithmetic constraints are taken together but there are no answers A in 1..5, X=[A] and A in 3..8, X=[A].
Now lets try this in yet another way:
?- bagof(Q, (Q=A, ((1 #=< A, A #=< 5) ; (3 #=< A, A #=< 8))), X).
X = [A],
A in 3..5 ;
X = [A],
A in 3..5.
The arithmetic constraints are combined like before, but we have two answers instead of one.
How can all this be explained?
EDIT: Some more strange results. Compare this:
?- A=[_,_], bagof(Q, K1^K2^(Q=A, (A=[a,K1] ; A=[K2,b])), X).
A = [_G16886, b],
X = [[_G16886, b]] ;
A = [a, _G16889],
X = [[a, _G16889]].
with this:
?- A=[a,b], bagof(Q, K1^K2^(Q=A, (A=[a,K1] ; A=[K2,b])), X).
A = [a, b],
X = [[a, b], [a, b]].
Thats an artefact of SWI-Prolog, which also does copy attributed variables while taking findall/3 copies. findall/3 copies are used inside bagof/3 before doing keysort/2. But the effect can already be explained by means of findall/3:
SWI-Prolog, findall/3 copies attributed variables conditions:
?- findall(A, A in 1..5, L).
L = [_3464],
_3464 in 1..5.
?- findall(A, (A in 1..5, (true; true)), L).
L = [_3762, _3768],
_3762 in 1..5,
_3768 in 1..5
Jekejeke Prolog, findall/3 does not copy attributed variables conditions:
?- findall(A, A in 1..5, L).
L = [_A]
?- findall(A, (A in 1..5, (true; true)), L).
L = [_A, _B]
Inside bagof/3, there is not only a keysort/2 step, but also step where variables are restored. In this step for SWI-Prolog, constraints might be joined, since constraints will be present.
This explains the first result in the question of the OP. The second result in the question of the OP can be explained in that SWI-Prolog does goal expansion and introduce new variables in the case of (#=<)/2. You can check yourself:
?- [user].
test(A) :- A in 1..5 ; A in 3..8.
test(A) :- (1 #=< A, A #=< 5) ; (3 #=< A, A #=< 8).
?- listing(test/1).
test(A) :-
( ( integer(A)
-> between(1, 5, A)
; clpfd:clpfd_in(A, 1..5)
)
; integer(A)
-> between(3, 8, A)
; clpfd:clpfd_in(A, 3..8)
).
test(A) :-
( ( integer(A)
-> A>=1
; B=1,
clpfd:clpfd_geq(A, B)
),
( integer(A)
-> 5>=A
; C=5,
clpfd:clpfd_geq(C, A)
)
; ( integer(A)
-> A>=3
; D=3,
clpfd:clpfd_geq(A, D)
),
( integer(A)
-> 8>=A
; E=8,
clpfd:clpfd_geq(E, A)
)
).
There are no fresh variables in the expansion of (in)/2. But I guess the fresh variables inside the (#=<)/2 expansion, then causes bagof/3 to see two solutions, instead of only one.
Edit 19.08.2019:
Now I wonder how tabling with CLP(FD) solves the problem...

How to write earlier statement in prolog?

I was looking at prolog progrm and was unable to understand the following
earlier(X, _, [X|_]).
earlier(_, Y, [Y|_]) :- !, fail.
earlier(X, Y, [_|T]) :- earlier(X, Y, T).
Can anyone explain what does it mean??
As the name suggests, earlier(X, Y, Zs) is apparently supposed to check whether the element X appears earlier than the first occurrence of Y in the list Zs. It kind of does this:
?- earlier(a, b, [a, b, c, d]).
true ;
false.
?- earlier(b, d, [a, b, c, d]).
true ;
false.
With peculiar handling if the second argument is not in the given list:
?- earlier(a, not_in_list, [a, b, c, d]).
true ;
false.
How does this work? The first clause says that if X is the head of the list, then X appears earlier in the list than anything, represented by the anonymous variable _. The second clause says that if Y is the head of the list, then nothing (_ in first argument position) is before Y. In this case, the predicate fails and uses a cut to avoid finding spurious solutions. The third clause just recurses on the list of neither the first nor second clauses applied.
Due to the cut, this definition is not very declarative, and some interesting uses don't work as one might expect:
?- earlier(X, Y, Zs).
Zs = [X|_G947] ;
false.
?- earlier(a, b, Zs).
Zs = [a|_G923] ;
false.
?- earlier(X, Y, [a, b, c, d]).
X = a ;
false.
The last case, in particular, might be interesting for some use cases. Here is a more declarative version:
earlier_than(X, Y, Zs) :-
append(InitialPart, [X | _Rest], Zs),
notmember_of(Y, InitialPart).
notmember_of(_X, []).
notmember_of(X, [Y|Xs]) :-
dif(X, Y),
notmember_of(X, Xs).
You can use this to enumerate solutions more nicely:
?- earlier_than(X, Y, Zs).
Zs = [X|_G947] ;
Zs = [_G1162, X|_G1166],
dif(Y, _G1162) ;
Zs = [_G1254, _G1257, X|_G1261],
dif(Y, _G1257),
dif(Y, _G1254) ;
Zs = [_G1346, _G1349, _G1352, X|_G1356],
dif(Y, _G1352),
dif(Y, _G1349),
dif(Y, _G1346) .
?- earlier_than(a, b, Zs).
Zs = [a|_G923] ;
Zs = [_G1086, a|_G1090],
dif(_G1086, b) ;
Zs = [_G1169, _G1172, a|_G1176],
dif(_G1169, b),
dif(_G1172, b) ;
Zs = [_G1252, _G1255, _G1258, a|_G1262],
dif(_G1252, b),
dif(_G1255, b),
dif(_G1258, b) .
?- earlier_than(X, Y, [a, b, c, d]).
X = a ;
X = b,
dif(Y, a) ;
X = c,
dif(Y, b),
dif(Y, a) ;
X = d,
dif(Y, c),
dif(Y, b),
dif(Y, a) ;
false.
Personally, if the specification permits, I would also add a member(Y, Rest) to the definition of earlier_than/3. This makes things even nicer:
?- earlier_than(X, Y, Zs).
Zs = [X, Y|_G950] ;
Zs = [X, _G949, Y|_G953] ;
Zs = [X, _G949, _G952, Y|_G956] .
?- earlier_than(a, b, Zs).
Zs = [a, b|_G926] ;
Zs = [a, _G925, b|_G929] ;
Zs = [a, _G925, _G928, b|_G932] .
?- earlier_than(X, Y, [a, b, c, d]).
X = a,
Y = b ;
X = a,
Y = c ;
X = a,
Y = d ;
X = b,
Y = c ;
X = b,
Y = d ;
X = c,
Y = d ;
false.

I want to create two Prolog relations and place their definitions in a single Prolog file

I want to create two Prolog relations and place their definitions in a single Prolog file. Define the relations prefix and postfix on lists, meaning that the first argument is a prefix or postfix, respectively, of the second.
?- consult(prepost).
% prepost compiled 0.00 sec, 956 bytes
true.
?- prefix([a,b,c],[a,b,c,e,f]).
true.
?- prefix([a,b,c], [a,b,e,f]).
false.
?- prefix([a,b],[a]).
false.
?- prefix([],[a,b,c,d]).
true.
?- prefix(X,[a,b,c,d]).
X = [] ;
X = [a] ;
X = [a, b] ;
X = [a, b, c] ;
X = [a, b, c, d] ;
false.
?- postfix([n,e],[d,o,n,e]).
true .
?- postfix([],[a,n,y,t,h,i,n,g]).
true .
?- postfix([a,b,c],[a,b,c,d,e]).
false.
?- postfix(X,[a,b,c,d]).
X = [a, b, c, d] ;
X = [b, c, d] ;
X = [c, d] ;
X = [d] ;
X = [] ;
false.
?-
You can use the predicate append/3 to solve your problem in a simple way.
A list of elements is prefix of some other list, if there is a combination where this first list concatenated with another (not relevant), results in your full list.
prefix(Prefix_list, Full_list):- append(Prefix_list, _, Full_list).
You can infer your predicate postfix/2 in the same way:
postfix(Postfix_list, Full_list):- append(_, Postfix_list, Full_list).
Now, put both predicate in a text file, name it prepost.pl, and that's it.

Prolog compute the permutation

I'm writing a permutation function [a,b]-->[[[a], [b]], [[a, b]]
I have this so far, but it doesn't work.
perm([],[]).
perm(L,[H|T]) :- append(V,[H|U],L), append(V,U,W), perm(W,T).
Given your example, it looks like you might actually be wanting the powerset, not the permutation, of the given list.
For instance, the powerset of [a,b] is the set {[a,b], [a], [b], []}.
To compute the powerset of a list of items in Prolog, look at this answer by #gusbro. If this helps you, also please upvote that answer.
If you want all solutions of the powerset of a list L at once, you can wrap the call to powerset/2 in a findall/3 call like this:
?- findall(S, powerset(L, S), Ss).
If, on the other hand, you're after the partitions (as you've mentioned in one of your earlier edits), consider the following:
partition(L, PL) :-
partition(L, [], PL).
partition([], [], []).
partition([X|Xs], As, R) :-
% add X into the new partition...
append(As, [X], NewAs),
partition(Xs, NewAs, R).
partition(L, [A|As], [[A|As]|R]) :-
% ...or, collect the current non-empty partition
partition(L, [], R).
The predicate partition/2 takes a list and returns all partitions, as you've described. For example:
?- partition([a,b,c],L).
L = [[a, b, c]] ;
L = [[a, b], [c]] ;
L = [[a], [b, c]] ;
L = [[a], [b], [c]] ;
false.
Really? It seems to work in SWI-Prolog:
?- [user].
|: perm([],[]).
|: perm(L,[H|T]) :- append(V,[H|U],L), append(V,U,W), perm(W,T).
|: % user://1 compiled 0.00 sec, 3 clauses
true.
?- perm([a,b,c], X).
X = [a, b, c] ;
X = [a, c, b] ;
X = [b, a, c] ;
X = [b, c, a] ;
X = [c, a, b] ;
X = [c, b, a] ;
false.
?- perm([a,b,c,d], X).
X = [a, b, c, d] ;
/* trimming 22 solutions */
X = [d, c, b, a] ;
false.
This also yields the number of answers you'd expect: 3! = 6, 4! = 24. What's not working for you?
Quick note: Prolog doesn't offer functions, but relations.
In this case, perm/2 will hold true when the arguments are one the permutation of the other.
I find this definition more readable than your.
perm([], []).
perm([E|Es], P) :-
perm(Es, Q),
select(E, P, Q).
It's almost the same as that of permutation/2 SWI-Prolog, but hides a bug...

Resources