How do i get all combination in prolog? - prolog

this is my code, I don't understand why this does not look like what I thought
com([],[]).
com([H|T1],[H|T2]):-
com(T1,T2).
com([_|T1],T2):-
com(T1,T2).
three([X1,X2|T]) :-
X2 is X1 + 1,
(
T = []
; three([X2|T])
).
then I tried "findall(Tests, (com([6,7,8,8,9],Tests),three(Tests),Length(Test,N)), N>=3,Alltests)", this is to find all possible cases that continuous number with at least length 3,
'com' return all the tests
'three' is to find all continuous number with at least length 3.
but, the results were wrong.
[trace] findall(..,....,[[6, 7, 8, 9], [6, 7, 8], [6, 7, 8], [7, 8, 9]])
why I just got one [6,7,8,9] and [7,8,9], it should return both I think

findall(Tests, (com([6,7,8,8,9],Tests),three(Tests),Length(Test,N)), N>=3,Alltests)
You have Test instead of Tests here, so it's a different variable.
And Length with a capital needs to be length
And you have N>=3 outside the () so you are using findall/4 instead of findall/3.
With those changes, it seems to work for me:
?- findall(Tests, (com([6,7,8,8,9],Tests),three(Tests),length(Tests,N), N>=3),Alltests).
Alltests = [[6, 7, 8, 9], [6, 7, 8], [6, 7, 8, 9], [6, 7, 8], [7, 8, 9], [7, 8, 9]]

Everything seems to work alright:
?- com([6,7,8,8,9],Tests), three(Tests), length(Tests,N), N >= 3.
N = 4, Tests = [6,7,8,9]
; N = 3, Tests = [6,7,8]
; N = 4, Tests = [6,7,8,9]
; N = 3, Tests = [6,7,8]
; N = 3, Tests = [7,8,9]
; N = 3, Tests = [7,8,9]
; false.
Tip: always do the pure parts first; aggregate later.

Just wanted to give an easy way to define three/1
three(Lst) :-
LstDigits = [1, 2, 3, 4, 5, 6, 7, 8, 9],
between(3, 9, Len),
length(Lst, Len),
append([_, Lst, _], LstDigits).
Result in swi-prolog:
?- three(L).
L = [1,2,3] ;
L = [2,3,4] ;
L = [3,4,5] ;
L = [4,5,6] ;
L = [5,6,7] ;
L = [6,7,8] ;
L = [7,8,9] ;
L = [1,2,3,4] ;
L = [2,3,4,5] ;
etc.

Related

Assigning values in a predicate

Is there a way to assing 2 times a different value in a variable inside a predicate?For example can we somehow make
X is 10,
X is 3.
produce true?
Please don't do it like this. is/2 is for evaluating arithmetic expressions.
Without any context whatsoever it is difficult impossible to suggest what is the right way to do it. The traditional way is to have a predicate that looks like this:
ten_or_three(10).
ten_or_three(3).
You can do all kinds of Prolog-y things with a predicate like that.
?- ten_or_three(10).
true.
?- ten_or_three(4).
false.
?- length(L, 3), maplist(ten_or_three, L), sumlist(L, Sum).
L = [10, 10, 10],
Sum = 30 ;
L = [10, 10, 3],
Sum = 23 ;
L = [10, 3, 10],
Sum = 23 ;
L = [10, 3, 3],
Sum = 16 ;
L = [3, 10, 10],
Sum = 23 ;
L = [3, 10, 3],
Sum = 16 ;
L = [3, 3, 10],
Sum = 16 ;
L = [3, 3, 3],
Sum = 9.
For example,
p(X) :- X is 3;X is 5.
is true of X = 3 or 5.

Making prolog predicates deterministic

