Skip to main content

Lists and finite trees are \(E_3\)

In order to prove the fgoagog thing we need to be able to do computations on trees at a low level of the Grzegorczyk hierarchy, so it doesn’t mess up the complexity of the whole group computation. I will give a model of finite trees that lies in \(E_3\), the same level as Cannonito/Gatterdam’s standard index for the free group. (( this post has been sitting as a draft since the beginning of May because I wanted to make some nice tree pictures, but I’d rather just publish it now. So, the trees section is copied out of my notes and might not make sense ))


First of all, I’ll show how to encode sequences of numbers so that they can be manipulated and read by \(E_3\) functions. Let \((x_1, \dots,x_n)\) be a sequence of \(n\) non-negative numbers.

First encode the list as a Gödel number:

\[ encode(x_1, \dots, x_n) = {\bf x} = \prod_{i=1}^n (p_i)^{x_n+1}, \]

where \(p_i\) is the \(i^\textrm{th}\) prime. (( it’s just occurred to me that I haven’t shown that things such as finding primes and divisiblity tests and so on are \(E_3\) computable. I’ll do another post after this one with suitable definitions for all that stuff ))

In order to actually do anything with this encoded list, we need to be able to find out its length and the value of the entry at any given position. \(plog({\bf x},p)\) return the exponent of the prime \(p\) in \({\bf x}\):

\[ \begin{eqnarray*} plog({\bf x},p) &=& \left \{ \begin{array}{lr} 1+plog(\frac{{ '{{' }}\bf x}}{p},p), & p \nmid {\bf x}, \\ 0, & p \nmid {\bf x}. \end{array} \right . \\ ({\bf x})_i &=& plog({\bf x},p_i) – 1 \end{eqnarray*} \]

I’m using \(({\bf x})_i\) instead of \(x_i\) to denote the \(i^\textrm{th}\) element of an encoded list, just so it’s clear that’s what’s happening later on.

\(lh({\bf x})\) finds the length of an encoded list:

\[ lh({\bf x}) = \underset{i \leq {\bf x}}{\mu} ( (p_i \nmid {\bf x}) – 1) \]

Note that \(\underset{i \leq {\bf x}}{\mu} P(i) = {\bf x}+1\) if there is no \(i \leq {\bf x}\) such that \(P(i)\) holds. The \(i \leq {\bf x}\) bit in the minimisation is so that the function is bounded – it doesn’t matter what upper bound I pick as long as it’s “enough”.

\(find({\bf x},n)\) returns the first occurence of \(n\) in an encoded list \({\bf x}\):

\[ find({\bf x},n) = \underset{i \leq {\bf x}}{\mu} ({\bf x})_i = n \]

Make use of \(find\) to determine whether an encoded list contains a given value:

\[ contains({\bf x},n) \Leftrightarrow ({\bf x})_{find({\bf x},n)} = n \]

This function to find the largest element of a list \({\bf x}\), \(biggest({\bf x})\), is defined by using a helper function \(biggest'({\bf x},n)\), which gives the biggest element up to \(({\bf x})_n\):

\[ \begin{eqnarray*} biggest({\bf x}) &=& biggest'({\bf x},lh({\bf x})) \\ \\ biggest'({\bf x},0) &=& ({\bf x})_0 \\ biggest'({\bf x},n+1) &=& \max \left ( ({\bf x})_{n+1},biggest'({\bf x},n) \right ) \end{eqnarray*} \]

\(slice({\bf x},s,e)\), which I will also write \({\bf x}[s \dots e]\), gives you the sublist of \({\bf x}\) starting at position \(s\) and ending at position \(e\). The max/min stuff is to make sure this function works sensibly even when given wrong inputs:

