how to find all connected path from node to another node using prolog? - prolog

how can i find all path of node that are connected between : a to g
by using rules on Prolog ?
The graph
my simple code:
cites(a,c).
cites(a,c).
cites(b,d).
cites(b,e).
cites(c,f).
cites(e,g).
cites(f,g).
cites(g,d).
cites(h,g).
connected(A,B):-cites(A ,B).
connected(A,B):-cites(A ,C),connected(C ,B).

The first thing you need is a way to generate or test routes. I would do that like this. It will successively find all possible routes via backtracking:
cities(a,b).
cities(a,c).
cities(b,d).
cities(b,e).
cities(c,f).
cities(e,g).
cities(f,g).
cities(g,d).
cities(h,g).
% ------------------------------------------
%
% route( Origin, Destination, Route)
%
% Does Route connect Origin and Destination?
%
%-------------------------------------------
route( A , B , R ) :- % find route R between A and B by...
route( A , B , [A] , P ) , % - invoke the helper, seeding the list of visited nodes with the origin
reverse(R,P) % - and reversing the path to get the route.
. % Easy!
% -----------------------------------------------------------
%
% route( Origin, Destination, Visited, Path )
%
% Finds the path from Origin to Destination, using Visited to
% detect cycles in the graph, building out the final route
% in reverse order.
% -----------------------------------------------------------
route( A , B , Vs , [B|Vs] ) :- % We can get from A to B if...
cities(A,B) , % - A is directly connected to B, and
not_yet_visited(B,Vs) % - we've not yet visited B
. % otherwise...
route( A , B , Vs , Rs ) :- % we can get from A to B if...
cities(A,C) , % - A is connected to some city C, and
not_yet_visited(C,Vs) , % - we've not yet visited C, and
route(C,B,[C|Vs],Rs) % - C is [recursively] connected to B
. % Easy!
%----------------------------------------------------------
%
% not_yet_visited( Node, Visited )
%
% succeeds if Node is not found in Visited; false otherwise
%
%----------------------------------------------------------
not_yet_visited( X , Xs ) :- \+ memberchk(X,Xs) .
Once you have that, then it's a simple matter of using findall/3, bagof/3 or setof/3 to collect all solutions in a list of lists. Something like:
all_routes( A , B , Rs ) :- findall( route(A,B,R), route(A,B,R), Rs ) .

Following short and simple code is adapted from here.
cities(1,2).
cities(2,3).
cities(3,4).
cities(3,5).
cities(2,5).
cities(5,6).
cities(2,6).
connected(X,Y,[cities(X,Y)]) :- cities(X,Y).
connected(X,Y,[cities(X,Z)|P]) :- cities(X,Z),connected(Z,Y,P).
Then one can search for paths:
?- connected(1,6,P).
P = [cities(1, 2), cities(2, 6)] ;
P = [cities(1, 2), cities(2, 3), cities(3, 5), cities(5, 6)] ;
P = [cities(1, 2), cities(2, 5), cities(5, 6)] ;

Related

Comparing the number of nodes at a given depth in Prolog

