I am trying to implement a Prolog predicate that gets a binary tree (represented as t(Left, Root, Right)) and returns a list that is the Maximal Independent Set (MIS) of this tree, and its size.
I first understood that MIS(T) is the maximum between the MIS with root and the MIS without the root.
Then, I used two theorems, stating that the MIS with root is the unification of the MIS's without the root for all the subtrees, and that MIS without root is the unification of the MIS's of all the subtrees.
% mis is a predicate for finding the Max Independent Set (MIS) in a binary tree.
% It has three arguments: one is input - a binary tree T - and the other two are output - List which is a list of elements in the max independent set of tree T, with N being the number of elements in this set.
mis(Tree, List, N) :-
mis_no_root(Tree, List1, N1), % find mis without root
mis_with_root(Tree, List2, N2), % find mis with root
max_set(List1, N1, List2, N2, List, N). % choose the bigger set of nodes
% This is a helping predicate, that gets lists List1 and List2 of lengths N1 and N2 respectively, and instantiates List to be the bigger list, with N being its size
max_set(List1, N1, _, N2, List, N) :-
N1>=N2, % if N1 is bigger or equal
List=List1, % then max set is List1
N=N1. % of length N1
max_set(_, N1, List2, N2, List, N) :-
N2>N1, % if N2 is bigger
List=List2, % then max set is List2
N=N2. % of length N2
% a helping predicate to find the max independent set of t(L,_,R), excluding the root
mis_no_root(nil, [], 0). % the empty subtree has an empty max independent set of size 0
mis_no_root(t(L,_,R), List, N) :-
mis(L, LeftList, LeftN), % calculate mis of left subtree
mis(R, RightList, RightN), % calculate mis of right subtree
conc(LeftList, RightList, List), % concatenate lists of nodes according to the given formula (unification of all mis of subtrees)
N is LeftN + RightN. % and assign N with the accumulated size of the concatenated independent set, without adding something for the root.
% a helping predicate to find the max independent set of t(L,X,R), including the root
mis_with_root(nil, [], 0). % the empty subtree has an empty max independent set of size 0
mis_with_root(t(L,Root,R), [Root|List], N) :-
mis_no_root(L, LeftList, LeftN), % calculate mis of left subtree without root
mis_no_root(R, RightList, RightN), % calculate mis of right subtree without root
conc(LeftList, RightList, List), % concatenate lists of nodes according to the given formula (unification of all mis_no_root of subtrees)
N is LeftN + RightN + 1. % and assign N with the accumulated size of the concatenated independent set, incremented by 1 (including the root).
It does succeed retrieving a set of maximal size, but it does NOT continue searching for other MIS's of the same size.
Thanks in advance for any help!
Don't get mad when you see what the annoying issue was! just add = on the second max_set (N2>=N1). :)
Related
I have a different request than what I saw on stackoverflow. Say my binary tree is of the form tree(Node, Leafs). There is no left or right leafs, only the attribute leafs.
How would you go about counting the node in that tree?
For example the tree could be:
tree(node1, [tree(node2)]), tree(node3, []), tree(node4, [tree(node6,[tree(node2,[])]).
An unordered binary tree is a tree where each node can have up to two children, but the order between the children is not important. Thus, each node in a non-empty unordered binary tree can be represented as a term of the form tree(Node,Children), where Children is an empty set (if Node is a leaf), or a set of one or two trees (if Node is an internal node). An empty unordered tree can be represented as nil. To simplify the implementation, we can represent sets as lists. For example, the unordered binary tree:
a
/ \
b c
/ \ |
d e f
can be represented as:
mytree(tree(a,
[tree(b,
[tree(d,[]),
tree(e,[])]),
tree(c,
[tree(f,[])])])).
To count the nodes in an unordered binary tree, we can use maplist/3 and sum_list/2 as following:
count_nodes(nil, 0).
count_nodes(tree(_Root, Children), N) :-
maplist(count_nodes, Children, Ns), % call count_nodes, recursively, for each child
sum_list([1|Ns], N). % add 1 to count the root
Here are some examples:
?- count_nodes(nil, N).
N = 0.
?- count_nodes(tree(a,[]), N).
N = 1.
?- count_nodes(tree(a,[tree(b,[])]), N).
N = 2.
?- count_nodes(tree(a,[tree(b,[]),tree(c,[])]), N).
N = 3.
?- mytree(T), count_nodes(T, N).
T = tree(a, [tree(b, [tree(d, []), tree(e, [])]), tree(c, [tree(f, [])])]),
N = 6.
A binary tree of numbers is called a heap (or, it is said to satisfy the heap property) if, for every non-leaf node in the tree, the number stored at that node is less than or equal to the number stored at each of its children. For example, the following tree satisfies the heap property, because 3 ≤ 5, 5 ≤ 8 and 5 ≤ 7.
tree(empty,3,tree(tree(empty,8,empty),5,tree(empty,7,empty)))
On the other hand, the following tree does not satisfy the heap property, because 6 is not less than or equal to 5.
tree(tree(tree(empty,4,empty),
3,tree(empty,5,empty)),6,tree(tree(empty,9,empty),7,empty))
Example :
?- is_heap(tree(tree(tree(empty,4,empty),
3,tree(empty,5,empty)),6,tree(tree(empty,9,empty),7,empty))).
false.
?- is_heap(tree(empty,3,tree(tree(empty,8,empty),5,tree(empty,7,empty)))).
true
Any help will be appriciated.
You can start like this. Here tree is tree(Value, Left, Right) but you can change this easily. Then you start:
is_heap(empty).
is_heap(tree(X, L, R)) :-
is_heap(L, X),
is_heap(R, X).
Now you only need to write is_heap/2 and then you are ready. Something like:
is_heap(empty, ...).
is_heap(tree(X, L, R), X0) :-
...,
is_heap(L, X),
....
I'm learning prolog in a course.
I've been given a question similar to this one, and I also got the same problem (in which it doesnt produce all solutions),
any idea why, will using cuts help?
thanks in advance
EDIT:
The exercise I've been given is to generate all possible max independent sets from a binary tree.
In the second part of the question, I get an integer binary tree, from which i need to get all the mis's, and from those i need to get the one with the maximum on adding its numbers.
i.e. if i have a mis with 1,3,9 and a mis with 1,3,4 - i'll return the one with 1,3,9.
I changed a little bit the solution from the link ,so it's not entirely my solution it is just the code corrected and i think now it's working fine :
mis(Tree, List, N) :-
mis_no_root(Tree, List1, N1),
mis_with_root(Tree, List2, N2),!,
max_set(List1, N1, List2, N2, List, N).
max_set(List1, N1, List2, N2, List, N) :-
(N1>N2,List=List1,N=N1;
N2>N1,List=List2,N=N2;
N2=:=N1,N=N1,(List=List1;List=List2)).
mis_no_root(nil, [], 0).
mis_no_root(t(L,_,R), List, N) :-
mis(L, LeftList, LeftN),
mis(R, RightList, RightN),
append(LeftList, RightList, List),
N is LeftN + RightN.
mis_with_root(nil, [], 0).
mis_with_root(t(L,Root,R), [Root|List], N) :-
mis_no_root(L, LeftList, LeftN),
mis_no_root(R, RightList, RightN),
append(LeftList, RightList, List),
N is LeftN + RightN + 1.
If you want to return one list with solutions you could write:
final_mis(Tree,List,N):-findall(L,mis(Tree, L,_),List),List=[H|_],length(H,N).
I have an assignment in which I have to design a binary tree in Prolog and then implement some predicates for it(E.g. Insert, traversal, search and height.)
I am confident enough to implement them but as a starting point I was given this:
A binary tree can be defined in terms of 2 predicates:
emptyBT, the empty binary tree
btTree(N,T1,T2) that is true if N is the root of a binary tree with left subtree T1 and right subtree T2, where all the items in T1 are less than or equal to N and all the items in T2 are greater than N.
Could someone point me in the direction of the BT implementation using the above two predicates? I have searched online and through some Prolog books and they all define BTs differently and this has confused me somewhat.
isEmptyBinTree( btEmpty ).
that's one. Right?
isNonEmptyBinTree( btTree(N,Left,Right) ):-
( isEmptyBinTree(Left)
; % or
isNonEmptyBinTree(Left),
getMaxElement(Left,Max),
N >= Max
) , % and
( isEmptyBinTree(Right)
; % or
isNonEmptyBinTree(Right),
.... % can you complete this definition?
).
that's the other one. Now all that's left is to define the missing getMaxElement/2 and getMinElement/2 predicates. Both of them can assume their argument is not an empty binary tree:
getMinElement( btTree(N,Left,_), M ) :-
isEmptyBinTree(Left),
M = N. % right?
getMinElement( btTree(_,Left,_), M ) :-
getMinElement( ... , M ).
btEmpty is not a predicate; it is an atom. btTree/3 is not a predicate either; it is a compound term. If your assignment calls those two predicates then there is something very fishy.
The definitions in different sources might be different, but they are all probably some variation of an atom representing the empty tree and a term with arity 3 representing a non-empty node.
Anyway, this for example is a tree representing the numbers {1, 2, 3}:
btTree(2, btTree(1, btEmpty, btEmpty), btTree(3, btEmpty, btEmpty))
This is a nested compound term. The tree structure should be recognizable: from your example, the N, the actual element at that tree node, is always the first argument of the term, and the left and right sub-trees are T1 and T2.
And just to get you started, this is a very simple predicate to traverse a tree defined like this in-order:
in_order(btTree(_, Left, _), N) :-
in_order(Left, N).
in_order(btTree(N, _, _), N).
in_order(btTree(_, _, Right), N) :-
in_order(Right, N).
This delivers elements upon backtracking.
This is a problem I encountered. How do you subtract values in a binary tree recursively?
subtractTree(tree(leaf(4), tree(leaf(2), leaf(1))),S).
S = 3.
For this example, it first subtracts the leaves in each tree before subtracting the values between the trees. So for the first tree, it has the value 4. The second tree, it has the value 1 because 2-1=1. Then it subtracts 4-1 between the trees and the answer is 3.
because your tree structure has arity 2 (as it must be), you can do a very simple visit
subtractTree(leaf(N), N).
subtractTree(tree(L, R), S) :-
subtractTree(L, X),
subtractTree(R, Y),
S is X - Y.
test:
?- subtractTree(tree(leaf(4), tree(leaf(2), leaf(1))),S).
S = 3.
You have 4 cases :
Base case : a tree with only leaves
subtractTree(tree(leaf(A), leaf(B)),S) :-
S is A-B.
2 intermediate cases, trees with one leaf and a tree as a leaf
subtractTree(tree(leaf(A), Tree2),S) :-
subtractTree(Tree2, S1),
S is A - S1.
subtractTree(tree(Tree1, leaf(B)),S) :-
subtractTree(Tree1, S1),
S is S1 - B.
A general case, a tree with leaves which are trees :
subtractTree(tree(Tree1, Tree2),S) :-
subtractTree(Tree1, S1),
subtractTree(Tree2, S2),
S is S1 - S2.