<?xml-model href='http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng' schematypens='http://relaxng.org/ns/structure/1.0'?><TEI xmlns="http://www.tei-c.org/ns/1.0">
	<teiHeader>
		<fileDesc>
			<titleStmt><title level='a'>Parallel Algorithms for Hierarchical Nucleus Decomposition</title></titleStmt>
			<publicationStmt>
				<publisher>ACM</publisher>
				<date>03/12/2024</date>
			</publicationStmt>
			<sourceDesc>
				<bibl> 
					<idno type="par_id">10526829</idno>
					<idno type="doi">10.1145/3639287</idno>
					<title level='j'>Proceedings of the ACM on Management of Data</title>
<idno>2836-6573</idno>
<biblScope unit="volume">2</biblScope>
<biblScope unit="issue">1</biblScope>					

					<author>Jessica Shi</author><author>Laxman Dhulipala</author><author>Julian Shun</author>
				</bibl>
			</sourceDesc>
		</fileDesc>
		<profileDesc>
			<abstract><ab><![CDATA[Nucleus decompositions have been shown to be a useful tool for finding dense subgraphs. The coreness value of a clique represents its density based on the number of other cliques it is adjacent to. One useful output of nucleus decomposition is to generate a hierarchy among dense subgraphs at different resolutions. However, existing parallel algorithms for nucleus decomposition do not generate this hierarchy, and only compute the coreness values. This paper presents a scalable parallel algorithm for hierarchy construction, with practical optimizations, such as interleaving the coreness computation with hierarchy construction and using a concurrent union-find data structure in an innovative way to generate the hierarchy. We also introduce a parallel approximation algorithm for nucleus decomposition, which achieves much lower span in theory and better performance in practice. We prove strong theoretical bounds on the work and span (parallel time) of our algorithms.</p> <p>On a 30-core machine with two-way hyper-threading, our parallel hierarchy construction algorithm achieves up to a 58.84x speedup over the state-of-the-art sequential hierarchy construction algorithm by Sariyuce et al. and up to a 30.96x self-relative parallel speedup. On the same machine, our approximation algorithm achieves a 3.3x speedup over our exact algorithm, while generating coreness estimates with a multiplicative error of 1.33x on average.]]></ab></abstract>
		</profileDesc>
	</teiHeader>
	<text><body xmlns="http://www.tei-c.org/ns/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink">
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="1">Introduction</head><p>Dense subgraph and substructure detection is a fundamental tool in graph mining, with many applications in areas including social network analysis <ref type="bibr">[13,</ref><ref type="bibr">61]</ref>, fraud detection <ref type="bibr">[24]</ref>, and computational biology <ref type="bibr">[3,</ref><ref type="bibr">21]</ref>. Sariy&#252;ce et al. <ref type="bibr">[52]</ref> introduced the nucleus decomposition problem, a generalization of the &#119896;-core <ref type="bibr">[45,</ref><ref type="bibr">53]</ref> and &#119896;-truss <ref type="bibr">[12]</ref> problems which better captures higher-order structures in graphs. In this problem, a &#119888;-(&#119903;, &#119904;) nucleus is defined to be the maximal induced subgraph such that every &#119903; -clique in the subgraph is contained in at least &#119888; &#119904;-cliques. The goal of the (&#119903;, &#119904;) nucleus decomposition problem is to (1) identify for each &#119903; -clique in the graph, the largest &#119888; such that it is in a &#119888;-(&#119903;, &#119904;) nucleus (known as the coreness value) and (2) generate a nucleus hierarchy over the nuclei, where for &#119888; &#8242; &lt; &#119888; a &#119888; &#8242; -(&#119903;, &#119904;) nucleus &#119860; is a descendant of a &#119888;-(&#119903;, &#119904;) nucleus &#119861; if &#119860; is a subgraph of &#119861;. Figure <ref type="figure">1</ref> shows the hierarchy for (1, 3) nucleus. The nucleus hierarchy is an unsupervised method for revealing dense substructures at different resolutions in the graph. Since the hierarchy is a tree, it is easy to visualize and explore as part of structural graph analysis tasks <ref type="bibr">[49]</ref>.</p><p>Sariy&#252;ce and Pinar present the first algorithm for solving the nucleus decomposition problem <ref type="bibr">[49]</ref>. However, their algorithm is sequential, and in order to scale to the large graph sizes of today, it is important to design parallel algorithms that take advantage of modern parallel hardware. The existing parallel algorithms for nucleus decomposition include those by Sariy&#252;ce et al. <ref type="bibr">[51]</ref> and by Shi et al. <ref type="bibr">[55]</ref>, but these algorithms only compute the coreness values. Importantly, they do not generate the hierarchy, which limits their applicability and which is non-trivial to generate in parallel. In this paper, we design the first work-efficient parallel algorithm for hierarchy construction in nucleus decomposition, where the work, or the total number of operations, matches the best sequential time complexity. Our algorithm runs in &#119874; (&#119898;&#120572; &#119904; -2 ) expected work and &#119874; (&#119896; log &#119899; + &#120588; (&#119903;,&#119904; ) (&#119866;) log &#119899; + log 2 &#119899;) span w.h.p. (parallel time), where &#120572; is the arboricity of the input graph &#119866;, &#120588; (&#119903;,&#119904; ) (&#119866;) is the (&#119903;, &#119904;) peeling complexity of &#119866;, and &#119896; is the maximum (&#119903;, &#119904;)-clique core number in &#119866;. The key to our theoretical efficiency is our careful construction of subgraphs representing the &#119904;-clique-connectivity of &#119903; -cliques, that allows us to exploit linear-work graph connectivity instead of more expensive union-finds as used in prior work. Our approach gives as a byproduct the most theoreticallyefficient serial algorithm for computing the hierarchy, improving upon the previous best known serial bounds by Sariy&#252;ce and Pinar <ref type="bibr">[49]</ref>.</p><p>We also present a practical parallel algorithm that interleaves the hierarchy construction with the computation of the coreness values. Prior work by Sariy&#252;ce and Pinar <ref type="bibr">[49]</ref> also includes a (serial) interleaved hierarchy algorithm. However, their algorithm requires storing all adjacent &#119903; -cliques with different coreness values, which could potentially be proportional to the number of &#119904;-cliques in &#119866; (i.e., use &#119874; (&#119898;&#120572; &#119904; -2 ) space), and which results in sequential dependencies in their post-processing step to construct the hierarchy. Our parallel algorithm fully interleaves the hierarchy construction with the coreness computation, and uses only two additional arrays of size proportional to the number of &#119903; -cliques in &#119866;. Our algorithm uses a concurrent union-find data structure in an innovative way. Also, our post-processing step to construct the hierarchy tree is fully parallel. Our main insight is a technique to fully extract the connectivity information from adjacent &#119903; -cliques with different core numbers while computing the coreness values.</p><p>Note that the span of the above algorithms can be large for graphs with large peeling complexity (&#120588; (&#119903;,&#119904; ) (&#119866;)). We introduce an approximate algorithm for nucleus decomposition and show that it can achieve work efficiency and polylogarithmic span. Our algorithm relaxes the peeling order by allowing all &#119903; -cliques within a ( &#119904; &#119903; + &#120598;) factor of the current value of &#119896; to be peeled in parallel. We show that our algorithm generates coreness estimates that are an ( &#119904; &#119903; + &#120598;)-approximation of the true coreness values.</p><p>We experimentally study our parallel algorithms on real-world graphs using different (&#119903;, &#119904;) values, for up to &#119903; &lt; &#119904; &#8804; 7. On a 30-core machine with two-way hyper-threading, our exact algorithm which generates both the coreness numbers and the hierarchy achieves up to a 30.96x self-relative parallel speedup, and a 3.76-58.84x speedup over the state-of-the-art sequential algorithm by Sariy&#252;ce and Pinar <ref type="bibr">[49]</ref>. In addition, we show that on the same machine our approximate algorithm is up to 3.3x faster than our exact algorithm for computing coreness values, while generating coreness estimates with a multiplicative error of 1-2.92x (with a median error of 1.33x). Our algorithms are able to compute the (&#119903;, &#119904;) nucleus decomposition hierarchy for &#119903; &gt; 3 and &#119904; &gt; 4 on graphs with over a hundred million edges for the first time.</p><p>We summarize our contributions below: &#8226; The first exact and approximate parallel algorithms for nucleus decomposition that generates the hierarchy with strong theoretical bounds on the work, span, and approximation guarantees. &#8226; A number of practical optimizations that lead to fast implementations of our algorithms. &#8226; Experiments showing that our new exact algorithm achieves 3.7-58.8x speedups over state of the art on a 30-core machine with two-way hyper-threading. &#8226; Experiments showing that our new approximate algorithm achieves up to 3.3x speedups over our exact algorithm, while generating coreness estimates with a multiplicative error of 1-2.9x (with a median error of 1.3x).</p><p>Our code is publicly available at <ref type="url">https://github.com/jeshi96/arb-nucleus-hierarchy</ref>.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2">Related Work</head><p>The &#119896;-core <ref type="bibr">[45,</ref><ref type="bibr">53]</ref> and &#119896;-truss problems <ref type="bibr">[12,</ref><ref type="bibr">65,</ref><ref type="bibr">68]</ref> are classic problems relating to dense substructures in graphs. Many algorithms have been developed for &#119896;-cores and &#119896;-trusses in the static <ref type="bibr">[5, 8, 9, 14, 16, 17, 20, 23, 33-35, 42, 46, 58, 62, 64, 69]</ref> and dynamic <ref type="bibr">[1, 2, 26-28, 32, 38, 39, 41, 43, 44, 48, 59, 64, 66, 67]</ref> settings. Similar ideas have been studied in bipartite graphs <ref type="bibr">[29,</ref><ref type="bibr">36,</ref><ref type="bibr">40,</ref><ref type="bibr">50,</ref><ref type="bibr">57,</ref><ref type="bibr">63]</ref>.</p><p>A related problem is the &#119896;-clique densest subgraph problem <ref type="bibr">[60]</ref>, which defines the density of subgraphs based on the number of &#119896;-cliques in it, rather than the number of edges. Fang et al. <ref type="bibr">[19]</ref> further generalize this notion to arbitrary fixed-sized subgraphs (although they only present experiments for cliques). Similar to &#119896;-core and &#119896;-truss, algorithms for approximating the &#119896;-clique densest subgraph are based on iteratively peeling (removing) elements from the graph. Shi et al. <ref type="bibr">[54]</ref> present efficient parallel algorithms for solving the &#119896;-clique densest subgraph problem.</p><p>Sariy&#252;ce et al. define the (&#119903;, &#119904;) nucleus decomposition problem and show that it can be used to find higher quality dense substructures in graphs that previous approaches. They provide efficient sequential <ref type="bibr">[49,</ref><ref type="bibr">52]</ref> and parallel algorithms <ref type="bibr">[51]</ref> for this problem. Sariy&#252;ce et al. <ref type="bibr">[51]</ref> present two parallel algorithms for the nucleus decomposition problem: (1) a global peeling-based algorithm and (2) a local update model that iterates until convergence. They also introduce a sequential algorithm for constructing the nucleus decomposition hierarchy <ref type="bibr">[49]</ref>, but as far as we know there are no parallel algorithms for constructing this hierarchy. Their algorithm is not work-efficient as it uses union-find. We also note that their space-usage can in theory be as large as &#119874; (&#119899;&#120572; &#119904; -2 ), i.e., proportional to the number of &#119904;-cliques in the graph. Chu et al. <ref type="bibr">[11]</ref> present a parallel algorithm for generating the &#119896;-core decomposition hierarchy, which is a special case of nucleus decomposition for &#119903; = 1 and &#119904; = 2, but their algorithm does not trivially generalize to higher &#119903; and &#119904;. Their serial and parallel algorithms both use union-find and run in &#119874; (&#119898;&#120572; (&#119899;)) work (where &#120572; (&#119899;) is the inverse Ackermann function), which is not work-efficient, and their parallel algorithm has depth that depends on the peeling-complexity of the input. Shi et al. <ref type="bibr">[55]</ref> present an improved parallel algorithm for nucleus decomposition, with good theoretical guarantees and practical performance, but it does not generate the hierarchy. Their algorithm is work-efficient, in that it runs in work proportional to enumerating all &#119904;-cliques, i.e., &#119874; (&#119898;&#120572; &#119904; -2 ) work. They leverage a work-efficient parallel clique counting algorithm <ref type="bibr">[54]</ref>, along with a multi-level hash table structure to store data associated with cliques space efficiently, and techniques for traversing this structure in a cache-friendly manner. More recently, Sariy&#252;ce generalizes the &#119903; -cliques and &#119904;-cliques in nucleus decomposition to any pair of subgraphs <ref type="bibr">[47]</ref>. There has also been work on nucleus decomposition in probabilistic graphs <ref type="bibr">[18]</ref>.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3">Preliminaries</head><p>Model of Computation. We use the work-span model of computation for our theoretical analysis, which is a standard model for shared-memory parallel algorithms <ref type="bibr">[15,</ref><ref type="bibr">30]</ref>. The work W of an algorithm is the total number of operations, and the span (parallel time) S of an algorithm is the longest dependency path. Using a randomized work-stealing scheduler <ref type="bibr">[7]</ref> on P processors, we can obtain a running time of W/P + &#119874; (S) in expectation. Our goal is to develop work-efficient parallel algorithms under this model, or algorithms with a work complexity that asymptotically matches the best-known sequential time complexity for the given problem. Graph Notation and Definitions. We consider simple and undirected graphs &#119866; = (&#119881; , &#119864;). We let &#119899; = |&#119881; | and &#119898; = |&#119864;|. For analysis, we assume &#119898; = &#937;(&#119899;). The arboricity (&#120630; ) of a graph is the minimum number of spanning forests needed to cover the graph. &#120572; is upper bounded by &#119874; ( &#8730; &#119898;) and lower bounded by &#937;(1) <ref type="bibr">[10]</ref>. An &#119896;-clique is a set of vertices such that all &#119896; 2 edges exist among them. Enumerating &#119896;-cliques can be done in &#119874; (&#119898;&#120572; &#119896; -2 ) work and &#119874; (log 2 &#119899;) span with high probability (w.h.p.) <ref type="bibr">[54]</ref>. <ref type="foot">1</ref>A &#119888;-(&#119903;, &#119904;) nucleus is a maximal subgraph &#119867; of an undirected graph formed by the union of &#119904;-cliques &#119878;, such that each &#119903; -clique &#119877; in &#119867; has induced &#119904;-clique degree at least &#119888; (i.e., each &#119903; -clique is contained within at least &#119888; induced &#119904;-cliques). The goal of the (&#119903;, &#119904;) nucleus decomposition problem is to compute the following: (1) the (&#119903;, &#119904;)-clique core number of each &#119903; -clique &#119877;, or the maximum &#119888; such that &#119877; is contained within a &#119888;-(&#119903;, &#119904;) nucleus and (2) a hierarchy over the nuclei, where for</p><p>In this paper, similar to all prior work on nucleus computations, we take &#119903; and &#119904; to be constants and ignore constants depending on these values in our bounds. The &#119896;-core and &#119896;-truss problems correspond to the &#119896;-(1, 2) and &#119896;-(2, 3) nucleus, respectively. Figure <ref type="figure">1</ref> shows the hierarchy for (1, 3) nucleus. We call two &#119903; -cliques &#119904;-clique-adjacent if there exists an &#119904;-clique &#119878; such that both &#119903; -cliques are subgraphs of &#119878;. We also define the &#119904;-clique-degree of a &#119903; -clique &#119877; to be the number of &#119904;-cliques that &#119877; is contained within.</p><p>We also consider approximate nucleus decompositions in this paper. If the true (&#119903;, &#119904;)-clique core number of an &#119903; -clique &#119877; is &#119896; &#119877; , then a &#120574;-approximate (&#119903;, &#119904;)-clique core number of &#119877; is a value that is at least &#119896; &#119877; and at most &#120574;&#119896; &#119877; , where &#120574; &gt; 1.</p><p>An &#119886;-orientation of an undirected graph is a total ordering on the vertices such that when edges in the graph are directed from vertices lower in the ordering to vertices higher in the ordering, the out-degree of each vertex is bounded by &#119886;. Shi et al. and Besta et al. <ref type="bibr">[4]</ref> provide parallel workefficient algorithms for computing an &#119874; (&#120572;)-orientation, which take &#119874; (&#119898;) work and &#119874; (log 2 &#119899;) span.</p><p>A connected component in an undirected graph is a maximal subgraph such that all vertices in the subgraph are reachable from one another. Computing the connected components in a graph can be done in &#119874; (&#119898;) work and &#119874; (log &#119899;) span w.h.p. <ref type="bibr">[22]</ref>.</p><p>A union-find data structure is used to represent collections of sets and supports the following two operations: unite(&#119909;,&#119910;) joins the sets that contain &#119909; and &#119910; and find(&#119909;) returns the identifier of the set containing &#119909;. Trees are used to implement union-find data structures, where elements have a parent pointer, and the root of a tree corresponds to the representative of the set. Path compression can be done during unite and find operations to shortcut the pointers of elements traversed to point to the root of the set. We use the concurrent union-find data structure by Jayanti et al. <ref type="bibr">[31]</ref>.</p><p>We use the notation [&#119899;] to refer to the range of integers [1, . . . , &#119899;].</p><p>Parallel Primitives. We use the following parallel primitives in our algorithms. We use parallel hash tables, which support &#119899; insertion, deletion, and membership queries, in &#119874; (&#119899;) work and &#119874; (log &#119899;) span w.h.p. <ref type="bibr">[25]</ref>. List ranking takes a linked list as input and returns the distance of each element to the end of the linked list. For a linked list of &#119899; elements, list ranking can be solved in &#119874; (&#119899;) work and &#119874; (log &#119899;) span <ref type="bibr">[30]</ref>. In our algorithms, we use list ranking to compute a unique identifier for each element in a linked list so that we can write them to an array in parallel.</p><p>Compare-and-swap(&#119909;, &#119900;&#119897;&#119889;, &#119899;&#119890;&#119908;) attempts to atomically write the value &#119899;&#119890;&#119908; into memory location &#119909; if &#119909; current stores the value &#119900;&#119897;&#119889;; it returns true if the write succeeds and false otherwise (meaning the value of &#119909; was changed by another thread after it was read into &#119900;&#119897;&#119889;). We assume compare-and-swaps take &#119874; (1) work and span.</p><p>A parallel bucketing structure maintains a mapping from identifiers to buckets, which we use to group &#119903; -cliques according to their incident &#119904;-clique counts <ref type="bibr">[16]</ref>. The buckets can change, and the structure can efficiently update these buckets. We take identifiers to be values associated with &#119903; -cliques, and use the structure to repeatedly extract all &#119903; -cliques in the minimum bucket, which can cause the buckets of other &#119903; -cliques to change (other &#119903; -cliques sharing vertices with extracted &#119903; -cliques in our algorithm).</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4">Overview of Contributions</head><p>We present several novel algorithms for efficient parallel hierarchy construction for (&#119903;, &#119904;) nucleus decomposition. The prior state-of-the-art work on parallel (&#119903;, &#119904;) nucleus decomposition, arbnucleus <ref type="bibr">[55]</ref>, only computes the (&#119903;, &#119904;)-clique core numbers and does not construct the hierarchy, which is non-trivial to accomplish. We first present in Section 5 a new theoretically efficient parallel hierarchy construction algorithm, arb-nucleus-hierarchy, that given the (&#119903;, &#119904;)-clique core numbers from <ref type="bibr">[55]</ref>, constructs the full hierarchy. In this two-phase algorithm, the hierarchy construction is entirely separate from the computation of the core numbers. The main innovation is a clever technique to store subgraphs corresponding to each (&#119903;, &#119904;)-clique core, such that the each subgraph only needs to be materialized when processing the corresponding level in the hierarchy tree. This limits the number of times we must iterate over each &#119903; -clique, and allows us to use a linear-work connectivity subroutine, giving us our theoretically efficient bounds.</p><p>We also present in Section 6 a new parallel approximation algorithm, approx-arb-nucleus, that computes approximate (&#119903;, &#119904;)-clique core numbers in polylogarithmic span without increasing the work. Notably, our parallel approximation algorithm is the first to achieve the dual guarantees of work-efficiency and polylogarithmic span. We then combine approx-arb-nucleus with our theoretically efficient hierarchy construction subroutine, to form an approximate hierarchy algorithm, arb-approx-nucleus-hierarchy.</p><p>We observe that it is often not practically efficient to conduct a two-phase hierarchy algorithm (separating the hierarchy construction from the computation of the core numbers), and it is instead faster to construct the hierarchy directly while computing the core numbers. However, this presents a new series of challenges, where core numbers obtained later in the algorithm given by <ref type="bibr">[55]</ref> may affect all levels of the hierarchy tree, causing significant global changes in the tree structure as core numbers are computed. We present practical solutions in Section 7 limiting the cascading effects of these changes by compactly storing the tree using two simple data structures, a union-find structure and a hash table, and grouping &#119903; -cliques on-the-fly to reduce the propagating changes. We then introduce an efficient parallel post-processing step, to explicitly construct the final hierarchy tree from the two data structures.</p><p>Finally, we implement all of our algorithms, and present a comprehensive experimental evaluation in Section 8.</p><p>Algorithm 1 Parallel (&#119903;, &#119904;) nucleus hierarchy algorithm 1: Initialize &#119903; , &#119904; &#8882; &#119903; and &#119904; for (&#119903;, &#119904; ) nucleus decomposition 2: procedure arb-nucleus-hierarchy(&#119866; = (&#119881; , &#119864; )) 3: &#119873; &#119863; &#8592; arb-nucleus(&#119866;) &#8882; Compute the nucleus core numbers, where &#119873; &#119863; maps &#119903; -cliques to their core numbers 4: &#119896; &#8592; maximum core number in &#119873; &#119863; 5: For each &#119894; &#8712; [&#119896; ], let &#119871; &#119894; denote a hash table, where the keys are &#119903; -cliques and the values are linked lists 6: parfor all &#119904;-cliques &#119878; in &#119866; do 7: parfor all pairs of &#119903; -cliques &#119877;, &#119877; &#8242; in &#119878; where &#119873; &#119863; [&#119877; &#8242; ] &#8804; &#119873; &#119863; [&#119877; ] do 8: Add &#119877; &#8242; to the linked list keyed by &#119877; in &#119871; &#119873; &#119863; [&#119877; &#8242; ] 9: Initialize the hierarchy tree &#119879; with leaves corresponding to each &#119903; -clique 10: For each &#119894; &#8712; [&#119896; ], let &#119868; &#119863; &#119894; denote a hash table, where the keys are &#119903; -cliques and the values are &#119903; -cliques 11:</p><p>Initialize each &#119868; &#119863; &#119894; to contain each key in &#119871; &#119894; , mapped to itself 12:</p><p>for &#119894; &#8712; {&#119896;, &#119896; -1, . . . , 1} do 13:</p><p>Relabel each &#119903; -clique in each linked list in &#119871; &#119894; with its corresponding value in &#119868; &#119863; &#119894; 14:</p><p>Apply parallel list ranking to transform the linked lists in &#119871; &#119894; into arrays, which forms a graph &#119867; (where the edges are given by each key paired with each element in its corresponding linked list) 15:</p><p>Run parallel linear-work connectivity on &#119867; 16:</p><p>parfor</p><p>Construct a new parent in &#119879; for all of the nodes corresponding to each &#119877; &#8467; (for &#8467; &#8712; [&#119888; ]), and represent the parent as the &#119903; -clique &#119877; 1 18:</p><p>parfor each &#119895; &lt; &#119894; do 19:</p><p>Concatenate in parallel the linked lists corresponding to all &#119877; &#8467; (for &#8467; &#8712; [&#119888; ]) in &#119871; &#119895; , as the updated value for the key &#119877; 1 in &#119871; &#119895; 20:</p><p>For each &#119877; &#8467; (for &#8467; &#8712; [&#119888; ]), update the value of &#119877; &#8467; in &#119868; &#119863; &#119895; to be &#119877; 1</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head>21:</head><p>return &#119879; Fig. <ref type="figure">2</ref>. An example of the &#119871; &#119894; data structures maintained by arb-nucleus-hierarchy while computing the (1, 3)-nucleus hierarchy on the graph in Figure <ref type="figure">1</ref>. For each round &#119894; of the hierarchy construction, the connected components of &#119867; and the &#119868;&#119863; &#119894; table used to construct &#119867; is shown (except &#119868;&#119863; 4 , which maps every &#119903; -clique to itself).</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="5">Nucleus Decomposition Hierarchy</head><p>We now describe our theoretically efficient parallel nucleus decomposition hierarchy algorithm, arb-nucleus-hierarchy. arb-nucleus-hierarchy computes the hierarchy by first running an efficient parallel nucleus decomposition algorithm, arb-nucleus <ref type="bibr">[55]</ref>, in order to obtain the (&#119903;, &#119904;)clique core numbers corresponding to each &#119903; -clique. It then constructs a data structure consisting of &#119896; levels, where &#119896; is the maximum (&#119903;, &#119904;)-clique core number. Each level is represented by a hash table mapping sets of &#119903; -cliques to a linked list of &#119903; -cliques, which is used to efficiently store &#119904;-clique-adjacent &#119903; -cliques. arb-nucleus-hierarchy proceeds in levels through this data structure to construct the hierarchy tree from the bottom up, by performing linear-work connectivity on each level and updating the connectivity information in prior levels as a result.</p><p>Parallel Algorithms for Hierarchical Nucleus Decomposition 32:7 Fig. <ref type="figure">3</ref>. An example of the intermediate hierarchy trees &#119879; after each round &#119894; in arb-nucleus-hierarchy, while computing the (1, 3)-nucleus hierarchy on the graph in Figure <ref type="figure">1</ref>.</p><p>Our Algorithm. We now provide a more detailed description of our algorithm. The pseudocode is in Algorithm 1. Note that we have highlighted in blue the parts that derive directly from prior work; the remaining pseudocode is novel to this paper. We refer to the example of (1, 3)-nucleus decomposition in Figure <ref type="figure">1</ref>. For simplicity, we have omitted labeling some of the vertices in the graph, and do not include them in our discussion. The number in front of each vertex label is its core number. arb-nucleus-hierarchy first calls arb-nucleus on Line 3, to compute the (&#119903;, &#119904;)-clique core numbers of each &#119903; -clique. Note that this is the only instance where arb-nucleus-hierarchy uses a subroutine from the prior work <ref type="bibr">[55]</ref>, and the rest of the pseudocode is novel. It stores these values in a hash table, &#119873; &#119863;, keyed by the &#119903; -cliques. Then, it constructs a data structure consisting of &#119896; hash tables on Line 5, where &#119896; is the maximum (&#119903;, &#119904;)-clique core number. Each hash table, &#119871; &#119894; , maps &#119903; -cliques to a linked list of &#119903; -cliques, where &#119894; corresponds to a core number. The first stage of arb-nucleus-hierarchy inserts all &#119904;-clique-adjacent &#119903; -cliques into the hash tables on Lines 6-8. Specifically, for adjacent &#119903; -cliques &#119877; and &#119877; &#8242; where &#119873; &#119863; [&#119877; &#8242; ] &#8804; &#119873; &#119863; [&#119877;], we insert &#119877; &#8242; into the hash table corresponding to &#119877; &#8242; 's core number, &#119871; &#119873; &#119863; [&#119877; &#8242; ] , with {&#119877;} as the key. If an entry for {&#119877;} already exists in &#119871; &#119873; &#119863; [&#119877; &#8242; ] , we append &#119877; &#8242; to the existing linked list. The hash tables are shown in Figure <ref type="figure">2</ref>. For instance, &#119877; &#8242; = 1&#119886; is adjacent to &#119877; = 3&#119886;, so we add 1&#119886; to the linked list keyed by 3&#119886; in &#119871; 1 . In order to iterate in parallel over all &#119903; -cliques and over all &#119904;-cliques containing each &#119903; -clique, our algorithm uses a &#119904;-clique enumeration algorithm based on previous work by Shi et al. <ref type="bibr">[54]</ref>, which recursively finds and lists &#119888;-cliques in parallel and which can efficiently extend given &#119903; -cliques to find the &#119904;-cliques they are contained within. arb-nucleus-hierarchy then takes all combinations of &#119903; vertices in each discovered &#119904;-clique to find adjacent &#119903; -cliques in Lines 7-8. Note that this &#119904;-clique enumeration subroutine is already used in arb-nucleus in order to compute the (&#119903;, &#119904;)-clique core numbers of each &#119903; -clique, and in practice, we construct the hash tables &#119871; &#119894; while computing the core numbers in arb-nucleus (rather than running the &#119904;-clique enumeration subroutine twice).</p><p>After constructing the initial set of hash tables, arb-nucleus-hierarchy proceeds to construct the nucleus decomposition hierarchy on Lines 9-20. The broad idea is to construct the hierarchy starting at the leaf nodes, each of which correspond to an &#119903; -clique, and to merge tree nodes from the bottom up (i.e., in decreasing order of core number). The algorithm begins by considering only connected components formed by &#119903; -cliques with the greatest core number, &#119896;, which dictate the leaf nodes to be merged into super-nodes at the second-to-last level of the hierarchy tree based on their &#119904;-clique connectivity. In subsequent rounds, when processing core number &#119894;, the algorithm considers connected components formed by &#119903; -cliques with core numbers &#8805; &#119894;, which similarly dictate the merges to be performed in the next level of the hierarchy tree. arb-nucleus-hierarchy efficiently maintains connected components from higher core numbers when computing connected components at lower core numbers, by concatenating the relevant linked lists in the hash tables corresponding to the lower core numbers when processing higher core numbers. Figure <ref type="figure">3</ref> shows the construction of this hierarchy throughout the different rounds (for &#119894; = 4, . . . , 1), and Figure <ref type="figure">2</ref> lists the connected components computed in each round. In our example, since we omit the other vertices in the 4-(1, 3)-nucleus besides 4&#119886;, 4&#119887;, 4&#119888;, and 4&#119889; (for simplicity), we begin with singleton leaf nodes after processing round &#119894; = 4.</p><p>In more detail, on Line 9, we begin with a hierarchy tree &#119879; consisting only of leaf nodes corresponding to each &#119903; -clique. We also initialize a data structure consisting of &#119896; hash tables on Lines 10-11, where each hash table &#119868; &#119863; &#119894; maps &#119903; -cliques to &#119903; -cliques. The idea is to maintain a mapping of each &#119903; -clique to the component that it is contained within in &#119871; &#119894; , for the corresponding level. Initially, each &#119868;&#119863; &#119894; maps each key in &#119871; &#119894; to itself.</p><p>Then, arb-nucleus-hierarchy considers each core number &#119894;, starting from &#119896; and going down to 1 (Line 12). For each &#119894;, we relabel each &#119903; -clique in each linked list in &#119871; &#119894; with its corresponding value in &#119868; &#119863; &#119894; (Line 13). Then, it uses parallel list ranking to convert all linked lists in &#119871; &#119894; to arrays, forming a graph &#119867; , where edges are given by each key paired with each element in its corresponding linked list (Line 14). Note that the edges actually denote &#119904;-clique-adjacent &#119903; -cliques (or components of &#119903; -cliques). The vertices correspond to &#119903; -cliques, which represent components of &#119903; -cliques in &#119866;. In our example, we note that there is nothing to be done for round &#119894; = 4, since &#119871; 4 is empty. Therefore, we begin by processing the hash table &#119871; 3 in round &#119894; = 3. &#119868; &#119863; 3 maps every vertex to itself, so we do not relabel any of the labels in &#119871; 3 . The graph &#119867; that we construct consists of the vertices 3&#119886;, 3&#119887;, 3&#119888;, 4&#119886;, 4&#119887;, and 4&#119888;, with edges given by {3&#119886;, 3&#119887;, 3&#119888;} &#215; {4&#119886;, 4&#119887;, 4&#119888;}.</p><p>arb-nucleus-hierarchy proceeds by running a linear-work parallel connectivity algorithm on &#119867; (Line 15), and processes the given connected components. Note that each connected component &#119862; consists of a set of vertices in &#119867; , which represents a set of &#119903; -cliques, say {&#119877; 1 , . . . , &#119877; &#119888; }. In our example, in round &#119894; = 3, we have a single connected component in &#119867; consisting of all of the vertices, 3&#119886;, 3&#119887;, 3&#119888;, 4&#119886;, 4&#119887;, and 4&#119888;. Then, for each such connected component representing more than one &#119903; -clique, in the hierarchy tree &#119879; , we construct a new parent for the nodes corresponding to each &#119877; &#8467; for &#8467; &#8712; [&#119888;] (Line 17). Note that each &#119877; &#8467; could correspond to a subtree containing multiple tree nodes, owing to parent nodes constructed in previous steps. We represent the new parent by the &#119903; -clique &#119877; 1 , which we designate arbitrarily as the representative for the connected component &#119862;. In Figure <ref type="figure">3</ref>, under &#119894; = 3, we construct a new parent node labeled by 3&#119886;, which we designate as the representative of the component {3&#119886;, 3&#119887;, 3&#119888;, 4&#119886;, 4&#119887;, 4&#119888;}.</p><p>Finally, for each core number &#119895; &lt; &#119894;, we update the connectivity information on each hash table &#119871; &#119895; , by concatenating all linked lists in &#119871; &#119895; corresponding to the &#119903; -cliques in the component &#119862; (Line 19). More precisely, we update the value of the key &#119877; 1 to be the concatenation, or we insert the concatenation into &#119871; &#119895; with &#119877; 1 as the key if &#119877; 1 does not already exist in the hash table (this is possible if &#119877; 1 had no neighbors with core number &#119895;). We use tombstones to delete the other keys &#119877; &#8467; (&#8467; &#8800; 1) in each &#119871; &#119895; . Additionally, on Line 20, we update the component ID in &#119868; &#119863; &#119895; of each &#119877; &#8467; to be &#119877; 1 . For &#119894; = 3, we see that in our example there are no lists to concatenate, but in &#119868; &#119863; 2 , we map each of 3&#119887;, 3&#119888;, 4&#119886;, 4&#119887;, and 4&#119888; to the representative 3&#119886;.</p><p>We repeat this process until we have processed all &#119896; rounds. In our example, for round &#119894; = 2, we relabel 4&#119888; in &#119871; 2 with 3&#119886;, as given by &#119868; &#119863; 2 , and we construct a subgraph &#119867; with vertices 2&#119886;, 3&#119886;, and 4&#119889;, and edges (2&#119886;, 3&#119886;) and (2&#119886;, 4&#119889;). Again, there is only one connected component, given by {2&#119886;, 3&#119886;, 4&#119889; }. In the hierarchy tree for round &#119894; = 2, we construct a new parent labeled with the representative 2&#119886;, whose children are the leaves 2&#119886; and 4&#119889;, and the previously constructed parent node 3&#119886;. Again, there are no lists to concatenate in &#119871; 1 , but in &#119868; &#119863; 1 , we map both 3&#119886; and 4&#119889; to the representative 2&#119886;. Then, for round &#119894; = 1, we relabel 3&#119886; in &#119871; 1 with 2&#119886;, as given by &#119868; &#119863; 1 . We construct a subgraph &#119867; with vertices 1&#119886; and 2&#119886;, and a single edge between them. There is only one connected component, {1&#119886;, 2&#119886;}, and in the hierarchy tree for round &#119894; = 1, we construct a new parent labeled with the representative 1&#119886;, whose children are the leaf 1&#119886; and the previously constructed parent node 2&#119886;. This concludes the construction of the hierarchy &#119879; in our example.</p><p>Parallel Algorithms for Hierarchical Nucleus Decomposition 32:9</p><p>Theoretical Efficiency. We now analyze the theoretical efficiency of our hierarchy algorithm, arb-nucleus-hierarchy. Note that as in Shi et al.'s <ref type="bibr">[55]</ref> work, &#120588; (&#119903;,&#119904; ) (&#119866;) is defined to be the (&#119955;, &#119956;) peeling complexity of &#119866;, or the number of rounds needed to peel the graph where in each round, all &#119903; -cliques with the minimum &#119904;-clique count are peeled (removed). Importantly, &#119896; &#8804; &#120588; (&#119903;,&#119904; ) (&#119866;) &#8804; &#119874; (&#119898;&#120572; &#119903; -2 ), since at least one &#119903; -clique is peeled in each round, and the number of rounds is at least the maximum (&#119903;, &#119904;)-clique core number in &#119866;.</p><p>Theorem 5.1. arb-nucleus-hierarchy computes the (&#119903;, &#119904;) nucleus decomposition hierarchy in &#119874; (&#119898;&#120572; &#119904; -2 ) expected work and &#119874; (&#119896; log &#119899; + &#120588; (&#119903;,&#119904; ) (&#119866;) log &#119899; + log 2 &#119899;) span w.h.p., where &#120588; (&#119903;,&#119904; ) (&#119866;) is the (&#119903;, &#119904;) peeling complexity and &#119896; is the maximum (&#119903;, &#119904;)-clique core number.</p><p>Proof. First, the theoretical complexity of computing the (&#119903;, &#119904;)-clique core numbers of each &#119903; -clique (Line 3) is given by Shi et al. <ref type="bibr">[55]</ref>, which they show takes &#119874; (&#119898;&#120572; &#119904; -2 ) work and &#119874; (&#120588; (&#119903;,&#119904; ) (&#119866;) log &#119899; + log 2 &#119899;) span w.h.p. for constant &#119903; and &#119904;. Note that the work bound is given by the version of their algorithm that takes space proportional to the number of &#119904;-cliques in &#119866;, which we incur regardless to store the hash tables &#119871; &#119894; . Additionally, iterating through all &#119904;-cliques in &#119866; (Line 6) is superseded by the work required to compute the (&#119903;, &#119904;)-clique core numbers. For every pair of &#119903; -cliques in each &#119904;-cliques, we hash each &#119903; -clique and append to a linked list (Lines 7-8), which in total takes &#119874; (&#119898;&#120572; &#119904; -2 ) work and &#119874; (log 2 &#119899;) span w.h.p. for constant &#119903; and &#119904;.</p><p>We now discuss the work and span of constructing the hierarchy tree &#119879; level-by-level, in &#119896; rounds (Lines 12-20). The key idea here is that the linked lists in each hash table &#119871; &#119894; are iterated over at most once across all rounds, and the concatenation of linked lists in intermediate rounds incurs minimal costs (since concatenating linked lists does not require iterating through the linked lists). The sum of the lengths of the linked lists in each &#119871; &#119894; remains invariant throughout this portion of the construction, so in total, the cost of iterating over the linked lists is bounded by &#119874; (&#119898;&#120572; &#119904; -2 ) work, matching the work needed to construct each linked list in each &#119871; &#119894; originally. Also, the number of keys in each &#119871; &#119894; only monotonically decreases, so processing the connected components of the constructed subgraphs &#119867; takes at most &#119874; (&#119898;&#120572; &#119904; -2 ) work as well.</p><p>In more detail, for fixed &#119894;, let the sum of the lengths of the linked lists in &#119871; &#119894; be &#8467; &#119894; , and let the number of keys in &#119871; &#119894; be &#119910; &#119894; . For each round &#119894; &#8712; [&#119896;], applying &#119868; &#119863; &#119894; and parallel list ranking on the linked lists in &#119871; &#119894; (Lines 13-14) takes work proportional to &#8467; &#119894; and &#119874; (log &#119899;) span w.h.p.. The number of edges in the subgraph &#119867; constructed from the linked lists in &#119871; &#119894; is at most &#8467; &#119894; , so performing connectivity on &#119867; (Line 15) takes work linear in &#8467; &#119894; and &#119874; (log &#119899;) span w.h.p. <ref type="bibr">[22]</ref>. Also, there are at most &#119874; (&#119910; &#119894; ) vertices in &#119867; , so processing each connected component and updating the hierarchy tree &#119879; (Line 17) takes &#119874; (&#119910; &#119894; ) work and &#119874; (1) span. In total, for Lines 13-17, we incur &#119874; ( &#119894; (&#8467; &#119894; + &#119910; &#119894; )) = &#119874; (&#119898;&#120572; &#119904; -2 ) expected work and &#119874; (&#119896; log &#119899;) span w.h.p.</p><p>It remains to bound the cost of of the loop in Lines 18-20. First, note that across all rounds, each value corresponding to every key in each &#119871; &#119894; is concatenated at most once (Line 19). This is because we concatenate linked lists and store the concatenation under exactly one existing key. We empty the corresponding values for the previously associated keys, which allows us to maintain the invariant that the sum of the lengths of the linked lists in each &#119871; &#119894; remains fixed. Also, the previously associated keys are never used again, since we update the value associated with each &#119903; -clique in &#119868; &#119863; &#119895; . Thus, the concatenations are bounded by &#119874; (&#119898;&#120572; &#119904; -2 ) work across all rounds, matching the work of constructing all &#119871; &#119894; . Additionally, iterating through all levels &#119895; &#8804; &#119894; for each component C does not increase the work. This is because we only reach this loop if |C| &#8805; 2, which means that we are effectively merging multiple &#119903; -cliques together in each hash table &#119871; &#119895; for &#119895; &#8804; &#119894;, and assigning the &#119903; -clique &#119877; 1 as the new representative for the other &#119903; -cliques in the component (updating &#119868; &#119863; &#119895; ). Thus, we can assign the work of iterating through all &#119895; &#8804; &#119894; to the &#119903; -cliques that are being merged (&#119877; &#8467; where &#8467; &#8800; 1). Once the &#119903; -clique &#119877; &#8467; is merged, due to the concatenation on Line 19 and the update in &#119868; &#119863; &#119895; on Line 20, it never participates as a vertex in &#119867; again in future rounds, so is never re-processed in a future connected component of &#119867; ; this is due to the mapping on Line 13. The amount of work that we assign per merged &#119903; -clique &#119877; &#8467; is at most the core number of &#119877; &#8467; . This is because the amount of work we assign to &#119877; &#8467; is given by the number of rounds in which we merge, or &#119894;, and &#119877; &#8467; only appears in &#119871; &#119894; if &#119873; &#119863; [&#119877; &#8467; ] &#8805; &#119894;, by construction on Line 8. Thus, in total, for each &#119903; -clique, we incur work upper bounded by the core number. We have in total &#119874; ( &#119903; -clique &#119877; &#8712;&#119866; &#119873; &#119863; [&#119877;]) = &#119874; (&#119898;&#120572; &#119904; -2 ) work, since the sum of the (&#119903;, &#119904;)-clique core numbers in &#119866; is necessarily bounded by the number of &#119904;-cliques for constant &#119903; and &#119904;. This is because each &#119904;-clique contributes to at most &#119904; &#119903; &#119903; -clique's core numbers, so the summation across all core numbers is upper bounded by &#119904; &#119903; &#8226; (the number of &#119904;-cliques). Thus, in total, the loop in Lines 18-20 incurs &#119874; (&#119898;&#120572; &#119904; -2 ) work and &#119874; (&#119896; log &#119899;) span, where the span is due to list ranking.</p><p>In total, we have &#119874; (&#119898;&#120572; &#119904; -2 ) expected work and &#119874; (&#119896; log &#119899; + &#120588; (&#119903;,&#119904; ) (&#119866;) log &#119899; + log 2 &#119899;) span w.h.p., as desired. &#9633;</p><p>Comparison to Prior Work. The prior state-of-the-art algorithm is the sequential (&#119903;, &#119904;) nucleus decomposition hierarchy algorithm by Sariy&#252;ce and Pinar <ref type="bibr">[49]</ref>. They provide an algorithm similar to arb-nucleus-hierarchy in that it first computes the (&#119903;, &#119904;)-clique core numbers of each &#119903; -clique, and then builds the hierarchy tree from the bottom up. They show that the time complexity is upper bounded by the time complexity of computing the (&#119903;, &#119904;)-clique core numbers. Note that they omit a factor of &#119874; (&#120572; (&#119899; &#119904; , &#119899; &#119903; )) where &#120572; is the inverse Ackermann function and &#119899; &#119904; and &#119899; &#119903; are the number of &#119904;-cliques and &#119903; -cliques, respectively, in the graph; this factor is necessary for their algorithm, since they use union-find to construct the hierarchy tree. Thus, the time complexity of Sariy&#252;ce and Pinar's algorithm is &#119874; (&#119898;&#120572; &#119904; -2 &#120572; (&#119899; &#119904; , &#119899; &#119903; )) (this is achieved using the state-of-the-art algorithm for computing the (&#119903;, &#119904;)-clique core numbers <ref type="bibr">[55]</ref>). Our arb-nucleus-hierarchy algorithm avoids the additional inverse Ackermann factor, by efficiently constructing graphs to represent different levels of the hierarchy tree and using linear-work graph connectivity to construct the hierarchy tree. Thus, we improve the sequential running time of constructing the (&#119903;, &#119904;) nucleus decomposition hierarchy to &#119874; (&#119898;&#120572; &#119904; -2 ), and arb-nucleus-hierarchy is work-efficient. Shi et al. <ref type="bibr">[55]</ref> present a parallel algorithm to compute the (&#119903;, &#119904;)-clique core numbers in &#119874; (&#119898;&#120572; &#119904; -2 ) expected work. A vanilla extension of their algorithm to compute the hierarchy would be to run connected components for each non-empty core number &#119894;, with vertices being the (&#119903;, &#119904;)-cliques that have core number &#119894; or above, in a top-down manner. This incurs &#119874; (&#119898;&#120572; &#119904; -2 ) expected work per level, and there can be &#120588; (&#119903;,&#119904; ) (&#119866;) levels in the worst case, leading to &#119874; (&#120588; (&#119903;,&#119904; ) (&#119866;)&#119898;&#120572; &#119904; -2 ) total expected work. In contrast, our algorithm has a much lower total expected work of &#119874; (&#119898;&#120572; &#119904; -2 ).</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="6">Approximate Nucleus Decomposition</head><p>Given the potentially large span (i.e., longest critical path) of computing the exact nucleus decomposition hierarchy, we develop a new parallel approximate nucleus decomposition hierarchy algorithm, arb-approx-nucleus-hierarchy. Instead of computing exact (&#119903;, &#119904;)-clique-core numbers of each &#119903; -clique, the main idea of the new algorithm is to compute an approximation of the (&#119903;, &#119904;)-clique core number. Specifically, we compute a ( &#119904; &#119903; +&#120576;)-approximate (&#119903;, &#119904;)-clique core number of each &#119903; -clique; that is to say, if we let the true (&#119903;, &#119904;)-clique core number of each &#119903; -clique be &#119896; &#119877; , our approximation is at least &#119896; &#119877; and at most ( &#119904; &#119903; + &#120576;) &#8226; &#119896; &#119877; . Our approximate computation uses the same peeling paradigm from Shi et al. <ref type="bibr">[55]</ref> for exact nucleus decomposition, but with an important modification that allows it to take only &#119874; (log 2 &#119899;) peeling rounds, thus significantly improving upon the span. As a result, we only have polylogarithmically many core numbers, leading to a hierarchy tree with polylogarithmic height. Our hierarchy construction for arb-approx-nucleus-hierarchy is exactly the same as that of arb-nucleushierarchy, and the only salient difference is that for arb-approx-nucleus-hierarchy, we replace the arb-nucleus subroutine in Line 3 of Algorithm 1 with our approximate nucleus decomposition subroutine, approx-arb-nucleus. Our Algorithm. We present our pseudocode for approx-arb-nucleus in Algorithm 2. Again, we have highlighted in blue the parts that derive directly from prior work, and the remainder is novel to this work. Note that it takes as input a parameter &#120575; &gt; 0, which controls the &#120576; in the ( &#119904; &#119903; + &#120576;)approximation. Specifically, approx-arb-nucleus gives a ( &#119904; &#119903; +&#120575;) &#8226; (1+&#120575;) = ( &#119904; &#119903; +&#120576;)-approximation, which we prove in Theorem 6.1.</p><p>First, on Line 3, approx-arb-nucleus computes a low out-degree orientation of the graph &#119866;, which directs the edges such that every vertex has out-degree at most &#119874; (&#120572;), using an efficient algorithm by Shi et al. <ref type="bibr">[54]</ref>. Then, on Lines 4-5, it counts the number of &#119904;-cliques per &#119903; -clique in &#119866;, and stores the result in a parallel hash table &#119880; . It uses an &#119904;-clique counting subroutine, rec-listcliqes, from Shi et al.'s previous work <ref type="bibr">[54]</ref>. The key difference between approx-arb-nucleus and arb-nucleus is on Line 6, where the buckets in the bucketing structure hold &#119903; -cliques with a range of &#119904;-clique-degrees instead of a single &#119904;-clique-degree. Specifically, for an input parameter &#120575;, we define the range of each bucket &#119861; &#119894; to be</p><p>) is a trivial upper bound on the maximum &#119904;-clique-degree possible in any given graph.</p><p>The peeling algorithm then proceeds as it does in <ref type="bibr">[55]</ref>, except using our modified bucketing structure. While not all &#119903; -cliques have been peeled, approx-arb-nucleus processes the set of &#119903; -cliques &#119860; (that have not yet been peeled) within the lowest bucket &#119861; &#119894; (starting with &#119894; = 0), and peels them from the graph (Lines 8-20). For each &#119903; -clique &#119877; in &#119860;, we iterate over all &#119904;-clique-adjacent &#119903; -cliques &#119877; &#8242; , and update the recorded &#119904;-clique-degree of &#119877; &#8242; given &#119877;'s removal (Lines 12-15). Then, we peel (remove) the &#119903; -cliques in &#119860; from the graph and update the buckets of all unpeeled &#119903; -cliques based on the updated &#119904;-clique-degrees on Line 16. Notably, if a &#119903; -clique &#119877;'s &#119904;-clique-degree falls below the range of the current bucket of &#119903; -cliques that is being peeled, we do not rebucket &#119877; into a lower bucket, and instead aggregate these &#119903; -cliques within the current bucket. As such, in any given round of peeling, we are actually peeling all &#119903; -cliques with &#119904;-clique-degree &#8804; ( &#119904; &#119903; + &#120575;) &#8226; (1 + &#120575;) &#119894; , which is important for our theoretical bounds. Note that we process a given bucket &#119861; &#119894; at most &#119874; (log 1+ &#120575;/( &#119904; &#119903; ) (&#119899;)) times; if we have exceeded this threshold, or if &#119861; &#119894; is empty, then we move on to processing the next bucket, &#119861; &#119894;+1 (Lines 17-20). If there are unpeeled &#119903; -cliques remaining in &#119861; &#119894; once we reach this threshold, we include them in the next bucket &#119861; &#119894;+1 (Line 18). Note that the approximate (&#119903;, &#119904;)-clique core number that we compute for each &#119903; -clique is given by the upper bound of the bucket in which it was peeled. In practice, we can improve this by taking the minimum of the upper bound of the bucket, and the &#119904;-clique-degree of each &#119903; -clique (in the original graph).</p><p>Once we have peeled all &#119903; -cliques, this concludes our subroutine. arb-approx-nucleus-hierarchy is then given by replacing arb-nucleus in Line 3 of Algorithm 1 with approx-arb-nucleus. Theoretical Guarantees and Efficiency. We now discuss the theoretical guarantees and theoretical efficiency of approx-arb-nucleus, and by extension, arb-approx-nucleus-hierarchy.</p><p>The main idea is to bound the proportion of &#119903; -cliques with core numbers &#8804; &#8467; for some fixed &#8467;, but with &#119904;-clique-degree &gt; &#8467; ( &#119904; &#119903; + &#120575;). We can then set &#8467; such that at any given step of our peeling process, we obtain a bound on the maximum proportion of &#119903; -cliques with core number at most &#8467; that is not within the current bucket to be peeled. In essence, this gives us a bound on the number of times that a bucket must be reprocessed, such that moving on to the next bucket does not degrade the approximation factor, which gives us our approximation guarantees. Due to space constraints, we defer the proof of the following theorem to the full paper <ref type="bibr">[56]</ref>.</p><p>Algorithm 2 Approximate parallel (&#119903;, &#119904;) nucleus algorithm 1: Initialize &#119903; , &#119904; &#8882; &#119903; and &#119904; for (&#119903;, &#119904; ) nucleus decomposition 2: procedure approx-arb-nucleus(&#119866; = (&#119881; , &#119864; ), &#120575;) 3: &#119863;&#119866; &#8592; Arb-Orient(&#119866;) &#8882; Apply an arboricity-orientation algorithm 4: Initialize &#119880; to be a parallel hash table with &#119903; -cliques as keys, and &#119904;-clique counts as values 5: rec-list-cliqes(&#119863;&#119866;, &#119904;, &#119880; ) &#8882; Count &#119904;-cliques, and store the counts per &#119903; -clique in &#119880; 6: Let &#119873; &#119863; be a bucketing structure mapping each &#119903; -clique to a bucket based on # of &#119904;-cliques, where each bucket &#119861; &#119894; contain all &#119903; -cliques with &#119904;-clique-degree in the range [ ( &#119904; &#119903; +&#120575; ) &#8226; (1+&#120575; ) &#119894; , ( &#119904; &#119903; +&#120575; ) &#8226; (1+&#120575; ) &#119894;+1 ], for all &#119894; &#8712; [&#119904; log ( &#119904; &#119903; )+&#120575; &#119899;] 7: finished &#8592; 0, num_rounds &#8592; 0, &#119894; &#8592; 0 8: while finished &lt; |&#119880; | do 9: &#119860; &#8592; &#119903; -cliques in the bucket &#119861; &#119894; in &#119873; &#119863; (to be peeled) 10: finished &#8592; finished + |&#119860;| 11: num_rounds &#8592; num_rounds + 1 12: parfor all &#119903; -cliques &#119877; in &#119860; do 13: parfor all &#119904;-cliques &#119878; containing &#119877; do 14: parfor all &#119903; -cliques &#119877; &#8242; in &#119878; where &#119877; &#8242; &#8800; &#119877; do 15: Update &#119904;-clique count of &#119877; &#8242; in &#119880; 16: Peel &#119860;, assign the upper bound of the bucket as the coreness value for peeled &#119903; -cliques, and update the buckets of &#119903; -cliques with updated &#119904;-clique counts 17: if num_rounds &#8805; &#119874; (log 1+ &#120575;/ ( &#119904; &#119903; ) (&#119899;) ) or &#119861; &#119894; is empty then 18: Add the remaining &#119903; -cliques in &#119861; &#119894; (if it is non-empty) to &#119861; &#119894;+1 19: &#119894; &#8592; &#119894; + 1 20: num_rounds &#8592; 0 21: return &#119873; &#119863; Theorem 6.1. arb-approx-nucleus-hierarchy computes a ( &#119904; &#119903; + &#120576;)-approximate (&#119903;, &#119904;) nucleus decomposition hierarchy in &#119874; (&#119898;&#120572; &#119904; -2 ) expected work and &#119874; (log 3 &#119899;) span w.h.p.</p><p>Note that in the theorem above, &#120598; does not affect the work bound, and affects the base of one of the logarithms in the span bound (which we omitted as we treat &#120598; as a constant).</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="7">Practical Implementations</head><p>While the algorithm presented in Section 5 (Algorithm 1) is efficient in theory, we present a number of optimizations that improve its practical performance. Algorithm 1 requires two passes over the &#119903; -cliques and their &#119904;-clique-adjacent neighbors, first to compute the (&#119903;, &#119904;)-clique core numbers and then to construct the hierarchy. We present algorithms that interleave these two computations, so that only a single pass is required. Specifically, we present two algorithms that are not as theoretically efficient as Algorithm 1, but are faster in practice, particularly when the difference between &#119903; and &#119904; is large, as we demonstrate in Section 8.1.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="7.1">Interleaved Hierarchy Framework</head><p>Our algorithms use the same framework, given in Algorithm 3, and the main difference between the two algorithms is the implementation of the key subroutines link and construct-tree. The framework is based on the peeling process used to compute the (&#119903;, &#119904;)-clique core numbers in Shi et al.'s work <ref type="bibr">[55]</ref>. The main idea is that when we peel an &#119903; -clique &#119877;, while computing the updated &#119904;-clique counts due to peeling &#119877;, we are already iterating over all &#119904;-clique-adjacent &#119903; -cliques &#119877; &#8242; . Note that additionally, the nucleus decomposition algorithm in Shi et al. <ref type="bibr">[55]</ref> uses a bucketing structure that maintains the intermediate (&#119903;, &#119904;)-clique core numbers of each &#119903; -clique throughout the peeling process (which begin as simply the &#119904;-clique count of each &#119903; -clique, and throughout the peeling process are updated to the actual (&#119903;, &#119904;)-clique core numbers). Then, if the intermediate (&#119903;, &#119904;)-clique core number of &#119877; &#8242; is less than or equal to that of &#119877;, as maintained in the bucketing structure, the intermediate (&#119903;, &#119904;)-clique core numbers of &#119877; and &#119877; &#8242; are actually the final (&#119903;, &#119904;)-clique</p><p>Parallel Algorithms for Hierarchical Nucleus Decomposition 32:13 Algorithm 3 Parallel (&#119903;, &#119904;) nucleus hierarchy framework 1: Initialize &#119903; , &#119904; &#8882; &#119903; and &#119904; for (&#119903;, &#119904; ) nucleus decomposition 2: procedure arb-nucleus-decomp-hierarchy-framework(&#119866; = (&#119881; , &#119864; )) 3: &#119863;&#119866; &#8592; Arb-Orient(&#119866;) &#8882; Apply an arboricity-orientation algorithm 4: Initialize &#119880; to be a parallel hash table with &#119903; -cliques as keys, and &#119904;-clique counts as values 5: rec-list-cliqes(&#119863;&#119866;, &#119904;, &#119880; ) &#8882; Count &#119904;-cliques, and store the counts per &#119903; -clique in &#119880; 6: Let &#119873; &#119863; be a bucketing structure mapping each &#119903; -clique to a bucket based on # of &#119904;-cliques 7: finished &#8592; 0 8: while finished &lt; |&#119880; | do 9: &#119860; &#8592; &#119903; -cliques in the next bucket in &#119873; &#119863; (to be peeled) 10: finished &#8592; finished + |&#119860;| 11: parfor all &#119903; -cliques &#119877; in &#119860; do 12: parfor all &#119904;-cliques &#119878; containing &#119877; do 13: parfor all &#119903; -cliques &#119877; &#8242; in &#119878; where &#119877; &#8242; &#8800; &#119877; do 14: if &#119873; &#119863; [&#119877; &#8242; ] &#8804; &#119873; &#119863; [&#119877; ] then 15: link(&#119877; &#8242; , &#119877;, &#119873; &#119863; ) 16: else Update &#119904;-clique count of &#119877; &#8242; in &#119880; 17: Update the buckets of &#119903; -cliques with updated &#119904;-clique counts, peeling &#119860; 18:</p><p>return construct-tree(&#119873; &#119863;) &#8882; Return the hierarchy tree &#119879; , constructed based on link core numbers of &#119877; and &#119877; &#8242; , respectively. Thus, each such &#119877; and &#119877; &#8242; pair are connected in the nucleus decomposition hierarchy up to the level given by min(&#119873; &#119863; [&#119877;], &#119873; &#119863; [&#119877; &#8242; ]), and after the peeling process completes, we will have all of the relevant connectivity information to completely compute the nucleus decomposition hierarchy. In this sense, it suffices to define a link subroutine to process the &#119904;-clique-adjacent &#119903; -cliques given the intermediate (&#119903;, &#119904;)-clique core numbers throughout the peeling algorithm. Based on link, construct-tree constructs the final hierarchy tree.</p><p>In more detail, arb-nucleus-decomp-hierarchy-framework first uses an efficient low outdegree orientation algorithm by Shi et al. <ref type="bibr">[54]</ref> to direct the graph &#119866; such that every vertex has out-degree at most &#119874; (&#120572;) (Line 3). Then, it counts the number of &#119904;-cliques per &#119903; -clique in &#119866; and stores the counts in a parallel hash table &#119880; , where the keys are &#119903; -cliques and the values are the counts (Lines 4-5). Note that arb-nucleus-decomp-hierarchy-framework uses a subroutine rec-list-cliqes based on previous work by Shi et al. <ref type="bibr">[54]</ref>, to count the number of &#119904;-cliques per &#119903; -clique. Also, our algorithm initializes a parallel bucketing structure &#119873; &#119863; that maps &#119903; -cliques to buckets, initially based on their &#119904;-clique counts (Line 6). We use the bucketing structure by Dhulipala et al. <ref type="bibr">[16]</ref>. This structure &#119873; &#119863; stores the aforementioned intermediate (&#119903;, &#119904;)-clique core numbers of each &#119903; -clique, and supports efficient operations to update buckets and return the lowest unpeeled bucket. Our algorithm then proceeds with a classic peeling paradigm, where until all &#119903; -cliques have been peeled, it processes the &#119903; -cliques (that have not yet been peeled) incident to the lowest number of &#119904;-cliques and peels them from the graph (Lines 8-17). For a set &#119860; of &#119903; -cliques with the lowest number of incident &#119904;-cliques (Line 9), we iterate over all &#119904;-clique-adjacent &#119903; -cliques &#119877; &#8242; to each &#119903; -clique &#119877; in &#119860; (Lines 11-13).</p><p>Note that if &#119873; &#119863; [&#119877; &#8242; ] &#8804; &#119873; &#119863; [&#119877;], this means that &#119877; &#8242; was either previously peeled or is currently being peeled (and is also in &#119860;); this is because at any given peeling step, we process the bucket of unpeeled &#119903; -cliques with the minimum incident &#119904;-clique count. This also means that &#119873; &#119863; [&#119877; &#8242; ] and &#119873; &#119863; [&#119877;] are the actual (&#119903;, &#119904;)-clique core numbers of &#119877; &#8242; and &#119877; respectively, which follows directly from the correctness of the peeling paradigm <ref type="bibr">[52]</ref>. Thus, each such &#119877; and &#119877; &#8242; pair are connected in the nucleus decomposition hierarchy up to the level given by min(&#119873; &#119863; [&#119877;], &#119873; &#119863; [&#119877; &#8242; ]), which we process using the link subroutine (Lines 14-15). The link subroutine will construct the hierarchy, and we describe it in Sections 7.2 and 7.3.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head>Algorithm 4 Basic link and tree construction</head><p>1: Initialize &#119896; union-find data structures, &#119906; &#119891; &#119894; for &#119894; &#8712; [&#119896; ], where &#119896; is the maximum (&#119903;, &#119904; )-clique core number 2: procedure link-basic(&#119877;, &#119876;, &#119873; &#119863;) 3: parfor &#119894; &#8712; [min(&#119873; &#119863; [&#119877; ], &#119873; &#119863; [&#119876; ] ) ] do 4: &#119906; &#119891; &#119894; .unite(&#119877;, &#119876; ) 5: procedure construct-tree-basic(&#119873; &#119863;) 6: Initialize the hierarchy tree &#119879; with leaves corresponding to each &#119903; -clique 7: for &#119894; &#8712; {&#119896;, &#119896; -1, . . . , 1} do 8: parfor each connected component &#119862; = {&#119877; 1 , . . . , &#119877; &#119888; } in &#119906; &#119891; &#119894; do 9: Construct a new parent in &#119879; , to be the parent of the roots of the leaf nodes corresponding to each &#119877; &#8467; (for &#8467; &#8712; [&#119888; ]) 10: return &#119879; On the other hand, if &#119873; &#119863; [&#119877;] &gt; &#119873; &#119863; [&#119877; &#8242; ], then this means that &#119877; &#8242;</p><p>has not yet been peeled, and the &#119904;-clique removed by &#119877; must be properly accounted for. In this case, arb-nucleus-decomphierarchy-framework updates the &#119904;-clique count of &#119877; &#8242; in the hash table &#119880; (Line 16). After processing all &#119877; and &#119877; &#8242; pairs, we then update the buckets of the &#119903; -cliques with updated &#119904;-clique counts in &#119880; (Line 17). We omit the details of these steps for conciseness, since they are described in Shi et al.'s parallel nucleus decomposition algorithm <ref type="bibr">[55]</ref>.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="7.2">Basic Version of link</head><p>The remaining details are in how we perform the link subroutine (Line 15) and how we construct the hierarchy tree &#119879; with construct-tree (Line 18).</p><p>In Algorithm 4, we present a basic link subroutine, link-basic, and the corresponding constructtree subroutine, construct-tree-basic. link-basic maintains a parallel union-find data structure &#119906; &#119891; &#119894; per core number &#119894; &#8712; [&#119896;], which corresponds to a level of the hierarchy tree &#119879; . Each &#119906; &#119891; &#119894; connects &#119903; -cliques that are &#119904;-clique-adjacent considering only &#119903; -cliques with core numbers &#8805; &#119894;. To construct these &#119906; &#119891; &#119894; 's, given two &#119903; -cliques &#119877; and &#119876;, link-basic simply unites &#119877; and &#119876; in each &#119906; &#119891; &#119894; where &#119894; &#8804; max(&#119873; &#119863; [&#119877;], &#119873; &#119863; [&#119876;]) (Lines 3-4). Then, given the &#119906; &#119891; &#119894; for all &#119894; &#8712; [&#119896;], we construct the hierarchy tree &#119879; from the bottom up, starting with leaf nodes corresponding to &#119903; -cliques. construct-tree-basic begins with &#119894; = &#119896;, where for each connected component in &#119906; &#119891; &#119896; (Line 8), we construct a parent in &#119879; where its children are the leaf nodes corresponding to the &#119903; -cliques in the connected component (Line 9). Then, for &#119894; = &#119896; -1, . . . , 1 (Line 7), we construct a new parent for each connected component in &#119906; &#119891; &#119894; , where its children are the parents of the leaf nodes corresponding to the &#119903; -cliques that compose the component (Line 9). This produces the desired &#119879; .</p><p>However, link-basic is not efficient, since it requires a union-find data structure per level, and for every pair of &#119903; -cliques, we could perform up to &#119896; unite operations. Indeed, in Section 8.1, we empirically show that link-basic performs many unnecessary unite operations in practice. If we let &#119899; &#119903; and &#119899; &#119904; denote the number of &#119903; -cliques and the number of &#119904;-cliques in the graph, respectively, link-basic incurs additional space proportional to &#119874; (&#119896;&#119899; &#119903; ) and total work upper bounded by &#119874; (&#119896;&#119899; &#119904; ) (since there are at most &#119874; (&#119899; &#119904; ) pairs of &#119904;-clique-adjacent &#119903; -cliques). In the next subsection, we introduce more efficient link and construct-tree subroutines.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="7.3">Efficient Version of link</head><p>Our improved subroutines link-efficient and construct-tree-efficient are shown in Algorithm 5. We refer to an example of (1, 3)-nucleus decomposition in the graph in Figure <ref type="figure">1</ref>. Recall that we have omitted labeling some vertices in the graph for simplicity.</p><p>The main idea of link-efficient is instead of maintaining &#119896; union-find data structures, we maintain a single parallel union-find data structure &#119906; &#119891; and an additional hash table &#119871; that maps &#119903; -cliques to &#119903; -cliques. First, &#119906; &#119891; stores connected &#119903; -cliques considering only other &#119903; -cliques with equal core numbers. For instance, in Figure <ref type="figure">1</ref>, the vertices 3&#119886;, 3&#119887;, and 3&#119888; are connected and all have</p><p>Parallel Algorithms for Hierarchical Nucleus Decomposition 32:15 Algorithm 5 Efficient link and tree construction 1: Initialize a union-find data structure, &#119906; &#119891; , of length equal to the number of &#119903; -cliques 2: Initialize a hash table, &#119871;, where the keys and values are &#119903; -cliques 3: procedure link-efficient(&#119877;, &#119876;, &#119873; &#119863;) 4: if &#119877; or &#119876; is empty then return 5: if &#119873; &#119863; [&#119876; ] &lt; &#119873; &#119863; [&#119877; ] then Swap &#119877; and &#119876; 6: &#119877; &#8592; &#119906; &#119891; .parent(&#119877;), &#119876; &#8592; &#119906; &#119891; .parent(&#119876; ) 7: if &#119873; &#119863; [&#119877; ] = &#119873; &#119863; [&#119876; ] then 8: &#119906; &#119891; .unite(&#119877;, &#119876; ) 9: if &#119906; &#119891; .parent(&#119877;) &#8800; &#119877; then link-efficient(&#119871;[&#119877; ], &#119906; &#119891; .parent(&#119877;), &#119873; &#119863; ) 10: if &#119906; &#119891; .parent(&#119876; ) &#8800; &#119876; then link-efficient(&#119871;[&#119876; ], &#119906; &#119891; .parent(&#119876; ), &#119873; &#119863; ) 11: else &#8882; &#119873; &#119863; [&#119877; ] &lt; &#119873; &#119863; [&#119876; ] 12: while true do 13: &#119871;&#119876; &#8592; &#119871;[&#119876; ] 14: &#119876; &#8592; &#119906; &#119891; .parent(&#119876; ) 15: if compare-and-swap(&#119871;[&#119876; ], empty, &#119877;) then 16: if &#119906; &#119891; .parent(&#119876; ) &#8800; &#119876; then 17: link-efficient(&#119877;, &#119906; &#119891; .parent(&#119876; ), &#119873; &#119863;) 18: break 19: else if &#119873; &#119863; [&#119871;&#119876; ] &lt; &#119873; &#119863; [&#119877; ] then 20: if compare-and-swap(&#119871;[&#119876; ], &#119871;&#119876;, &#119877;) then 21: if &#119906; &#119891; .parent(&#119876; ) &#8800; &#119876; then 22: link-efficient(&#119877;, &#119906; &#119891; .parent(&#119876; ), &#119873; &#119863;) 23: link-efficient(&#119877;, &#119871;&#119876;, &#119873; &#119863;) 24: break 25: else 26: link-efficient(&#119877;, &#119871;[&#119876; ], &#119873; &#119863;) 27: break 28: procedure construct-tree-efficient(&#119873; &#119863;) 29: Initialize the hierarchy tree &#119879; with leaves corresponding to each &#119903; -clique 30: parfor each connected component C = {&#119877; 1 , . . . , &#119877; &#119888; } in &#119906; &#119891; do 31: Construct a parent node &#119906; &#119891; C in &#119879; , where its children are the leaves corresponding to the &#119903; -cliques in C 32: parfor each parent node &#119906; &#119891; C in &#119879; do 33: if &#119871;[ C ] is non-empty then 34: &#119877; &#8592; &#119906; &#119891; .parent(&#119871;[ C ] ) &#8882; Note that C is the &#119903; -clique representing the component in &#119906; &#119891; 35: Make &#119906; &#119891; C a child of &#119906; &#119891; &#119877; in &#119879; &#8882; Note that &#119906; &#119891; &#119877; necessarily exists since &#119877; represents a component in &#119906; &#119891; 36:</p><p>return &#119879; core number 3, so we would store these as a component in &#119906; &#119891; . Note that for all core numbers &#119894;, we can store this information using a single union-find data structure because the sets of &#119903; -cliques with distinct core numbers are disjoint. We can arbitrarily represent each connected component in &#119906; &#119891; by a single &#119903; -clique in that component.</p><p>The main idea of &#119871; is to connect the components in &#119906; &#119891; to the "nearest" core with a different core number that it is contained within (if it exists). For instance, in Figure <ref type="figure">1</ref>, we note that the component in &#119906; &#119891; corresponding to 4&#119886; (consisting of vertices with core number 4) is contained within the 3-core consisting of the component {3&#119886;, 3&#119887;, 3&#119888;}. In &#119871;, we would store one of 3&#119886;, 3&#119887;, or 3&#119888; in an entry corresponding to key 4&#119886;, indicating that this is the "nearest" core that 4&#119886; must join in the hierarchy. We note that 4&#119886; is also contained within a larger 2-core and a larger 1-core, but its "nearest" core, or the smallest core such that the component 4&#119886; is a proper subset of that core, is given by the 3-core. It is sufficient to store only the "nearest" core to 4&#119886; in &#119871;, because the component in &#119906; &#119891; corresponding to {3&#119886;, 3&#119887;, 3&#119888;} is responsible for storing its "nearest" core in &#119871; as well, to the 2-core it is contained within. On the other hand, the component corresponding to  4&#119889; is not contained within the 3-core, and its "nearest" core would be the 2-core containing the component 2&#119886;, so 4&#119889; would store in &#119871; the value 2&#119886;.</p><p>More formally, for each &#119903; -clique &#119877; representing a connected component in &#119906; &#119891; , let &#119877; &#8242; be an &#119903; -clique with the maximum &#119873; &#119863; [&#119877; &#8242; ] such that &#119873; &#119863; [&#119877; &#8242; ] &lt; &#119873; &#119863; [&#119877;], and &#119877; &#8242; is connected to &#119877; through &#119904;-cliques considering only &#119903; -cliques with core number &#8805; &#119873; &#119863; [&#119877; &#8242; ]. Then, each such &#119903; -clique &#119877; is a key in &#119871;, and &#119871; stores the corresponding &#119877; &#8242; that satisfies these conditions as the value. Note that if there are multiple such &#119877; &#8242; where &#119873; &#119863; [&#119877; &#8242; ] is maximized under these conditions, it is irrelevant which &#119877; &#8242; is stored in &#119871;, because it is simple to look up the component that &#119877; &#8242; corresponds to using &#119906; &#119891; . That is to say, it is irrelevant which of 3&#119886;, 3&#119887;, and 3&#119888; we store for 4&#119886; in &#119871;, because we can look up the parent of 3&#119886;, 3&#119887;, and 3&#119888; in &#119906; &#119891; , which would resolve to the same parent. link-efficient updates &#119906; &#119891; and &#119871;, depending on the core numbers of the given &#119903; -cliques &#119877; and &#119876;. Tree Construction. We describe first how construct-tree-efficient constructs the hierarchy tree &#119879; given the specifications for &#119906; &#119891; and &#119871;. We refer to the construction shown in Figure <ref type="figure">5</ref>, where &#119906; &#119891; and &#119871; are given under "After Round 4" in Figure <ref type="figure">4</ref>.</p><p>The main idea for the construction is that if we begin with a hierarchy tree &#119879; consisting of only leaf nodes corresponding to each &#119903; -clique, the highest (bottom-most) level in which that leaf node may join a non-trivial connected component is the level corresponding to the leaf node's &#119903; -clique's (&#119903;, &#119904;)-clique core number. That is to say, starting from &#119894; = &#119896; and iterating to &#119894; = 1, an &#119903; -clique &#119877; is necessarily a singleton component from &#119894; = &#119896; to &#119894; = &#119873; &#119863; [&#119877;] + 1. The union-find structure &#119906; &#119891; denotes the parent of each leaf node on the level corresponding to its core number.</p><p>Then, once we have the connected components per level corresponding to each core number, it remains to describe how components with different core numbers are contained within each other. This containment is necessarily hierarchical, where components corresponding to larger core numbers are contained within successive components corresponding to smaller core numbers, as can be seen in Figure <ref type="figure">1</ref>. This containment is precisely what &#119871; describes; it points each component within a given core &#119894; to a component on the greatest core number &#119895; such that &#119895; &lt; &#119894;, where the two components are connected on level &#119895; (that is to say, connected through &#119903; -cliques with core numbers &#8805; &#119895;). Thus, using &#119871;, we can point each parent constructed using our &#119906; &#119891; to another parent, which represents the first instance (from the bottom up in &#119879; ) in which the original parent is merged into another component.</p><p>In more detail, in construct-tree-efficient, we begin with a hierarchy tree &#119879; consisting of isolated &#119903; -cliques (Line 29). For each component C = {&#119877; 1 , . . . , &#119877; &#119888; } in &#119906; &#119891; , representing a connected component of &#119903; -cliques with the same core number, we construct a parent in &#119879; , where its children are leaves corresponding to the &#119903; -cliques in C (Lines 30-31). C is one of these cliques, and is chosen arbitrarily. The new parent is &#119906; &#119891; C . This process is shown in Stage 1 in Figure <ref type="figure">5</ref>; each vertex has itself as its parent in &#119906; &#119891; , except the vertices 3&#119886;, 3&#119887;, and 3&#119888;, which have 3&#119887; as their parent. Thus, we create a new parent node &#119906; &#119891; 3&#119887; for the leaves 3&#119886;, 3&#119887;, and 3&#119888;.</p><p>Then, for each parent node &#119906; &#119891; C , we look up the nearest connected component that it should hierarchically connect to using &#119871;. What this means is that the component &#119906; &#119891; We make a subtle note that it is not strictly necessary to maintain parent nodes in the hierarchy tree with exactly one child; we can remove all such parents &#119875; and make the child &#119862; a direct child of its grandparent &#119866;. This is because it is inherently implied that the component that the child &#119862; represents in unchanged until it joins the component represented by &#119866;. For instance, &#119906; &#119891; 4&#119889; 's sole child is 4&#119889;. If we set 4&#119889; to be a direct child of its grandparent, &#119906; &#119891; 2&#119886; , and remove &#119906; &#119891; 4&#119889; , then it is implied that the vertex 4&#119889; remains its own component until it joins the 2-core containing 2&#119886; (and notably, 4&#119889; represents an unchanged component in the 3-core and in the 4-core of the graph). In this sense, the final hierarchy tree produced in Figure <ref type="figure">5</ref> is actually equivalent to that in Figure <ref type="figure">3</ref>. link Subroutine. We now describe link-efficient. The key to link-efficient is to properly maintain &#119906; &#119891; and &#119871; according to their definitions given new information obtained by connected &#119903; -cliques. The main subtlety is that after updating the connectivity information of &#119877; or &#119876;, in &#119906; &#119891; or in &#119871;, there may be cascading effects resulting in new calls to link-efficient.</p><p>In more detail, link-efficient first ensures that &#119873; &#119863; [&#119877;] &#8804; &#119873; &#119863; [&#119876;] (Line 5). We need only perform operations on the parents of the components of the &#119903; -cliques in &#119906; &#119891; , so we set &#119877; and &#119876; to their respective parents in &#119906; &#119891; (Line 6).</p><p>The first case is if &#119873; &#119863; [&#119877;] = &#119873; &#119863; [&#119876;] (Line 7). Then, we need only unite &#119877; and &#119876; in &#119906; &#119891; , to maintain that &#119906; &#119891; tracks the connectivity between &#119903; -cliques with the same core number (Line 8). However, the new parent &#119875; may now need to update its value in &#119871; based on &#119871;[&#119877;] and &#119871;[&#119876;]. This is because it is possible that &#119871;[&#119875;] must be updated; for instance, if &#119871;[&#119877;] has a strictly greater core number than the current &#119871;[&#119875;], &#119871;[&#119875;] must be updated to be &#119871; <ref type="bibr">[&#119877;]</ref>. link-efficient performs these updates by calling itself on &#119871;[&#119877;] and &#119875;, and on &#119871;[&#119876;] and &#119875;, if &#119875; &#8800; &#119877; and &#119875; &#8800; &#119876;, respectively (Lines 9-10).</p><p>The second case is if &#119873; &#119863; [&#119877;] &lt; &#119873; &#119863; [&#119876;] (Line 11). There are two main considerations. First, &#119877; may replace the current value of &#119871;[&#119876;], which we call &#119871;&#119876;, if &#119873; &#119863; [&#119877;] &gt; &#119873; &#119863; [&#119871;&#119876;]. Second, &#119877; and &#119871;&#119876; must be linked, since they are connected through &#119876; and could affect each other's parent or value in &#119906; &#119891; or &#119871;, respectively. We handle these cases with a series of if statements and compare-and-swaps.</p><p>We first perform a compare-and-swap, checking if &#119871;[&#119876;] is empty and replacing it with &#119877; if so (Line 15); if this compare-and-swap succeeds, then there is still the possibility that &#119876;'s parent in &#119906; &#119891; changed before the compare-and-swap completed, in which case &#119876;'s new parent is unaware of its connection to &#119877;. In this scenario, we must call link-efficient again on &#119877; and the new parent of &#119876;, since &#119877; could potentially modify the &#119903; -clique stored in &#119871; corresponding to &#119876;'s new parent (Lines <ref type="bibr">[16]</ref><ref type="bibr">[17]</ref>.</p><p>If the previous compare-and-swap failed, then we check if &#119873; &#119863; [&#119871;&#119876;] &lt; &#119873; &#119863; [&#119877;] (Line 19), which if true, means that &#119877; is a candidate to replace &#119871;&#119876; in &#119871;. We perform another compare-and-swap to replace &#119871;&#119876; with &#119877; (Line 20), and if it succeeds, we must again check if &#119876;'s parent in &#119906; &#119891; has potentially changed before the compare-and-swap completed. Again, if this occurs, we must call link-efficient on &#119877; and the new parent &#119876; (Lines 21 <ref type="bibr">-22)</ref>. We must also call link-efficient on &#119877; and &#119871;&#119876; (Line 23), to store &#119877;'s connectivity to &#119871;&#119876;. This is because &#119877;'s "nearest" core as stored in &#119871; may be superseded by &#119871;&#119876;. If the compare-and-swap fails, we simply try again, hence the while loop (Line 12).</p><p>The last case is if &#119873; &#119863; [&#119871;&#119876;] &#8805; &#119873; &#119863; [&#119877;] (Line 25), in which case &#119877; is not a candidate to replace &#119871;&#119876; in &#119871;, and we store &#119877;'s connectivity to &#119876; by calling link-efficient on &#119877; and &#119871; <ref type="bibr">[&#119876;]</ref>. Note that this is necessary because &#119877; and &#119871;[&#119876;] could be united in &#119906; &#119891; if they have the same core number, or &#119877; could be a "nearest" core to &#119871;[&#119876;].</p><p>This concludes our efficient link subroutine, link-efficient. We show in Section 8.1 that linkefficient performs many fewer unite and link operations, and achieves significant speedups, over link-basic. We provide an example of running link-efficient. Example of link-efficient. As an example of these cascading effects, we refer to an intermediate state of &#119906; &#119891; and &#119871; on the example graph in Figure <ref type="figure">1</ref>, given after the third round of peeling in arb-nucleus-decomp-hierarchy-framework (immediately before peeling the final set of vertices in the graph, given by the components 4&#119886;, 4&#119887;, 4&#119888;, and 4&#119889;). This state is shown in the data structures under "After Round 3" in Figure <ref type="figure">4</ref>. In &#119906; &#119891; , every vertex is its own parent, and in &#119871;, we have identified that the component corresponding to 3&#119886; is connected to 1&#119886;. Note that many link operations occur from peeling 4&#119886;, 4&#119887;, 4&#119888;, and 4&#119889;, including for the (&#119877;, &#119876;) pairs (3&#119886;, 4&#119888;), (3&#119887;, 4&#119888;), and (2&#119886;, 4&#119888;), which we consider in this example. We show in Figure <ref type="figure">4</ref> the state of &#119906; &#119891; and &#119871; after each of these three calls to link-efficient (including the cascading calls that these calls generate). We list the &#119877; and &#119876; for each link-efficient operation, as well as the cascading calls that they invoke. We assume the operations happen sequentially for clarity, although in practice they can happen concurrently.</p><p>&#8226; &#119877; = 3&#119886;, &#119876; = 4&#119888;: We now know that 4&#119888; is connected to 3&#119886;'s component, and 4&#119888; does not have a previously set "nearest" core, so we set &#119871;[4&#119888;] = 3&#119886; (Line 15). &#8226; &#119877; = 3&#119887;, &#119876; = 4&#119888;: We note that &#119871;[4&#119888;] is now already set to a "nearest" core with core number 3, so there is nothing new to update for &#119871;[&#119876;]. However, we gain from this new link the knowledge that 3&#119886; and 3&#119887; are connected (since &#119871;[4&#119888;] = 3&#119886;), so we must cascade a new link-efficient call to (&#119877;, &#119871;[&#119876;]) = (3&#119887;, 3&#119886;) (Line 26), so that 3&#119886; and 3&#119887; can be set to the same component in &#119906; &#119891; .</p><p>-&#119877; = 3&#119886;, &#119876; = 3&#119887;: We now call unite on 3&#119886; and 3&#119887; in &#119906; &#119891; (Line 8). Say that arbitrarily, 3&#119887; is set as the new parent of 3&#119886; and 3&#119887; in &#119906; &#119891; . Since the parents in &#119906; &#119891; are responsible for maintaining the connection to the "nearest" core, we must transfer</p><p>We do so by calling link-efficient on (&#119871;[&#119877;], &#119906; &#119891; .parent(&#119877;)) = (1&#119886;, 3&#119887;) (Line 9). * &#119877; = 1&#119886;, &#119876; = 3&#119887;: Now, we can set &#119871;[&#119876;] = &#119871;[3&#119887;] to &#119877; = 1&#119886;, since 3&#119887;'s "nearest" core is now 1&#119886; (Line 15).</p><p>&#8226; &#119877; = 2&#119886;, &#119876; = 4&#119888;: Since 4&#119888; already has an entry in &#119871; that's "nearer" to it than 2&#119886;, there is nothing new to update for &#119871; <ref type="bibr">[&#119876;]</ref>. However, we now know that 3&#119886; and 2&#119886; are connected, so we must cascade a new link-efficient call to (&#119877;, &#119871;[&#119876;]) = (2&#119886;, 3&#119886;) (Line 26).</p><p>-&#119877; = 2&#119886;, &#119876; = 3&#119886;: Since the parent of &#119876; in &#119906; &#119891; is 3&#119887;, we can treat this as &#119877; = 2&#119886; and &#119876; = 3&#119887; (since we only need to maintain connections in &#119871; for the parents in &#119906; &#119891; ). Now, we find that 3&#119887; has recorded its "nearest" core as &#119871;[3&#119887;] = 1&#119886;, but 2&#119886; is "nearer". Thus, we update &#119871;[3&#119887;] to be 2&#119886; (Line 20), but now we know that 2&#119886; is connected to 1&#119886;. So, we call link-efficient on (&#119877;, &#119871;[&#119876;]) = (2&#119886;, 1&#119886;) (Line 23). * &#119877; = 1&#119886;, &#119876; = 2&#119886;: We discover that 2&#119886;'s "nearest" core is given by 1&#119886;. We set</p><p>Note that it is necessary for us to perform these cascading calls to link-efficient, because the only way for 3&#119886; and 3&#119887; to discover that they should be connected is through one of the 4-core components, and the only way for 3&#119887; to realize that the component with 2&#119886; is its "nearest" core is also through one of the 4-core components. Similarly, the only way for 2&#119886; to realize that the component with 1&#119886; is its "nearest" core is through first one of the 4-core components, then through the 3-core component, in which 3&#119886;, which we now know is connected to 3&#119887;, had the original adjacency to 1&#119886;. Thus, information must be constantly propagated through &#119906; &#119891; and &#119871;. Comparison to Prior Work. Sariy&#252;ce and Pinar <ref type="bibr">[49]</ref> also provide a hierarchy construction algorithm, nh, that is performed interleaved with the peeling process. They maintain a union-find data structure that stores the connectivity of all &#119903; -cliques considering only &#119903; -cliques with the same core number. However, for adjacent &#119903; -cliques with different core numbers, they simply store all pairs of such &#119903; -cliques in a list. They process this list after the peeling process to construct the hierarchy tree, and their method for processing this list requires a global view, since nh first sorts the pairs of &#119903; -cliques in the list based on their core numbers. Storing this list incurs additional space potentially proportional to the number of &#119904;-cliques in the graph, which is a significant overhead.</p><p>Our main innovation in link-efficient is that we need only incur additional space overhead proportional to the number of &#119903; -cliques in the graph, because we process adjacent &#119903; -cliques with different core numbers while performing the peeling process. We are able to process this information into a hash table &#119871; proportional to the number of &#119903; -cliques, so our memory overhead overall is 2&#119899; &#119903; , where &#119899; &#119903; is the number of &#119903; -cliques. In contrast, nh uses &#119904; &#119903; &#8226; &#119899; &#119904; + &#119899; &#119903; additional space, where &#119899; &#119904; is the number of &#119904;-cliques. In addition, nh is sequential, whereas link-efficient is thread-safe and carefully resolves conflicts in updating &#119906; &#119891; and &#119871;. Also, the post-processing step to construct the hierarchy tree in nh involves many sequential dependencies, where even merges on the same level of the tree may conflict with each other, whereas our post-processing step, construct-treeefficient, is fully parallel.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="7.4">Practical Version of arb-nucleus-hierarchy</head><p>Finally, we make certain optimizations to our theoretically-efficient (&#119903;, &#119904;) nucleus decomposition hierarchy algorithm, arb-nucleus-hierarchy (Algorithm 1) to improve its performance in practice. We maintain the two-pass paradigm of first computing the (&#119903;, &#119904;)-clique core numbers of each &#119903;clique and then constructing the hierarchy tree &#119879; . However, we do not explicitly store linked lists containing all pairs of &#119904;-clique-adjacent &#119903; -cliques, since this represents too much of a memory overhead to be practical, particularly for larger &#119903; and &#119904;. We also do not explicitly generate the graph &#119867; given by these linked lists (Line 14).</p><p>Instead, we use a single union-find data structure to maintain the connected components (throughout the loop on Lines 12-20), and for each &#119894; &#8712; {&#119896;, &#119896; -1, . . . , 1} (Line 12), we iterate through all &#119903; -cliques &#119877; with core number &#119894; and their &#119904;-clique-adjacent &#119903; -cliques &#119877; &#8242; . We perform a parallel sort on the &#119903; -cliques based on their core numbers, which allows us to efficiently extract &#119903; -cliques</p><p>&#119899; &#119898; amazon 334,863 925,872 dblp 317,080 1,049,866 youtube 1,134,890 2,987,624 skitter 1,696,415 11,095,298 livejournal 3,997,962 34,681,189 orkut 3,072,441 117,185,083 friendster 65,608,366 1.806 &#215; 10 9</p><p>Table <ref type="table">1</ref>. Sizes of our input graphs, which are from SNAP <ref type="bibr">[37]</ref>.</p><p>with the same core numbers; this adds a small additional memory overhead, which we observe in Section 8.1. For each such pair of &#119903; -cliques &#119877; and &#119877; &#8242; where &#119873; &#119863; [&#119877; &#8242; ] &#8805; &#119873; &#119863; [&#119877;], we directly unite them in our union-find data structure to obtain the desired connected components; this replicates the same information stored in the linked lists (on Lines 6-8). We construct the requisite new parents in the hierarchy tree &#119879; given the computed connected components, and we reuse the same union-find data structure for subsequent &#119894;.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="8">Evaluation</head><p>Environment and Inputs. We run our experiments on a Google Cloud Platform instance with a 30-core machine with two-way hyper-threading, with 3.9 GHz Intel Cascade Lake processors and 240 GB of main memory. We use all cores when testing parallel implementations, unless specified otherwise. Our implementations are written in C++ and we compile our code using g++ (version 7.4.0) with the -O3 flag. We use parallel primitives and the work-stealing scheduler from ParlayLib by Blelloch et al. <ref type="bibr">[6]</ref>. We terminate any experiment that takes over 4 hours. We test our algorithms on real-world graphs from the Stanford Network Analysis Project (SNAP) <ref type="bibr">[37]</ref>, shown in Table <ref type="table">1</ref>.</p><p>We implement all three versions of our exact (&#119903;, &#119904;) nucleus decomposition hierarchy algorithms, including our theoretically-efficient arb-nucleus-hierarchy (Algorithm 1, with the optimizations described in Section 7.4), which we call anh-te, and our nucleus decomposition hierarchy framework arb-nucleus-decomp-hierarchy-framework (Algorithm 3) using both link-basic (Algorithm 4) and link-efficient (Algorithm 5), which we call anh-bl and anh-el, respectively.</p><p>We also implement our approximate (&#119903;, &#119904;) nucleus decomposition hierarchy algorithm, arbapprox-nucleus-hierarchy (using Algorithm 2). We integrate approx-arb-nucleus with each of anh-te, anh-el, and anh-bl for the hierarchy construction, giving us three implementations, approx-anh-te, approx-anh-el, and approx-anh-bl, respectively.</p><p>We compare our hierarchy algorithms to nh, the state-of-the-art sequential (&#119903;, &#119904;) nucleus decomposition hierarchy implementation by Sariy&#252;ce and Pinar <ref type="bibr">[49]</ref> for (1, 2), (2, 3), and (3, 4) nucleus decomposition. Note that nh does not generalize to other &#119903; and &#119904; values. nh, like anh-bl and anh-el, constructs the hierarchy while computing the (&#119903;, &#119904;)-clique-core numbers of the graph. For the special case of &#119896;-core, we also compare to phcd, the state-of-the-art parallel &#119896;-core hierarchy implementation by Chu et al. <ref type="bibr">[11]</ref>. 8.1 Comparison of anh-te, anh-el, and anh-bl Figure <ref type="figure">6</ref> compares our exact (&#119903;, &#119904;) nucleus decomposition hierarchy algorithms, anh-te, anh-el, and anh-bl, against each other, for various &#119903; and &#119904;. We show &#119903; &lt; &#119904; &#8804; 5 here, but we ran all of our algorithms for &#119903; &lt; &#119904; &#8804; 7. Also, the running times listed in these figures do not include the time needed to compute the low out-degree orientation or to compute the initial &#119904;-clique-degrees of each &#119903; -clique, which are the same across all of our algorithms (note that we do include these times when comparing to other work in Section 8.2). However, our running times do include the time required to compute the (&#119903;, &#119904;)-clique-core numbers of each &#119903; -clique, which notably for anh-te is given by arb-nucleus from <ref type="bibr">[55]</ref>.</p><p>Parallel Algorithms for Hierarchical Nucleus Decomposition 32:21 1 amazon (0.034 s) dblp (0.058 s) youtube (0.12 s) skitter (0.28 s) livejournal (1.03 s) orkut (2.61 s) friendster (35.53 s) 0 20 40 60 80 100 120 140 160 180 200 220 240 260 280 Multiplicative slowdowns (1, 2) ANH-TE ANH-EL ANH-BL amazon (0.074 s) dblp (0.098 s) youtube (0.3 s) skitter (2.82 s) livejournal (8.64 s) orkut (36.56 s) friendster (436.28 s) 0 1 2 3 4 5 6 7 8 9 10 11 12 Multiplicative slowdowns (2, 3) ANH-TE ANH-EL ANH-BL 1 amazon (0.12 s) dblp (2.67 s) youtube (4.22 s) skitter (75.51 s) friendster (1141.32 s)</p><p>0 10 20 30 40 50 60 70 80 Multiplicative slowdowns (2, 4) ANH-TE ANH-EL ANH-BL amazon (0.09 s) dblp (80.69 s) youtube (9.38 s) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Multiplicative slowdowns (2, 5) ANH-TE ANH-EL ANH-BL amazon (0.1 s) dblp (1.39 s) youtube (3.2 s) skitter (42.59 s) livejournal (652.26 s) orkut (1091.51 s) 0 1 2 3 4 5 6 7 8 9 10 Multiplicative slowdowns (3, 4) ANH-TE ANH-EL ANH-BL amazon (0.07 s) dblp (88.32 s) youtube (8.18 s) 1 2 3 4 5 6 7 8 9 10 11 12 13 Multiplicative slowdowns (3, 5) ANH-TE ANH-EL ANH-BL amazon (0.058 s) dblp (51.63 s) youtube (7.09 s) skitter (478.27 s) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Multiplicative slowdowns (4, 5)</p><p>ANH-TE ANH-EL ANH-BL Fig. <ref type="figure">6</ref>. Multiplicative slowdowns of our parallel nucleus decomposition hierarchy implementations anh-te, anh-el, and anh-bl, over the fastest of the three for each graph, for &#119903; &lt; &#119904; &#8804; 5. We have omitted bars where our implementations run out of memory or time out after 4 hours, and we have omitted graphs where only one of anh-te, anh-el, and anh-bl completes. Below each graph in parentheses is the fastest running time among the three implementations. We have also included a line marking a multiplicative slowdown of 1.</p><p>Overall, we find that anh-el is faster if the difference between &#119904; and &#119903; is small (generally, if &#119904; -&#119903; &#8804; 2), and anh-te is faster in all other cases. The exception is for &#119896;-core (or (1, 2)-nucleus) decomposition, where anh-te is 2.38-21.95x faster than anh-el. This is because the &#119896;-core decomposition requires far lower overhead to compute the core numbers per vertex compared to higher &#119903; and &#119904;, since we need only maintain the degree of each vertex. The benefit of anh-el is due to the improved locality in iterating over and processing &#119904;-cliques once, rather than recomputing the &#119904;-cliques twice. This is not a benefit for &#119896;-core, because iterating over edges is a much simpler and cache-friendly pattern. Also, anh-bl is significantly slower than both anh-te and anh-el, and runs out of memory for many values of &#119903; and &#119904;, since it has a much larger memory footprint from storing a union-find structure per core number. Overall, anh-el is up to 2.37x faster than anh-te, and anh-te is up to 41.55x faster than anh-el, where we see the largest speedups in anh-te over anh-el when &#119904; is much larger than &#119903; . anh-bl is up to 14.55x slower than anh-el, and up to 11.96x slower than anh-te.</p><p>The cases in which anh-el outperforms anh-te and vice versa, and the reason for the slowness of anh-bl, is due to the number of link and unite operations. Indeed, for the dblp and youtube graphs, particularly for larger &#119903; and when the difference between &#119903; and &#119904; is small, the number of times in which anh-te calls link and unite is 1.08-13.67x the number of times in which anh-el calls link and unite. For smaller &#119903; and when the difference between &#119903; and &#119904; is large, anh-el calls link and unite between 1.02-18.94x more than anh-te. Looking at fixed &#119903; and increasing &#119904;, we observe that anh-el performs many more cascading calls to itself as &#119904; increases, since &#119904; &#119903; increases and anh-el more likely needs to connect two &#119903; -cliques across multiple levels of the hierarchy tree. anh-bl is much slower than both anh-te and anh-el, performing up to 39.75x the number of link and unite calls. anh-bl repeatedly performs unite operations equal to the core number of each &#119903; -clique, which can be redundant, since if two &#119903; -cliques are connected in a higher core, they are necessarily connected in the lower core.</p><p>In terms of memory usage, considering the memory overhead of building and constructing the hierarchy (not including the space required to store the graph or the (&#119903;, &#119904;)-clique-core numbers of each &#119903; -clique), on dblp and youtube, anh-bl uses 1.53-10.03x the amount of overhead that anh-el uses, and anh-te uses 1.08-1.11x the amount of overhead that anh-el uses. We observe</p><p>10 2 10 3 10 4 amazon (0.002 s) dblp (0.058 s) youtube (0.12 s) skitter (0.28 s) livejournal (1.03 s) orkut (2.61 s) friendster (35.53 s) 0 5 10 15 20 25 30 35 40 45 50 Multiplicative slowdowns (1, 2) (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (3, 5) (3, 6) (3,7) (4,5) (4,6) (4, 7) (5,6) (5,7) (6,7) Fig. 7. Multiplicative slowdowns of parallel arbnucleus-hierarchy for each (&#119903;, &#119904;) combination over the fastest running time for parallel arb-nucleushierarchy across all &#119903; &lt; &#119904; &#8804; 7 for each graph, considering the fastest of anh-te, anh-el, and anh-bl. The fastest time is labeled in parentheses below each graph. We have omitted bars where arb-nucleus-hierarchy runs out of memory or times out after 4 hours. 1 2 4 8 16 30 30h 0 5 10 15 20 25 30 Number of workers Speedup over single-threaded (2, 3) dblp (2, 4) dblp (2, 5) dblp (3, 4) dblp (3, 5) dblp (4, 5) dblp (2, 3) skitter (2, 4) skitter (3, 4) skitter (4, 5) skitter 1 2 4 8 16 30 30h 0 5 10 15 20 25 30 Number of workers Speedup over single-threaded (2, 3) dblp (2, 4) dblp (2, 5) dblp (3, 4) dblp (3, 5) dblp (4, 5) dblp (2, 3) skitter (2, 4) skitter (3, 4) skitter (4, 5) skitter that anh-el is the most memory efficient overall, since it only maintains two arrays proportional to the number of &#119903; -cliques (&#119906; &#119891; and &#119871;). anh-te incurs almost the same memory overhead, with a minor additional cost attributed to maintaining &#119903; -cliques sorted by their core numbers (which we discuss in Section 7.4), and anh-bl incurs much more overhead to maintain union-find data structures proportional to the number of &#119903; -cliques per core number.</p><p>To provide some context into how long the hierarchy construction takes compared to the coreness computation, we measured the time for just computing coreness values and compared it to the total time for each of our algorithms. The coreness computation time represents 46.53%, 35.26%, and 36.08% of the total time on average in anh-el, anh-bl, and anh-te, respectively. Note that this ignores the locality effects of interleaving the computations in anh-el and anh-bl. Nevertheless, we see that on average, anh-el spends the least amount of time on hierarchy construction, indicating the effectiveness of our optimizations.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="8.2">Performance of Exact Hierarchy</head><p>Figure <ref type="figure">7</ref> shows the best running times for all graphs, over &#119903; &lt; &#119904; &#8804; 7, considering all of our exact (&#119903;, &#119904;) nucleus decomposition hierarchy algorithms, anh-te, anh-el, and anh-bl, excluding the time needed to compute our low out-degree orientation and the initial &#119904;-clique-degrees of each &#119903; -clique. In general, larger (&#119903;, &#119904;) values correspond to longer running times. However, some of the times for larger values of (&#119903;, &#119904;) are faster than for smaller values of (&#119903;, &#119904;) (especially on amazon) because the maximum coreness values for the larger values of (&#119903;, &#119904;) are small and the algorithms finish quickly.</p><p>Figure <ref type="figure">8</ref> shows the scalability of anh-te and anh-el over different numbers of threads on dblp and skitter, and we see good scalability overall. Across all of our graphs and for &#119903; &lt; &#119904; &#8804; 7, we observe up to 24.75x self-relative speedups (and a median of 15.57x) for anh-te and up to 30.96x self-relative speedups (and a median of 14.13x) for anh-el. Generally, we observe greater self-relative speedups for larger &#119903; and &#119904; and for larger graphs. Comparison to Other Implementations. Figure <ref type="figure">9</ref> shows the comparison of our parallel (1, 2), (2, 3), and (3, 4) nucleus decomposition hierarchy implementations to other implementations. Note that here, we include in our implementations the time needed to compute the low out-degree orientation and to compute the initial &#119904;-clique-degrees of each &#119903; -clique. We do not include the time required to load the graph in both our and other implementations.</p><p>For (1, 2) nucleus (&#119896;-core) decomposition, we compare to the parallel phcd <ref type="bibr">[11]</ref> and the sequential nh <ref type="bibr">[49]</ref>. Our fastest implementation for &#119896;-core is anh-te, and we see that anh-te is up to 2.57x slower than phcd overall, but 1.87x faster than phcd on dblp. We note that phcd is optimized</p><p>Parallel Algorithms for Hierarchical Nucleus Decomposition 32:23 1 amazon (0.031 s) dblp (0.058 s) youtube (0.1 s) skitter (0.18 s) livejournal (0.49 s) orkut (1.02 s) friendster (32 s)</p><p>0 5 10 15 20 25 30 35 40 45 50 55 60 Multiplicative slowdowns (1, 2) ANH-TE (parallel) PHCD (parallel) NH (sequential) ANH-TE (single-threaded) 1 amazon (0.097 s) dblp (0.12 s) youtube (0.35 s) skitter (2.89 s) livejournal (9.29 s) orkut (40.43 s) friendster (526.3 s) 0 5 10 15 20 25 30 35 40 45 50 55 Multiplicative slowdowns (2, 3) ANH-TE (parallel) ANH-EL (parallel) NH (sequential) ANH-TE (single-threaded) ANH-EL (single-threaded) 1 amazon (0.12 s) dblp (1.5 s) youtube (3.27 s) skitter (43.46 s) livejournal (677.92 s) orkut (1113.85 s) 0 5 10 15 20 25 30 35 40 Multiplicative slowdowns (3, 4) ANH-TE (parallel) ANH-EL (parallel) NH (sequential)</p><p>ANH-TE (single-threaded) ANH-EL (single-threaded) Fig. <ref type="figure">9</ref>. Multiplicative slowdowns, comparing anh-te, anh-el, the parallel phcd <ref type="bibr">[11]</ref>, and the sequential nh <ref type="bibr">[49]</ref>, for (1, 2), (2, 3), and (3, 4) nucleus decomposition. We give the multiplicative slowdown over the fastest implementation for each graph and each (&#119903;, &#119904;), where the fastest running time is labeled in parentheses below each graph. We include end-to-end running times in this comparison, excluding only the time required to load the graph. We have omitted bars where the implementation runs out of memory or times out after 4 hours. We have also included a line marking a multiplicative slowdown of 1. for the &#119896;-core decomposition, rather than general (&#119903;, &#119904;) nucleus decomposition, whereas anh-te generalizes for larger &#119903; and &#119904;. Like anh-te, phcd constructs the hierarchy tree from the bottom-up after computing the core numbers of each vertex, but unlike anh-te, phcd leverages the information from computing the core numbers to optimize for the &#119896;-core hierarchy, by reordering vertices based on their core numbers. This optimization allows them to more efficiently divide the work of constructing the hierarchy across different threads, and allows them to reduce the work in practice when iterating over the neighbors of a vertex &#119907; with larger core numbers than that of &#119907;. Compared to the sequential nh, anh-te is 4.67-58.84x faster, particularly on larger graphs. For (1, 2), (2, 3), and (3, 4) nucleus decomposition, we compare our parallel anh-te and anh-el to the sequential nh <ref type="bibr">[49]</ref>. Considering the fastest of anh-te and anh-el for each graph, our implementations are 3.76-23.54x faster, demonstrating that we achieve good speedups from our use of parallelization. Sequentially, our fastest algorithm is between 2.02x faster and 4.2x slower than nh. We get slowdowns due to the additional overheads of parallel subroutines and the fact that our code has a general structure for supporting arbitrary (&#119903;, &#119904;) values, whereas the code of <ref type="bibr">[49]</ref> is specialized for the specific values of (1, 2), (2, 3), and (3, 4). These slowdowns are somewhat counteracted by our faster clique enumeration algorithm, leading to speedups in some cases. Usefulness of the Hierarchy. In Figure <ref type="figure">10</ref>, we show the edge densities of various (2, &#119904;)-nuclei in the youtube graph. The edge density of a subgraph &#119878; is defined to be the number of edges in &#119878; divided by |&#119878; |  2 (the total possible number of edges). Edge density is the metric used to evaluate the quality of subgraphs from nucleus decompositions <ref type="bibr">[52]</ref>, and finding dense subgraphs subject to a size constraint has important applications.</p><p>For a fixed &#119903; and &#119904;, having the nucleus hierarchy enables us to efficiently find all of the &#119888;-(&#119903;, &#119904;) nuclei for any value of &#119888; by simply removing all internal nodes corresponding to &#119888; &#8242; -(&#119903;, &#119904;) nuclei for &#119888; &#8242; &lt; &#119888;, and having each resulting subtree be a &#119888;-(&#119903;, &#119904;) nucleus that contains all of its leaves. On the other hand, given only the core numbers and no hierarchy, to find the &#119888;-(&#119903;, &#119904;) nuclei for a given value of &#119888;, one would need to run connected components on all &#119903; -cliques with core number &#8805; &#119888;, with connectivity defined by &#119904;-clique adjacency, which is much more expensive than simply cutting the hierarchy. Indeed, Figure <ref type="figure">10</ref> shows the time needed to generate all (2, &#119904;) nuclei for various values of &#119904; with and without the hierarchy for the youtube graph. We see that using the hierarchy is 5.84-834.09x faster than not using the hierarchy.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="8.3">Performance of Approximate Hierarchy</head><p>We considered &#120575; = 0.1, 0.5, and 1 for our experiments for approximate (&#119903;, &#119904;) nucleus decomposition (&#120575; is the approximation parameter in Algorithm 2). We first compare approx-arb-nucleus to arb-nucleus <ref type="bibr">[55]</ref> and see a speedup of up to 16.16x for &#120575; = 0.1, up to 8.35x for &#120575; = 0.5, and up to 10.88x for &#120575; = 1.</p><p>Besides the computation of the (&#119903;, &#119904;)-clique-core numbers, approx-anh-te, approx-anh-el, and approx-anh-bl are identical to anh-te, anh-el, and anh-bl, respectively. In other words, their hierarchy construction procedure is the same. We observe up to a 3.3x speedup considering the fastest of our approximate algorithms for each graph and &#119903; &lt; &#119904; &#8804; 7, over the fastest of our exact algorithms. Notably, for &#120575; = 0.1, we are able to compute the (2, 5) nucleus decomposition hierarchy on friendster in 8783.2 seconds, where our exact implementations timeout at 4 hours. The improvements in running time using our approximate algorithms are lower than when comparing approx-arb-nucleus to arb-nucleus <ref type="bibr">[55]</ref> because even in our approximate algorithms, &#119904;-cliques must be exactly counted per &#119903; -clique, and much of the time is spent doing this.</p><p>In terms of accuracy, the average error in the (&#119903;, &#119904;)-clique-core number per &#119903; -clique is relatively low for all of our &#120575; values. For &#120575; = 0.1, across all of our graphs and for &#119903; &lt; &#119904; &#8804; 7, our coreness estimates per &#119903; -clique are have a multiplicative error of 1-2.92x on average (with a median of 1.33x) compared to the exact coreness numbers. For &#120575; = 0.5, the coreness estimates range from having a multiplicative error of 1-2.92x on average as well, with a median of 1.34x, and for &#120575; = 1, the coreness estimates range from having a multiplicative error of 1-3.05x on average, with a median of 1.35x. The multiplicative errors of the maximum (&#119903;, &#119904;)-clique-core number, across all graphs and for &#119903; &lt; &#119904; &#8804; 7, are also reasonably low, with a median of 1.6x for &#120575; = 0.1, a median of 2x for &#120575; = 0.5, and a median of 2x for &#120575; = 1. The maximum multiplicative error for a given &#119903; -clique is 6.73x for &#120575; = 0.1, 6.98x for &#120575; = 0.5, and 7.32x for &#120575; = 1, but these arise for large &#119904;, notably when &#119903; = 5 and &#119904; = 7 for all &#120575;, and these errors are still much lower than the theoretical guarantee of ( &#119904; &#119903; + &#120575;) &#8226; (1 + &#120575;) given by Theorem 6.1. Note that the theoretical bound is a worst case bound. In practice, (&#119903;, &#119904;)-cliques whose core numbers are close to the end of the range of each bucket will have a much better approximation. Furthermore, graphs with a low peeling complexity will likely have more (&#119903;, &#119904;)-cliques peeled before moving to the next round (Line 17 of Algorithm 2), which will make the approximation better.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="9">Conclusion</head><p>We have presented new parallel exact and approximate algorithms for nucleus hierarchy construction with strong theoretical guarantees. We have developed optimized implementations of our algorithms, which interleave the coreness number computation with the hierarchy construction. Our experiments showed that our implementations outperform state-of-the-art implementations while achieving good parallel scalability.</p></div><note xmlns="http://www.tei-c.org/ns/1.0" place="foot" xml:id="foot_0"><p>Proc. ACM Manag. Data, Vol. 2, No. 1 (SIGMOD), Article 32. Publication date: February 2024.</p></note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" n="1" xml:id="foot_1"><p>We say &#119874; (&#119891; (&#119899;) ) with high probability (w.h.p.) to indicate &#119874; (&#119888; &#119891; (&#119899;) ) with probability at least 1 -&#119899; -&#119888; for &#119888; &#8805; 1, where &#119899; is the input size.Proc. ACM Manag. Data, Vol.</p></note>
			<note xmlns="http://www.tei-c.org/ns/1.0" place="foot" xml:id="foot_2"><p>2, No. 1 (SIGMOD), Article 32. Publication date: February 2024.</p></note>
		</body>
		</text>
</TEI>
