I'm trying to return distinct items in a list. I've come up with the following code. I seem to run into a problem when checking the members of the list using member(X,Y), and it runs into an infinite loop.
get_unique(Y, [H|T]) :-
memberchk(H, Y)-> get_unique(Y, T) ; get_unique([H|T], T).
get_unique(_, []) :- true.
final_list(X, L) :-
get_unique(Y, L), member(X,Y).
There are two input cases:
?- final_list(dog,[dog,cat,bat,dog]).
true;
true;
true;
true;
(infinitely)
In this case I would expect just
true;
false.
The other input case:
?- final_list(X,[dog,cat,bat,dog]).
X = dog;
X = cat;
X = bat;
true ;
true ;
true ;
true ;
true ;
true ;
(infinitely)
In this case I would expect just
X = dog;
X = cat;
X = bat;
false.
I tried to do some debugging and I think I can see that member(X,Y) is generating the infinite loop -- tracing steps seen below. I don't know how to stop this, such that member stops checking once it returns bat.
X = bat ;
Redo: (9) lists:member(_6632, [dog, cat, bat|_6882]) ? creep
Exit: (9) lists:member(_6632, [dog, cat, bat, _6632|_6888]) ? creep
Exit: (8) final_list(_6632, [dog, cat, bat, dog]) ? creep
true ;
Redo: (9) lists:member(_6632, [dog, cat, bat, _6886|_6888]) ? creep
Exit: (9) lists:member(_6632, [dog, cat, bat, _6886, _6632|_6894]) ? creep
Exit: (8) final_list(_6632, [dog, cat, bat, dog]) ? creep
true ;
Redo: (9) lists:member(_6632, [dog, cat, bat, _6886, _6892|_6894]) ? creep
Exit: (9) lists:member(_6632, [dog, cat, bat, _6886, _6892, _6632|_6900]) ? creep
Exit: (8) final_list(_6632, [dog, cat, bat, dog]) ? creep
true ;
Redo: (9) lists:member(_6632, [dog, cat, bat, _6886, _6892, _6898|_6900]) ? creep
Exit: (9) lists:member(_6632, [dog, cat, bat, _6886, _6892, _6898, _6632|...]) ? creep
Exit: (8) final_list(_6632, [dog, cat, bat, dog]) ? creep
true ;
Thank you!
Try get_unique/2 alone:
?- get_unique(Y,[dog,cat,bat,dog]).
Y = [dog,cat,bat|_A].
% ^^^
Thus, Y is only a partial list, but not a (real) list. It comprises all lists with three or more elements.
The second clause should read get_unique([], []). to avoid this problem. And also the first needs some rearrangement:
get_unique(Y, [H|T]) :-
( memberchk(H, T) -> get_unique(Y, T) ; Y = [H|Y1], get_unique(Y1, T) ).
% ^^ ^^^^^^^^^^ ^^
get_unique([], []).
But still, your definition makes some odd assumptions:
?- final_list(X,[dog,Cat]).
X = dog, Cat = dog.
So it forces variables to become one specific value.
There is no clean way out of this, except by reconsidering member/2. See this answer for a clean solution. Here is the answer memberd/2 produces:
?- memberd(X,[dog,Cat]).
X = dog
; X = Cat, dif(Cat,dog)
; false.
So the answer says: X = dog as before and additionally, X = Cat but only if Cat is different to dog.
Related
Many predicates define some kind of an acyclic path built from edges defined via a binary relation, quite similarly to defining transitive closure. A generic definition is thus called for.
Note that the notions defined in graph theory do not readily match what is commonly expected. Most notably, we are not interested in the edges' names.
Worse, also graph theory has changed a bit, introducing the notion of walk, noting
Traditionally, a path referred to what is now usually known as an open walk. Nowadays, when stated without any qualification, a path is usually understood to be simple, meaning that no vertices (and thus no edges) are repeated. (The term chain has also been used to refer to a walk in which all vertices and edges are distinct.)
So my question is: How to name and define this functionality?
What I have done so far is to define:
path(Rel_2, Path, X0,X)
The first argument has to be the continuation of the relation which is an incomplete goal that lacks two further arguments. Then comes either the Path or the pair of vertices.
Example usage
n(a, b).
n(b, c).
n(b, a).
?- path(n,Xs, a,X).
Xs = [a], X = a
; Xs = [a, b], X = b
; Xs = [a, b, c], X = c
; false.
Implementation
:- meta_predicate(path(2,?,?,?)).
:- meta_predicate(path(2,?,?,?,+)).
path(R_2, [X0|Ys], X0,X) :-
path(R_2, Ys, X0,X, [X0]).
path(_R_2, [], X,X, _).
path(R_2, [X1|Ys], X0,X, Xs) :-
call(R_2, X0,X1),
non_member(X1, Xs),
path(R_2, Ys, X1,X, [X1|Xs]).
non_member(_E, []).
non_member(E, [X|Xs]) :-
dif(E,X),
non_member(E, Xs).
How about defining path/4 like this?
path(R_2, Xs, A,Z) :- % A path `Xs` from `A` to `Z` is ...
walk(R_2, Xs, A,Z), % ... a walk `Xs` from `A` to `Z` ...
all_dif(Xs). % ... with no duplicates in `Xs`.
To aid universal termination, we swap the two goals in above conjunction ...
path(R_2, Xs, A,Z) :-
all_dif(Xs), % enforce disequality ASAP
walk(R_2, Xs, A,Z).
... and use the following lazy implementation of all_dif/1:
all_dif(Xs) :- % enforce pairwise term inequality
freeze(Xs, all_dif_aux(Xs,[])). % (may be delayed)
all_dif_aux([], _).
all_dif_aux([E|Es], Vs) :-
maplist(dif(E), Vs), % is never delayed
freeze(Es, all_dif_aux(Es,[E|Vs])). % (may be delayed)
walk/4 is defined like path/4 and path/5 given by the OP:
:- meta_predicate walk(2, ?, ?, ?).
walk(R_2, [X0|Xs], X0,X) :-
walk_from_to_step(Xs, X0,X, R_2).
:- meta_predicate walk_from_to_step(?, ?, ?, 2).
walk_from_to_step([], X,X, _).
walk_from_to_step([X1|Xs], X0,X, R_2) :-
call(R_2, X0,X1),
walk_from_to_step(Xs, X1,X, R_2).
IMO above path/4 is simpler and more approachable, particularly for novices. Would you concur?
I want to focus on naming the predicate.
Unlike maplist/2,
the argument order isn't of primary importance here.
The predicate name should make the meaning of the respective arguments clear.
So far, I like path_from_to_edges best, but it has its pros and cons, too.
path_from_to_edges(Path,From,To,Edges_2) :-
path(Edges_2,Path,From,To).
Let's pick it apart:
pro: path is a noun, it cannot be mis-read a verb. To me, a list of vertices is implied.
pro: from stands for a vertex, and so does to.
con: edges is somewhat vague, but using lambdas here is the most versatile choice.
con: According to Wikipedia, a path is a trail in which all vertices (except possibly the first and last) are distinct. So that would need to be clarified in the description.
Using lambdas for a lists of neighbor vertices Ess:
?- Ess = [a-[b],b-[c,a]],
From = a,
path_from_to_edges(Path,From,To,\X^Y^(member(X-X_neibs,Ess),member(Y,X_neibs))).
Ess = [a-[b],b-[c,a]], From = a, To = a, Path = [a]
; Ess = [a-[b],b-[c,a]], From = a, To = b, Path = [a,b]
; Ess = [a-[b],b-[c,a]], From = a, To = c, Path = [a,b,c]
; false.
Edit 2015-06-02
Another shot at better naming! This leans more on the side of maplist/2...
graph_path_from_to(P_2,Path,From,To) :-
path(P_2,Path,From,To).
Here, graph, of course, is a noun, not a verb.
Regarding the meaning of "path": paths definitely should allow From=To and not exclude that by default (with pairwise term inequalities). It is easy to exclude this with an additional dif(From,To) goal, but not the other way round.
I do not see the reason to define in path/4 the arguments "start node" and "end node". It seems that a simple path/2 with the rule and the list of nodes must be enough.
If the user wants a list starting with some node (by example, 'a'), he can query the statement as: path( some_rule, ['a'|Q] ).
A user could, by example, request for path that have length 10 in the way: length(P,10), path( some_rule, P).
* Addendum 1 *
Some utility goals can be easily added, but they are not the main subject. Example, path/3 with start node is:
path( some_rule, [start|Q], start ) :-
path ( some_rule, [start|Q ] ).
* Addendum 2 *
Addition of last node as argument could give the false idea that this argument drives the algorithm, but it doesn't. Assume by example:
n(a, b).
n(a, c).
n(a, d).
and trace algorithm execution for the query:
[trace] ?- path( n, P, X, d ).
Call: (6) path(n, _G1025, _G1026, d) ? creep
Call: (7) path(n, _G1107, _G1026, d, [_G1026]) ? creep
Exit: (7) path(n, [], d, d, [d]) ? creep
Exit: (6) path(n, [d], d, d) ? creep
P = [d],
X = d ;
Redo: (7) path(n, _G1107, _G1026, d, [_G1026]) ? creep
Call: (8) n(_G1026, _G1112) ? creep
Exit: (8) n(a, b) ? creep
Call: (8) non_member(b, [a]) ? creep
Call: (9) dif:dif(b, a) ? creep
Exit: (9) dif:dif(b, a) ? creep
Call: (9) non_member(b, []) ? creep
Exit: (9) non_member(b, []) ? creep
Exit: (8) non_member(b, [a]) ? creep
Call: (8) path(n, _G1113, b, d, [b, a]) ? creep
Call: (9) n(b, _G1118) ? creep
Fail: (9) n(b, _G1118) ? creep
Fail: (8) path(n, _G1113, b, d, [b, a]) ? creep
Redo: (9) non_member(b, []) ? creep
Fail: (9) non_member(b, []) ? creep
Fail: (8) non_member(b, [a]) ? creep
Redo: (8) n(_G1026, _G1112) ? creep
Exit: (8) n(a, c) ? creep
Call: (8) non_member(c, [a]) ? creep
Call: (9) dif:dif(c, a) ? creep
Exit: (9) dif:dif(c, a) ? creep
Call: (9) non_member(c, []) ? creep
Exit: (9) non_member(c, []) ? creep
Exit: (8) non_member(c, [a]) ? creep
Call: (8) path(n, _G1113, c, d, [c, a]) ? creep
Call: (9) n(c, _G1118) ? creep
Fail: (9) n(c, _G1118) ? creep
Fail: (8) path(n, _G1113, c, d, [c, a]) ? creep
Redo: (9) non_member(c, []) ? creep
Fail: (9) non_member(c, []) ? creep
Fail: (8) non_member(c, [a]) ? creep
Redo: (8) n(_G1026, _G1112) ? creep
Exit: (8) n(a, d) ? creep
Call: (8) non_member(d, [a]) ? creep
Call: (9) dif:dif(d, a) ? creep
Exit: (9) dif:dif(d, a) ? creep
Call: (9) non_member(d, []) ? creep
Exit: (9) non_member(d, []) ? creep
Exit: (8) non_member(d, [a]) ? creep
Call: (8) path(n, _G1113, d, d, [d, a]) ? creep
Exit: (8) path(n, [], d, d, [d, a]) ? creep
Exit: (7) path(n, [d], a, d, [a]) ? creep
Exit: (6) path(n, [a, d], a, d) ? creep
P = [a, d],
X = a .
as you can see, in this case algorithm fails to brute force.
For this reason, if algorithm is not improved, I suggest do not add "end node" as "path" argument.
I believe that the problem I have is very silly, but couldn't find an answer searching online. I want a function to always return a list of elements, even in the case the list consists of just one element. I don't know if it is always like that in prolog (i.e. that one element lists are transformed in a simple constant) but here I go into detail.
First off, I have a set of predicates (like composeBase(<,<,[<]).) based on which the function I was talking about, compose/3, makes its computations:
compose(X, Y, Z):-
compositionBase(X,Y,Z).
So, for instance, compose/3 does this:
compose(<, <, L).
L = (<) .
compose(<, =, L).
L = (<) .
compose(=, =, L).
L = (=) .
So, why in the first example does it not return [<] if the predicate says composeBase(<,<,[<]).? Is there a way to make it return the list [<] instead?
If there is not or my question doesn't make any sense, here is where the problem comes with not being able to do so (if there is, don't even bother to go on reading of course! :) Unless you feel like giving me suggestions for my naive code, which I would very much appreciate as a newbie).
I have to write a function composeList/3 which, given two lists of elements, should compute a list containing all the possible compositions of the elements in the two set.
Therefore, for example, composeList/3 should do this:
composeList([<], [<, =], L).
L = [<, =] .
composeList([<,=], [<, =], L).
L = [<, =] .
And here's the code:
composeList(_,[],[]).
composeList([],_,[]).
composeList([X| Xs], [Y| Ys], L):-
compose(X,Y,L1),
composeList(Xs, [Y| Ys], L2),
composeList([X| Xs], Ys, L3),
union(L1, L2, L4),
union(L3,L4,L).
So, as confirmed by doing trace., I believe the problem occurs when compose/3 returns a simple constant and not a list. For instance, in the example above it returns false . because, since L1 is set <, the first union fails. How can I fix this in a casual way?
By the way, here is what trace. does:
[trace] 123 ?- compositionListe([<],[<,=],L).
Call: (7) compositionListe([<], [<, =], _G8032) ? creep
Call: (8) compose(<, <, _G8122) ? creep
Call: (9) compositionBase(<, <, _G8122) ? creep
Exit: (9) compositionBase(<, <, [<]) ? creep
Exit: (8) compose(<, <, [<]) ? creep
Call: (8) compositionListe([], [<, =], _G8128) ? creep
Exit: (8) compositionListe([], [<, =], []) ? creep
Call: (8) compositionListe([<], [=], _G8131) ? creep
Call: (9) compose(<, =, _G8131) ? creep
Exit: (9) compose(<, =, <) ? creep
Call: (9) compositionListe([], [=], _G8134) ? creep
Exit: (9) compositionListe([], [=], []) ? creep
Call: (9) compositionListe([<], [], _G8137) ? creep
Exit: (9) compositionListe([<], [], []) ? creep
Call: (9) lists:union(<, [], _G8137) ? creep
Fail: (9) lists:union(<, [], _G8137) ? creep
Thank you very much in advance!
I have the following code that generates all possible permutations of a list, but I can't figure it out why it is working.
remove(X,[X|T],T).
remove(X,[F|T],[F|T1]) :- remove(X,T,T1).
perm([X|Y],Z) :- perm(Y,W), remove(X,Z,W).
perm([],[]).
Could someone give me some explanation or send me to a reference, please?
I'm just picking up Prolog, so I don't know the correct terms, but I think the logic goes as following:
The rules for remove(X,L,T) is straightforward, it defines T as a list with X removed from L. For example, given T=[1], which L satisfies X=2? the answer is [1,2] or [2,1].
For perm, let's take the example of perm([1,2,3], P).
According to the definition, P is a permutation of [1,2,3] if W is a permuation of [2,3], where W is P with 1 removed.
Assuming we somehow know W is [2,3] or [3,2] through the magic of backtracking, then P must be [1,2,3],[2,1,3],[2,3,1],...
How did we find out permutation of [2,3] is [2,3] or [3,2]? It happens when W2 is a permutation of [3], where W2 is P2 with 2 removed.
Assuming we somehow know W2 is [3], then P2 must be [2,3] or [3,2].
How did we find out permutation of [3] is [3]? It happens when W3 is a permutation of [], where W3 is P3 with 3 removed. Since W3 must be [] due to the base case, then P3 must be [3].
Just learned about the trace mode, it provides a step-by-step explanation:
?- trace.
true.
[trace] 2 ?- perm([1,2],X).
Call: (7) perm([1, 2], _G22903) ? creep
Call: (8) perm([2], _G22988) ? creep
Call: (9) perm([], _G22988) ? creep
Exit: (9) perm([], []) ? creep
Call: (9) remove(2, _G22988, []) ? creep
Exit: (9) remove(2, [2], []) ? creep
Exit: (8) perm([2], [2]) ? creep
Call: (8) remove(1, _G22903, [2]) ? creep
Exit: (8) remove(1, [1, 2], [2]) ? creep
Exit: (7) perm([1, 2], [1, 2]) ? creep
X = [1, 2] ;
Redo: (8) remove(1, _G22903, [2]) ? creep
Call: (9) remove(1, _G22984, []) ? creep
Exit: (9) remove(1, [1], []) ? creep
Exit: (8) remove(1, [2, 1], [2]) ? creep
Exit: (7) perm([1, 2], [2, 1]) ? creep
X = [2, 1] ;
Redo: (9) remove(1, _G22984, []) ? creep
Fail: (9) remove(1, _G22984, []) ? creep
Fail: (8) remove(1, _G22903, [2]) ? creep
Redo: (9) remove(2, _G22988, []) ? creep
Fail: (9) remove(2, _G22988, []) ? creep
Fail: (8) perm([2], _G22988) ? creep
Fail: (7) perm([1, 2], _G22903) ? creep
false.
I have to write a function that filters out palindromes from a given list (palindrome are words which are the same in reverse like abba)
palindroom([], []).
palindroom([X|Xs], Y):-
( atom_chars(X, Z),
reverse(Z, K),
atom_chars(D,K),
atom_chars(P,Z),
D==P,
palindroom(Xs,[P|Y])
;
palindroom(Xs,Y)
).
I make the list elem into char array then reverse it and make it back into a string then compare the two, if it is I add it Y.
Here is my stacktrace where everything is going correctly until:
[trace] 44 ?- palindroom(["abba"], X).
Call: (7) palindroom(["abba"], _G5269) ? creep
Call: (8) atom_chars("abba", _G5351) ? creep
Exit: (8) atom_chars("abba", [a, b, b, a]) ? creep
Call: (8) lists:reverse([a, b, b, a], _G5363) ? creep
Exit: (8) lists:reverse([a, b, b, a], [a, b, b, a]) ? creep
Call: (8) atom_chars(_G5386, [a, b, b, a]) ? creep
Exit: (8) atom_chars(abba, [a, b, b, a]) ? creep
Call: (8) atom_chars(_G5386, [a, b, b, a]) ? creep
Exit: (8) atom_chars(abba, [a, b, b, a]) ? creep
Call: (8) abba==abba ? creep
Exit: (8) abba==abba ? creep
Call: (8) palindroom([], [abba|_G5269]) ? creep
Fail: (8) palindroom([], [abba|_G5269]) ? creep
Redo: (7) palindroom(["abba"], _G5269) ? creep what is happening here? and why?
Call: (8) palindroom([], _G5269) ? creep
Exit: (8) palindroom([], []) ? creep
Exit: (7) palindroom(["abba"], []) ? creep
X = [].
I have another program with the same problem, could anyone help me? is the base of the recursion wrong or smt?
EDIT!!
got it working with
palindrome(Xs) :-
reverse(Xs, Xs).
cycle([],[]).
cycle([X|Xs], Y):-
atom_chars(X,Z),
palindrome(Z),
Y = [X|K],
cycle(Xs,K);
cycle(Xs,Y).
I misunderstood recursion in Prolog afterall. thanks #repeat and #lurker
How about defining palindrome/1 like this, using the widely available list predicate reverse/2?
palindrome(Xs) :-
reverse(Xs, Xs).
Sample queries:
:- palindrome([a,b,b,a]).
true.
:- palindrome([a,b,X,Y]).
X = b, Y = a.
Last, let's not forget about the most general query!
?- palindrome(Xs).
Xs = []
; Xs = [_A]
; Xs = [_A,_A]
; Xs = [_A,_B,_A]
; Xs = [_A,_B,_B,_A]
; Xs = [_A,_B,_C,_B,_A]
...
I am trying to write a simple translator, where you enter a list of numerical numbers and it returns their string values like so :
translate([1,2,3], X).
X=[one, two, three].
The code I have written works...except it returns an empty list. Here is my code and the trace:
means(1, one).
means(2, two).
means(3, three).
means(4, four).
means(5, five).
means(6, six).
means(7, seven).
means(8, eight).
means(9, nine).
means(10, ten).
translate([], X).
translate([H|T], []):-
means(H, X),
translate(T, X).
translate([H|T], X):-
means(H, Y),
translate(T, [X|Y]).
[trace] 1 ?- translate([1,2,3], X).
Call: (6) translate([1, 2, 3], _G2219) ? creep
Call: (7) means(1, _G2301) ? creep
Exit: (7) means(1, one) ? creep
Call: (7) translate([2, 3], one) ? creep
Call: (8) means(2, _G2301) ? creep
Exit: (8) means(2, two) ? creep
Call: (8) translate([3], [one|two]) ? creep
Call: (9) means(3, _G2304) ? creep
Exit: (9) means(3, three) ? creep
Call: (9) translate([], [[one|two]|three]) ? creep
Exit: (9) translate([], [[one|two]|three]) ? creep
Exit: (8) translate([3], [one|two]) ? creep
Exit: (7) translate([2, 3], one) ? creep
Exit: (6) translate([1, 2, 3], []) ? creep
X = [] .
My other question is: why is my list concatenating as [[one|two]|three]? instead of [one, two, three]?
Thanks,
You get empty list because of translate([H|T], []) clause.
The whole program (except means facts) can be just this simple:
translate([], []).
translate([NumH | NumT], [WordH | WordT]) :-
means(NumH, WordH),
translate(NumT, WordT).
Doing it manually Sergey's way is good practice, but you can simplify even further with maplist/3:
translate(Numbers, Words) :- maplist(means, Numbers, Words).