Prolog, result correctly given but false is printed - prolog

I have for example the following function computing the set of all internal nodes in a binary tree (nodes which have at least one child, i.e. are no leaves)
internals(nil,[]).
internals(t(_,nil,nil),[]).
internals(t(X,L,nil),[X|S]) :- L = t(_,_,_), internals(L,S).
internals(t(X,nil,R),[X|S]) :- R = t(_,_,_), internals(R,S).
internals(t(X,L,R),[X|S]) :- L = t(_,_,_), R = t(_,_,_),
internals(L,SL), internals(R,SR), append(SL,SR,S).
the result of this is
?- internals(t(3, t(2, t(1, nil, nil), nil), t(5, nil, t(7, nil, nil))), X).
X = [3, 2, 5] ;
false.
Why does it end in false and how come the following code does the same but does not result in false
internals(nil,[]).
internals(t(_,nil,nil),[]) :- !.
internals(t(X,L,R),[X|Xs]):-
internals(L,LI), internals(R,RI),
append(LI,RI,Xs).
?- internals(t(3, t(2, t(1, nil, nil), nil), t(5, nil, t(7, nil, nil))), X).
X = [3, 2, 5].

Related

treeMerge in swi-prolog

I am trying to build a predicate treeMerge(A,B,C) that returns true if C is the result of merging the two trees A and B. Any suggestions on how I can implement this? I have a rough idea, I am thinking of merging the root, then first child then second and so on, but I am fairly new to prolog.
The idea is to get the list of the nodes inside a tree then add each nodes in the other tree. I've developed a predicate merge/3 which merges the two tree as input in a third tree (insert all the nodes of the first tree into the second). A tree is represented as t(Node,Left,Right). Here is the code:
getNodes(nil,[]).
getNodes(t(E,L,R),[E|S]) :-
append(SL,SR,S),
getNodes(L,SL),
getNodes(R,SR),!.
insert(Node,nil,t(Node,nil,nil)).
insert(Node,t(El,Left,Right),t(El,L,R)):-
(Node > El ->
insert(Node,Right,R),
L = Left
; insert(Node,Left,L),
R = Right).
insertNodesList([],T,T).
insertNodesList([H|T],Tree,M):-
insert(H,Tree,T1),
insertNodesList(T,T1,M).
merge(T1,T2,Merged):-
getNodes(T1,LNodesT1),
insertNodesList(LNodesT1,T2,Merged).
Query:
?-merge(t(3,t(2,t(1,nil,nil),nil),t(4,nil,t(7,nil,t(5,nil,nil)))),t(3,t(2,nil,nil),t(4,nil,t(7,nil,t(5,nil,nil)))),T).
T = t(3, t(2, t(2, t(1, nil, nil), nil), t(3, nil, nil)), t(4, t(4, nil, nil), t(7, t(7, t(5, nil, nil), nil), t(5, nil, nil))))

Prolog in-order traversal