I've written a predicate, shuffle/3, which generates "shuffles" of two lists. When the second and third argument are instantiated, the first argument becomes a list which has all the elements of both Left and Right, in the same order that they appear in Left and Right.
For example:
?- shuffle(X, [1, 2], [3, 4]).
X = [1, 3, 2, 4] ;
X = [1, 3, 4, 2] ;
X = [1, 2, 3, 4] ;
X = [3, 4, 1, 2] ;
X = [3, 1, 2, 4] ;
X = [3, 1, 4, 2] ;
false.
Here's the code I've come up with to implement it:
shuffle([], [], []).
shuffle([H|R], [H|Left], Right) :- shuffle(R, Right, Left).
shuffle([H|R], Left, [H|Right]) :- shuffle(R, Right, Left).
This works well, and even generates reasonable results for "the most general query", but it fails to be deterministic for any query, even one where all arguments are fully instantiated: shuffle([1, 2, 3, 4], [1, 2], [3, 4]).
My real question is: is there anything I can do, while maintaining purity (so, no cuts), which makes this predicate deterministic when all arguments are fully instantiated?
And while I'm here, I'm new to Prolog, I wonder if anyone has advice on why I would care about determinism. Is it important for real prolog programs?
No, there is no way to make this predicate deterministic while still maintaining pure code. To see this, consider:
?- shuffle([1, 1], [1], [1]).
true
; true.
There are two answers to this. Why? The best is not to use a debugger to understand this, but rather to use a generalized query:
?- shuffle([X1, X2], [Y1], [Y2]).
X1 = Y1, X2 = Y2
; X1 = Y2, X2 = Y1.
So here you can see the "true" connection between the arguments! And now our specific query is an instance of this more general query. Thus, no way to remove the two answers.
However, you might use cut in a pure way, provided it is guarded such that the result will always be pure. Like testing ground(shuffe(Xs, Ys, Zs)) but all of this is quite ad hoc.
On second thought, there might be a pure, determinate answer, but only if the answers to shuffle([X1, X2], [Y1], [Y2]). are changed somehow. The answer actually should be:
?- shuffledet([X1, X2], [Y1], [Y2]).
X1 = X2, X2 = Y1, Y1 = Y2 % all equal
; dif(X1, X2), X1 = Y1, X2 = Y2
; dif(X1, X2), X1 = Y2, X2 = Y1.
So that might be a possibility... I will had put a 500 bounty on this ASAP, but no response. And again I try another one.
The way to make the more det version of shuffle is using if_/3 from library module reif:
shuffle_det1( A,B,C):-
if_( B=[], A=C,
if_( C=[], A=B,
( B=[BH|BT], C=[CH|CT], A=[AH|AT], (
AH=BH, shuffle_det1( AT, BT, C)
;
AH=CH, shuffle_det1( AT, B, CT) ) ))).
Working positionally, it's OK, and indeed eliminates some (most?) spurious choice points:
40 ?- shuffle_det1(X, [1, 2], [3, 4]).
X = [1, 2, 3, 4] ;
X = [1, 3, 2, 4] ;
X = [1, 3, 4, 2] ;
X = [3, 1, 2, 4] ;
X = [3, 1, 4, 2] ;
X = [3, 4, 1, 2].
41 ?- shuffle_det1(X, [11,12], [11,22]).
X = [11, 12, 11, 22] ;
X = [11, 11, 12, 22] ;
X = [11, 11, 22, 12] ;
X = [11, 11, 12, 22] ;
X = [11, 11, 22, 12] ;
X = [11, 22, 11, 12].
81 ?- shuffle_det1([1,2,3,4], [3, 4], [1, 2]).
true.
But:
82 ?- shuffle_det1([1,2,3,4], [1, 2], [3, 4]).
true ;
false.
Also, as [user:false] points out, if two lists' head elements are equal, there's some redundancy in the answers:
11 12 13 .. B
21 22 23 .. C
11 (12.. + 21..) | 21 (11.. + 22..)
12 (13.. + 21..) 11 (12.. + 22..) *
| 21 (12.. + 22..) * | 22 (11.. + 23..)
Here the two cases marked with * actually conflate when 11 == 21. To combat that, we "unroll" the picking by doing two in a row in such cases:
shuffle_det( A,B,C):-
if_( B=[], A=C,
if_( C=[], A=B,
( B=[BH|BT], C=[CH|CT], A=[AH|AT],
if_( \X^(dif(BH,CH),X=true ; BH=CH,X=false),
(
AH=BH, shuffle_det( AT, BT, C)
;
AH=CH, shuffle_det( AT, B, CT) ),
(
AH=BH, AT=[CH|A2], shuffle_det( A2, BT, CT) % **
;
pull_twice( A,B,C)
;
pull_twice( A,C,B)
))))).
pull_twice([BH|AT],[BH|BT],C):- % B,C guaranteed to be non-empty
if_( BT=[], AT=C,
( BT=[BH2|B2], AT=[BH2|A2], shuffle_det(A2,B2,C) )).
Testing:
35 ?- shuffle_det(A, [11,12], [11,22]).
A = [11, 11, 12, 22] ;
A = [11, 11, 22, 12] ;
A = [11, 12, 11, 22] ;
A = [11, 22, 11, 12].
This is already much better than shuffle_det1. But it's not fully right yet:
38 ?- shuffle_det(A, [1], [1]).
A = [1, 1] ;
A = [1, 1] ;
A = [1, 1].
The two pull_twice calls are probably the culprit. Somehow there must be only one, which would decide whether to do the other one or not...

