Fully Compact Routing in Low Memory Self-Healing Trees

The paper (Compact Routing Messages in Self-Healing Trees, TCS 2017) introduced CompactFTZ, the first self-healing compact routing algorithm that works in a distributed network with each node using only O(log n) words (i.e. O(log2 n) bits) memory and thus O(log n) sized messages. The routing uses only O(1) and O(log n) words routing table and packet labels respectively on a self-healing tree that also works using only O(1) words repairing the network in face of a strong adversary deleting nodes. This deterministic algorithm sets up its data structures in a preprocessing phase and then updates the required data structures in only O(1) parallel time per healing round during execution of the algorithm. However, CompactFTZ has no constraints in its preprocessing phase which could be done in distributed large memory or even centrally. In this paper, we correct that by developing the algorithms for preprocessing of CompactFTZ in a fully distributed manner using only O(log n) words memory in optimal time. In fact, the preprocessing for the self-healing tree (ForgivingTree) component takes only O(1) memory. We develop a local function which each node invokes to instantly compute and then relay its repair instructions (known as its Will) in only O(1) time. We formalise the low memory CONGEST model setting used in previous low memory algorithms (e.g.[24]); nodes' working memory is restricted to be much smaller (in our case, O(log n)) than the numbers of their neighbours to whom they communicate through their I/O ports. We expand the model to allow for non-contiguous ports (e.g. empty ports or neighbours unmarked or lost in dynamic settings) and adversarial order of inputs from neighbours. Besides the Wills, we set up the tree structures and traversals for the routing scheme using only O(log n) memory and O(D) parallel time, where D is the diameter. Thus, we devise the first self-healing compact routing algorithm that can be fully set up and executed in low memory.