Given two binary trees T1 and T2 having the same height, I would like to know how to check if the number of nodes of T1 is equal to the number of nodes in T2, for each value of depth D.
I wrote a predicate numberOfNodesatD(T, N, D) which calculates the number of nodes at a depth D, but I am not able to define in Prolog the equality between the number of nodes if N1 == N2.
Riffing off my answer to your earlier question, Prolog - Find the depth of an element in a binary tree,
We can use
visit(T,P,D) :- visit(T,0,P,D) .
visit( t(_,L,_) , N, P, D ) :- N1 is N+1, visit(L,N1,P,D) .
visit( t(P,_,_) , D, P, D ) .
visit( t(_,_,R) , N, P, D ) :- N1 is N+1, visit(R,N1,P,D) .
and do something like this:
node_count_by_depth(T,D,N) :-
findall( D, visit(T,_,D), Ds ) ,
msort(Ds,Ss)l ,
groups(Ss,Fs) .
groups( [] , [] ) .
groups( [X|Xs] , Ys ) :- groups(Xs, X:1, Ys ).
groups( [] , Y:N , [Y:N] ) . % the end of the source list is a sequence break.
groups( [X|Xs] , X:N , Ys ) :- % if we haven't hit a sequence break...
N1 is N+1 , % - increment the count
groups(Xs,X:N1,Ys) . % - and recurse down
groups( [X|Xs] , Y:N , [Y:N|Ys] ) :- % otherwise...
X \= Y , % - we have hit a sequence break,
groups(Xs,X:1,Ys) % - recurse down, having moved the tuple to the result list
. % Easy!
And once you have that, then it's a matter of:
same_number_of_nodes_at_depth(T1,T2,D,N) :-
node_count_by_depth(T1,L1),
node_count_by_depth(T2,L2),
member( D:N, L1 ),
member( D:N, L2 ).

Find path in graph by backtracking using prolog