Prolog constraint logic programming - How to set a domain on a List of Domain Variables given a List of Integers?

Basically what I want to achieve is :
Given a list of domain Variables set these Variables with a domain relative to a List of Numbers. Example:
......
List=[A1,A2,A3],
domain(List,1,5],
setDomain(List,[1,2]),
labeling([],List).
Result:
A1=1, A2=1, A3=1 or
A1=1, A2=1, A3=2 or
A1=1, A2=2, A3=1
and so on...
What I have tried:
setDomain(List,ListIntegers):-
element(X, List, Element),
member(Element,ListIntegers),
main(List):-
List=[A1,A2,A3],
domain(List,1,5],
setDomain(List,[1,2]),
labeling([],List).
but not success...
Can anyone help understand how can I accomplish this?
In your solution, you're using labeling/2 but haven't defined its arguments using CLP(FD), so it doesn't do anything for you. It's not very clear from your question or simple example, but it sounds like you want a list of a given length whose elements are each taken from a domain consisting of an arbitrary list of elements?
You could do so with something like this:
member_(List, Element) :- member(Element, List).
domain_list(Length, Domain, List) :-
length(List, Length),
maplist(member_(Domain), List).
This would give:
6 ?- domain_list(3, [1,3], L).
L = [1, 1, 1] ;
L = [1, 1, 3] ;
L = [1, 3, 1] ;
L = [1, 3, 3] ;
L = [3, 1, 1] ;
L = [3, 1, 3] ;
L = [3, 3, 1] ;
L = [3, 3, 3].
7 ?-
This also works for any kind of elements:
7 ?- domain_list(3, [tom, a(b)], L).
L = [tom, tom, tom] ;
L = [tom, tom, a(b)] ;
L = [tom, a(b), tom] ;
L = [tom, a(b), a(b)] ;
L = [a(b), tom, tom] ;
L = [a(b), tom, a(b)] ;
L = [a(b), a(b), tom] ;
L = [a(b), a(b), a(b)].
8 ?-
If you wanted to use CLP(FD), you'd need to keep a couple of things in mind. CLP(FD) is for integer domains, and CLP(FD) has its own way of specifying domains, which is not in list form.
For instance, if you wanted a list of length N whose elements were in the domain described by [1,2,3,5,6,8], you would write it as:
length(List, N),
List ins 1..3 \/ 5..6 \/ 8,
label(List).
Which would result in, for example:
2 ?- length(List, 3), List ins 1..3 \/ 5..6 \/ 8, label(List).
List = [1, 1, 1] ;
List = [1, 1, 2] ;
List = [1, 1, 3] ;
List = [1, 1, 5] ;
List = [1, 1, 6] ;
List = [1, 1, 8] ;
List = [1, 2, 1] ;
List = [1, 2, 2]
...
Using ECLiPSe Prolog you can write:
:-lib(fd).
applyDomain([],_).
applyDomain([H|T],D):-
var_fd(H,D),
applyDomain(T,D).
domainList(ListDomain,LengthList,ListOutput):-
length(ListOutput,LengthList),
list_to_dom(ListDomain,Domain),
applyDomain(ListOutput,Domain).
Query:
?- domainList([2,3,5,7,8],5,L).
L = [_530{[2, 3, 5, 7, 8]}, _547{[2, 3, 5, 7, 8]}, _564{[2, 3, 5, 7, 8]}, _581{[2, 3, 5, 7, 8]}, _598{[2, 3, 5, 7, 8]}]
Yes (0.00s cpu)
The output means that each variable (in this case _530, _547 and so on) in the list L has the specified domain {[2, 3, 5, 7, 8]}. If you want to label the list you can simply add
labeling(ListOutput).
as last line of domainList/3 and you get:
?- domainList([2, 3, 5, 7, 8], 5, L).
L = [2, 2, 2, 2, 2]
Yes (0.00s cpu, solution 1, maybe more)
L = [2, 2, 2, 2, 3]
Yes (0.00s cpu, solution 2, maybe more)
L = [2, 2, 2, 2, 5]
Yes (0.00s cpu, solution 3, maybe more)
and so on... If you want that all the list will be different, just add
alldifferent(ListOutput),
before labeling/1, and you'll get
?- domainList([2, 3, 5, 7, 8], 5, L).
L = [2, 3, 5, 7, 8]
Yes (0.00s cpu, solution 1, maybe more)
L = [2, 3, 5, 8, 7]
Yes (0.00s cpu, solution 2, maybe more)
L = [2, 3, 7, 5, 8]
Yes (0.00s cpu, solution 3, maybe more)
I usually don't use SWI prolog for clpfd problems, so i don't know if there is a similar solution in SWI...