INTRODUCTION
As the number of nodes in modern distributed networks rapidly increase and large networks of low memory devices evolve, there is a need to design truly scalable solutions. These algorithms should work with small messages while using low memory. For example, networks like the Internet of Things (IoT) will deploy systems with large number of weak devices. Similarly, ad-hoc sensor or vehicular networks may have dynamically evolving and unpredictable node neighbourhoods. In such scenarios, solutions using local polynomial memory (in n -the number of nodes in the system) may not be desirable. Even with advancements in technology, node memory will remain at a premium with increasing demand for applications and a light memory footprint will be desired. The natural question is what can be achieved if nodes have limited working memory even if they may have large neighbourhoods?. This, of course, has always been an interesting theoretical question (e.g [14,25,26,34]). A similarly important question is what can be achieved despite failures in a distributed network?. There are a multitude of ways in which failure can happen and be handled in distributed networks; in this paper, we concentrate on node crash failures in the self-healing healing paradigm [7, 35-37, 49, 50] developing the first compact selfhealing routing scheme fully setup and executed in low (logarithmic in n) memory.
We develop a self-healing compact routing scheme using only O(log n) words local memory per node with small messages (as in the CONGEST model (see 2 for details). Throughout, unless otherwise mentioned, space is given in the unit of memory words. There has been intense interest in designing efficient routing schemes for distributed networks [1,8,13,19,33,53,56,58] with compact routing trading stretch (factor increase in routing length) for memory used. In essence, the challenge is to use small memory per node overcoming the need for large routing tables or/and packet headers. In fact, we define local memory as compact if it is o(n) bits and, by extension, an algorithm as compact if it works in compact memory -however, we use much smaller (only O(polyloд n)) per node.
A routing scheme (with routing tables at nodes and headers/labels at packets to route them) consists of two parts -a pre-processing algorithm (scheme construction) and a routing protocol [30]. The routing results mentioned previously assume sequential centralized pre-processing. Since routing is inherently a distributed networks problem, it makes sense to have the scheme construction distributed too. Awerbuch et al. [3] were the first to introduce this question which has recently led to a spurt in designing efficient preprocessing algorithms for compact routing schemes in the CONGEST model (discussed in Section 2) [21,22,32,46]. These algorithms did not seek to explicitly optimize internal working memory. We develop a pre-processing scheme (for a tree routing scheme from Thorup and Zwick's seminal work [58]) assuming that nodes do not even have any excess space and therefore, have, to develop the whole solution in compact memory itself. Elkin and Neiman [24] with a similar motivation develop efficient routing solutions using the least working memory required per node. As they point out, since compact routing is motivated by having limited memory at nodes, it is inconsistent to use much larger memory to setup such schemes in the first place. We develop preprocessing for tree routing in a similar manner to [25] (though they give the scheme for general routing too) but differ in two important aspects: we are interested in deterministic solutions whereas the previous solutions are all randomized, and we are interested in a fault-tolerant solution as discussed in the following paragraph.
Deterministic routing schemes, in the preprocessing phase, rely on discovery and efficient distributed 'encoding' of the network's topology to reduce the memory requirement (a routing scheme on an arbitrary network with no prior topology or direction knowledge would essentially imply large memory requirements). This makes them sensitive to any topology change and, hence, it is challenging to design fault tolerant compact routing schemes. There has been some work in this direction e.g. in the dynamic tree model [38,40] or with additional capacity and rerouting in anticipation of failures [9,10,12,17,29,31]. Self-healing is a responsive faulttolerace paradigm seeking minimal anticipatory additional capacity and has led to a series of work [35,37,48,50,55,57,59,60] in the recent past for maintaining topological properties (connectivity, degrees, diameter/stretch, expansion etc.). Algorithms were also proposed to 'self-heal' computations e.g. [54].
Combining the above motivations, [7] introduced a fault-tolerant compact routing solution CompactFTZ in the (deletion only) selfhealing model (details in Section 2) However, as in previous routing schemes, CompactFTZ's pre-processing assumed large (not compact) memory. This paper addresses that important problem developing a compact pre-processing deterministic algorithm for CompactFTZ. We also develop a compact pre-processing deterministic algorithm for CompactFT (a compact version of Forgiv-ingTree [35]). This leads to a fully compact (i.e. completely distributed and in compact memory) routing scheme, a fully compact self-healing routing scheme and a fully compact self-healing algorithm.  Table 1: Results in this paper To develop the preprocessing (CompactFTZ and its preprocessing is discussed in detail in Section 5), a number of subproblems such as BFS, DFS traversals, convergecast and Will creation need to be solved. Our results are summarised in Table 1. Our memory requirements are the same as that of the final data structures setup in the CompactFTZ algorithm [7] (and the centralised ) and ForgivingTree [35]) and, hence, optimal.

MODEL
Our communication model is similar to the CONGEST model [52] and the CONGEST RAM model of [23,24] (in which they develop low memory algorithms). We assume a connected network of arbitrary topology represented by an undirected graph G = (V , E) with |V | = n and |E| = m for n nodes and m bidirectional links. Each node has a unique ID and O(n) communication ports with locally unique Port-IDs interfacing with the links. In the CONGEST model, nodes communicate with one another in discrete rounds, via short (of size (O(log n) bits) messages. In the CONGEST RAM variant, each message is allowed to contain a vertex ID, a graph distance, or anything of size within the same constant factor size. As in [24], each node also has o(n) working (internal) memory (we call this compact) -however, we further restrict node memory to only O(log n) in this paper.
Again, as in [24], in every (synchronous/asynchronous) round, a node can read from and write to any of its ports while doing internal computation as long as it reads and/or writes to a port only once [20]. However, in addition, in our model, neighbours need not be on contiguous ports i.e. there may be 'dead' ports interspersed with live ones. Even starting from contiguous ports, this can happen due to node deletions or due to subnetworks generated (e.g. spanning trees). To accomodate this, we state our model in more formal terms as follows: Every round, v 'sweeps' through its ports reading and writing to its ports in some order interleaving the reads and writes with internal processing as long as it reads and writes to a port at most once in that round. That is, a round may be represented as pr i pw i ′r j pw j ′p . . ., where p,r and w stand for processing (possibly none), reading and writing, subscripted by port numbers. Notice that it may not be possible for a node to execute any random read order (without repetition) due to memory restrictions, (some orders can only be stored in θ (n) memory) thus, often, a node may just execute a sequential read order reading from the first port to the last port hosting a neighbour. Note that the above can be viewed as simply a regular message passing round at a finer granularity with interleaved local computations; hence, the time complexity measure (number of distributed rounds) is the same as that of regular message passing.
Note that memory restriction bounds the local computation between reads and writes in the same round and the message size, thus, O(1) local memory generalizes CONGEST with the additional constraint that only polynomial time local computations can be performed between reads and writes. Even though local computations are usually assumed to be negligible compared to the communication, we would like the computation between two consecutive reads and/or writes to be quick: we say that such computations are given by locally compact functions where a locally compact function takes as input the previous read and the node state to produce the next state and message(s) -the function should be quick (constant/polynomial) taking low memory. The function we devise in Section 4 takes only constant internal computation per execution. The subtelty in designing our algorithms is the awareness of the memory constraints -maybe 'distribute' information (e.g. port numbers) to siblings and parents for future use. The overall distributed algorithm coordinates the messages and compact functions.
In effect, this paper only deals with the static setting described above as it only describes the preprocessing phase -the dynamic self-healing setting is handled in [7]. In the following section, we describe the self-healing model for completeness and understanding of the background that follows.

Bounded Memory Deletion only Self-healing Model
The deletion only self-healing model [7,35,55,59] is a model for reconfigurable (e.g. P2P/overlay) networks where an omniscient adversary attacks by removing nodes and the affected nodes distributively respond by adding connections, with the aim of achieving global fault tolerance by local actions. Before the adversary can delete nodes, a pre-processing phase is permitted where nodes can exchange messages with their neighbors and setup data structures as required on the initial graph G 0 .
The adversarial process can be described as deleting some node v t from G t −1 , forming H t . All neighbors of v t are informed of the deletion. In the healing stage nodes of H t communicate (concurrently, asynchronously) with their immediate neighbors and nodes may decide to add edges to other nodes they know about or drop earlier edges forming G t . The objective is to minimise the following "complexity" measures (excluding the preprocessing stage): The maximum number of bits/words. sent by a single node in each recovery phase • Recovery time: The maximum total time for a recovery phase, assuming it takes a message no more than 1 time unit to traverse any edge • Local Memory: The amount of memory a single node needs to run the algorithm.

BACKGROUND: COMPACT SELF-HEALING ROUTING (COMPACTFTZ)
Algorithm CompactFTZ [5,7] is a self-healing (i.e. fault-tolerant) compact routing algorithm based on two algorithms: a Thorup-Zwick tree routing scheme, TZ [58] and the self-healing algorithm ForgivingTree, CompactFT [35]. In this paper, we give deterministic setup (preprocessing) of TZ and CompactFT. Since CompactFTZ directly runs in our low memory model (the routing scheme is compact and CompactFTZ works in the bounded memory selfhealing model tagging every message with port numbers), we get the first fully distributed, deterministic, fault-tolerant and compact memory routing scheme. Before going into the details of CompactFT and TZ, let us give the high level picture that makes CompactFTZ work. To begin with, consider that we have a network in the form of a rooted tree and the compact routing scheme TZ (Section 3.2) setup on it: this will successfully route if there were no failures. What happens if there is an adversarial crash failure of a node? How do we seamlessly route packets which are still in the network or new ones which are later generated? CompactFT (Section 3.1) works by replacing the subgraph of the deleted node (i.e. the star with the deleted node at the centre) by a 'healing' subgraph of virtual nodes simulated by its children. Importantly, this subgraph structure is routable and has its own (compact) routing scheme, say, R. Also, nodes know if they are connected to a healing structure and through which edges. Now, when a packet is traversing through the undamaged part of the network, it is routed by the nodes following the TZ scheme. However, when the TZ scheme pushes the packet towards a healed substructure, the nodes seamlessly switch to the scheme R. In the paper [7], it is shown that not only does R route the packet to the same intermediate node as it would have done with TZ in an undamaged network (with a small additional stretch) but also that there is no need to update the topological information that is gathered in the preprocessing to implement TZ (CompactFT information is purely local and updated in O(1) time with O(1) messages). Of course, the deleted node may itself have been routing packets and it is possible that the adversary deletes destinations or sources of packets still in transit; CompactFTZ can handle these cases and inform the sender of non-delivery and also continue delivery of dropped packets by retaining copies with neighbouring nodes. Now, we give a brief overview of CompactFT and TZ, particularly with reference to their combined preprocessing as done in CompactFTZ (Please refer to Algorithm 3.1). Let us begin with CompactFT and lines 2 and 6 of Algorithm 3.1.

Compact Forgiving Tree
CompactFT is a self-healing algorithm in the bounded memory deletion only self-healing model (Section 2). On a spanning tree T of a network graph G and in face of any series of adversarial deletions, after attack number t, it guarantees that G t is connected, where ∆ is the largest degree of a node in G 0 ; each recovery takes only O(1) parallel rounds with O(1) messages of O(1) size (i.e. in the Congest model). Further, the repair at each node uses only O(1) node IDs and, thus, O(1) words for repair assuming O(1) words are enough to store any node's I D.
CompactFT is an example of algorithm design using virtual structures (ref. [59,60] for a discussion). We will maintainT as a structure with 'virtual' nodes and through a mapping between the virtual forgiving tree T t and the real graph G t at any time t, it will be enough for us to maintain bounds on T t for them to carry over to G t . To begin with, if T is a BFS spanning tree, we know that D(T )/D(G) ≤ 2 and we only need to bound D(T t ) to get the diameter bounds wrt D(G). Following is the basic idea of the algorithm: if a non-leaf node is deleted, replace it with a Reconstruction Tree (RT) having its children as the leaf nodes and virtual nodes simulated by the children as internal node with the invariant that every leaf simulates no more than one internal node. This is illustrated in Figure 1. Over a series of deletions, we maintain this invariant by a clever mechanism of promotion of designated nodes called heirs.
If the RT is a binary tree correctly labeled, we get our degree bound over any series of deletions. If it is also balanced, we also get our diameter stretch. A balanced binary tree is thus sufficient. However, since we want to use CompactFT for routing with a routing scheme R, we make the RT a balanced binary search tree (BBST). Now, our routing scheme R is simply a binary search on the tree which, in fact, uses no routing tables and has zero memory requirement on nodes. In fact, we use a half-full trees (hafts) (introduced in [36,37]) for its special properties. A haft is simply defined as follows ( [37]: Definition 3.1 (Half -full Tree(haft)). A haft is a rooted binary tree where every non-leaf node v satisfies the following properties: (1) v has exactly two children (2) The left child of v heads a complete binary subtree containing at least half of v's descendants.
A complete tree is an example of a haft, so is the tree in figure 2. Definition 4.1 is an alternate definition. Refer to [37] for a detailed exposition.
Healing on a leaf deletion is a bit different: if the deleted node has no virtual duties, it is simply removed otherwise its simulated node is also 'short-circuited' from the graph. Figure 1: Deleted node replaced by its reconstruction tree with virtual internal nodes simulated by real leaf nodes [37] How do we implement the above idea in a distributed network? For this we use the idea of Wills. A will of a node is nothing but its RT -i.e. for node v, will(v) is simply RT (v). The idea is that on the demise/deletion of v, its children will execute will(v) i.e. construct RT (v). Thus, each child could be given a copy of will(v) in advance to enable the fix. However, will(v) could be too large (O(n) size) to be transmitted. However, notice a child only needs the subgraph it is involved in -this is what we call a willportion and is only of O(1) size. This is illustrated in Fig. 2: the haft on the left corresponding to the Will of a node with children a to e and the boxes on the right giving the children's willportions. Once the wills are setup, the major technical challenge is to maintain the wills which is what CompactFTZ does in low memory. It is easy to setup the will in preprocessing with O(n) memory because the node only needs to collect the IDs of its children in its memory to compute RT (v). However, with only O(1) memory, it is a challenging problem. We show how this is done in Section 4

Thorup-Zwick Tree Routing
TZ is a non fault-tolerant compact routing scheme on trees, inspired on simple interval routing. In interval routing (on a rooted tree), DFS labels are used as routing labels and each node, for each of its children, stores an interval indicating the labels in the subtree rooted at that child. Routing is simple: when a node receives a message to a node with (DFS) label x, it checks which interval x belongs to and forwards the message to the corresponding child; if x does not belong to any interval, the message is forwarded to the parent. This simple solution is not compact as a node in the tree can have Ω(n) children. TZ solves this problem by storing the interval of only a constant number of children per node at the cost of increasing size of routing labels to O(log 2 n). To do so, the nodes in a tree are partitioned into two disjoint classes, heavy and light, depending on the number of nodes in the subtree rooted at the node. A good property of this partition is that each node has only a constant number of heavy children. Each node only stores intervals of heavy nodes. With this information interval routing cannot be performed as a node might need to forward a message to a light child. TZ solves this issue by appending this missing information to DFS labels; this is called light path of a node: the sequence of light nodes in the path from the root to the node, which is of length O(log 2 n). The resulting scheme is still simple: first a process checks intervals of heavy nodes and, if there is no success, then checks the light path in the routing label; if both fail then the message is forwarded to its parent.
Steps 3, 4 and 5 of Algorithm 3.1 perform TZ's preprocessing: first heavy and light nodes are identified, then DFS labels are computed and finally interval for heavy nodes and routing labels are computed.
To conclude CompactFTZ's preprocessing, step 6 computes and distributes Wills and Willportions to all processes in one round. As mentioned, the last step of the preprocessing is the main challenge of the whole process.

COMPACTFT PREPROCESSING: COMPUTING WILLPORTIONS IN OPTIMAL TIME
As explained in Section 3.1, the central idea in the fault-tolerant mechanism of CompactFT is that of a node's Will (its RT), which is computed in CompactFT's preprocessing stage (using non-compact memory): each node v gathers all IDs from its children, locally produces its RT (v), and then, to each of its children, sends back part of its Will, called Willportion or subwill, of size O(1). Due to compact local memory, a node v cannot store all its children's IDs, and thus cannot store its whole RT (v). To cope with this problem, in Subsection 4.1 we design a local function using compact memory that works in an uninterpreted version of RT (v) in which each node u in RT (v) is replaced with k if the k-th port number of v connects to u. Thus, v can compute the uninterpreted Willportion of its child in its kth port. To compute the interpreted version of the Willportion, v simply needs to send a message asking for IDs through the port numbers involved in the uninterpreted Willportion, and replace port number with IDs accordingly.
As an example, consider again the RT (v) in Figure 1, and suppose that the first port of v connects to a, the second one to b and so on. Thus, in the uninterpreted RT (v), a is replaced with 1, b with 2 and so on. When v wants to compute the Willportion of one of its child, say the one connected to its 6-th port (corresponding to f ), v queries our local function which returns that the parent of 6-th port is the 4-th port, and its children are the 5-th and 7-th ports (corresponding to the subgraph involving f ′ in RT (v) ), and also the 6-th port as a leaf has parent the 5-th port (corresponding to the leaf e). With this information, v only needs to ask for the IDs of the processors connected to its 4-th, 5-th and 7-th ports, replace the IDs accordingly and send the Willportion to f through its 6-th port in the next round. Using this simple scheme, v can compute and distribute all its Willportions in at most 2∆ rounds. Remarkably, in Section 4.2, we show that, in fact, all Willportions of v can be optimally computed and distributed in a single round.

Computing Half-Full Trees with Compact Memory
Given a power of two, 2 x , consider the full binary tree with 2 x leaves defined recursively as follows. The root of the tree is the string 0, and each node v has left child v 0 and right child v 1. It is easy to see that the nodes at height h are the binary representation of 0, . . . , 2 x −h −1. Letṽ denote the integer represented by the string v. For any node v, its left and right children represent the number 2ṽ and 2ṽ + 1, respectively. Let B(2 x ) denote the previous tree. We now define a function ℓ used in CompactFT that labels the nodes of B(2 x ) in the space [0, 2 x − 1]; ℓ represents the ports in the uninterpreted Will of a node. Of course the labelling is not proper but it has nice properties that will allow us to compute it using low memory. Consider a node v of B(2 x ). Let h v denote the height of v in B(2 x ). Then, we define ℓ as follows: In words, if v is of height 0, its label is simplyṽ, otherwise its label is computed using a base number, 2 h v −1 − 1, plusṽ times an offset, 2 h v . As an illustration, Figure 3 depicts the tree B(2 3 ) and its labelling ℓ.
The root r of B(2 x ) has height h r = x andr = 0, hence, by definition, ℓ(r ) = 2 x −1 − 1. Now, consider any y ∈ [0, 2 x − 1]. Since all leaves are at height 0, there is a unique leaf v with ℓ(v) = y. Suppose that y ≤ 2 x − 2. There exists a unique integer factorization of y + 1 then there exists unique h ≥ 0 and p ≥ 0 such that y + 1 = 2 h (2p + 1). This decomposition can be easily obtained from the binary representation of y + 1. By construction, we have h ≤ log(y + 1) < log(2 x ) = x then h + 1 ≤ x and we have 2p < 2 x −h then p ≤ 2 x −h−1 − 1. Let us consider the unique (non-leaf) node u such thatũ = p and h u = h + 1 ≥ 1. It means that u is the unique node such that ℓ(u) = y. Finally, there is no non-leaf u of B(2 x ) such that ℓ(u) = 2 x − 1 because we just proved that each element of [0, 2 x − 2] has a unique inverse image under ℓ. Since the number of non-leaf node is exactly 2 x − 1 = |[0, 2 x − 2]|, there is no non leaf node u such that ℓ(u) = 2 x − 1. □ By Lemma 4.1, for the labelling ℓ, each y ∈ [0, 2 x − 1] appears one or two times in B(2 x ), on one leaf node and at most on one non-leaf node. Thus, we can use the labelling ℓ to unambiguously refer to the nodes of B(2 x ). Namely, we refer to the leaf v of B(2 x ) with label ℓ(v) = y as leaf y, and, similarly, if y ≤ 2 x − 2, we refer to the non-leaf u of B(2 x ) with label ℓ(u) = y as non-leaf y. By abuse of notation, in what follows B(2 x ) denotes the tree itself and its labelling ℓ as defined above. The following lemma directly follows from the definition of ℓ.   that is a power of two, and hence the uninterpreted RT is precisely B(2 x ). If not, the Will of a node is a half-full tree, defined below. Let B(2 x , a) denote the tree B(2 x ) together with the labelling ℓ ′ (v) = ℓ(v) + a. Clearly, ℓ ′ labels the nodes of B(2 x , a) in the space [a, a + 2 x − 1]. For ease of representation, we use B(2 x ) to represent B(2 x , 0) (i.e. B(2 x ) with labelling ℓ(v)) in the discussion that follows.    12]) and its induced ℓ ′ labelling. The label ℓ ′ plays the role of the ports of a node and, as before, our target is to compute the parts of the half-full tree a given label belongs to. By construction and using Remark 4.3, if y ∈ [a, a + 2 x − 1], there is a unique leaf v in the right subtree of the root such that y = ℓ(v) and for all leaf v ′ outside this the subtree we have ℓ(v ′ ) ∈ [a + 2 x , b]. By induction on the HT construction, if y ∈ [a + 2 x + 1, b], there is a unique leaf v in the left subtree of the root such that y = ℓ(v) and for all leaf v ′ outside this the subtree we have ℓ(v ′ ) ∈ [a, a + 2 x ].
By the inductive construction of the HT ([a, b]), all leaf nodes belongs to one full binary subtree, and all the full binary subtrees cover disjoint intervals. By Remark 4.3, there exists a unique leaf node v such that ℓ(v) = y. □ As with full binary trees, by Lemma 4.4, when considering the labelling ℓ ′ of HT ([a, b]), each y ∈ [a, b] appears one or two times in HT ([a, b]), on one leaf node and at most on one non-leaf node. Thus, those two nodes in the half-full tree can be unambiguously referred as leaf node y and non-leaf node y. The very definition of half-full trees, Definition 4.1, Lemmas 4.2 and 4.4 suggest a natural low memory (sublinear on the size of the interval) recursive function that obtains the parent and children of a node in HT ([a, b]), which is the uninterpreted Willportion of the node. We call this function SearchHT in Algorithm 4.1.

Computing and Distributing Willportions
in One Round.
Suppose that we have a rooted spanning tree T of the original graph Here we present a one-round compact protocol that, for any node v, computes and sends to each child of v in T its corresponding Willportion. Let δ denote the number of children of v in T . The Will of v is the half-full tree HT ([0, δ − 1]), where each label ℓ is replaced with the ID of the ℓ-th child of v in T ; namely, we give an interpretation to the uninterpreted Will HT ([0, δ − 1]). Let RT (v) denote this tree with the IDs at its nodes. Thus each child of v with ID y appears two times in y, one as leaf node and one as a non-leaf node, and the subwill of y in RT (v) is made of the parent of the leaf y and the parent and children of the non-leaf y in RT (v). This is the information that v has to compute and send to y. We can efficiently compute the subwill of a child using a slight adaptation of function SearchHT previously defined.
The representation of T is compact: v only knows its number of children in T and the port of its first children (the ports of its children do not have to be contiguous). Additionally, the ℓ-th child of v has the port number of v, nxt_port, that is connected to the (ℓ + 1)-th child of v. In our solution, shown in Algorithm 4.2, v first indicates to all its children to send its ID and nxt_port so that this data is in the in-buffers of v. Then, with the help of the nxt_port, v can sequentially read and collect the IDs of its children, and in between compute and send will portions. In order to be compact, v has to "forget" the ID of a child as soon as it is not needed anymore for computing the will portion of a child (possibly the same or a different one). For example, if δ = 13, then v uses the half-full tree HT ([0, 12]) in Figure 4, and the label ℓ in HT ([0, 12]) denotes to the ℓ-th child of v in T . After reading and storing the IDs of its first four children (corresponding to 0, 1, 2, 3), v can compute and send the subwill of its first and second children (0 and 1). The leaf 0 in HT ([0, 12]) has parent non-leaf 0 while the non-leaf 0 has parent non-leaf 1 and children leaf 0 and leaf 1. Similarly, the leaf 1 has parent non-leaf 0 while the non-leaf 1 has parent non-leaf 3 and children non-leaf 0 and non-leaf 2. Moreover, at that point v does not need to store anymore the ID of its first child because (leaf or non-leaf) 0 is not part of any other will portion. An invariant of

Algorithm 4.2 Wills
Init : if DFS walk is over : then cur r ent ← f st _p ; k ← 0 if not I s Leader then send <MYI d , myI d , nx t _p, ichild > via par ent _por t Receive <WI LL, p, p h , c l , c r , bool > from X : nx tpar ent ← p ; nx t hpar ent ← ph nx t child l ← c l ; nx t child r ← c r heir ← bool Terminate Receive< MYI d ,z,nx t Por t , _ > from cur r ent : ) cur r ent ← nx t Por t ; k ++ our algorithm is that, at any time, v stores at most four IDs of its children. The rules appear in Algorithm 4.2. The algorithm uses function SubWill in Algorithm 4.1, which computes the subwill of a child node. Theorem 4.6. Algorithm 4.2 correctly computes all the subwills and sends all of them in 1 round. Moreover, at any time, the memory contains at most 5 log δ IDs (node or port) and subwills.
Proof. By construction, all the children form a chain starting with f st_p and going on via the pointers nxt_p. If those are correct, all the in-buffers corresponding to children are read during this one round. Thus k goes from 0 to δ − 1 and current from f st_p to the last one through every port. This means that for every k, at some point Node[k] and W ill[k] are filled. For each k, W ill[k] is freed only after use and Node[k] only after 4 uses. No Node[k] need more than 4 uses. Let 0 ≤ k < δ . Let k 0 ≤ k 1 ≤ k 2 ≤ k 3 the nodes used in W ill [k]. Eventually Node[k 3 ] will be filled. At this point Node[k i ] is filled for i = 0, 1, 2, 3 and none of them were freed, since there were still at least one missing use. The subwill can be correctly sent to the k t h child. In conclusion, each child's port is read and each subwill is correctly computed and sent in one round. Now, we define the uncompleted edges as the edges (u, v) such that u is already registered in Node and v is not. For each of those edges we have to remember informations about u (its id, its port id, its subwill with the ids of corresponding nodes (except v, then at most 3 nodes id)). The size of this information is at most 5 Ids of size O(log n). If u is linked to the k t h 0 port and v to the k t h 1 port, then we have k 0 ≤ k < k 1 . By construction, For any value of h, there can be only one such edge (this edge being between the port number 2 h+1 ⌊ k −2 h−1 2 h+1 ⌋ − 2 h−1 − 1 and a port whose number is smaller or equal to 2 h+1 ⌊ k −2 h−1 2 h+1 ⌋ + 3.2 h−1 − 1). Thus there are at most log n such edges. At any moment the total amount of used memory is O(log 2 n) bits. □

THORUP-ZWICK TREE ROUTING PREPROCESSING WITH BASIC TREE TRAVERSALS
We discuss here simple implementations of the following which are used in CompactFTZ preprocessing (Algorithm 3.1 lines 1 -5): i) BFS spanning tree construction, ii) Convergecast, iii) DFS traversal, tree construction and renaming. These can, of course, be vital subroutines for a number of distributed algorithms. As mentioned, the subtelty in designing these algorithms is to be aware of memory constraints and maybe 'distribute' information (e.g. port numbers) to siblings and parents for future use. Hence, sometimes messages also carry port numbers. However, before we go further, remember that CompactFTZ assumes a rooted tree. We can either assume a leader to construct one or we can do leader election as shown in the next section:

