I have predicate P1 that returns values one after the other like this:
-? P1(ARGUMENTS, RETURN).
-? RETURN = 1;
-? RETURN = 2;
-? RETURN = 3;
-? fail.
I also have another predicate called P2:
P2(ARGUMENTS, LIST) :- P1(ARGUMENTS, RETURN),... % SOMEHOW HERE I NEED TO INSERT ALL VALUES OF RETURN TO LIST.
How do find all of the values of RETURN and assign them to LIST?
Use findall to accomplish this:
P2(ARGUMENTS, LIST) :- findall(X, P1(ARGUMENTS, X), LIST).
This is related to the bagof function mentioned in the question linked to by Anders Lindahl. There is a good explanation on the relationship between the two functions (and a third function setof) here:
To illustrate the differences consider
a little example:
listing(p).
p(1,3,5).
p(2,4,1).
p(3,5,2).
p(4,3,1).
p(5,2,4).
Try the following goals. (The answer
displays have been modified to save
space.)
?- bagof(Z,p(X,Y,Z),Bag).
Z = _G182 X = 1 Y = 3 Bag = [5] ;
Z = _G182 X = 2 Y = 4 Bag = [1] ;
Z = _G182 X = 3 Y = 5 Bag = [2] ;
Z = _G182 X = 4 Y = 3 Bag = [1] ;
Z = _G182 X = 5 Y = 2 Bag = [4] ;
No
?- findall(Z,p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [5, 1, 2, 1, 4] ;
No
?- bagof(Z,X^Y^p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [5, 1, 2, 1, 4] ;
No
?- setof(Z,X^Y^p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [1, 2, 4, 5] ;
No
The predicates bagof and setof yield
collections for individual bindings of
the free variables in the goal. setof
yields a sorted version of the
collection without duplicates. To
avoid binding variables, use an
existential quantifier expression. For
example the goal
bagof(Z,X^Y^p(X,Y,Z),Bag) asks for
"the Bag of Z's such that there exists
an X and there exists a Y such that
p(X,Y,Z)". findall acts like bagof
with all free variables automatically
existentially quantified. In addition
findall returns an empty list [] there
is no goal satisfaction, whereas bagof
fails.
Related
I'm trying to generate every combination possible given a list. I want every [X,Y] combination possible.
Here's an example :
?- arguments(A,[1,2,3]).
A = [1,2] ; A = [1,3] ; A = [2,1] ; A = [2,3] ; A = [3,1] ;
A = [3,2]
I have tried multiple things, but I've yet to find a working one.
I am pretty sure the idea is to use prolog's ability to try every possibility as such :
element(X,[X|_],1).
element(X,[_|Q],N) :- element(X,Q,NewN), N is NewN + 1.
This predicate can return the element at the position N, or return the position of the element X, or generate every possibility. Exemple :
?- element(X,[a,b,c],N).
N = 1
X = a
N = 2
X = b
N = 3
X = c
Thanks for the help.
Edit following gusbro answer :
I can't use already existing predicates, it's part of a course.
Reading your answer, I came up with this :
remove_element_x(X, [X|Q], Q).
remove_element_x(X, [T|Q], [T|Res]) :- remove_element_x(X,Q,Res).
arguments([X,Y],L) :-
element(X,L,_),
remove_element_x(X,L,L2),
element(Y,L2,_).
remove_element_x/3 remove the element x from the list and returns the new list.
But the backtracking is not working :
?- arguments(A,[1,2,3]).
A = [1,2] ?
yes
You can use select/3 to select an element from a list (and get the remaining list), then do it again to select another element from the remaining list).
i.e.:
arguments([A,B], L):-
select(A, L, L1),
select(B, L1,_).
Test case:
?- arguments(A,[1,2,3]).
A = [1, 2] ;
A = [1, 3] ;
A = [2, 1] ;
A = [2, 3] ;
A = [3, 1] ;
A = [3, 2]
I'm exploring dependent structures of constraints like this one:
assign(X,Y) :-
X in 1..5,
((X mod 2 #= 1) #=> Y in 2..3),
((X mod 2 #= 0) #=> Y #= 5).
What I'm looking for is a representation of X's and Y's domains that is as sparse as possible - in this case it would be something along the lines of X in {1,3,5} and Y in {2,3} or X in {2,4} and Y = 5.
One way of doing that would be to detect all variables on the left side of the #=>, enumerate all their values and collect and merge them together, something like ?- assign(X, Y), findall(X-D, (indomain(X),fd_dom(Y,D)), C), do stuff with C, but maybe there is a more efficient way?
I've also encountered an error trying to label([X,Y]): Arguments are not sufficiently instantiated that goes away when I add another constraint on Y's domain.
When should I expect this error to occur? I feel I have a poor understanding of clpfd's mechanisms and limitations, are there any resources I could learn from? I already know the basics of constraint programming, arc consistency etc.
To keep clpfd enumeration predicates (like indomain/1, label/1, labeling/2, etc.) from ever throwing instantiation errors, simply ensure that all variables have been assigned some finite domain before any enumeration predicates is executed.
So how about directly translating what you wrote to code?
assign(X,Y) :- X in 1\/3\/5, Y in 2..3. % X in {1,3,5} and Y in {2,3}
assign(X,Y) :- X in 2..4, Y in 5. % or X in {2,4} and Y = 5
A simple query (with SWI-Prolog):
?- assign(X,Y), labeling([],[X,Y]).
X = 1, Y = 2
; X = 1, Y = 3
; X = 3, Y = 2
; X = 3, Y = 3
; X = 5, Y = 2
; X = 5, Y = 3
; X = 2, Y = 5
; X = 3, Y = 5
; X = 4, Y = 5.
I'm trying to write a prolog code which will take a list and return all pairs of each element of that list. So for example:
X = 1, Y = 2, Zs = [3] ;
X = 1, Y = 3, Zs = [2] ;
X = 2, Y = 1, Zs = [3] ;
X = 2, Y = 3, Zs = [1] ;
X = 3, Y = 1, Zs = [2] ;
X = 3, Y = 2, Zs = [3]
So far I am able to get uptil the third line and not able to get the rest of the output. My code is:
select_pair(X,Y,[X|Xs],Zs):- select(Y,Xs,Zs).
select_pair(X,Y,[H|Z1],[H|Z2]):- select_pair(X,Y,Z1,Z2).
In words, what you want to achieve is:
Take any X from the input list
Take any Y different from X from the input list
Elements other than X and Y are in Zs
This translates quite easily into a prolog predicate:
select_pair(X, Y, L, Zs) :-
select(X, L, Xs),
select(Y, Xs, Zs).
First we select X from the input L. From the remaining elements Xs we select Y. After this, the remaining elements is Zs.
I have written the following program to compute all pairs of members in a list. Here is my code:
select_pair(X, Y, [X|[Y|T]], T).
select_pair(X, Y, [Head|[X|[Y|T]]], [Head|Rest]) :- select_pair(X, Y, T, Rest).
I am supposed to call my code with this 3-member list only:
select pair(X, Y, [1,2,3], Zs).
But this doesn't generate all possible combinations. It only generates
X = 1, Y = 2, Zs = [3]
and it is supposed to generate this, but it does not:
X = 1, Y = 2, Zs = [3] ;
X = 1, Y = 3, Zs = [2] ;
X = 2, Y = 1, Zs = [3] ;
X = 2, Y = 3, Zs = [1] ;
X = 3, Y = 1, Zs = [2] ;
X = 3, Y = 2, Zs = [3]
So, how can I modify this code to generate all possible pairs of members of the list [1, 2, 3]?
I'd use procedure select/3:
select_pair(X, Y, List, Rest):-
select(X, List, MList),
select(Y, MList, Rest).
The first select would remove the first element from List into X and put the rest of the list in MList.
Then the second select would get you the second element and the Rest.
I am trying to write a function - decListRange(X,List) which give a list in range [X-1:1] by descending order. For example -
decListRange(9,List).
Will give -
List = [8,7,6,5,4,3,2,1].
I tried the following but it goes into infinite loop -
decListRange(1,[]) :- !.
decListRange(X,[H|Rest]) :-
H = X-1, NextX = X - 1 ,decListRange(NextX,Rest).
You have two problems. The first real one is that you need to use is instead of =:
H is X-1
This is needed to trigger arithmetic evaluation. Your second problem isn't a real problem but speaks to a bigger misunderstanding, which is that H and NextX are equivalent. Because Prolog only has bindings and not "assignables" as it were, you should never really need to create two "variables" with the same binding. There's no state being kept around for you to modify later.
Cleaning up both you get this:
decListRange(1, []) :- !.
decListRange(X, [H|Rest]) :-
X > 1,
H is X-1,
decListRange(H, Rest).
Edit 2: a clpfd implementation
:- use_module(library(clpfd)).
declist(N, L) :- N == 1, !, L = []. % green cut
declist(1, []).
declist(N, [N1|Ns]) :-
N #> 1,
N1 #= N - 1,
declist(N1, Ns).
This one has the properties #false mentions below in the comments:
?- declist(3, L).
L = [2, 1] ;
false.
?- declist(3, [2,1]).
true ;
false.
?- declist(N, [3,2,1]).
N = 4.
?- declist(N, X).
N = 1,
X = [] ;
N = 2,
X = [1] ;
N = 3,
X = [2, 1] ;
N = 4,
X = [3, 2, 1] ;
N = 5,
X = [4, 3, 2, 1] .
Edit: a short interlude on the difference between = and is.
In procedural languages = is almost always syntax for assigning a particular value to a variable. In Prolog, variables are bindings, and once established they cannot be directly modified by reassigning the variable a different value. Instead they work more like variables in math and logic, where the variable "stands in" for interesting values, but those values are themselves basically immutable. In Prolog, = essentially asks the unification engine to establish bindings. So if you were to do something like this:
?- name(X, Y) = name(bob, tony).
Prolog responds with variable bindings:
X = bob,
Y = tony.
Once those bindings exist, contradictory bindings will fail and affirmative bindings will succeed:
?- name(X, Y) = name(bob, tony), X = bob.
X = bob,
Y = tony.
?- name(X, Y) = name(bob, tony), X = william.
false.
The unification algorithm itself doesn't know anything about arithmetic. This has the pleasant side-effect that you can use any expression raw. For instance:
?- Expr = X + 3, Z + Q = Expr.
Expr = Z+3,
X = Z,
Q = 3.
This is probably really surprising looking. You may expect that somehow Prolog was smart enough to keep the expression around because it noticed X was a variable or something, but that isn't true either:
?- X = 4, Expr = X + 3, Z + Q = Expr.
X = 4,
Expr = 4+3,
Z = 4,
Q = 3.
Another way of looking at this is that Prolog is considering + to be just another operator, so X+3 is a fact just like add(X, 3) that doesn't necessarily have any special meaning. Whichever way you look at it, the is/2 operator exists to apply arithmetic reasoning and produce a value:
?- X = 4, Expr is X + 3.
X = 4,
Expr = 7.
Notice that Expr has the computed value but none of the original structure:
?- X = 4, Expr is X + 3, Z + Q = Expr.
false.
In practice, if you need to do a lot of reasoning with arithmetic, you will want to use a library like clpfd or clpqr depending on whether you're interested in integers or reals. This library enables you to do more interesting things more easily, like specify that an equation holds for values in a certain range and get those values out.