PROLOG List filter predicate not aswering true or false

I'm trying to make a predicate that takes two vectors/lists and uses the first one as a filter. For example:
?- L1=[0,3,0,5,0,0,0,0],L2=[1,2,3,4,5,6,7,8],filter(L1,L2,1).
L1 = [0, 3, 0, 5, 0, 0, 0, 0],
L2 = [1, 2, 3, 4, 5, 6, 7, 8] .
That's what I'm getting but I would want true or false if L2 has 3 as the second element, 5 as the fourth element, etc. The 0s are ignored, that's the "filter" condition.
What I know from the input is that L1 and L2 are always length=8 and only L1 has 0s.
My code is:
filter(_,_,9).
filter([Y|T],V2,Row):-
Y=:=0,
NewRow is Row + 1,
filter([Y|T],V2,NewRow).
filter([Y|T],V2,Row):-
Y=\=0,
nth(Row,[Y|T],X1),
nth(Row,V2,X2),
X1=:=X2,
NewRow is Row + 1,
filter([Y|T],V2,NewRow).
nth(1,[X|_],X).
nth(N,[_|T],R):- M is N-1, nth(M,T,R).
I know there are better ways of doing the function, for example comparing the first element of the first to the nth of the second and delete the head of the first with recursion but I just want to know why I'm not getting true or false, or any "return" value at all.
Can someone help me?, got it working
New code:
filter([],R,_,R).
filter([Y|T],V2,Row,R):-
Y=:=0,
NewRow is Row + 1,
filter(T,V2,NewRow,R).
filter([Y|T],V2,Row,R):-
Y=\=0,
nth(Row,V2,X2),
Y=:=X2,
NewRow is Row + 1,
filter(T,V2,NewRow,R).
Example of expected behaviour:
permutation([1,2,3,4,5,6,7,8],X),filter([1,2,3,4,0,0,0,0],X,1,R).
X = R, R = [1, 2, 3, 4, 5, 6, 7, 8] ;
X = R, R = [1, 2, 3, 4, 5, 6, 8, 7] ;
X = R, R = [1, 2, 3, 4, 5, 7, 6, 8] ;
X = R, R = [1, 2, 3, 4, 5, 7, 8, 6] .
Now i can get all the permutations that starts with 1,2,3,4.
If someone knows a better way to achieve the same, plz share, but i already got what i needed =).
seems like could be a perfect task for maplist/3
filter(L1, L2, _) :-
maplist(skip_or_match, L1, L2).
skip_or_match(E1, E2) :- E1 == 0 ; E1 == E2.
yields
?- permutation([1,2,3,4,5,6,7,8],X),filter([1,2,3,4,0,0,0,0],X,_).
X = [1, 2, 3, 4, 5, 6, 7, 8] ;
X = [1, 2, 3, 4, 5, 6, 8, 7] ;
X = [1, 2, 3, 4, 5, 7, 6, 8] ;
X = [1, 2, 3, 4, 5, 7, 8, 6] ;
...
We could do that more useful, using Prolog facilities - namely, use an anonymus variable to express don't care.
Then filter/N is a simple application of maplist:
?- permutation([1,2,3,4,5,6,7,8],X),maplist(=,[1,2,3,4,_,_,_,_],X).
X = [1, 2, 3, 4, 5, 6, 7, 8] ;
X = [1, 2, 3, 4, 5, 6, 8, 7] ;
X = [1, 2, 3, 4, 5, 7, 6, 8] ;
X = [1, 2, 3, 4, 5, 7, 8, 6] ;
...
Your code always tests the first item of the filtering list for being zero. For example, look at the case when you're checking second value:
filter([0,3,0,5,0,0,0,0], [1,2,3,4,5,6,7,8], 2).
This call will perform the following unifications:
# first case: obvious fail…
filter([0,3,0,5,0,0,0,0], [1,2,3,4,5,6,7,8], 2) =\= filter(_, _, 9).
# second case:
filter([0,3,0,5,0,0,0,0], [1,2,3,4,5,6,7,8], 2) = filter([Y|T],V2,Row).
# unification succeeds with substitutions:
Y = 0
T = [3,0,5,0,0,0,0]
V2 = [1,2,3,4,5,6,7,8]
Row = 2
# and what happens next?
Y =:= 0 # success!
You probably wanted here to check whether second element of [Y|T] is zero; instead, you're checking the first one. If you want to fix it without changing the rest of your code, you should instead perform comparisons to X1:
filter(V1,V2,Row):-
nth(Row, V1, X1),
X1 =:= 0,
NewRow is Row + 1,
filter(V1,V2,NewRow).
filter(V1,V2,Row):-
nth(Row,V1,X1),
X1=\=0,
nth(Row,V2,X2),
X1=:=X2,
NewRow is Row + 1,
filter(V1,V2,NewRow).
Also, there's one more thing that I think you might not be getting yet in Prolog. If a predicate fails, Prolog indeed prints false and stops computation. But if a predicate succeeds, there are two cases:
If there were no variables in your query, Prolog prints true.
If there were any variables in your query, Prolog does not print true. Instead, it prints values of variables instead. This also counts as true.
In your case Prolog actually “returns” true from your predicate—except that because you have used variables in your query, it printed their value instead of printing true.

