1:- module(tree, 2 [ print_tree/1 3 , print_tree/2 4 , empty_tree/2 5 , tree_node/2 6 , tree_canonical/2 7 , maptree/2 8 , maptree/3 9 , node_label/2 10 , node_children/2 11 , tree_cursor/2 12 , tree_depth/2 13 , cursor_node/2 14 , cursor_move/3 15 , cursor_add_sibling/3 16 , cursor_ins_sibling/3 17 , cursor_ins_child/3 18 , get_node/3 19 , set_node/3 20 ]). 21 22:- meta_predicate maptree( , ), maptree( , , ).
40empty_tree(A,node(A,[])).
45tree_node(T,T). 46tree_node(node(_,NX),N) :- member(T,NX), tree_node(T,N).
49node_label(node(A,_),A).
52node_children(node(_,C),C).
59maptree(P,node(A,AX)) :- call(P,A), maplist(maptree(P),AX). 60maptree(P,node(A,AX),node(B,BX)) :- call(P,A,B), maplist(maptree(P),AX,BX).
66tree_depth(node(_,[]),0). 67tree_depth(node(_,[C1|CX]),N) :- 68 maplist(tree_depth,[C1|CX],DX), 69 foldl(max,DX,0,M), 70 succ(M,N). 71 72 73max(L,M,N) :- N is max(L,M).
77tree_canonical(node(D,CX1),node(D,CX3)) :- 78 sort(CX1,CX2), maplist(tree_canonical,CX2,CX3). 79 80 81print_node(NA,T,T2) :- 82 with_output_to(string(AA),print(node(NA))), string_length(AA,L), 83 with_output_to(string(SA),tab(L)), string_concat(T,SA,T2), 84 write(AA).
print(node(X))
produces and so can be customised by declaring clauses of portray/1.
If the prefix Pre is supplied, the tree is started at the current position
in the output stream, but subsequent new lines are prefixed with Pre,
to allow arbitrary indenting.
If the child list for any node is a frozen variable, the variable is unfrozen.
100print_tree(T) :- write(' '), print_tree(' ',T), nl. 101print_tree(_,V) :- var(V), !, write('_'). 102print_tree(T,node(NA,CX)) :- 103 print_node(NA,T,T2), 104 unfreeze_list(CX), 105 print_subtree(T2,first,CX). 106 107print_subtree(_,first,CX) :- var(CX), !, write('\u2500'). 108print_subtree(_,_,Z) :- (var(Z);Z=[]), !. 109 110print_subtree(T,first,[C1|CX]) :- 111 write_symbols(first,CX), 112 print_subtree_x(T,C1,CX). 113 114print_subtree(T,rest,[C1|CX]) :- 115 nl, write(T), write_symbols(rest,CX), 116 print_subtree_x(T,C1,CX). 117 118print_subtree_x(T,C1,CX) :- 119 list_prefix(CX,T,T2), 120 print_tree(T2,C1), 121 print_subtree(T,rest,CX). 122 123write_symbols(first,V) :- nonvar(V), V=[], !, write('\u2500\u2500\u2500'). 124write_symbols(rest,V) :- nonvar(V), V=[], !, write(' \u2514\u2500'). 125write_symbols(first,_) :- write('\u2500\u252C\u2500'). 126write_symbols(rest,_) :- write(' \u251C\u2500'). 127 128list_prefix(V,T,T2) :- (var(V);V=[]), !, atom_concat(T,' ',T2). 129list_prefix(_,T,T2) :- atom_concat(T,' \u2502 ',T2). 130 131unfreeze_list(X) :- 132 frozen(X,G), 133 (G=true->true;(X=[_|_];X=[])).
140tree_cursor(Root, cursor(Root,top)).
145get_node(N,cursor(N,P),cursor(N,P)).
149set_node(N,cursor(_,P),cursor(N,P)).
154cursor_node(cursor(N,_),N).
164cursor_move(down, cursor(node(D,[C1|CX]),Path), cursor(C1,point(Path,D,[],CX))). 165cursor_move(right, cursor(N,point(Up,D,LX,[R|RX])), cursor(R,point(Up,D,[N|LX],RX))). 166cursor_move(left, cursor(N,point(Up,D,[L|LX],RX)), cursor(L,point(Up,D,LX,[N|RX]))). 167cursor_move(up, cursor(N,point(Up,D,Left,Right)), cursor(node(D,CX),Up)) :- 168 rev_append(Left,[N|Right],CX).
173cursor_add_sibling(M, cursor(N,point(Up,D,LX,RX)), cursor(M,point(Up,D,[N|LX],RX))).
179cursor_ins_sibling(M, cursor(N,point(Up,D,LX,RX)), cursor(M,point(Up,D,LX,[N|RX]))).
185cursor_ins_child(M, cursor(node(X,CX),Path), cursor(M,point(Path,X,[],CX))). 186 187rev_append([],RX,RX). 188rev_append([L|LX],RX,LR) :- rev_append(LX,[L|RX],LR)
Trees
This module provides predicates for manipulated trees. The tree data-type is defined polymorphically over payload data types A as:
Thus, in this representation, data of type A is associated with each node including the root node, and every node has list of child nodes, which will be empty for leaf nodes.
*/