Getting node from a graph prolog - prolog

I'm a newbie in Prolog, I have this question.
From this fact need getting every single node from this nodelist, how I can do?
nodelist([[a,[2,3],[b,d]],[b,[5,1],[a,c,d]],[c,[3,2],[b,d]]).
where nodelist([[node,[coordinate_node],[neighbours]]])
I've tried
node(Nodelist,Node):- nodelist(Nodelist), findall(Node,Nodelist(Nodes),Nodes).
syntax error operator expected

I show you two ways to do the job :
First way, "functionnal design" because you work with every element of the list of nodes
:- use_module(library(lambda)).
nodelist([[a,[2,3],[b,d]],[b,[5,1],[a,c,d]],[c,[3,2],[b,d]]]).
fetch_nodes(In, Out) :-
foldl(\X^Y^Z^(X = [_, _, Nodes], union(Y,Nodes, Z)), In, [], Out).
example
?- nodelist(L), fetch_nodes(L, Nodes).
L = [[a, [2, 3], [b, d]], [b, [5, 1], [a, c, d]], [c, [3, 2], [b, d]]],
Nodes = [a, c, b, d].
The second way is more "prologish", aggregate_all extends findall :
nodes(Nodelist,Nodes):-
aggregate_all(set(Node), (member([_, _, L], Nodelist), member(Node, L)),Nodes).
PS You can find details for library lambda, foldl, union and aggregate_all on the site of SWI-Prolog

Here is a complete program. Note that I had to fix your definition of nodelist/1.
nodelist([[a,[2,3],[b,d]],[b,[5,1],[a,c,d]],[c,[3,2],[b,d]]]).
node(X) :-
nodelist(L),
member([X,_,_], L).
nodes(Xs) :-
nodelist(L),
nodes(L, Xs).
nodes([], []).
nodes([[X,_,_]|L], [X|Xs]) :-
nodes(L, Xs).
and now:
?- node(X).
X = a ;
X = b ;
X = c.
?- nodes(Xs).
Xs = [a, b, c].

Related

A Prolog program for permutation parity

I wrote this small program in Prolog.
odd_even_flip(odd, even).
odd_even_flip(even, odd).
% flip_one, for A = a, B = b, P = [a, .., b, ..], gives M = [b, .., a, ..]
flip_one(A, B, P, M) :-
append([A|As], [B|Bs], P),
append([B], As, L),
append([A], Bs, R),
append(L, R, M).
permutation_parity([X|L], [X|P], R) :- permutation_parity(L, P, R).
% abc
permutation_parity([X|L], [Y|P], R) :-
X \= Y,
flip_one(Y, X, [Y|P], M),
permutation_parity([X|L], M, Res),
odd_even_flip(Res, R).
permutation_parity([], [], even).
I expect it to find the parity of a permutation P of list L. The few queries that assert that a given permutation of a given list is indeed even or odd worked fine.
However, from my experience with Prolog, I would expect that permutation_parity([a, b, c], X, Y). would show me all permutations of [a, b, c] but that is not happening.
Rather, I get X = [a, b, c], Y = even. and that is all.
I tried to add member(Y, L) in the rule that follows %abc as I was thinking that will help Prolog to know how to instantiate X in permutation_parity([a, b, c], X, Y) but that helped to no avail.
If someone could help me see what I am missing it would be great. Thanks in advance.
You only need to use unification to correctly instantiate the variable X (assuming that permutation_parity/3 is called with a proper list as its first argument). So I suggest you modify your code as follows:
permutation_parity([], [], even).
permutation_parity([X|Xs], [X|Zs], P) :-
permutation_parity(Xs, Zs, P).
permutation_parity([X|Xs], Zs, P) :-
permutation_parity(Xs, Ys, Q),
flip_first([X|Ys], Zs),
odd_even_flip(Q, P).
flip_first(L0, L1) :-
append([X|Xs], [Y|Ys], L0),
append([Y|Xs], [X|Ys], L1).
odd_even_flip(odd, even).
odd_even_flip(even, odd).
Examples:
?- permutation_parity([a,b,c], Permutation, Parity).
Permutation = [c, a, b],
Parity = even ;
Permutation = [b, c, a],
Parity = even ;
Permutation = [b, a, c],
Parity = odd ;
Permutation = [c, b, a],
Parity = odd ;
Permutation = [a, c, b],
Parity = odd ;
Permutation = [a, b, c],
Parity = even.
?- permutation_parity([a,b,c], [a,c,b], Parity).
Parity = odd ;
false.
?- permutation_parity([a,b,c], Permutation, even).
Permutation = [c, a, b] ;
Permutation = [b, c, a] ;
Permutation = [a, b, c].
EDIT
perm_parity(L0, L1, P) :-
same_length(L0, L1),
permutation_parity(L0, L1, P).
The predicate same_length/2 is defined in SWI-Prolog as follows:
same_length([], []).
same_length([_|T1], [_|T2]) :-
same_length(T1, T2).
Example:
?- perm_parity(L, [a,b,c], P).
L = [b, c, a],
P = even ;
L = [c, a, b],
P = even ;
L = [b, a, c],
P = odd ;
L = [c, b, a],
P = odd ;
L = [a, c, b],
P = odd ;
L = [a, b, c],
P = even.

Prolog: how can I change the output of combinations(N, [H|T], P) to return a list of pairs, rather than just the first one before ;?

Prolog: How can I change the output of combinations(N, [H|T], P) to return a list of pairs, rather than just the first one before ; ? The program works well as long as I press ; in the command line, but I want to return directly a list of pairs.
comb(1, [H|_], [H]).
comb(N, [H|T], [H|C]) :- N1 is N - 1, N1 > 0, comb(N1, T, C).
comb(N, [_|T], C):- comb(N, T, C).
This is my program. Thank you very much!
You are looking for findall/3.
findall(+Template, :Goal, -Bag)
Create a list of the instantiations Template gets successively on backtracking over Goal and unify the result with Bag. Succeeds with an empty list if Goal has no solutions. findall/3 is equivalent to bagof/3 with all free variables bound with the existential operator (^), except that bagof/3 fails when Goal has no solutions.
Example:
?- findall(X, comb(2, [a,b,c,d], X), Xs).
Xs = [[a, b], [a, c], [a, d], [b, c], [b, d], [c, d]].

Prolog Zip Function

Im in rew to Prolog. I'm trying to write a zip function. The question goes like this.
zip(L1, L2, X): The list X is formed by “zipping” the first 2 arguments.
the result should be like this:
?- zip([a, b, c], [x, y, z], X).
L = [a, x, b, y, c, z]
?- zip([a, b], [x, y, z], X).
false
?- zip([a, b, c, d], X, [a, p, b, q, c, r, d, s]).
X = [p, q, r, s]
I have done this so far.
I can get the result for 1st 3rd but not the 2nd one. Can anybody can help me solving it for the 2nd one? thank you
zip([X],[Y],[X,Y]).
zip([], [], []).
zip([X|Xs], [Y|Ys], [X,Y|Zs]) :-
zip(Xs,Ys,Zs).
zip([X|Xs],[],[X|Xs]).
zip([Y|Ys],[],[Y|Ys]).
zip(Xs, [], Xs).
zip([], Ys, Ys).
How do I define this function where:
allsame(L): The list L contains identical elements.
I should get this.
?- allsame([b, b, b]).
true
?- allsame([c, c, c, Y, c, c, X, c]).
X = c, Y = c
You had it:
zip([], [], []).
zip([X|Xs], [Y|Ys], [X,Y|Zs]) :- zip(Xs,Ys,Zs).
This alone is enough to define the relation you're seeking. The extra clauses don't help.
Test:
?- zip([a, b, c], [x, y, z], X).
X = [a, x, b, y, c, z].
?- zip([a, b], [x, y, z], X).
false.
?- zip([a, b, c, d], X, [a, p, b, q, c, r, d, s]).
X = [p, q, r, s].
#m09 gave the correct answer. But I'd like to explain why what you have isn't correct:
(1) zip([X],[Y],[X,Y]).
This rule says that [X,Y] is what you get when you zip [X] with [Y]. That is correct, and will not lead to a problem. The rule is simply redundant with the rules below (which I'll explain...).
(2) zip([], [], []).
This rule says [] is what you get when you zip [] with [] which is correct and as simple a rule as you can have for zip.
(3) zip([X|Xs], [Y|Ys], [X,Y|Zs]) :-
zip(Xs,Ys,Zs).
This rule says that [X,Y|Zs] is what you get when you zip [X|Xs] with [Y|Ys] if Zs is what you get when you zip Xs with Ys. That is also logical and correct. Notice that zip([X], [Y], [X,Y]) is zip([X|[]], [Y|[]], [X,Y|[]]). so it can be derived from rules (2) and (3). It would match rule (3) first, zip([X|[]], [Y|[]], [X,Y|Zs]) :- zip([], [], Zs)., then Zs would become [] by rule (2)`.
(4) zip([X|Xs],[],[X|Xs]).
(5) zip([Y|Ys],[],[Y|Ys]).
Rule (4) says [X|Xs] is what you get when you zip [X|Xs] with []. Rule (5) says exactly the same thing, logically, only with a different variable name. These are incorrect, since that would mean, for example, zip([a,b,c], [], Z) would be true if Z = [a,b,c].
(6) zip(Xs, [], Xs).
This rule says that Xs is what you get when you zip Xs with []. Or stated another way, any input, zipped with [], would be that input value again. It wouldn't even have to be a list! This is clearly incorrect. Queries like zip(x, [], Z) would succeed with Z = x, and zip(friend(bill,mary), [], Z) would succeed with Z = friend(bill,mary).
(7) zip([], Ys, Ys).
This rule says that Ys is what you get when you zip [] with Ys. It is incorrect for the same reason (6) is incorrect. In fact, this rule, combined with (2) and (3) are why the query zip([a, b], [x, y, z], X). will yield a result rather than fail. Rules (2) and (3) will recurse to zip([b], [y,z], [b,y|T]) :- zip([], [z], T). and then zip([], [z], T) will finally succeed on rule (7) with T = [z], and ultimately yielding a final result to zip([a, b], [x, y, z], X) of X = [a, x, b, y, z].

Prolog creating a list of sets from ith elements of lists

I have list structure
L=[[a,b,c,d],[a,f,c,h]]
Length of L can be greater than 2.I want to unite the elements of list so that L or a NewL become
L=[a,[b,f],c,[d-h]]
This is probably what you want:
unite([[],[]], []).
unite([[X|Ls], [X|Rs]], [X|Rest]) :- unite([Ls, Rs], Rest).
unite([[L|Ls], [R|Rs]], [[L,R]|Rest]) :- L \= R, unite([Ls, Rs], Rest).
However, I agree with #false because this is a strange API and there are a lot of unhandled edge cases.
What you're requiring is an aggregation schema. I think I got it:
unite(Ls, [E|Es]) :-
aggreg(Ls, E, Ns),
unite(Ns, Es).
unite(_, []).
aggreg(L, E, LLs) :-
maplist(first, L, Fs, LLs),
setof(X, member(X, Fs), S),
( [E] = S -> true ; E = S ).
first([E|Es], E, Es).
yields
?- L=[[a,b,c,d],[a,f,c,h],[a,f,c,g]],unite(L,U).
L = [[a, b, c, d], [a, f, c, h], [a, f, c, g]],
U = [a, [b, f], c, [d, g, h]] ;
L = [[a, b, c, d], [a, f, c, h], [a, f, c, g]],
U = [a, [b, f], c] .
I think that a cut after the first solution would be well placed (use once/1 for that).
Note that the schema it's rather general: just substitute in setof/3 some more applicative task (if any) than unification (you could call into your DB, for instance).

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