NAME
Math::PlanePath::ChanTree  tree of rationals
SYNOPSIS
use Math::PlanePath::ChanTree;
my $path = Math::PlanePath::ChanTree>new (k => 3, reduced => 0);
my ($x, $y) = $path>n_to_xy (123);
DESCRIPTION
This path enumerates rationals X/Y in a tree as per
Song Heng Chan, "Analogs of the Stern Sequence", Integers 2011, http://www.integersejcnt.org/l26/l26.pdf
The default k=3 visits X,Y with one odd, one even, and perhaps a common factor 3^m.
14  728 20 12
13  53 11 77 27
12  242 14 18
11 
10  80
9  17 23 9 15
8  26 78
7 
6  8 24 28
5  5 3 19
4  2 6 10 22
3 
2  0 4 16 52
1  1 7 25 79 241 727
Y=0 
+
X=0 1 2 3 4 5 6 7 8 9 10 11 12 13
There are 2 tree roots (so technically it's a "forest") and each node has 3 children. The points are numbered by rows starting from N=0. This numbering corresponds to powers in a polynomial product generating function.
N=0 to 1 1/2 2/1
/  \ /  \
N=2 to 7 1/4 4/5 5/2 2/5 5/4 4/1
/  \ ... ... ... ... /  \
N=8 to 25 1/6 6/9 9/4 ... ... 5/9 9/6 6/1
N=26 ...
The children of each node are
X/Y
/  \
  
X/(2X+Y) (2X+Y)/(X+2Y) (X+2Y)/Y
Which as X,Y coordinates means vertical, 45degree diagonal, and horizontal.
X,Y+2X X+(X+Y),Y+(X+Y)
 /
 /
 /
 /
X,Y X+2Y,Y
The slowest growth is on the far left of the tree 1/2, 1/4, 1/6, 1/8, etc advancing by just 2 at each level. Similarly on the far right 2/1, 4/1, 6/1, etc. This means that to cover such an X or Y requires a powerof3, N=3^(max(X,Y)/2).
GCD
Chan shows that these top nodes and children visit all rationals X/Y with X,Y one odd, one even. But the X,Y are not in least terms, they may have a powerof3 common factor GCD(X,Y)=3^m for some m.
The GCD is unchanged in the first and third children. The middle child GCD might gain an extra factor 3. This means the power is at most the number of middle legs taken, which is the count of ternary 1digits of its position across the row.
GCD(X,Y) = 3^m
m <= count ternary 1digits of N+1, excluding high digit
As per "N Start" below, N+1 in ternary has high digit 1 or 2 which indicates the tree root. Ignoring that high digit gives an offset into the row of that tree and the digits are 0,1,2 for left,middle,right.
For example the first GCD is at N=9 with X=6,Y=9 common factor GCD=3. N+1=10="101" ternary, which without the high digit is "01" which has a single "1" so GCD <= 3^1. The mirror image of this point is X=9,Y=6 at N=24 and there N+1=24+1=25="221" ternary which without the high digit is "21" with a single 1digit likewise.
For various points the power m is equal to the count of 1digits.
k Parameter
Parameter k => $integer
controls the number of children and top nodes. There are k1 top nodes and each node has k children. The top nodes are
k odd, k1 many tops, with h=ceil(k/2)
1/2 2/3 3/4 ... (h1)/h h/(h1) ... 4/3 3/2 2/1
k even, k1 many tops, with h=k/2
1/2 2/3 3/4 ... (h1)/h h/h h/(h1) ... 4/3 3/2 2/1
Notice the list for k odd or k even is the same except that for k even there's an extra middle term h/h. The first few tops are as follows. The list in each row is spread to show how successive bigger h adds terms in the middle.
k X/Y top nodes
 
k=2 1/1
k=3 1/2 2/1
k=4 1/2 2/2 2/1
k=5 1/2 2/3 3/2 2/1
k=6 1/2 2/3 3/3 3/2 2/1
k=7 1/2 2/3 3/4 4/3 3/2 2/1
k=8 1/2 2/3 3/4 4/4 4/3 3/2 2/1
As X,Y coordinates these tops are a run up along X=Y1 and back down along X=Y+1, with a middle X=Y point if k even. For example,
7  5 k=13 top nodes N=0 to N=11
6  4 6 total 12 top nodes
5  3 7
4  2 8
3  1 9
2  0 10
1  11
Y=0 
+
X=0 1 2 3 4 5 6 7
k=14 top nodes N=0 to N=12
7  5 6 total 13 top nodes
6  4 7
5  3 8 N=6 is the 7/7 middle term
4  2 9
3  1 10
2  0 11
1  12
Y=0 
+
X=0 1 2 3 4 5 6 7
Each node has k children. The formulas for the children can be seen from sample cases k=5 and k=6. A node X/Y descends to
k=5 k=6
1X+0Y / 2X+1Y 1X+0Y / 2X+1Y
2X+1Y / 3X+2Y 2X+1Y / 3X+2Y
3X+2Y / 2X+3Y 3X+2Y / 3X+3Y
2X+3Y / 1X+2Y 3X+3Y / 2X+3Y
1X+2Y / 0X+1Y 2X+3Y / 1X+2Y
1X+2Y / 0X+1Y
The coefficients of X and Y run up to h=ceil(k/2) starting from either 0, 1 or 2 and ending 2, 1 or 0. When k is even there's two h coeffs in the middle. When k is odd there's just one. The resulting tree for example with k=4 is
k=4
1/2 2/2 2/1
/ \ / \ / \
1/4 4/6 6/5 5/2 2/6 6/8 8/6 6/2 2/5 5/6 6/4 4/1
Chan shows that this combination of top nodes and children visits
if k odd: rationals X/Y with X,Y one odd, one even
possible GCD(X,Y)=k^m for some integer m
if k even: all rationals X/Y
possible GCD(X,Y) a divisor of (k/2)^m
When k odd, GCD(X,Y) is a power of k, so for example as described above k=3 gives GCD=3^m. When k even GCD(X,Y) is a divisor of (k/2)^m but not necessarily a full such power. For example with k=12 the first such nonpower GCD is at N=17 where X=16,Y=18 has GCD(16,18)=2 which is only a divisor of k/2=6, not a power of 6.
N Start
The n_start => $n
option can select a different initial N. The tree structure is unchanged, just the numbering shifted. As noted above the default Nstart=0 corresponds to powers in a generating function.
n_start=>1
makes the numbering correspond to digits of N written in basek. For example k=10 corresponds to N written in decimal,
N=1 to 9 1/2 ... ... 2/1
N=10 to 99 1/4 4/7 ... ... 7/4 4/1
N=100 to 999 1/6 6/11 ... ... 11/6 6/1
In general n_start=>1
makes the tree
N written in basek digits
depth = numdigits(N)1
NdepthStart = k^depth
= 100..000 basek, high 1 in high digit position of N
NNdepthStart = position across whole row of all top trees
And the high digit of N selects which toplevel tree the given N is under, so
N written in basek digits
top tree = high digit of N
(1 to k, selecting the k1 many top nodes)
Nrem = digits of N after the highest
= position across row within the highdigit tree
depth = numdigits(Nrem) # top node depth=0
= numdigits(N)1
Diatomic Sequence
Chan shows that each denominator Y becomes the numerator X in the next point. The last Y of a row becomes the first X of the next row. This is a generalization of Stern's diatomic sequence and of the CalkinWilf tree of rationals. (See Math::NumSeq::SternDiatomic and "CalkinWilf Tree" in Math::PlanePath::RationalsTree.)
The case k=2 is precisely the CalkinWilf tree. There's just one top node 1/1, being the even k "middle" form h/h with h=k/2=1 as described above. Then there's two children of each node (the "middle" pair of the even k case),
k=2, CalkinWilf tree
X/Y
/ \
(1X+0Y)/(1X+1Y) (1X+1Y)/(0X+1Y)
= X/(X+Y) = (X+Y)/Y
FUNCTIONS
See "FUNCTIONS" in Math::PlanePath for behaviour common to all path classes.
$path = Math::PlanePath::ChanTree>new ()
$path = Math::PlanePath::ChanTree>new (k => $k, n_start => $n)

Create and return a new path object. The defaults are k=3 and n_start=0.
$n = $path>n_start()

Return the first N in the path. This is 0 by default, otherwise the
n_start
parameter. $n = $path>xy_to_n ($x,$y)

Return the point number for coordinates
$x,$y
. If there's nothing at$x,$y
then returnundef
.
Tree Methods
Each point has k children, so the path is a complete kary tree.
@n_children = $path>tree_n_children($n)

Return the children of
$n
, or an empty list if$n < n_start()
, ie. before the start of the path. $num = $path>tree_n_num_children($n)

Return k, since every node has k children. Or return
undef
if$n < n_start()
, ie. before the start of the path. $n_parent = $path>tree_n_parent($n)

Return the parent node of
$n
, orundef
if$n
has no parent either because it's a top node or beforen_start()
. $n_root = $path>tree_n_root ($n)

Return the N which is root node of
$n
. $depth = $path>tree_n_to_depth($n)

Return the depth of node
$n
, orundef
if there's no point$n
. The tree tops are depth=0, then their children depth=1, etc. $n = $path>tree_depth_to_n($depth)
$n = $path>tree_depth_to_n_end($depth)

Return the first or last N at tree level
$depth
in the path. The top of the tree is depth=0.
Tree Descriptive Methods
$num = $path>tree_num_roots ()

Return the number of root nodes in
$path
, which is k1. For example the default k=3 return 2 as there are two root nodes. @n_list = $path>tree_root_n_list ()

Return a list of the N values which are the root nodes of
$path
. This isn_start()
throughn_start()+k2
inclusive, being the first k1 many points. For example in the default k=2 and Nstart=0 the return is two values(0,1)
. $num = $path>tree_num_children_minimum()
$num = $path>tree_num_children_maximum()

Return k since every node has k many children, making that both the minimum and maximum.
$bool = $path>tree_any_leaf()

Return false, since there are no leaf nodes in the tree.
FORMULAS
N Children
For the default k=3 the children are
3N+2, 3N+3, 3N+4 n_start=0
If n_start=>1
then instead
3N, 3N+1, 3N+2 n_start=1
For this n_start=1
the children are found by appending an extra ternary digit, or basek digit for arbitrary k.
k*N, k*N+1, ... , k*N+(k1) n_start=1
In general for k and Nstart the children are
kN  (k1)*(Nstart1) + 0
...
kN  (k1)*(Nstart1) + k1
N Parent
The parent node reverses the children calculation above. The simplest case is n_start=1
where it's a division to remove the lowest basek digit
parent = floor(N/k) when n_start=1
For other n_start
adjust before and after to an n_start=1
basis,
parent = floor((N(Nstart1)) / k) + Nstart1
For example in the default k=0 Nstart=1 the parent of N=3 is floor((3(11))/3)=1.
The postadjustment can be worked into the formula with (k1)*(Nstart1) similar to the children above,
parent = floor((N + (k1)*(Nstart1)) / k)
But the first style is more convenient to compare to see that N is past the top nodes and therefore has a parent.
N(Nstart1) >= k to check N is past topnodes
N Root
As described under "N Start" above, if Nstart=1 then the tree root is simply the most significant basek digit of N. For other Nstart an adjustment is made to N=1 style and back again.
adjust = Nstart1
Nroot(N) = high_base_k_digit(Nadjust) + adjust
N to Depth
The structure of the tree means
depth = floor(logk(N+1)) for n_start=0
For example if k=3 then all of N=8 through N=25 inclusive have depth=floor(log3(N+1))=2. With an n_start
it becomes
depth = floor(logk(N(Nstart1)))
n_start=1
is the simplest case, being the length of N written in basek digits.
depth = floor(logk(N)) for n_start=1
OEIS
This tree is in Sloane's Online Encyclopedia of Integer Sequences as
http://oeis.org/A191379 (etc)
k=3, n_start=0 (the defaults)
A191379 X coordinate, and Y=X(N+n)
As noted above k=2 is the CalkinWilf tree. See "OEIS" in Math::PlanePath::RationalsTree for "CW" related sequences.
SEE ALSO
Math::PlanePath, Math::PlanePath::RationalsTree, Math::PlanePath::PythagoreanTree
HOME PAGE
http://user42.tuxfamily.org/mathplanepath/index.html
LICENSE
Copyright 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Kevin Ryde
This file is part of MathPlanePath.
MathPlanePath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
MathPlanePath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with MathPlanePath. If not, see <http://www.gnu.org/licenses/>.