Here is some working code
:- op(500,xfx,'is_parent').
a is_parent b. c is_parent g. f is_parent l. j is_parent q.
a is_parent c. c is_parent h. f is_parent m. j is_parent r.
a is_parent d. c is_parent i. h is_parent n. j is_parent s.
b is_parent e. d is_parent j. i is_parent o. m is_parent t.
b is_parent f. e is_parent k. i is_parent p.
start(Parent,In_order) :-
queue([Parent],[],In_order).
queue([],In_order,In_order).
queue([Parent|Queue0],In_order0,In_order) :-
append(In_order0,[Parent],In_order1),
findall(Child,Parent is_parent Child,Children),
append(Queue0,Children,Queue),
queue(Queue,In_order1,In_order).
I still don’t like that I am using findall/3 for a beginner example as it hides some of the details.
Example run:
?- start(a,In_order);true.
In_order = [a, b, c, d, e, f, g, h, i|...] [write]
In_order = [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t] .
Since the answer was long made use of Help: I want the whole answer
Here are the details.
The first thing needed is to find the children of a parent. This is accomplished using findall/3, e.g.
?- findall(Child,a is_parent Child,Children).
Children = [b, c, d].
says to use a is_parent Child
on the facts and only remember the Child
and collect them into Children
The next thing is to keep a FIFO queue of the nodes visited. This is done using
start(Parent,_) :-
queue([Parent],_,_).
queue([],_,_).
queue([Parent|Queue0],_,_) :-
...,
findall(_,_,Children),
append(Queue0,Children,Queue),
queue(Queue,_,_).
where the queue is initialized with queue([Parent],_,_)
new nodes to add to the queue are found with findall(_,_,Children)
the new nodes are added to the queue with append(Queue0,Children,Queue)
and the new queue is passed along in queue(Queue,_,_)
for the recursion.
Also a base case is needed for the recursion queue([],_,_)
.
Instead of printing out the nodes as they were visited I just accumulated them into the in_order
list, e.g.
start(_,In_order) :-
queue(_,[],In_order).
queue(_,In_order,In_order).
queue([Parent|_],In_order0,In_order) :-
append(In_order0,[Parent],In_order1),
...,
...,
queue(_,In_order1,In_order).
The in_order list is internalized with []
in queue(_,[],In_order)
The in_order list accumulates the current node Parent
with append(In_order0,[Parent],In_order1)
and the new in_order list is passed along in queue(_,In_order1,In_order)
for the recursion.
Also a base case is needed for the recursion queue(_,In_order,In_order)
that moves the accumulated values into the output variable to be passed back up.
You can add the fancy formatting with ->
but this gives you the more technical parts of the FIFO queue.
Also note that this code only works on trees, no DAGs or graphs. The reason being that it does not keep track of which nodes it has visited. That is easily added and would not be surprised if that is one of the next exercises.