\[ \begin{eqnarray*} slice({\bf x},s,e) &=& \prod_{i=s’}^{e’}(p_{i+1-s’})^{({\bf x})_i+1} \\ e’ &=& \max(1,\min(e,lh({\bf x}))) \\ s’ &=& \max(1,\min(s,e’)) \end{eqnarray*}

\(splice({\bf x},n)\), also written \({\bf x}:n\), appends a value \(n\) to the end of an encoded list \({\bf x}\):

\[ splice({\bf x},n) = {\bf x} \cdot p_{lh({\bf x})+1}^{n+1} \]


A tree consists of a set of vertices \(V\) and a set of edges \(E\) connecting pairs of vertices, with no loops.

A rooted tree has a unique vertex \(v_0\) said to be at the ‘top’. In an ordered tree, the set of children of each vertex is ordered, so there is a leftmost child, and so on. A plane recursive tree is a rooted, ordered tree constructed by a process which begins with the root node and recursively adds vertices below existing ones.

We can assign a labelling to a plane recursive tree by giving vertices labels corresponding to the order in which they were added to the tree, beginning with \(0\) for the root. This way, the sequence of labels encountered heading outwards from the root is always increasing. Every edge can also be given a unique labelling by saying that the edge \(e_{ij}\), connecting vertex \(v_i\) to \(v_j\), has label \(\max(i,j)\).

Suppose we have a tree \(T=(V,E)\) with root vertex \(v_0\). \(T\) is \(E_n\) computable if there is an \(E_n\)-decidable labelling \(i: V \rightarrow \mathbb{N}\) (we can assume \(i(v_0) = 0\)) and an \(E_n\)-computable “parent function” \(p_T:i(V) \rightarrow i(V)\) which gives the label of the parent of a vertex. We also require that \(p_T(v_0) = 0\).

A finite plane recursive tree can be entirely described in a canonical way by a depth-first walk. Note that every node has a single parent and a finite ordered set of children. The process on ‘visiting’ a vertex \(v_i\) goes as follows: for each child node \(v_j\), travel along \(e_{ij}\) and visit \(v_j\), then travel backwards along \(e_{ij}\). The sequence of labelled edges travelled along by beginning this process at \(v_0\) is the depth-first walk of the tree. Note that each edge is visited exactly twice – once heading outwards, and again heading back towards the root.

This sequence can then be encoded as a Gödel number by the method in Section 1. We will define a function \(\phi({\bf x},n)\) which takes an encoded tree \({\bf x}\) and gives the parent of the vertex with label \(n\). Note that the root vertex’s label will not appear in this sequence because it has no associated edge.

Some functions to work with encoded trees:

To find the first and second occurrences of the edge with label \(n\) in the walk:

\[ \begin{eqnarray*} fst({\bf x},n) &=& find({\bf x},n) \\ snd({\bf x},n) &=& find({\bf x}[fst({\bf x},n)+1 \dots lh({\bf x})],n) \end{eqnarray*} \]

To get the label of the \(n^{\textrm{th}}\) child of the root:

\[ \begin{eqnarray*} child({\bf x},0) &=& ({\bf x})_0 \\ child({\bf x},n+1) &=& ({\bf x})_{snd({\bf x},child({\bf x},n))+1} \end{eqnarray*} \]

To find the subtree descended from the \(n^{\textrm{th}}\) child node:

\[ \begin{eqnarray*} subtree({\bf x},n) &=& {\bf x}[fst(child({\bf x},n))+1 \dots snd(child({\bf x},n))-1] \\ \end{eqnarray*} \]

The number of children of the root node:

\[ numchildren({\bf x}) = \underset{i \lt {\bf x}}{\mu} child({\bf x},i)=0 \]

Whether the root has a child with label \(n\):

\[ haschild({\bf x},n) = \underset{i \lt numchildren({\bf x})}{\mu} child({\bf x},i)=n \]

Finally, the parent function. The idea is to basically do the depth-first walk, remembering which vertex you just came from. If you reach a subtree which doesn’t contain \(n\) then turn back, or if you reach the required vertex then return the label of the vertex you just came from.

\[ \begin{eqnarray*} p_{\bf x}(0) &=& 0 \\ p_{\bf x}(n) &=& parent({\bf x},n,0) \\ parent({\bf x},n,p) &=& \left \{ \begin{array}{lr} 0, & \neg (contains({\bf x},n)), \\ p, & haschild({\bf x},n), \\ parent(subtree({\bf x},z),n,child({\bf x},z)), & \textrm{otherwise.} \end{array} \right . \end{eqnarray*} \]

where \(z := \underset{i \lt numchildren({\bf x})}{\mu} contains(subtree({\bf x},i),n)\).

We will also need to know if the tree contains an edge \(e_{ij}\):

\[ hasedge({\bf x},i,j) \Leftrightarrow p_{\bf x}(i) = j \wedge p_{\bf x}(j) = i \]


A finite ordered tree is \(E_3\) computable.


As the tree is finite, of course its labelling is \(E_3\)-decidable, and \(p_{bf x}(n)\) as defined above is \(E_3\)-computable. \(\square\)