I have the following graph:
maniere(v11,h11).
maniere(h11,v12).
maniere(h11,h21).
maniere(v12,v22).
maniere(v22,h13).
maniere(v22,h23).
maniere(h13,v21).
maniere(v22,h23).
maniere(h12,h22).
maniere(h23,v23).
maniere(h33,v23).
maniere(v13,h32).
maniere(v23,h32).
The required output is:
?- traverser(v11, v23).
v11 to h11
h11 to v12
v12 to v22
v22 to h13
h13 to v21
v22 to h23
h23 to v23
true .
I'm having trouble when I don't format the output as requested.
The general rule for traversing a graph is pretty simple:
The simple/special case:
We can get from A to B if A and B are directly connected.
The more general/recursive case:
We can get from A to B if A is connected to some intermediate node X, and we can then get from X to B.
Correct?
That can be expressed directly in Prolog.
For the sake of argument we will use edge/2 to define our graph, so edge(a,b). is a fact that tell us that we can travel from a to b (but not from b to a — our graph is a directed graph.
traverse(A,B) :- edge(A,B).
traverse(A,B) :- edge(A,X), traverse(X,B).
To get what you need, though, you'll want to track your path through the graph. To do that, you need to use a helper predicate that takes additional arguments to carry state and return results, The other reason for tracking your path through the graph is so that you can detect cycles in the graph — if you wind up back at a node you've already visited, you'll wind up going into an infinite loop (or at least, until the stack overflows). That gets you to this:
traverse(A,B) :- % we can get from A to B iff...
traverse(A,B,[A]). % - we invoke the helper, seeding the list of visited nodes with A, the origin node
% ---------------------------------------
% traverse(Origin, Destination, Visited )
% ---------------------------------------
traverse( A , B , _ ) :- % we can get from A to B iff...
edge(A,B). % - A and B are directly connected.
traverse( A , B , V ) :- % Otherwise, we can get from A to B iff...
edge(A,X), % - An edge exists from A to X, and
not_visited(X,V), % - We have not yet visited X, and
traverse(X,B,[X|V]). % - We can get from X to B
not_visited(N,V) :- % we haven't visited node N...
\+ member(N,V). % - if N is not contained in the list of visited nodes (V).
But you need to return the complete path, which is just a matter of adding an additional argument to the helper predicate:
traverse(A,B,P) :- % we can get from A to B iff...
traverse(A,B,[A],P). % - we invoke the helper, seeding the list of visited nodes with A, the origin node
% ---------------------------------------
% traverse(Origin, Destination, Visited )
% ---------------------------------------
traverse( A , B , V, [B|V] ) :- % we can get from A to B iff...
edge(A,B). % - A and B are directly connected.
traverse( A , B , V, P ) :- % Otherwise, we can get from A to B iff...
edge(A,X), % - An edge exists from A to X, and
not_visited(X,V), % - We have not yet visited X, and
traverse(X,B,[X|V],P). % - We can get from X to B
not_visited(N,V) :- % we haven't visited node N...
\+ member(N,V). % - if N is not contained in the list of visited nodes (V).
And then, you need a way to display the path.
You might notice that the path is returned in reverse order. You can use recursion to deal with that:
display_path([]).
display_path([_]).
display_path([To,From|Ns]) :-
display_path([From|Ns]),
display_leg(From,To).
display_leg(From,To) :- write(From), write(' --> '), write(To), nl.
But that's a little counter-intuitive. Better to have the helper reverse the list on success:
traverse(A,B,P) :- % we can get from A to B iff...
traverse(A,B,[A],P). % - we invoke the helper, seeding the list of visited nodes with A, the origin node
% ---------------------------------------
% traverse(Origin, Destination, Visited )
% ---------------------------------------
traverse( A , B , V, P ) :- % we can get from A to B iff...
edge(A,B), % - A and B are directly connected,
reverse([B|V],P).
traverse( A , B , V, P ) :- % Otherwise, we can get from A to B iff...
edge(A,X), % - An edge exists from A to X, and
not_visited(X,V), % - We have not yet visited X, and
traverse(X,B,[X|V],P). % - We can get from X to B
not_visited(N,V) :- % we haven't visited node N...
\+ member(N,V). % - if N is not contained in the list of visited nodes (V).
That makes display_path/1 much more intuitive:
display_path([]).
display_path([_]).
display_path([From,To|Ns]) :-
display_leg(From,To),
display_path([To|Ns]).
display_leg(From,To) :-
write(From),
write(' --> '),
write(To),
nl.
And we can wrap our traverse/3 up with display_path/1:
visit(A,B) :- traverse(A,B,P), display_path(P).
Wrapping it all up, we get this (you can fiddle with it at https://swish.swi-prolog.org/p/rmEdFAqE.pl):
edge(a,b).
edge(a,c).
edge(b,c).
edge(c,d).
visit(A,B) :- traverse(A,B,P), display_path(P).
traverse(A,B,P) :- % we can get from A to B iff...
traverse(A,B,[A],P). % - we invoke the helper, seeding the list of visited nodes with A, the origin node
% ---------------------------------------
% traverse(Origin, Destination, Visited )
% ---------------------------------------
traverse( A , B , V, P ) :- % we can get from A to B iff...
edge(A,B), % - A and B are directly connected,
reverse([B|V],P).
traverse( A , B , V, P ) :- % Otherwise, we can get from A to B iff...
edge(A,X), % - An edge exists from A to X, and
not_visited(X,V), % - We have not yet visited X, and
traverse(X,B,[X|V],P). % - We can get from X to B
not_visited(N,V) :- % we haven't visited node N...
\+ member(N,V). % - if N is not contained in the list of visited nodes (V).
display_path([]).
display_path([_]).
display_path([A,B|Ns]) :-
display_leg(A,B),
display_path([B|Ns]).
display_leg(From,To) :-
write(From),
write(' --> '),
write(To),
nl.

Even sum & Odd product of a list, Swi-Prolog [duplicate]

I have a list of numbers, I need to calculate the sum of the even numbers of the list and the product of the odd numbers of the same list. I'm new in Prolog, and my searches so far weren't successful. Can anyone help me solve it ?
l_odd_even([]).
l_odd_even([H|T], Odd, [H|Etail]) :-
H rem 2 =:=0,
split(T, Odd, Etail).
l_odd_even([H|T], [H|Otail], Even) :-
H rem 2 =:=1,
split(T, Otail, Even).
Here is a suggestion for the sum of the even numbers from a list:
even(X) :-
Y is mod(X,2), % using "is" to evaluate to number
Y =:= 0.
odd(X) :- % using even
Y is X + 1,
even(Y).
sum_even(0, []). % empty list has zero sum
sum_even(X, [H|T]) :-
even(H),
sum_even(Y, T),
X is Y+H.
sum_even(X, [H|T]) :-
odd(H),
sum_even(X, T). % ignore the odd numbers
Note: My Prolog has oxidized, so there might be better solutions. :-)
Note: Holy cow! There seems to be no Prolog support for syntax highlighting (see here), so I used Erlang syntax.
Ha, it really works. :-)
Running some queries in GNU Prolog, I get:
| ?- sum_even(X,[]).
X = 0 ?
yes
| ?- sum_even(X,[2]).
X = 2 ?
yes
| ?- sum_even(X,[3]).
X = 0 ?
yes
| ?- sum_even(X,[5,4,3,2,1,0]).
X = 6 ?
yes
The ideas applied here should enable you to come up with the needed product.
Use clpfd!
:- use_module(library(clpfd)).
Building on meta-predicate foldl/4, we only need to define what a single folding step is:
sumprod_(Z,S0,S) :-
M #= Z mod 2,
rem_sumprod_(M,Z,S0,S).
rem_sumprod_(0,Z,S0-P,S-P) :-
S0 + Z #= S.
rem_sumprod_(1,Z,S-P0,S-P) :-
P0 * Z #= P.
Let's fold sumprod_/3 over the list!
l_odd_even(Zs,ProductOfOdds,SumOfEvens) :-
foldl(sumprod_,Zs,0-1,SumOfEvens-ProductOfOdds).
Sample query:
?- l_odd_even([1,2,3,4,5,6,7],Odd,Even).
Odd = 105,
Even = 12.
Alternatively, we can define sumprod_/3 even more concisely by using if_/3 and zeven_t/3:
sumprod_(Z,S0-P0,S-P) :-
if_(zeven_t(Z), (S0+Z #= S, P0=P),
(P0*Z #= P, S0=S)).
untested!
sum_odd_product_even([], S, P, S, P).
sum_odd_product_even([H|T], S0, P0, S, P) :-
S1 is S0 + H,
sum_even_product_odd(T, S1, P0, S, P).
sum_even_product_odd([], S, P, S, P).
sum_even_product_odd([H|T], S0, P0, S, P) :-
P1 is P0 * H,
sum_odd_product_even(T, S0, P1, S, P).
sum_odd_product_even(L, S, P) :-
sum_odd_product_even(L, 0, 1, S, P).
sum_even_product_odd(L, S, P) :-
sum_even_product_odd(L, 0, 1, S, P).
It shouldn't get much simpler than
%
% invoke the worker predicate with the accumulators seeded appropriately.
%
odds_and_evens( [O] , P , S ) :- odds_and_evens( [] , O , 0 , P , S ) .
odds_and_evens( [O,E|Ns] , P , S ) :- odds_and_evens( Ns , O , E , P , S ) .
odds_and_evens( [] , P , S , P , S ) . % if the list is exhausted, we're done.
odds_and_evens( [O] , X , X , P , S ) :- % if it's a single element list, we've only an odd element...
P is X*O , % - compute it's product
. % - and we're done.
odds_and_evens( [O,E|Ns] , X , Y , P , S ) :- % if the list is at least two elements in length'e both an odd and an even:
X1 is X*O , % - increment the odd accumulator
Y1 is Y+E , % - increment the even accumulator
odds_and_evens( Ns , X1 , Y1 , P , S ) % - recurse down (until it coalesces into one of the two special cases)
. % Easy!

Finding the k'th occurence of a given element

I just started in Prolog and have the problem:
(a) Given a list L, an object X, and a positive integer K, it returns
the position of the K-th occurrence of X in L if X appears at least K
times in L otherwise 0.
The goal pos([a,b,c,b],b,2,Z) should succeed with the answer Z = 4.
So far I have:
pos1([],H,K,F).
pos1([H],H,1,F).
pos1([H|T],H,K,F):- NewK is K - 1, pos1(T,H,NewK,F), F is F + 1.
pos1([H|T],X,K,F):- pos1(T,X,K,F).
But I can't figure out why I'm getting:
ERROR: is/2: Arguments are not sufficiently instantiated
Any help would be much appreciated!
Use clpfd!
:- use_module(library(clpfd)).
We define pos/4 based on (#>)/2, (#=)/2, if_/3, dif/3, and (#<)/3:
pos(Xs,E,K,P) :-
K #> 0,
pos_aux(Xs,E,K,1,P).
pos_aux([X|Xs],E,K,P0,P) :-
P0+1 #= P1,
if_(dif(X,E),
pos_aux(Xs,E,K,P1,P),
if_(K #< 2,
P0 = P,
(K0+1 #= K,
pos_aux(Xs,E,K0,P1,P)))).
Sample query as given by the OP:
?- X = b, N = 2, pos([a,b,c,b],X,N,P).
X = b, N = 2, P = 4. % succeeds deterministically
How about the following more general query?
?- pos([a,b,c,b],X,N,P).
X = a, N = 1, P = 1
; X = b, N = 1, P = 2
; X = b, N = 2, P = 4 % (exactly like in above query)
; X = c, N = 1, P = 3
; false.
Let's take a high-level approach to it, trading the efficiency of the resulting code for the ease of development:
pos(L,X,K,P):-
numerate(L,X,LN,1), %// [A1,A2,A3...] -> [A1-1,A2-2,A3-3...], where Ai = X.
( drop1(K,LN,[X-P|_]) -> true ; P=0 ).
Now we just implement the two new predicates. drop1(K,L,L2) drops K-1 elements from L, so we're left with L2:
drop1(K,L2,L2):- K<2, !.
drop1(K,[_|T],L2):- K1 is K-1, drop1(K1,T,L2).
numerate(L,X,LN,I) adds an I-based index to each element of L, but keeps only Xs:
numerate([],_,[],_).
numerate([A|B],X,R,I):- I1 is I+1, ( A=X -> R=[A-I|C] ; R=C ), numerate(B,X,C,I1).
Testing:
5 ?- numerate([1,b,2,b],b,R,1).
R = [b-2, b-4].
6 ?- pos([1,b,2,b],b,2,P).
P = 4.
7 ?- pos([1,b,2,b],b,3,P).
P = 0.
I've corrected your code, without changing the logic, that seems already simple enough.
Just added a 'top level' handler, passing to actual worker pos1/4 and testing if worked, else returning 0 - a debatable way in Prolog, imo is better to allow to fail, I hope you will appreciate how adopting this (see comments) simplified your code...
pos(L,X,K,F):- pos1(L,X,K,F) -> true ; F=0.
% pos1([],H,K,F). useless: let it fail
% pos1([H],H,1,F). useless: already handled immediatly bottom
pos1([H|T],H,K,P):- K==1 -> P=1 ; NewK is K - 1, pos1(T,H,NewK,F), P is F + 1.
pos1([_|T],X,K,P):- pos1(T,X,K,F),P is F+1.
I hope you're allowed to use the if/then/else construct. Anyway, yields
7 ?- pos([a,b,c,b],b,2,Z).
Z = 4.
8 ?- pos([a,b,c,b],b,3,Z).
Z = 0.
Something like this. An outer predicate (this one enforces the specified constraints) that invokes an inner worker predicate:
kth( L , X , K , P ) :-
is_list( L ) , % constraint: L must be a list
nonvar(X) , % constriant: X must be an object
integer(K) , K > 0 % constraint: K must be a positive integer
kth( Ls , X , K , 1 , P ) % invoke the worker predicate with its accumulator seeded to 1
. % easy!
is_list/2 ensures you've got a list:
is_list(X) :- var(X) , !, fail .
is_list([]).
is_list([_|_]).
The predicate that does all the work is this one:
kth( [] , _ , _ , _ , 0 ) . % if we hit the end of the list, P is 0.
kth( [X|Ls] , X , K , K , K ) :- ! . % if we find the Kth desired element, succeed (and cut: we won't find another Kth element)
kth( [_|Ls] , X , K , N , P ) :- % otherwise
N < K , % - if we haven't got to K yet ...
N1 is N+1 , % - increment our accumulator , and
kth(Ls,X,K,N1,P) % - recurse down.
. % easy!
Though the notion of returning 0 instead of failure is Not the Prolog Way, if you ask me.

Trying to break elements which are lists in a list?

I am trying to write a program which make the following:
?- g([2,3, [22,[3],9] ,4,[5],99],X).
X= [2,3,22,[3],9 ,4,5,99]
So it searches for lists in the given list and replace it by their elements without brackets [].
So I wrote this program:
The first block just searches for the first element in the list which is list
If there is no such element it returns [there_is_no_list].
first_list_in_the_list([],[there_is_no_list]):-!.
first_list_in_the_list([H|_],X):-is_list(H),X=H,!.
first_list_in_the_list([_|T],X):-first_list_in_the_list(T,X).
The first block works in prolog perfectly.
The second block just search in the list for an element X and then split the list into a two lists one is the list of all elements before X and the second is the elements after X.
splite_when_find_element([H|T],H,[],T):-!.
splite_when_find_element([H|T],X,F,G):-
splite_when_find_element(T,X,F1,G),append([H],F1,F).
it also works fine in Prolog.
and the third block is append, and it joins two list together in a new list.
append([],L,L).
append([H|T],L,[H|U1]):- append(T,L,U1).
and the last part is:
gg(L,L):-first_list_in_the_list(L,[there_is_no_list]),!.
gg(L,U):-first_list_in_the_list(L,X),
splite_when_find_element(L,X,F,G),gg(G,R),append(F,X,E),
append(E,R,U).
When I give a query [2,[3],5] I get also [2,[3],5] and I really don't understand why it does this.
A simple recursive solution will also work. Recursion is done by the head of the input list. In the non-trivial case, when the head is a list itself, we just append the rest of the flattened list to it. In the code below, it has not flattened Rest yet in append(H, Rest, Out), but it will be, after the recursive call of g(In, Rest). Cut after the append call ensures that backtracking won't consider the last case, where the head will appear in the output as-is.
% Base case, empty list.
g([], []).
% First recursive case: head is list.
% Append remaining elements to it.
g([H|In], Out):-
append(H, Rest, Out), !,
g(In, Rest).
% Second recursive case: head is not list.
% Will appear as-is in the output.
g([H|In], [H|Out]):-
g(In, Out).
also a DCG can do
lev, X --> [X], {is_list(X)}, lev.
lev, [X] --> [X], lev.
lev --> [].
test:
?- phrase(lev,[a,[b,c,[d]],e],L).
L = [a, b, c, [d], e] .
To flatten 1 level of a nested list, try something like this:
flatten1( Xs , Ys ) :- % to flatten a list
flatten1( Xs , [] , Ys ) , % - invoke the worker predicate
. %
flatten1( [] , T , R ) :- % if we get to to the empty list
reverse(T,R) % - just reverse the accumulator and we're done.
. %
flatten1( [X|Xs] , T , R ) :- % if the head of the list is unbound
var(X) , % - check for being a var
! , % - cut (to eliminate problems on backtracking
T1 = [X|T] , % - prepend the head of the list to the accumulator
flatten( Xs , T1 , R ) % - and recurse down
. %
flatten1( [[]|Xs] , T , R ) :- % if head of the list is an empty list, skip it
flatten1( Xs , T , R ) % - ignore it and recurse down
. %
flatten1( [[X|Ns]|Xs] , T , R ) :- % if head of the list is a non-empty list
X1 = [Ns|Xs] , % - prepend the tail of the sublist to the list
T1 = [X|T] , % - prepend the head of the sublist to the accumulator
flatten( X1 , T1 , R ) % - and recurse down
. %
flatten( [X|Xs] , T , R ) :- % if the head of the list is something else (except an unbound variable)
T1 = [X|T] , % - prepend the list head to the accumulator and
flatten( Xs , T1 , R ) % - recurse down
. %

Resources