Implement the predicate treeToList(X,List), where X is a given ordered non-empty binary tree, and List is an ordered list of elements in nodes of the tree.
4
/ \
2 6
/ \ / \
1 3 5 7
is an ordered tree given as an input to predicate "treeToList".
Your program must compute the list [1,2,3,4,5,6,7].
Here is the codes I had so far:
treeToList(X,List) :- binaryTree(X), convert(X,List).
convert( tree(Element,void,void), List) :- List=[Element].
The helping predicate convert(X,List) is true if X is a given non-empty tree, and List is a representation of this tree as an ordered list.
But I have no idea how to write the recursive part of this question
convert( tree(Root,Left,Right), List) :-
Can someone help me with this part?
You never explicitly said what your data structure looks like in Prolog, but I can infer that you have basically two kinds of tree node:
tree(Element, Left, Right)
void
To handle any recursive data structure, you write a recursive predicate. Usually (but not always) you want clauses for each kind of element. In Haskell, this is a bit more clear because you have to define your types and their constructors, but you can apply the same reasoning here. So your convert/2 predicate is going to have a clause for each of your kinds of element:
convert(void, ...) :- ...
convert(tree(Element, Left, Right), ...) :- ...
You can see right away that the first clause is going to be pretty simple:
convert(void, []).
The second clause is where things get a bit more interesting. The key is to recursively apply convert/2 to the subtrees on the left and right, and then you need to do something with the element you have:
convert(tree(Element, Left, Right), Rest) :-
convert(Left, LeftList),
convert(Right, RightList),
append(LeftList, [Element|RightList], Rest).
Note that I'm prepending the current element to the right list before appending. This is to insert the element in its proper place in the list for an in-order traversal, to get you the result you want:
?- convert(tree(4, tree(2, tree(1, void, void), tree(3, void, void)),
tree(6, tree(5, void, void), tree(7, void, void))),
List).
List = [1, 2, 3, 4, 5, 6, 7].
This gives you an in-order traversal. If you wanted a pre-order or a post-order traversal you would instead place the element in another position, such as at the start of the result or the end of the result.
Your tree has, based on the question, two "families" of data:
the constant void; and
a compound term with a tree/3 with as arguments the value and the left and right subtree.
We can implement a predicate like #DanielLyons demonstrated. We can slightly optimize this by defining a predicate convert/3 where we the first parameter is the tree to convert, the second parameter is the head of the list, and the third parameter is the tail of the list.
We can thus define our predicate as:
convert(void, L, L).
convert(tree(V, L, R), H, T2) :-
convert(L, H, [V|T1]),
convert(R, T1, T2).
If we thus encounter a void, then the start and the end of the list remain the same. If we encounter a tree(V, L, R), we will first recursively call convert(L, H, [V|T1]). By writing [V|T1] as tail, we thus force Prolog to yield the V value in the result. The tail T1 is then the start of the convert/3 of the second subtree.
We then can define convert/2 in terms of convert/3:
convert(T, L) :-
convert(T, L, []).
Related
I have a very simple program where a relation is defined between an AVL tree and a list of elements. I get correct results but after some semicolons I will receive an out of memory error, even for small inputs.
The code is not perfect as I am just trying at first to get to know the language, so it is not efficient but my question is where is the infinite loop or something similar hiding.
Only the last rule causes this problem, I tested the previous ones earlier and they worked fine.
:- use_module(library(clpfd)).
% Stuff
max(X,Y,X):- X#>=Y.
max(X,Y,Y):- Y#>X.
sub(X,Y,Z):- Z is X-Y.
append([],Ys,Ys).
append([X|Xs],Ys,[X|Zs]):-append(Xs,Ys,Zs).
% Checking "tree-ness" of a term
% is_tree(Tree)
is_tree(tree(_,Left,Right)) :-
Left=nil, Right=nil;
Left=nil, is_tree(Right);
Right=nil, is_tree(Left);
is_tree(Left), is_tree(Right).
% Computing tree height
% tree_height(Tree, Height)
tree_height(nil,0).
tree_height(tree(_,L,R),H) :-
tree_height(L,H1),
tree_height(R,H2),
H1#>=H2,
H is H1+1.
tree_height(tree(_,L,R),H) :-
tree_height(L,H1),
tree_height(R,H2),
H2#>H1,
H is H2+1.
% Checking "AVL tree-ness" of a term
% is_avl_tree(Tree, Height)
is_avl_tree_help(nil,0).
is_avl_tree_help(tree(_,L,R),H) :-
is_avl_tree_help(L,H1),
is_avl_tree_help(R,H2),
sub(H1,H2,D),
D in -1 .. 1,
max(H1,H2,H3),
H is H3+1.
is_avl_tree(Tree,H) :-
is_tree(Tree),
is_avl_tree_help(Tree,H).
% Define relation between a Tree and a List
tree_elements_help(nil,[]).
tree_elements_help(tree(X,Le,Ri),L) :-
tree_elements_help(Le,L1),
tree_elements_help(Ri,L2),
append(L1,[X|L2],L).
tree_elements(Tree,L) :-
is_tree(Tree),
tree_elements_help(Tree,L).
avl_tree_planter(Tree,L) :-
is_avl_tree(Tree,H),
tree_elements(Tree,L2),
permutation(L2,L).
The problem is that predicates like tree_elements/2 and avl_tree_planter/2 are not reversible. I assume you noticed the issue after calling avl_tree_planter/2 with its first argument uninstantiated. For example, the following queries do not terminate:
?- tree_elements(Tree,[]).
?- avl_tree_planter(Tree,[]).
I will focus on the simpler case of writing a reversible predicate inorder/2 that generates every binary tree having a given inorder traversal. The following implementation does not terminate when its first argument is uninstantiated:
inorder(leaf,[]).
inorder(node(X,L,R),L3) :-
inorder(L,L1),
inorder(R,L2),
append(L1,[X|L2],L3).
If you trace the query ?- inorder(Tree,[]) you will find that the first recursive call to inorder/2 causes the problem. In order to prove inorder(Tree,[]) it is necessary to prove infinitely many goals of the form inorder(X,[]). In general, the first recursive call to inorder/2 prevents the construction of the left subtree. This is analogous to the problem of left recursion in parsing.
Here is one solution. We introduce two arguments that track the state of the traversal. The first argument represents the input state and tracks the unprocessed elements. The second represents the output state and tracks the remaining elements. Their difference corresponds to the elements processed during a recursive call. It follows that inorder(Tree,List) should succeed with input state List and output state []. Here is one possible implementation:
inorder(Tree,List) :-
inorder(Tree,List,List,[]).
inorder(leaf,[],State,State).
inorder(node(X,L,R),List,[_|State1],State3) :-
inorder(L,Left,State1,State2),
inorder(R,Right,State2,State3),
append(Left,[X|Right],List).
For example:
?- inorder(leaf,List).
List = [].
?- inorder(node(1,leaf,leaf),List).
List = [1].
?- inorder(node(1,node(2,leaf,leaf),leaf),List).
List = [2, 1].
?- findall(Tree,inorder(Tree,[]),Trees).
Trees = [leaf].
?- findall(Tree,inorder(Tree,[1]),Trees).
Trees = [node(1, leaf, leaf)].
?- findall(Tree,inorder(Tree,[1,2]),Trees).
Trees = [node(1, leaf, node(2, leaf, leaf)), node(2, node(1, leaf, leaf), leaf)].
If this implementation reminds you of parsing, that's because it implements roughly the same functionality as the following definite clause grammar (DCG). The following code and a discussion of the relationship between nontermination and left recursion can be found at Markus Triska's DCG tutorial, which I suggest reading. Using DCG's for list processing is considered idiomatic Prolog.
:- use_module(library(dcg/basics)).
inorder(Tree,List) :-
phrase(inorder(Tree,List,_),List).
inorder(leaf,S,S) -->
[].
inorder(node(X,L,R),[_|S1],S3) -->
inorder(L,S1,S2),
[X],
inorder(R,S2,S3).
How to solve your original problem? In order to adapt these techniques to the setting of AVL trees, you need to place additional restrictions on which trees are generated (i.e., only succeed with binary search trees satisfying the AVL property). This should not be difficult. I hope you found this explanation helpful.
I am trying to make a List of Lists of Lists without values. If N_meses = 4 I want List =[[[A,B,C,D]]].
I get what I want ( List = [[[]]] ) but every lists have the same values as you can see in the print I attached. How can I change this code so every lists have a different "value"?
I am doing this
generate_table(Num_investigadores, Num_actividades, N_Meses, Tabela) :-
length(Row, Num_actividades),
length(X,N_Meses),
maplist(=(X), Row),
length(Tabela, Num_investigadores),
maplist(=(Row), Tabela).
The culprit is in essence the:
%% ...
maplist(=(X), Row),
%% ...
Here you basically defined a list X, and then you set with maplist/2 that all elements in Row are unified with that X. In the unification process. This thus means that all the elements of Row will in essence point to the same list.
Nevertheless, I think it would definitely help if you make the predicate less ambitious: implement helper predicates and let each predicate do a small number of things.
We can for example first design a predicate lengthlist/2 that is the "swapped" version of length/2, and thus has as first parameter the length and as second parameter the list, like:
lengthlist(N, L) :-
length(L, N).
Now we can construct a predicate that generates a 2d rectangular list, for example:
matrix(M, N, R) :-
lengthlist(M, R),
maplist(lengthlist(N), R).
here we thus first use lengthlist to construct a list with N elements, and then we use maplist/2 to call lengthlist(N, ...) on every element, such that every element is unified with a list of N elements. We thus construct a 2d list with M elements where every elements is a list of N elements.
Then finally we can construct a 3d tensor:
tensor3(L, M, N, T) :-
lengthlist(L, T),
maplist(matrix(M, N), T).
Here we thus construct an L×M×N tensor.
We can in fact generalize the above to construct a arbitrary deep cascade of lists that is "rectangular" (in the sense that for each dimension, the lists have the same number of elements), but I leave this as an exercise.
How do I check full binary tree in prolog? I have the 2 base cases
1) if is empty tree, return yes
2) if is just root only, return yes
I'm stuck at the third one and I not sure what should I do with it. We only allow to use 1 arity: full(T).
btree([]).
btree([H|T]):-btree(T).
btree([H|T]):-btree(H),btree(T).
full([]).
full([H]).
full([H|T]):-
anyone can guide me please. My idea is a tree does not have two nonempty tree then it is a full binary tree.
P/S: I am still new to stackoverflow. If I did ask something silly or improper way please do tell me. I want to learn how to use stackoverflow and also make sure of it in proper way.
I would first probably choose a different representation for binary tree. In Prolog, it's generally more conventional and efficient to use a simple atom (such as nil) as a nil node, and something like btree(Value, Left, Right) as the tree term. Outside of that, the solution looks quite like what #pyon suggested.
% full_btree succeeds if `Tree` is a full binary tree
full_btree(Tree) :-
full_btree(Tree, _).
full_btree(nil, 0).
full_btree(b(_, LeftTree, RightTree), Depth) :-
Depth #> 0,
SubDepth #= Depth - 1,
full_btree(LeftTree, SubDepth),
full_btree(RightTree, SubDepth).
The condition Depth #> 0 ensures, regardless of inputs, that the depth will not become negative, and thus helps ensure termination.
I'm going to assume that you represent trees as follows:
A leaf is an empty list.
A non-leaf node is a three-element list, whose last two elements are the subtrees.
Then:
helper([], 0).
helper([_,L,R], H) :- H #= G + 1, helper(L, G), helper(R, G).
/* Old version: helper([_,L,R], H) :- helper(L, G), helper(R, G), H is G + 1.
* The improvement in the new version was suggested by lurker. Thanks!
*/
full(T) :- helper(T, _).
This works because full binary trees can be inductively defined as follows:
A leaf node is a full binary tree of height 0.
An non-leaf node whose children are both full binary trees of height G, is itself a full binary tree of height G + 1.
Ok, since there is already an answer that doesn't answer the question at face value, here is mine. It doesn't add much anything to the answer by #lurker, it just offers details and explanations that were too much for comments. It also avoids CLP(FD) completely, which is why I felt it should be a separate answer.
You can start (as #lurker has) by using a more conventional binary tree representation. The empty tree is nil, and the non-empty tree is bt(Value, Left, Right) where Value is the value at this node and Left and Right are the left and right sub-trees. This is the conventional representation because it is at the very least more memory efficient. A "leaf" (a tree without sub-trees) is, in your original representation:
.(Value, .([], .([], [])))
instead of:
bt(Value, nil, nil)
The amount of memory needed to represent the two would be different between different Prolog implementations, but I don't know how to make the first smaller than the second.
Then: as #false commented above, a list is usually a collection of Things which conventionally has the following properties:
There can be no Things, or any number of Things in the collection;
The order of Things matters;
All the Things are somehow the same.
Using a list like you do breaks the last convention: the first argument is a value, while the second and third arguments are trees.
This doesn't exclude using list for representing a binary tree but it is unfamiliar.
With this out of the way: successor arithmetic is a silly way of doing actual arithmetic, but it is very convenient if you want to use pattern matching for non-negative integers. You cannot do it with the built-in integer type of Prolog, like 0 or -23 or whatever. Successor arithmetic gives you:
a zero which is structurally different from all positive integers: 0 vs s(_)
adding and subtracting is done by pattern matching, and both are done with the same operation: X + 1 is s(X).
negative numbers are not possible
So, you could define your "full tree" like this:
full_btree(T) :-
full_btree(T, _).
full_btree(nil, 0).
full_btree(bt(_, L, R), s(D)) :-
full_btree(L, D),
full_btree(R, D).
The s(D) and the two Ds state that the tree in your first argument is one deeper than the sub-trees, and that both sub-trees are the same depth. The empty tree nil has a depth of 0 (as defined in the first clause of full_btree/2).
This works as follows:
?- full_btree(nil).
true.
?- full_btree(bt(x, nil, nil)).
true.
?- full_btree(bt(x, bt(y, nil, nil), nil)).
false.
?- full_btree(bt(x, bt(y, nil, nil), bt(z, nil, nil))).
true.
?- full_btree(T), numbervars(T).
T = nil ;
T = bt(A, nil, nil) ;
T = bt(A, bt(B, nil, nil), bt(C, nil, nil)) ;
T = bt(A, bt(B, bt(C, nil, nil), bt(D, nil, nil)), bt(E, bt(F, nil, nil), bt(G, nil, nil))) . % and so on
One more thing: to close the circle, you can do successor arithmetic with lists, too. Just use [] instead of 0 and [_|X] for s(X). With this, you would have:
full_tree(nil, []).
full_tree(bt(_, L, R), [_|D]) :-
full_tree(L, D),
full_tree(R, D).
This is slightly less memory efficient, instead of s(s(s(0))) you would have .(_, .(_, ,(_, []))). However! it is now much easier to make actual integers out of the successor-notation integers, and the other way round: just use length/2. Writing a predicate that converts between s(s(...)) and an integer that works both ways in pure Prolog is not as trivial. I think it is possible to search Stackoverflow for such questions.
I am studying Prolog for an universitary exame using SWI Prolog and I have some problems to understand what my teacher do in this example (it seems to me that is is incomplete) that implement the predicate:
k(T1,T2,N)
that is TRUE if T1 and T2 are trees and if they have if they have exactly N subtrees in common (a subtree is common between two trees T1 and T2 if this subtree exist both in T1 and in T2)
He give me another predicate T(t) where t is a specific tree and T(t) give me all the subtrees of t (if you want to see a graphical interpretation of this thing you can see the slide 18 of this file: http://www.informatica.uniroma2.it/upload/2012/LPDA/08_Lezione_ZNZ.pptx )
So he say that:
k(T1,T2,N)
is TRUE if is TRUE that:
In practice it is TRUE that the trees T1 and T2 have N common subtrees if it is TRUE that the intersection of the subtrees of T1 (give from the T(T1) predicate) and all subtress of T2 (give from the T(T2) predicate) is precisely N in module (ie as a number)
Ok, so go on: he define the trees in the following way:
tree(F, LIST_OF_SUBTREES).
where R is the root of the current tree
So go to implement the predicate k(T1,T2,N) that is TRUE if the trees T1 and T2 have N common subtrees, using the previous property.
This predicate have to use an EXAUSTIVE SEARCH of the subtrees in the trees T1 and T2
Then he implement the k/3 predicate in this way:
k(T1,T2,N) :- t(T1, ST1),
t(T2, ST2),
intersect(ST1,ST2,LST),
lenght(LST,N).
This seems to me pretty clear (correct me if I'm wrong):
t(T1,ST1) put in ST1 the list of all the subtrees contained in T1
t(T2,ST2) put in ST2 the list of all the subtrees contained in T2
intersect(ST1,ST2,LST) put in LST the list of the commons subtrees of ST1 and ST2
lenght(LST,N) put in N the lenght of the commons subtrees of ST1 and ST2
So the predicate k(T1,T2,N) it is true if the calculated value of N unifies with the given N value.
Untill here I think that all is clear...bu now I have some problems to understand how he implement the **t(T,STL) predicate that take a tree T and put in STL the list of all its subtrees.
He give me the following code:
t(T,STL) :- bagof(ST, st(T,ST), STL).
st_r(tree(A,_), tree(A,[]).
st_r(tree(A,R), tree(A,R1) :- st_l(R,R1).
st_l([],[]).
st_l([X|R],[X1|R1]) :- st(X,X1),
st_l(R,R1).
st(T,T1) :- st_r(T,T1).
st(tree(A,R),T1) :- member(T,R),
st(T,T1).
Regarding the predicate:
t(T,STL) :- bagof(ST, st(T,ST), STL).
I think that simply execute the bagof built in predicate where ST is the subtree object that, if satisfy the goal st(T,ST) is put into the STL list (the list of subtree)
But now I am not understanding how the st/2 predicate (my goal) work !!! Someone can try to explain me the logic of this predicate and of the related st_l/2 and st_r/2 predicates?
And please, I have also some doubts about how to concretely build two trees that I can use to test this program. Can you give me two simple trees to use for the testing?
At last I think that, in this example, missing the intersect/3 predicate
Tnx
Andrea
Here the naming it's a bit cryptic, and I'll try to guess it.
st/2 should stand for subtree, its purpose is to enumerate, on backtracking, all subtrees.
st_r/2 should stand for subtree_root. It separately return the root and the leafs.
st_l/2 then should stand for subtree_leafs. It makes a list of 'flattened' trees, replacing actual subtrees.
I would disagree that st/2 enumerates only subtrees. Actually, it returns more trees, because of the pruning performed by the first clause st_r. This seems an unusual definition to me - but nevertheless, it's a definition.
The predicate intersect/3 is defined in SWI-prolog library(lists) as intersection/3.
After two typo correction, that code gives to me
?- t(tree(x,[tree(u,[]),tree(v,[tree(p,[]),tree(q,[])])]),L).
L = [tree(x, []), tree(x, [tree(u, []), tree(v, [])]), tree(x, [tree(u, []), tree(v, [tree(p, []), tree(..., ...)])]), tree(x, [tree(u, []), tree(v, [tree(..., ...)|...])]), tree(x, [tree(u, []), tree(v, [...|...])]), tree(x, [tree(u, []), tree(..., ...)]), tree(x, [tree(..., ...)|...]), tree(x, [...|...]), tree(..., ...)|...].
I want to generate all the sublists of a given list with the given property that they have a certain length mentioned as argument and also they have as a containing element a given element which is passed as a parameter. I have managed to do this but with the help of two predicates, and in terms of optimality is very slow:
sublist([], []).
sublist([A|T], [A|L]):-
sublist(T, L).
sublist(T, [_|L]):-
sublist(T, L).
choose(T, L):-
sublist(T, L),
(dimension(2, T); dimension(1, T)),
belongs(f, T).
In here I would like to return through the T parameter of the choose predicate all the sublists of the L list which have the dimension 2 or 1 and which contains the f element. The predicates dimension and member has the same usage as the predefined predicates length, respectively member.Can you please tell me how to incorporate this two conditions within the sublist predicate so that the program builds only those particular sublists?
The following builds subsequences of length MinLen =< Len =< MaxLen. I've no idea why you renamed length and member, so I'm going to use the originals. sublist/4 calls your sublist/2.
sublist(Sub,List,MinLen,MaxLen) :-
between(MinLen,MaxLen,Len),
length(Sub,Len),
sublist(Sub,List).
Note that length is called on two variables, so you get an iterative deepening search. choose/2 can now be defined as
choose(Sub,List) :-
sublist(Sub,List,1,2),
member(f,Sub).
This is the clean solution. If it's is not fast enough, then roll all the conditions into one predicate:
choose(Sub,List),
(Sub = [f] ; Sub = [f,_] ; Sub = [_,f]),
sublist(Sub,List).