Leader Election
We can implement flooding to elect a leader using the flooding based algorithm of Peleg [51]. Flooding a message to every neighbour from a node is fairly straightforward to implement in our low memory model. Consider flooding from a single source(s), say with a message M. The source writes M to all its ports which are received in the corresponding ports of its neighbours in the next round. The following then gets executed: CLS Flooding at a node v: Node v sweeps its ports executing all its reads first. If v gets M, it executes writes to all its ports in order copying M to them.
We can adapt e.g. the simple flooding algorithm of Peleg [51] where D stands for diameter of the graph and each node has a unique I D: Peleg's Leader Election Algorithm [51]: Nodes wake up simultaneously or spontaneously (i.e. not woken up by a message). In each round, nodes flood the highest ID seen so far and an estimate d of the diameter (initially d is 1 at every node). If a node sees a higher ID, it drops out as a candidate otherwise it updates d to the highest d seen. If a surviving candidate does not see a higher d for 3 consecutive rounds, this signals termination and that candidate as the winner.
All that is needed is a compact function (let's call it Max()) that stores the maximum value read (for both node IDs and d) as it sweeps through the ports. The nodes only store a constant number of IDs and a counter (of value at most n), therefore they only use O(1) storage. In every round, every edge is used twice, therefore, the following follows: A simultaneously efficient deterministic LE algorithm (O(D log n) time, O(m log n) messages) can be derived from the CONGEST Algorithm 2 of [43]. Though we don't go into details, using efficient low memory Breadth First Search (BFS) tree construction and convergecast, which we show in Sections 5.2 and 5.3, this can be derived in a straightforward manner.

Breadth First Search (BFS) spanning tree construction
A BFS tree can be constructed by a simple flooding process with a node only storing a pointer to its parent but not to its children. Not having children information would make traversals suboptimal, therefore, this information can be 'distributed' through a sibling chain where the l-th child of parent p stores, in local variable nxt_p, the port number in p of p's (l + 1)-st child. This compact representation of the tree will allow us to be round optimal later. Note that p may have much fewer children in the tree than its degree (O(∆), where ∆ is max degree).
Theorem 5.2. Our algorithm constructs a BFS tree in O(D) rounds using O(m) messages.

Convergecast (with heaviness computation)
A convergecast on a rooted tree (as previously constructed) can be done by broadcasting top-down and converging parent pointers bottom-up. This can be adapted to TZ weight computation: weight wt(v) of a node v is the size of the subtree it heads including itself. For a given constant b ≥ 2 and parent p, v is heavy if wt(v) ≥ wt (p) b , else v is light. Thus, besides aggregating wt(v), v needs wt(p). The heavy children inform their parent that stores their ID and port in lists H and P (of size O(log n)). The problem is p's subtree could have branches of different heights and thus p could receive children's weights in different rounds. When wt(p) is computed, p may have lost information about v's port. Thus, p could either broadcast (including to non-children neighbours) or v continuously sends its weights in every round leading to two possible variants.

Depth First Walk And Node Relabelling
In TZ, nodes are relabelled to their DFS number on the spanning tree with heavy nodes prioritised, which are computed using a DFS walk. After its DFS exploration, a node sends back its local variable nxt_p, informing its parent about the next port it should try. A simple DFS exploration on the tree will take O(n) rounds and O(n) messages.
However, we can do much better by executing DFS walks in parallel. Notice that during the previous algorithms, each node knows the size of the subtree it heads and so does the root. If there was enough memory, each node can execute a DFS on its own subtree and store the intervals. These would be local DFS numbers however. The root is the only one with the correct global number at the moment -it can now send to each of its children the correct offset (0 for its first child, size of the first child's interval to the second child and so on). This can be done in a top-down fashion at each node with each node adding the correct offset to get its DFS number. However, we can do this in low memory too as follows: each node, in every round, keeps sending its subtree size to its parent. Consider the root -the root sweeps through its input in order (each node has stored in H and P its highest priority traversal children and the rest are in port order) adding the size to the offset and converying it to the next node in order and so on. Root's chilldren receiving the offsets do the same and so on till all nodes achieve the correct global number. Remember that in the TZ scheme, these are the new labels (ID) of a node. [24] describe a similar algorithm.
Theorem 5.4. The relabeling of the nodes using a parallel DFS walk can be performed in O(D) rounds, using O(n) messages overall.

Computing Routing Labels.
We now have enough information ( a BFS spanning tree, node weights, DFS labels) to produce routing labels in TZ, and hence, to complete the preprocessing. For a node v, its light path is the sequence of port numbers for light nodes in the path from the root to v. The routing label of v in TZ is the pair (N ewI D, LiдhtPath), where N ewID is its DFS label and LiдhtPath its light path. The second routing label entry for the root is empty.
A simple variant of the BFS tree construction algorithm computes the routing labels if O(log n) sized messages are permitted. The root begins by sending its path(empty) to each port X along with the port number X . When a node receives a message < RL, path, X > from its parent, it sets its light path to path•X , if it is light, otherwise to path only, producing its routing label. Then, for each port Y , it sends its light path together with the port number Y .

RELATED WORK AND CONCLUSIONS
Our companion paper [6] discusses extensions of the low memory model in detail and provides deterministic CompactFTZ preprocessing in those. Independently, Elkin and Neiman [24] gave randomised low memory preprocessing for general Thorup-Zwick routing schemes with near-optimal complexity with low memory usage at nodes. Towards developing the general scheme, they also devised the preprocessing for Thorup-Zwick tree routing which are similar to ours. Though their overall algorithms are randomised, their tree routing preprocessing can be seen to be deterministic matching ours. However, our algorithm, as mentioned, also handles the preprocessing of the self-healing CompactFTZ and is wholly deterministic. We also state the low memory model more formally in the process.
Earlier works have looked at various memory settings in distributed networks. In the network finite state machine model [26], weak computational devices with constant local memory communicate in an asynchronous network. Any node only broadcasts symbols from a constant size alphabet and each time it reads its ports (all of them) can only distinguish up to a constant number of occurrences. They show probabilisitic solutions to MST and 3-coloring of trees in this model. In the beeping model of communication [14], nodes execute synchronous rounds. Every round, a node either "beeps" and sends or stays silent and listens. A listening node obtains a single bit encoding if one or more of its neighbours beeped. [34] have shown that there are probabilistic solutions to the leader election problem in this model for complete graphs where each node is a state machine with constant number of states. These solutions imply compact probabilistic solution in low memory models. [18] study the difference between broadcast and unicast, showing that the unicast model is strictly more powerful. [4] study the general case of nodes restricted to sending some number of distinct messages in a round. Finally. dynamic network topology and fault tolerance are core concerns of distributed computing [2,47] and various models (e.g. [41]) and topology maintenance [42] and self-* algorithms abound especially for self-stabilisation [15,16,28,39] and self-stabilising spanning trees and traversals [11,44,45].
To conclude, in this work, we gave the first fully distributed compact self-healing routing algorithm that can be wholly constructed and executed even if the nodes have only O(log n) memory. There are a number of directions to be explored yet. Fault-tolerant routing has not been well explored; this can be explored with respect to a number of different failure models. Though efficient randomised compact routing for general topologies seem to have been now settled [24], deterministic schemes in low memory still need to be fleshed out. Lastly, algorithms for other important problems (besides compact routing) need to be designed in the low memory settings.