Example of the node looks like:
node(3, nil, 14).
node(14, nil, 15).
node(15, nil, 92).
I have seen similar questions asked here however mine is different as my nodes have 3 instead of 2 values in the parameter.
Example of how it should run:
?- inOrder(3, X).
X = [3, 14, 15, 35, 65, 89, 92] .
My current code is:
% the in-order traversal of a leaf is the leaf
inOrder(X, [X]) :-
node(X, nil, nil).
% if the node only has a left child, we traverse that
inOrder(x, [X|T]) :-
node(X, L, [X|T]),
inOrder(L, T).
% if the node only has a right child we traverse that
inOrder(x, [X|T]) :-
node(X, nil, R),
inOrder(R, T).
% if the node has both, we traverse them both.
inOrder(x, [X|T]) :-
node(L, X, R),
L \= nil, R \= nil,
inOrder(L, T1),
inOrder(R, T2),
append(T1, T, T2).
It returns false instead of an actual value.
There are several twists in your representation. In general, treelike structures are not flattened out in the database, here with node/3, but rather maintained in a single term.
Also, it seems to be a good idea to insist that each node has its own fact. In your example 92 needs a fact!
So given all these precautions one can write, using DCGs:
node(3, nil, 14).
node(14, nil, 15).
node(15, nil, 92).
node(92, nil, nil). % added!
inorder(I, Xs) :-
phrase(inorder(I), Xs).
inorder(nil) -->
[].
inorder(I) -->
{dif(I, nil)},
{node(I, L, R)},
inorder(L),
[I],
inorder(R).
?- inorder(3,L).
L = [3,14,15,92]
; false.
The check your database for orphaned nodes:
orphan(Nr) :-
node(_, L, R),
( Nr = L ; Nr = R ),
dif(Nr, nil),
\+ node(Nr, _, _).
So orphan(N) should fail on your database.
To get rid of the leftover choicepoint ; false. add the following rule in front of inorder//1:
inorder(Nil) --> {Nil == nil}, !.
You are using a lower-case x in your recursive cases for inOrder; that should be a variable. But that probably isn't the only problem.

leaves in binary tree - to list and from list

I am going to implement getting all leaves from tree to list and vice versa - for list of leaves construct tree - I know that such trees is infitity.
leaves(nil) -->
[].
leaves(t(X, nil, nil)) -->
[X].
leaves(t(_, t(Y, L, R), nil)) -->
leaves(t(Y, L, R)).
leaves(t(_, t(X, LL, LR), t(Y, RL, RR))) -->
leaves(t(X, LL, LR)),
leaves(t(Y, RL, RR)).
Is seems to be even workin, for example
phrase( leaves( t(6, t(3,
t(1, nil, nil),
t(5, nil, nil)
),
t(4,
t(2, nil, nil),
t(8,
t(7, nil, nil),
t(9, nil, nil)
)
)
)
), X).
X = [1, 5, 2, 7, 9] ;
false.
One result, as expected. However, problem is in vice versa - it is looping - of course it is obvious that there are infitely such tree - but I dosen't give any result.
phrase(leaves(X), [1, 5, 2, 7, 9]) is looping, but for
phrase(leaves(X), [1]) it seems to be working in expected way:
X = t(1, nil, nil) ;
X = t(_G8388509, t(1, nil, nil), nil) ;
X = t(_G8388509, t(_G8388513, t(1, nil, nil), nil), nil)
Is it possible to implement it such that it will be working in the same way for one-element list ?
Edit
After reexamining your prior answers, I come to following conclusions:
leaves(nil, Ls, Ls) --> [].
leaves(t(X, nil, nil), Ls, Ls) -->[X].
leaves(t(_, t(Y, L, R), nil), [_|Ls0], Ls) -->
leaves(t(Y, L, R), Ls0, Ls).
leaves(t(_, nil, t(Y, L, R)), [_|Ls0], Ls) -->
leaves(t(Y, L, R), Ls0, Ls).
leaves(t(_, t(X, LL, LR), t(Y, RL, RR)), [_|Ls0], Ls) -->
leaves(t(X, LL, LR), Ls0, Ls1),
leaves(t(Y, RL, RR), Ls1, Ls).
phrase(leaves(X, [1,2], _), [1,2]).
X = t(_G1522, t(_G1526, t(1, nil, nil), t(2, nil, nil)), nil) ;
X = t(_G1522, nil, t(_G1526, t(1, nil, nil), t(2, nil, nil))) ;
X = t(_G1522, t(1, nil, nil), t(2, nil, nil)) ;
X = t(_G1522, t(1, nil, nil), t(_G1530, t(2, nil, nil), nil)) ;
X = t(_G1522, t(1, nil, nil), t(_G1530, nil, t(2, nil, nil))) ;
X = t(_G1522, t(_G1526, t(1, nil, nil), nil), t(2, nil, nil)) ;
X = t(_G1522, t(_G1526, nil, t(1, nil, nil)), t(2, nil, nil)) ;
false.
I expected infite result, but I got finite result. However, is it incorrect ?

