Undefined procedure when procedure is defined - prolog

I am trying to define a simple binary search tree. It is stored in lists like so: [Key, Left Tree, Right Tree].
I believe I have done this but when I try to use bstadd on an existing tree I get the following error.
?- bstadd(19,[],T1), bstadd(9, T1, T2).
ERROR: bstadd/3: Undefined procedure: right/3
Exception: (8) right(9, [[], []], _G3233) ?
I have defined right with three arugments on line 8. What follows is my code:
% bstadd(Key, Tree, NewTree)
% add the element Key to the tree Tree and return an
% new tree as NewTree. Element in the left subtree L must be less than Key and
% elements in the right subtree R must be greater than Key. This means duplicates
% are not allowed in the binary search tree. Don’t put print statements in this
% predicate.
right(Key, [TreeKey|TreeTail], [TreeKey|NewTree]) :- grabtail(KEY, TreeTail, NewTree]).
grabtail(KEY, [TreeKey|_], [TreeKey|NewTree]) :- bstadd(KEY, TreeKey, NewTree).
bstadd(KEY, [], [KEY,[],[]]).
bstadd(KEY, [TreeKey|TreeTail], [TreeKey|NewTree]) :- KEY > TreeKey, grabtail(KEY, TreeTail, NewTree).
bstadd(KEY, [TreeKey|TreeTail], [TreeKey|NewTree]) :- KEY < TreeKey, right(KEY, TreeTail, NewTree).
% inorder(Tree)
% given a binary search tree Tree perform an inorder traversal of the
% Tree printing (use print(X) ) the value of each vertex inorder.
inorder([TreeHead|TreeTail]) :- inright(TreeTail), print(TreeHead), intail(TreeTail).
inright([_|TreeTail]) :- intail(TreeTail).
intail([TreeHead|_]) :- inorder(TreeHead).
Any and all insight is appreciated.

Always look what the systems says while loading your file. I am sure there was some kind of syntax error. In your case, right/3 contains a syntax error at the end. There is an unmatched closing ].
right(Key, [TreeKey|TreeTail], [TreeKey|NewTree]) :- grabtail(KEY, TreeTail, NewTree]).
^^^

Related

Prolog- what causes the out of local stack error in this case?

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.

How to convert tree to list in Prolog?

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, []).

Finding the index of element in a list of lists

I have this data structure where the elements are always unique:
[[a,b,c], [d,e,f], [y,z]]
Now, I want to write a procedure to get the index of an element, say I have:
indexOf([[a,b,c], [d,e,f], [y,z]], a, H)
and H is 0. Or:
indexOf([[a,b,c], [d,e,f], [y,z]], f, H)
and H is 2.
This is what I have:
indexOf_single([X|_],X,0).
indexOf_single([_|T],X,H) :- indexOf_single(T,X,H1), H is H1 + 1.
indexOf([T],X,H) :- indexOf_single(T,X,H).
indexOf([Head|Tail],X,H) :- indexOf_single(Head,X,H),indexOf(Tail,X,H).
But I'm getting false all the time. Could you please give me any clues to solve it?
Try with
indexOf([Head|_],X,H) :- indexOf_single(Head,X,H).
indexOf([_|Tail],X,H) :- indexOf(Tail,X,H).
I see two errors in your indexOf/3.
(1) in your second clause
indexOf([Head|Tail],X,H) :- indexOf_single(Head,X,H),indexOf(Tail,X,H).
you ask that H is found in the Head (via indexOf_single/3) and in the Tail. And this is impossible when "the elements are always unique".
(2) in your first clause
indexOf([T],X,H) :- indexOf_single(T,X,H).
you search in T only if T is the last sub-list of the first argument.

Prolog - List concatenation in Trees

I have to write a predicate ListInTree(T,X) which is true when T is a tree with a list in each node, and X is the concatenation of all the lists (assuming to visit in Pre-order).
I really can't understand how to use the recursion to visit all the tree.
Thanks
You do not indicate what tree you are after, so I have to guess. The best in this case is to use a DCG, for grammars are built to model concatenation in the most natural manner possible:
seq([]) -->
[].
seq([E|Es]) -->
[E],
seq(Es).
flattened(empty) -->
[].
flattened(node(Xs, L, R)) -->
seq(Xs),
flattened(L),
flattened(R).
tree_flattened(T, Es) :-
phrase(flattened(T), Es).
For the sake of example, let us assume the following representation for a tree:
The atom nil represents the empty tree.
The structure tree/3 represents a non-empty tree tree( Left , Right , Payload ) where Left and Right represent (respectively and recursively) the left and right subtrees, and Payload is the payload for the node: in your case, a list.
Many/Most recursive problems have 1 or 2 "special cases" and the more general case. This is no different:
The special case is that of the empty tree: flattening it produces the empty list.
The general case is that of a non-empty tree: flatting it consists of the following steps:
Flatten the left subtree to produce a list
Flatten the right subtree to product a list
The result is that obtained by the concatenation of
the flattened left subtree
the current node's payload
the flattened right subtree
The Prolog code to accomplish this is pretty much identical to the English description above:
flatten_tree( nil , [] ) . % flattening the empty tree yields an empty list, n'est-ce-pas?
flatten_tree( tree(Left,Right,Payload) , Result ) :- % flattening a non-empty tree consists of
flatten_tree( Left , Prefix ) , % - flattening the left subtree,
flatten_tree( Right , Suffix ) , % - flattening the right subtree,
concatenate( Prefix , Payload , Suffix , Result ) % - concatenating the three parts
. % - easy!
concat( Xs, Ys , Zs , Rs ) :-
append(Xs,Ys,T1) ,
append(T1,Zs,Rs)
.
One might note that another approach might be to use findall/3 and append/2 (if you're using SWI prolog).
First you need a predicate to visit the tree via backtracking:
visit( tree(L,_,_) , P ) :- visit( L , P ) . % visit the left subtree
visit( tree(_,_,P) , P ) . % visit the current node
visit( tree(_,R,_) , P ) :- visit( R , P ) . % visit the right subtree
Feel free to rearrange the order of the clauses to get the ordering you'd like. Once you have that, flattening the tree is trivial:
flatten_tree( Tree , List ) :-
findall( X, visit(Tree,X) , Xs ) ,
append(Xs,List)
.

Prolog - writing a combination of k numbers in the given list

I am trying to define a function in prolog that takes arguments of the form combination(3,[a,b,c,d],L) , the result returns
L=a,b,c
L=a,b,d
L=a,c,d
L=b,c,d
My implementation is as follows:
combination(K,argList,L):-
unknown(X,argList,Y),
Z is select(X,argList),
length(Z,K),
L is Z,
combination(K,Z,L).
unknown(X,[X|L],L).
unknown(X,[_|L],R) :- unknown(X,L,R).
The unknown predicate behaves as follows:
![enter image description here][1]
Please help.
The simplest solution that comes to mind using your definition of unknown/3 is:
combination(0, _, []) :-
!.
combination(N, L, [V|R]) :-
N > 0,
NN is N - 1,
unknown(V, L, Rem),
combination(NN, Rem, R).
unknown(X,[X|L],L).
unknown(X,[_|L],R) :-
unknown(X,L,R).
Explanation: the second clause of combination/3 looks to select an element from the list L, which the predicate unknown/3 does in a linear manner, returning the remainder, Rem. Once the number of elements selected out of list L exceeds N, the base case is triggered (the first clause of combination/3) which terminates the branch. Note that the definition of combination/3 relies on the non-deterministic nature of unknown/3 which leaves choice-points for selecting alternate list elements.

Resources