Bubble Tree: private API
The bubble tree is the first half of the seam behind DBHTs: every function on this page and on DBHT Dendrogram reads matrices alone, so each is driven directly from a hand-built bubble structure in test/test_13f_dbht_seam.jl, and a wrong answer is caught at its own step rather than diagnosed backwards from the final clustering. Hb is sparse throughout, because DirectHb cuts an edge out of a copy of it.
PortfolioOptimisers.BubbleHierarchy — Function
BubbleHierarchy(Pred::VecNum, Sb::VecNum)Build the bubble hierarchy from the clique hierarchy and separating set information.
This function constructs the bubble hierarchy tree and the bubble membership matrix for 3-cliques, given the predicted parent indices (Pred) and separating set vector (Sb). It is a core step in the DBHT (Direct Bubble Hierarchical Tree) clustering pipeline, grouping 3-cliques into bubbles and building the adjacency structure among bubbles.
Algorithm
- Take
Root, the cliques whose entry ofPredis zero, and mark them inCliqCount. - When more than one root exists, open one bubble that holds all of them, as the first column of
Mb. - For each root
n, open a bubble that holdsnand its direct children — the cliques whose parent isn— append it as a column ofMb, and mark those children inCliqCount. - Collect as the next roots the direct children whose separating set is non-empty,
Sb[.] != 0. - Repeat from step 3 until
CliqCountmarks every clique. - Build
H: two bubbles are neighbours when at least one 3-clique belongs to both. - Symmetrise
Hand clear its diagonal, so a bubble is not its own neighbour.
Arguments
Pred:Nc×1vector of predicted parent indices for each 3-clique, as returned byBuildHierarchy.Sb:Nc×1vector indicating the size of the separating set for each 3-clique (Sb[n] ≠ 0means cliquenis separating).
Returns
H::SparseMatrixCSC{Int, Int}:Nb×Nbsymmetric adjacency matrix representing the bubble hierarchy tree, whereNbis the number of bubbles.Mb::Matrix{Int}:Nc×Nbbubble membership matrix for 3-cliques.Mb[n, bi] = 1indicates that 3-cliquenbelongs to bubblebi.
Related
PortfolioOptimisers.DirectHb — Function
DirectHb(Rpm::MatNum, Hb::MatNum,
Mb::MatNum, Mv::MatNum,
CliqList::MatNum)Compute the directed bubble hierarchy tree (DBHT) for a Maximal Planar Graph (MPG).
This function assigns directions to each separating 3-clique in the undirected bubble tree of a Planar Maximally Filtered Graph (PMFG), producing the directed bubble hierarchy tree (DBHT). The direction is determined by comparing the sum of edge weights on either side of each separating clique, enabling the identification of converging and diverging bubbles.
Mathematical definition
Each edge of the bubble tree carries one separating 3-clique. Cutting the edge splits the bubbles into two sides, and the mass each side draws through the clique decides the direction.
\[m(\mathcal{V}) = \sum_{u \in \mathcal{V}_{0}} \sum_{v \in \mathcal{V}} R_{u,\,v}\,.\]
Where:
- $R_{u,\,v}$: Weight of the PMFG edge between vertices $u$ and $v$.
- $\mathcal{V}_{0}$: The three vertices of the separating clique.
- $\mathcal{V}$: Vertices of one side of the cut, with $\mathcal{V}_{0}$ removed.
- $m(\mathcal{V})$: Mass the clique draws from that side.
The edge is directed towards the heavier side, so a bubble that draws mass from both of its neighbours has no outgoing edge and is a converging bubble.
Algorithm
- Reduce
Hbto binary, and read the row and column index of each edge of its upper triangle. - For each such edge, find the 3-cliques that both of its bubbles hold, and record
(row, column, clique)as a row ofCliqEdge. - For each row of
CliqEdge, remove that edge from a copy ofHb, runbreadthfrom bubble1, and mark every bubble it did not reach with-1. - Split the two bubbles of the edge into
bleft, the one on the reached side, andbright, the one on the cut side. - Collect
vleftandvright, the vertices of the bubbles of each side, and remove from both the three verticesvoof the separating clique. - Sum the PMFG weights from
vointo each side, givingleftandright, and write the heavier of the two intoHcas an edge directed towards the heavier side. - Set
Sep[b] = 1for a bubble with no outgoing edge inHc, then setSep[b] = 2for a bubble with no incoming edge that has more than one neighbour inHb.
Arguments
Rpm:N × Nsparse weighted adjacency matrix of the PMFG.Hb:Nb×Nbundirected bubble tree of the PMFG (as fromBubbleHierarchy). A non-zero entry joins two bubbles.Mb:Nc×Nbbubble membership matrix for 3-cliques.Mb[n, bi] = 1indicates 3-cliquenbelongs to bubblebi.Mv:N × Nbbubble membership matrix for vertices.Mv[n, bi] = 1means vertexnis a vertex of bubblebi.CliqList:Nc×3matrix. Each row lists the three vertices of a 3-clique in the MPG.
Returns
Hc::SparseMatrixCSC{Number, Int}:Nb×Nbdirected adjacency matrix of the DBHT. A non-zeroHc[i, j]is a directed edge from bubbleito bubblej, and its value is the mass of the heavier side.Sep::Vector{Int}:Nb×1vector of the type of each bubble.1is a converging bubble, which has no outgoing edge inHc.2is a diverging bubble, which has no incoming edge and more than one neighbour inHb.0is every other bubble.
Related
PortfolioOptimisers.BubbleCluster8s — Function
BubbleCluster8s(Rpm::MatNum, Dpm::MatNum,
Hb::MatNum, Mb::MatNum,
Mv::MatNum, CliqList::MatNum)Obtain non-discrete and discrete clusterings from the bubble topology of the Planar Maximally Filtered Graph (PMFG).
This function assigns each vertex to a cluster based on the directed bubble hierarchy tree (DBHT) structure. It computes both a non-discrete cluster membership matrix and a discrete cluster assignment vector, using the converging bubbles identified in the directed bubble tree.
Mathematical definition
A vertex that more than one converging bubble holds is given to the bubble whose edges bind it most tightly, per edge of that bubble.
\[\chi(v,\, b) = \frac{\displaystyle\sum_{u \in b} R_{u,\,v}}{3\left(\left|b\right| - 2\right)}\,.\]
Where:
- $R_{u,\,v}$: Weight of the PMFG edge between vertices $u$ and $v$.
- $b$: Vertex set of a converging bubble, and $\left|b\right|$ its vertex count.
- $\chi(v,\, b)$: Association of vertex $v$ with bubble $b$.
The denominator is the edge count of a maximal planar graph on $\left|b\right|$ vertices, which is the same $3n - 6$ the PMFG itself carries. It divides out the size of the bubble, so a large bubble does not win on its size alone.
Algorithm
- Direct the bubble tree with
DirectHb, givingHcandSep. - Take
indx, the converging bubbles,Sep .== 1. When one or none exists, put every vertex in cluster1, leaveAdjvat0 × 0, and stop. - For each converging bubble, run
breadthon the transpose ofHc, and mark in columnnofAdjvevery vertex of every bubble it reaches. A vertex can be marked in more than one column, which is what makesAdjvnon-discrete. - Gather
Bubv, the vertex membership of the converging bubbles alone. Copy intoMdjvthe rows ofBubvfor the verticescvthat exactly one converging bubble holds. - For each vertex of
uv, which more than one holds, take the converging bubble of largest $\chi$ and mark it inMdjv. - Read the discrete assignment
Tcoff the stored entries ofMdjv. - For a vertex that no converging bubble holds, take the mean shortest path length
Udjvto each converging bubble, block the bubbles thatAdjvdoes not reach withtypemax, and assign the closest of the rest.
Arguments
Rpm:N × Nsparse weighted adjacency matrix of the PMFG.Dpm:N × Nshortest path lengths matrix of the PMFG.Hb:Nb×Nbundirected bubble tree of the PMFG (fromBubbleHierarchy).Mb:Nc×Nbbubble membership matrix for 3-cliques.Mb[n, bi] = 1indicates 3-cliquenbelongs to bubblebi.Mv:N × Nbbubble membership matrix for vertices.Mv[n, bi] = 1means vertexnis a vertex of bubblebi.CliqList:Nc×3matrix. Each row lists the three vertices of a 3-clique in the MPG.
Returns
Adjv::SparseMatrixCSC{Int, Int}:N × Nkcluster membership matrix for vertices for non-discrete clustering via the bubble topology,Nkbeing the number of converging bubbles.Adjv[n, k] = 1indicates cluster membership of vertexnto thek-th non-discrete cluster, and a vertex can belong to more than one. It is0 × 0when step 2 of the algorithm stopped.Tc::Vector{Int}:N × 1cluster membership vector.Tc[n] = kindicates cluster membership of vertexnto thek-th discrete cluster. Every vertex carries exactly one.
Related
PortfolioOptimisers.BubbleMember — Function
BubbleMember(Rpm::MatNum, Mv::MatNum,
Mc::MatNum)Assign each vertex to a specific bubble in the bubble hierarchy.
This function determines the bubble membership of each vertex, resolving ambiguities when a vertex may belong to multiple bubbles. Assignment is based on the strength of connections (edge weights) between the vertex and each candidate bubble.
Mathematical definition
A vertex that more than one bubble of the cluster holds is given to the bubble whose internal weight it carries the largest fraction of.
\[\phi(v,\, b) = \frac{\displaystyle\sum_{u \in b} R_{u,\,v}}{\displaystyle\frac{1}{2}\sum_{u \in b} \sum_{u' \in b} R_{u,\,u'}}\,.\]
Where:
- $R_{u,\,v}$: Weight of the PMFG edge between vertices $u$ and $v$.
- $b$: Vertex set of a bubble.
- $\phi(v,\, b)$: Fraction of the internal weight of bubble $b$ that vertex $v$ draws.
The denominator is halved because the PMFG weights are symmetric and the double sum counts each edge twice. This differs from the $\chi$ of BubbleCluster8s: that one divides by the edge count of a maximal planar bubble, and this one by the edge weight the bubble actually holds.
Algorithm
- Split the vertices that
Mcmarks intov, held by exactly one bubble, andvu, held by more than one. - Copy the rows of
McatvintoMvv, which assigns them directly. - For each vertex of
vu, read its candidate bubblesbuboff its row ofMc, score each with $\phi$, and mark the largest inMvv.
Arguments
Rpm:N × Nsparse weighted adjacency matrix of the PMFG.Mv:N × Nbbubble membership matrix for vertices.Mv[n, bi] = 1means vertexnis a vertex of bubblebi.Mc:N × Nbbubble membership matrix restricted to one cluster.Mc[n, bi] = 1means vertexnis a vertex of bubblebiand belongs to that cluster. Every other entry is zero, so a bubble that the cluster does not reach carries an empty column.
Returns
Mvv::Matrix{Int}:N × Nbmatrix whereMvv[n, bi] = 1if vertexnis assigned to bubblebi. Each row of it carries at most one non-zero, which is what makes the assignment discrete.
Related