Prolog, reconstruct BST trees from inorder list

We well know inorder implementation for BST tree.
inorder(nil, []).
inorder(t(Root, L, R), List) :-
inorder(L, ListLeft),
inorder(R, ListRight),
append(ListLeft, [Root|ListRight], List).
However, is it possible to do it for list ? I mean reconstruct all possible BST trees, for example:
inorder(X, [1,2,3]).
X = t(1, nil, t(2, nil, t(3, nil, nil))));
X = t(3, t(2, t(1, nil, nil), nil), nil), nil);
X = t(2, t(1, nil, nil), t(3, nil, nil));
false.
It seems to be impossible for me.
First, let us use a Definite Clause Grammar (dcg) for relating trees to lists:
inorder(nil) --> [].
inorder(t(Root, L, R)) -->
inorder(L),
[Root],
inorder(R).
The trick I will now apply is described in Ulrich Neumerkel's dissertation in Taming Left Recursion.
"... we add another state for the number of tokens that can be used by newly encountered nonterminals. The number of tokens that will be read by the terminals within a single rule are therefore reserved in advance."
In our case:
inorder(nil, Es, Es) --> [].
inorder(t(Root, L, R), [_|Es0], Es) -->
inorder(L, Es0, Es1),
[Root],
inorder(R, Es1, Es).
Sample query (Ls omitted):
?- Ls = [1,2,3], phrase(inorder(Tree, Ls, _), Ls).
Tree = t(1, nil, t(2, nil, t(3, nil, nil))) ;
Tree = t(1, nil, t(3, t(2, nil, nil), nil)) ;
Tree = t(2, t(1, nil, nil), t(3, nil, nil)) ;
Tree = t(3, t(1, nil, t(2, nil, nil)), nil) ;
Tree = t(3, t(2, t(1, nil, nil), nil), nil) ;
false.
Another way to solve such issues is to use your Prolog system's tabling mechanism.
If you like the trick I've proposed here, the only change required could be
:- use_module(carlo(snippets/when_)).
inorder(t(Root, L, R), List) -:- ...
and now
?- inorder(T,[1,2,3]).
T = t(1, nil, t(2, nil, t(3, nil, nil))) ;
T = t(1, nil, t(3, t(2, nil, nil), nil)) ;
T = t(2, t(1, nil, nil), t(3, nil, nil)) ;
T = t(3, t(1, nil, t(2, nil, nil)), nil) ;
T = t(3, t(2, t(1, nil, nil), nil), nil) ;
false.

Prolog binary search tree test - unwanted parents' parent node comparison