Divide List to pieces of needed length

I was trying to write predicate divide(L,Len,Slist) which will be true when Slist can unify with a List of length Len allocated from List L. for example
divide([1,2,3,4,5,6,7],3,Slist).
Should give such answers
Slist=[1,2,3];
Slist=[2,3,4];
Slist=[3,4,5];
Slist=[4,5,6];
Slist=[5,6,7];
But i couldn't find a better way then length(X,Len), sublist(L,X). but it does work too slow.
How should look divide predicate?
Alternatively you could use DCG as mentionned by #false in this great answer:
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
divide(List, Length, Result) :-
length(Result, Length),
phrase((seq(_), seq(Result), seq(_)), List).
sublist/2 doesn't seems to work as expected:
?- [library(dialect/sicstus/lists)].
% library(dialect/sicstus/lists) compiled into sicstus_lists 0,00 sec, 14 clauses
true.
?- L=[1,2,3,4,5,6], length(T, 3),sublist(T,L).
L = [1, 2, 3, 4, 5, 6],
T = [1, 2, 3] ;
L = [1, 2, 3, 4, 5, 6],
T = [1, 2, 4] ;
L = [1, 2, 3, 4, 5, 6],
T = [1, 2, 5] ;
....
You could use append/3 instead:
?- L=[1,2,3,4,5,6], length(T, 3), append(_, Q, L), append(T, _, Q).
L = [1, 2, 3, 4, 5, 6],
T = [1, 2, 3],
Q = [1, 2, 3, 4, 5, 6] ;
L = [1, 2, 3, 4, 5, 6],
T = [2, 3, 4],
Q = [2, 3, 4, 5, 6] ;
L = [1, 2, 3, 4, 5, 6],
T = [3, 4, 5],
Q = [3, 4, 5, 6] ;
L = [1, 2, 3, 4, 5, 6],
T = Q, Q = [4, 5, 6] ;
false.
I don't think it's very fast, just essential...

Resources