I'm a Prolog rookie, please keep that in mind.
I try to write a predicate to determine if some given term is a binary search tree. I figured out this code:
is_btree(nil).
is_btree(node(N,L,R)) :-
number(N),
is_btree(L),
is_btree(R),
small(N, R),
big(N, L).
small(N, nil).
small(N, node(M,L,R)) :-
N < M,
small(N, L),
small(N, R).
big(N, nil).
big(N, node(M,L,R)) :-
N > M,
big(N, L),
big(N, R).
It works quite fine until I test a graph that has a node on the right side which passes the condition "higher than parent node", but it is higher or equal to parent node of the parent node. In this case Prolog reports failure.
Here is a sample query which fails unexpectedly:
?- is_btree(node(9,node( 3,node( 2,nil,nil),
node(10,nil,nil)),
node(12,node( 8,nil,nil),
node(15,nil,nil)))).
false.
A very similar problem arises when some node on the left side is higher than parent node of the parent node—a situation that is shown in the following illustration:
How can I check node values only with the value of their immediate parent node, but not the values of parents' parents?
Here's a slightly different take on the problem you want to solve.
dcg for collecting elements: in-order tree-traversal
in_order(nil) --> [].
in_order(node(X,L,R)) --> in_order(L), [X], in_order(R).
clpfd for relating adjacent list elements (which are all finite-domain variables)
chain(Zs, #<)
Let's put it all together and define is_bintreeFD/1 like this:
:- use_module(library(clpfd)).
is_bintreeFD(T) :-
phrase(in_order(T), Zs),
chain(Zs, #<).
Sample queries:
?- is_bintreeFD(node(9,node( 3,node(2,nil,nil),node(10,nil,nil)),
node(12,node(8,nil,nil),node(15,nil,nil)))).
false.
?- is_bintreeFD(node(9,node( 3,node( 2,nil,nil),node( 8,nil,nil)),
node(12,node(10,nil,nil),node(15,nil,nil)))).
true.
This answer directly follows up on this previous answer, particularly on a comment by #WillNess that suggested "[...] switch the two goals, so the traversal is stopped as soon as possible on failure [...] to have chain before the phrase [...]".
lazy_chain/2 is like chain/2, but utilizes prolog-coroutining to wait for sufficient instantiation:
:- use_module(library(clpfd)).
lazy_chain(Zs, R_2) :-
( var(R_2) -> instantiation_error(R_2)
; clpfd:chain_relation(R_2) -> freeze(Zs, lazy_chain_aux(Zs,R_2))
; otherwise -> domain_error(chain_relation, R_2)
).
lazy_chain_aux([], _).
lazy_chain_aux([Z0|Zs], R_2) :-
freeze(Zs, lazy_chain_aux_(Zs,R_2,Z0)).
lazy_chain_aux_([], _, _).
lazy_chain_aux_([Z1|Zs], R_2, Z0) :-
call(R_2, Z0, Z1),
freeze(Zs, lazy_chain_aux_(Zs,R_2,Z1)).
Based on lazy_chain/2 we define is_bintreeL/2 like this:
is_bintreeL(T) :-
lazy_chain(Zs, #<),
phrase(in_order(T), Zs).
So... what about "early failure"?
?- T = node(2, nil, node(1, nil, node(3, nil, node(4, nil, node(5, nil, node(6, nil, node(7, nil, node(8, nil, node(9, nil, node(10, nil, node(11, nil, node(12, nil, node(13, nil, node(14, nil, node(15, nil, node(16, nil, node(17, nil, node(18, nil, node(19, nil, node(20, nil, node(21, nil, node(22, nil, node(23, nil, node(24, nil, node(25, nil, node(26, nil, node(27, nil, node(28, nil, node(29, nil, node(30, nil, node(31, nil, node(32, nil, node(33, nil, node(34, nil, node(35, nil, node(36, nil, node(37, nil, node(38, nil, node(39, nil, node(40, nil, node(41, nil, node(42, nil, node(43, nil, node(44, nil, node(45, nil, node(46, nil, node(47, nil, node(48, nil, node(49, nil, node(50, nil, node(51, nil, node(52, nil, node(53, nil, node(54, nil, node(55, nil, node(56, nil, node(57, nil, node(58, nil, node(59, nil, node(60, nil, node(61, nil, node(62, nil, node(63, nil, node(64, nil, node(65, nil, node(66, nil, node(67, nil, node(68, nil, node(69, nil, node(70, nil, node(71, nil, node(72, nil, node(73, nil, node(74, nil, node(75, nil, node(76, nil, node(77, nil, node(78, nil, node(79, nil, node(80, nil, node(81, nil, node(82, nil, node(83, nil, node(84, nil, node(85, nil, node(86, nil, node(87, nil, node(88, nil, node(89, nil, node(90, nil, node(91, nil, node(92, nil, node(93, nil, node(94, nil, node(95, nil, node(96, nil, node(97, nil, node(98, nil, node(99, nil, node(100, nil, nil)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))),
time((phrase(in_order(T),Zs),eager_chain(Zs,#<))).
% 210 inferences, 0.000 CPU in 0.000 seconds (98% CPU, 4100201 Lips)
false.
?- T = node(2, nil, node(1, nil, node(3, nil, node(4, nil, node(5, nil, node(6, nil, node(7, nil, node(8, nil, node(9, nil, node(10, nil, node(11, nil, node(12, nil, node(13, nil, node(14, nil, node(15, nil, node(16, nil, node(17, nil, node(18, nil, node(19, nil, node(20, nil, node(21, nil, node(22, nil, node(23, nil, node(24, nil, node(25, nil, node(26, nil, node(27, nil, node(28, nil, node(29, nil, node(30, nil, node(31, nil, node(32, nil, node(33, nil, node(34, nil, node(35, nil, node(36, nil, node(37, nil, node(38, nil, node(39, nil, node(40, nil, node(41, nil, node(42, nil, node(43, nil, node(44, nil, node(45, nil, node(46, nil, node(47, nil, node(48, nil, node(49, nil, node(50, nil, node(51, nil, node(52, nil, node(53, nil, node(54, nil, node(55, nil, node(56, nil, node(57, nil, node(58, nil, node(59, nil, node(60, nil, node(61, nil, node(62, nil, node(63, nil, node(64, nil, node(65, nil, node(66, nil, node(67, nil, node(68, nil, node(69, nil, node(70, nil, node(71, nil, node(72, nil, node(73, nil, node(74, nil, node(75, nil, node(76, nil, node(77, nil, node(78, nil, node(79, nil, node(80, nil, node(81, nil, node(82, nil, node(83, nil, node(84, nil, node(85, nil, node(86, nil, node(87, nil, node(88, nil, node(89, nil, node(90, nil, node(91, nil, node(92, nil, node(93, nil, node(94, nil, node(95, nil, node(96, nil, node(97, nil, node(98, nil, node(99, nil, node(100, nil, nil)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))),
time((lazy_chain(Zs,#<),phrase(in_order(T),Zs))).
% 52 inferences, 0.000 CPU in 0.000 seconds (98% CPU, 1225664 Lips)
false.
Laziness wins—at least in above case:)
Note, however, that using lazy_chain/2 with dcg can lead to bugs that are hard to find!
For a more robust solution, see this alternative answer...
For the sake of completeness, here's the source code of eager_chain/2:
eager_chain(Zs, R_2) :-
( var(R_2) -> instantiation_error(R_2)
; clpfd:chain_relation(R_2) -> eager_chain_aux(Zs, R_2)
; otherwise -> domain_error(chain_relation, R_2)
).
eager_chain_aux([], _).
eager_chain_aux([Z0|Zs], R_2) :-
eager_chain_aux_(Zs, R_2, Z0).
eager_chain_aux_([], _, _).
eager_chain_aux_([Z1|Zs], R_2, Z0) :-
call(R_2, Z0, Z1),
eager_chain_aux_(Zs, R_2, Z1).
In this answer we use clpfd
for declarative integer arithmetics.
:- use_module(library(clpfd)).
:- asserta(clpfd:full_answer).
We define the predicates is_bintree/1 and bintree_in/2 like this:
is_bintree(T) :-
bintree_in(T, _).
bintree_in(nil, LB-UB) :- % LB-UB denotes the open interval (LB,UB)
LB #< UB. % that is all integers I suchthat LB<I<UB
bintree_in(node(Mid,L,R), LB-UB) :-
Mid #> LB,
Mid #< UB,
bintree_in(L, LB-Mid),
bintree_in(R, Mid-UB).
First, we test1,2 the tree given by the OP:
| ?- bintree_in(node(9,node( 3,node(2,nil,nil),node(10,nil,nil)),
node(12,node(8,nil,nil),node(15,nil,nil))), _).
no
Let's fix the tree and check again!
| ?- bintree_in(node(9,node( 3,node( 2,nil,nil),node( 8,nil,nil)),
node(12,node(10,nil,nil),node(15,nil,nil))), _).
_A in inf..1, _B in 16..sup ? ; % (somewhat sloppy)
no
OK! Next up are a few corner cases:
| ?- bintree_in(T, 0-0). % no solution (as expected)
no
| ?- bintree_in(T, 0-1). % empty tree
T = nil ? ;
no
| ?- bintree_in(T, 0-2). % singleton tree
T = nil ? ;
T = node(1,nil,nil) ? ;
no
Note that while is_btree/1 can only "test", bintree_in/2 can both3 "test" and "generate"!
So let's generate (all possible) binary trees of a certain size in a small domain:
| ?- bintree_in(T, 0-3). % T has less than 3 elements
T = nil ? ;
T = node(_A,nil,nil), _A in 1..2 ? ;
T = node(1,nil,node(2,nil,nil)) ? ;
T = node(2,node(1,nil,nil),nil) ? ;
no
| ?- bintree_in(T, 0-4). % T has less than 4 elements
T = nil ? ;
T = node(_A,nil,nil), _A in 1..3 ? ;
T = node(_A,nil,node(_B,nil,nil)), _A#=<_B+ -1, _B#>=_A+1, _B in 2..3, _A in 1..2 ? ;
T = node(1,nil,node(2,nil,node(3,nil,nil))) ? ;
T = node(1,nil,node(3,node(2,nil,nil),nil)) ? ;
T = node(_A,node(_B,nil,nil),nil), _A#>=_B+1, _A in 2..3, _B in 1..2 ? ;
T = node(2,node(1,nil,nil),node(3,nil,nil)) ? ;
T = node(3,node(1,nil,node(2,nil,nil)),nil) ? ;
T = node(3,node(2,node(1,nil,nil),nil),nil) ? ;
no
Last, we generate candidate solutions with bintree_in/2 and test these with is_btree/1!
is_btree/1 needs sufficient instantiation; labeling/2 provides us with ground terms.
| ?- call_time(( UB in 2..12,
indomain(UB),
bintree_in(T, 0-UB),
term_variables(T, Zs),
labeling([], Zs),
\+ is_btree(T)
; true
),
T_ms).
T_ms = 6270 ? ;
no
Footnote 1:
The code in this answer runs (at on sicstus-prolog and swi-prolog.
Footnote 2:
All prolog-toplevel output presented is that of
SICStus Prolog 4.3.2 (64-bit).
Footnote 3:
Not just do both, but
(almost) arbitrarily mix generate and test, as it can handle partially instantiated terms.
In a comment to this previous answer, #WillNess suggested adding "early-failure" as a feature.
in_order_inf_sup//3 effectively combines in_order//1 and
chain/2:
:- use_module(library(clpfd)).
in_order_inf_sup(nil, P, P) --> [].
in_order_inf_sup(node(X,L,R), P0, P) -->
in_order_inf_sup(L, P0, P1),
[X],
{ P1 #< X },
in_order_inf_sup(R, X, P).
Sample queries (same as in previous answer):
?- phrase(in_order_inf_sup(node(9,node( 3,node(2,nil,nil),node(10,nil,nil)),
node(12,node(8,nil,nil),node(15,nil,nil))),_,_),
Zs).
false.
?- phrase(in_order_inf_sup(node(9,node( 3,node( 2,nil,nil),node( 8,nil,nil)),
node(12,node(10,nil,nil),node(15,nil,nil))),_,_),
Zs).
Zs = [2,3,8,9,10,12,15].
But it should fail. That tree is an invalid BST and your predicate tests for valid BSTs.
There is something to be done here though. Right now you perform two passes over a tree - first in is_btree, second, with small/big.
The two can be fused into one, but an immediately apparent solution will do exactly what you want, and thus succeed on such invalid BSTs:
is_bst(nil).
is_bst(node(N,L,R)):-
( L = nil
; L = node(M,LL,LR), M < N, is_bst(L), ....
),
( R = nil
; ......
).
To fix it, we have to return one more result from the tree traversal — that is the tree's rightmost element — and use it in the comparisons for validation.
(edit: missed that the leftmost element also needs to be returned)

Resources