Centrality
PortfolioOptimisers.AbstractCentralityAlgorithm — Type
abstract type AbstractCentralityAlgorithm <: AbstractPhylogenyAlgorithmAbstract supertype for the algorithms that score how central each asset is in a network.
Every member wraps one routine of Graphs.jl.
All concrete and/or abstract types implementing specific centrality algorithms (e.g., betweenness, closeness, degree, eigenvector, Katz, pagerank, radiality, stress) should be subtypes of AbstractCentralityAlgorithm.
Each member declares the weights it needs
A member says which quantity its edge weights must be, through centrality_polarity, and centrality_graph supplies it. The declaration is about correctness — a shortest path over similarities is backwards — and never about capability: a member that declares nothing, and a source that carries no weights, both run on the plain graph rather than raising. The fallback declares nothing, so a new member is unweighted until it opts in.
The five members that do declare one carry an ov field, and TopologyOnly in it withdraws the declaration for that instance. centrality_polarity therefore answers the effective polarity, not the declared one.
Interfaces
In order to implement a new centrality algorithm that works seamlessly with the library, subtype AbstractCentralityAlgorithm with the routine's configuration as fields, and implement the following method:
calc_centrality
calc_centrality(ct::MyCentrality, g::Graphs.AbstractGraph) -> VecNum: Score every vertex ofg.centrality_graphhas already weightedgin the polarity the algorithm declares, so the method forwards to the routine and inspects nothing.
Arguments
ct: The concrete subtype instance.g: The graph to score, weighted or plain as the declared polarity decides.
Returns
scores::VecNum: One score per vertex ofg, in vertex order.
centrality_polarity
centrality_polarity(ct::MyCentrality) -> Option{<:AbstractCentralityPolarity}: Declare which quantity the edge weights must be. The fallback answersnothing, so a new algorithm runs on the plain graph until it opts in. DeclareDistancePolarityfor a routine defined over shortest paths, andSimilarityPolarityfor one that reads the adjacency matrix itself.
Arguments
ct: The concrete subtype instance.
Returns
polarity::Option{<:AbstractCentralityPolarity}: The effective polarity, ornothingfor an algorithm that reads the topology alone.
Related
centrality_polaritycentrality_graphTopologyOnlyBetweennessCentralityClosenessCentralityDegreeCentralityEigenvectorCentralityKatzCentralityPagerankRadialityCentralityStressCentrality
References
PortfolioOptimisers.TopologyOnly — Type
struct TopologyOnly <: AbstractAlgorithmWithdraws an algorithm's polarity declaration, so it reads the network's topology alone.
An algorithm that declares a polarity is handed weights wherever the source carries them. TopologyOnly in its ov field withdraws that request: centrality_polarity then answers nothing, and centrality_graph routes to the plain Graphs.SimpleGraph of phylogeny_matrix. The computation is the one that already runs for DegreeCentrality, Pagerank and KatzCentrality, so this is a redirect and never a new estimator.
The override runs one way only
It removes weights and never supplies them. There is no value that forces a polarity onto an algorithm, and the field is deliberately not typed over AbstractCentralityPolarity. A forced polarity would succeed rather than raise — calc_distance_weighted_graph carries distances on both branches — and the algorithm would read a distance where it needs a similarity, reversing its own ordering in silence. Polarity correctness is not a runtime property, so nothing could catch it.
Every request is honoured, on every source
The answer over the topology alone is available from every source, so the override never warns and never goes inert. On a partition source, on a precomputed PhylogenyResult, and on the tree branch under SimilarityPolarity, the plain graph is what those routes already build, so the request is satisfied before it is made.
Only the five algorithms that declare a polarity carry an ov field. DegreeCentrality, Pagerank and KatzCentrality already return the topology-only answer, so there is nothing for them to override and DegreeCentrality(; ov = TopologyOnly()) is a MethodError.
It is a choice, not a simplification, and it moves no default
A topology-only centrality is often argued to be the more fold-stable of the two, by the same reasoning that makes a fixed dmax fold-stable under PathLength. That is not a reason to default to it.
The shipped default is already unweighted. CentralityEstimator's ct defaults to DegreeCentrality, which declares no polarity, so a caller who names no algorithm gets this answer already. Defaulting ov to TopologyOnly would change the answer only for a caller who named one of the five deliberately — and for those five, reading the weights the source carries is the correct answer, which is what AbstractCentralityPolarity exists to say.
The override re-arms sep. The plain-graph route reads the separation closure phylogeny_matrix builds, and the weighted routes bypass it. So the override trades the edge weights for a second knob rather than removing one: measured over twenty assets, all five algorithms answer differently at HopCount(; n = 1) and at n = 3 once they carry it, including the four that are inert to sep without it. Under a bare PathLength that knob is the observed diameter, which is the data-dependent quantity the fold-stability argument set out to avoid.
Examples
julia> ClosenessCentrality(; ov = TopologyOnly())ClosenessCentrality args ┼ Tuple{}: () kwargs ┼ @NamedTuple{}: NamedTuple() ov ┴ TopologyOnly()julia> isnothing(centrality_polarity(ClosenessCentrality(; ov = TopologyOnly())))truejulia> centrality_polarity(ClosenessCentrality())DistancePolarity()Related
PortfolioOptimisers.BetweennessCentrality — Type
struct BetweennessCentrality{__T_args, __T_kwargs, __T_ov} <: AbstractCentralityAlgorithmScores each asset by the share of the network's shortest paths that run through it.
BetweennessCentrality computes the betweenness centrality of nodes in a graph, measuring the extent to which a node lies on shortest paths between other nodes.
Declares DistancePolarity, unless ov overrides it: it is defined over shortest paths, so its weights must be distances. On a tree the weighted answer equals the unweighted one — a tree has exactly one path between any two vertices, so no weighting can change the shortest-path set — which is a theorem about the graph rather than a limitation, and it does not hold on the similarity branch. Set ov to TopologyOnly to withdraw the declaration and read the topology alone.
Mathematical definition
\[\begin{align} \mathrm{BC}_i &= \dfrac{1}{(n - 1)(n - 2)} \sum_{s \neq i \neq t} \dfrac{\sigma_{s,\,t}(i)}{\sigma_{s,\,t}}\,, \end{align}\]
Where:
- $\mathrm{BC}_i$: Betweenness centrality of asset $i$.
- $\sigma_{s,\,t}$: Number of shortest paths between assets $s$ and $t$.
- $\sigma_{s,\,t}(i)$: Number of the shortest paths between assets $s$ and $t$ that pass through asset $i$.
- $n$: Number of assets, which is the number of vertices of the network.
The sum runs over the ordered pairs of distinct assets, so an undirected network counts each pair twice and the leading factor is the reciprocal of $(n - 1)(n - 2)$ rather than of half of it. Graphs.jl applies that factor by default, and kwargs = (; normalize = false) replaces it by $1/2$, which is the count over the unordered pairs. kwargs = (; endpoints = true) counts the two ends of every path as well, which raises every score.
A pair joined by several shortest paths shares one unit of score between them, because the summand is a fraction of $\sigma_{s,\,t}$. StressCentrality omits that division and counts the paths themselves.
Fields
args: Positional arguments for the centrality function.
kwargs: Keyword arguments for the centrality function.
ov: Polarity override.TopologyOnlyasks for the centrality over the network's topology alone, socentrality_polarityanswersnothingandcentrality_graphbuilds the plain graph.nothingleaves the algorithm's declared polarity in force.
Constructors
BetweennessCentrality(; args::Tuple = (), kwargs::NamedTuple = (;), ov::Option{TopologyOnly} = nothing) -> BetweennessCentralityKeywords correspond to the struct's fields.
Validation
- No entry of
argsis anAbstractMatrix. A weight matrix reaches a centrality algorithm throughcentrality_polarity, and never throughargs.
Examples
julia> BetweennessCentrality()BetweennessCentrality args ┼ Tuple{}: () kwargs ┼ @NamedTuple{}: NamedTuple() ov ┴ nothingRelated
AbstractCentralityAlgorithmcentrality_polarityDistancePolarityTopologyOnlyGraphs.betweenness_centrality
References
PortfolioOptimisers.ClosenessCentrality — Type
struct ClosenessCentrality{__T_args, __T_kwargs, __T_ov} <: AbstractCentralityAlgorithmScores each asset by the reciprocal of its mean shortest-path distance to the others.
ClosenessCentrality computes the closeness centrality of nodes in a graph, measuring how close a node is to all other nodes.
Declares DistancePolarity, unless ov overrides it: it sums shortest-path lengths, so its weights must be distances. It reads them on both branches, so its answer on a NetworkEstimator source differs from the unweighted one — measured over twenty assets, a maximum absolute change of 0.713 on a triangulated maximally filtered graph and 0.538 on a tree. Set ov to TopologyOnly to withdraw the declaration and read the topology alone.
Mathematical definition
\[\begin{align} \mathrm{CC}_i &= \dfrac{r_i}{\displaystyle\sum_{j \in \mathcal{R}_i} \ell_{i,\,j}} \cdot \dfrac{r_i}{n - 1}\,, \end{align}\]
Where:
- $\mathrm{CC}_i$: Closeness centrality of asset $i$.
- $\mathcal{R}_i$: Set of assets that asset $i$ reaches, excluding itself.
- $r_i$: Cardinality of $\mathcal{R}_i$.
- $\ell_{i,\,j}$: Length of a shortest path between assets $i$ and $j$. It counts the edges on an unweighted network, and sums the edge weights on a weighted one.
- $n$: Number of assets, which is the number of vertices of the network.
The first factor is the reciprocal of the mean length from asset $i$ to the assets it reaches. The second is the share of the universe it reaches, which Graphs.jl applies by default and kwargs = (; normalize = false) drops. On a connected network $r_i = n - 1$ and the second factor is one, so the two settings agree there and part only where the network falls into components.
An asset that reaches nothing scores zero rather than an infinity, because the sum in the denominator is over $\mathcal{R}_i$ alone and an unreachable asset never enters it.
Fields
args: Positional arguments for the centrality function.
kwargs: Keyword arguments for the centrality function.
ov: Polarity override.TopologyOnlyasks for the centrality over the network's topology alone, socentrality_polarityanswersnothingandcentrality_graphbuilds the plain graph.nothingleaves the algorithm's declared polarity in force.
Constructors
ClosenessCentrality(; args::Tuple = (), kwargs::NamedTuple = (;), ov::Option{TopologyOnly} = nothing) -> ClosenessCentralityKeywords correspond to the struct's fields.
Validation
- No entry of
argsis anAbstractMatrix. A weight matrix reaches a centrality algorithm throughcentrality_polarity, and never throughargs.
Examples
julia> ClosenessCentrality()ClosenessCentrality args ┼ Tuple{}: () kwargs ┼ @NamedTuple{}: NamedTuple() ov ┴ nothingRelated
AbstractCentralityAlgorithmcentrality_polarityDistancePolarityTopologyOnlyGraphs.closeness_centrality
References
- [64] L. C. Freeman. Centrality in social networks conceptual clarification. Social Networks 1, 215–239 (1979).
PortfolioOptimisers.DegreeCentrality — Type
struct DegreeCentrality{__T_kind, __T_kwargs} <: AbstractCentralityAlgorithmCounts the network edges that touch each asset, divided by the number of other assets.
DegreeCentrality computes the degree centrality of nodes in a graph. It is the simplest score of the family, and the shipped default of CentralityEstimator's ct.
Mathematical definition
The degree vector of an adjacency matrix $\mathbf{A}$ over $n$ assets is
\[\begin{align} \mathbf{D}_n &= \mathbf{A}\,\mathbf{1}_n\,, \end{align}\]
Where:
- $\mathbf{D}_n$: Degree vector of the network, whose $i$-th entry counts the edges that touch asset $i$.
- $\mathbf{A}$: Adjacency matrix of the network. It is binary on the unweighted route, and carries the edge weights of its own branch where the algorithm declares a polarity.
- $\mathbf{1}_n$: Column vector of ones of length $n$.
- $n$: Number of assets, which is the number of vertices of the network.
Graphs.jl normalises that vector by default, so what this type returns is $\mathbf{D}_n / (n - 1)$ and not $\mathbf{D}_n$. kwargs = (; normalize = false) recovers $\mathbf{D}_n$ exactly.
The factor is the whole difference, and it re-ranks nothing. average_centrality is linear in the score vector, so a constant scale moves the average by that same constant.
The three kind values coincide on these structures
kind selects the total, the in- or the out-degree. Every graph this library builds is undirected, where the three are one number: measured over the same tree, kind = 0, 1 and 2 agree exactly. The field is kept because Graphs.jl takes it, not because it selects anything here.
Declares no polarity and runs on the plain graph: Graphs.degree_centrality counts edges and ignores what they weigh. It is therefore one of the algorithms for which the estimator's sep stays live — the unweighted route reads the separation closure phylogeny_matrix builds, so HopCount(; n = 2) does change this answer.
It carries no ov field, and TopologyOnly is not applicable to it: the topology alone is what it already reads, so there is no declaration to withdraw. DegreeCentrality(; ov = TopologyOnly()) is a MethodError.
Fields
kind: Degree type (0: total, 1: in-degree, 2: out-degree).
kwargs: Keyword arguments for the centrality function.
Constructors
DegreeCentrality(; kind::Integer = 0, kwargs::NamedTuple = (;)) -> DegreeCentralityKeywords correspond to the struct's fields.
Validation
0 <= kind <= 2.
Examples
julia> DegreeCentrality(; kind = 1)DegreeCentrality kind ┼ Int64: 1 kwargs ┴ @NamedTuple{}: NamedTuple()Related
References
PortfolioOptimisers.EigenvectorCentrality — Type
struct EigenvectorCentrality{__T_ov} <: AbstractCentralityAlgorithmScores each asset by the leading eigenvector of the network's adjacency matrix.
EigenvectorCentrality computes the eigenvector centrality of nodes in a graph, measuring the influence of a node based on the centrality of its neighbours.
Mathematical definition
\[\begin{align} \mathbf{EC}_n &= \dfrac{1}{\lambda_{\mathrm{max}}}\,\mathbf{A}\,\mathbf{q}_{\mathrm{max}}\,, \end{align}\]
Where:
- $\mathbf{EC}_n$: Eigenvector centrality vector of the network.
- $\mathbf{A}$: Adjacency matrix of the network. It is binary on the unweighted route, and carries the edge weights of its own branch where the algorithm declares a polarity.
- $\lambda_{\mathrm{max}}$: Largest eigenvalue of $\mathbf{A}$.
- $\mathbf{q}_{\mathrm{max}}$: Eigenvector of $\lambda_{\mathrm{max}}$.
The right-hand side is $\mathbf{q}_{\mathrm{max}}$ itself, so the score is the leading eigenvector under whatever normalisation the eigensolver applies. Graphs.jl returns it with unit 2-norm, and takes the absolute value of every entry — the leading eigenvector of a non-negative matrix shares one sign, by the Perron-Frobenius theorem, so that changes no ordering. The returned vector matches the formula above to eigensolver precision, which moves by a few ulps between calls on one graph.
Declares SimilarityPolarity — the only member that declares it — unless ov overrides it: it is the leading eigenvector of the adjacency matrix itself, so a stronger link must contribute a larger entry. It therefore reads weights on the similarity branch alone. A tree is selected by minimising a distance and carries no similarity, so this algorithm runs unweighted there rather than being handed the wrong quantity. Set ov to TopologyOnly to withdraw the declaration and read the topology alone.
The weights change the answer by less than the shortest-path algorithms do, and they do change it: the weighted and unweighted vectors differ while still correlating closely, and withdrawing the weights also moves the structure's $\lambda_{\mathrm{max}}$.
Fields
ov: Polarity override.TopologyOnlyasks for the centrality over the network's topology alone, socentrality_polarityanswersnothingandcentrality_graphbuilds the plain graph.nothingleaves the algorithm's declared polarity in force.
Constructors
EigenvectorCentrality(; ov::Option{TopologyOnly} = nothing) -> EigenvectorCentralityKeywords correspond to the struct's fields.
Examples
julia> EigenvectorCentrality()EigenvectorCentrality ov ┴ nothingRelated
AbstractCentralityAlgorithmcentrality_polaritySimilarityPolarityTopologyOnlyGraphs.eigenvector_centrality
References
PortfolioOptimisers.KatzCentrality — Type
struct KatzCentrality{__T_alpha} <: AbstractCentralityAlgorithmScores each asset by every walk that reaches it, discounted geometrically by the walk's length.
KatzCentrality computes the Katz centrality of nodes in a graph, measuring the influence of a node based on the number and length of walks between nodes, controlled by the attenuation factor alpha.
Declares no polarity and runs on the plain graph: Graphs.katz_centrality binarises its input through adjacency_matrix(g, Bool), and throws an InexactError when the graph is weighted. The unweighted route is real code here rather than an absent check.
It carries no ov field, and TopologyOnly is not applicable to it: the topology alone is what it already reads, so there is no declaration to withdraw. KatzCentrality(; ov = TopologyOnly()) is a MethodError.
Mathematical definition
\[\begin{align} \boldsymbol{v} &= \sum_{k \geq 0} \alpha^{k}\,\mathbf{A}^{k}\,\mathbf{1}_n = \left(\mathbf{I}_n - \alpha\,\mathbf{A}\right)^{-1}\mathbf{1}_n\,, \\ \mathbf{KC}_n &= \dfrac{\boldsymbol{v}}{\lVert \boldsymbol{v} \rVert_2}\,. \end{align}\]
Where:
- $\boldsymbol{v}$: Walk sum of the network, whose $i$-th entry adds up every walk that reaches asset $i$, discounted by $\alpha$ for each edge on it.
- $\mathbf{KC}_n$: Katz centrality vector, the walk sum at unit 2-norm.
- $\alpha$: Attenuation factor,
alpha. - $\mathbf{A}$: Adjacency matrix of the network. It is binary on the unweighted route, and carries the edge weights of its own branch where the algorithm declares a polarity.
- $\lambda_{\mathrm{max}}$: Largest eigenvalue of $\mathbf{A}$.
- $\mathbf{I}_n$: Identity matrix of order $n$.
- $\mathbf{1}_n$: Column vector of ones of length $n$.
- $n$: Number of assets, which is the number of vertices of the network.
The series converges to the resolvent only for $\alpha < 1 / \lambda_{\mathrm{max}}$, and the two right-hand sides are equal only there. Outside that range the resolvent is still defined at almost every $\alpha$, and the vector it gives is the walk sum of nothing.
alpha must be below the reciprocal of the largest eigenvalue
Above the bound the linear solve still returns a vector, and the vector is not a centrality: some of its scores turn negative, and a negative centrality has no reading.
The constructor cannot check this. $\lambda_{\mathrm{max}}$ is a property of the graph, and the graph is built later by centrality_graph, so the validation is alpha > 0 and the bound is the caller's to respect. A dense network raises $\lambda_{\mathrm{max}}$ and lowers the bound, so a value that held on a tree can fail on a triangulated maximally filtered graph over the same assets — the default alpha = 0.3 is not safe against every graph shape.
Fields
alpha: Attenuation factor for Katz centrality.
Constructors
KatzCentrality(; alpha::Number = 0.3) -> KatzCentralityKeywords correspond to the struct's fields.
Validation
alpha > 0.
Examples
julia> KatzCentrality(; alpha = 0.1)KatzCentrality alpha ┴ Float64: 0.1Related
References
- [66] L. Katz. A new status index derived from sociometric analysis. Psychometrika 18, 39–43 (1953).
PortfolioOptimisers.Pagerank — Type
struct Pagerank{__T_n, __T_alpha, __T_epsilon} <: AbstractCentralityAlgorithmScores each asset by the stationary distribution of a damped random walk over the network.
Pagerank computes the PageRank of nodes in a graph, measuring the importance of nodes based on the structure of incoming links. The algorithm is controlled by the damping factor alpha, number of iterations n, and convergence tolerance epsilon.
Declares no polarity and runs on the plain graph: Graphs.pagerank walks outdegree and inneighbors alone and never reads an edge weight, so the weighted and the plain graph give the identical vector. Like DegreeCentrality it therefore keeps the estimator's sep live, reading the separation closure rather than the structure.
It carries no ov field, and TopologyOnly is not applicable to it: the topology alone is what it already reads, so there is no declaration to withdraw. Pagerank(; ov = TopologyOnly()) is a MethodError.
Mathematical definition
\[\begin{align} \mathrm{PR}_i &= \dfrac{1 - \alpha}{n} + \dfrac{\alpha}{n}\sum_{j \in \mathcal{D}} \mathrm{PR}_j + \alpha \sum_{j \in \mathcal{I}_i} \dfrac{\mathrm{PR}_j}{k_j}\,, \end{align}\]
Where:
- $\mathrm{PR}_i$: PageRank of asset $i$, the share of its time the damped walk spends there.
- $\alpha$: Damping factor,
alpha. It is the probability that the walk follows an edge rather than teleporting. - $\mathcal{I}_i$: Set of assets carrying an edge into asset $i$.
- $k_j$: Number of edges leaving asset $j$.
- $\mathcal{D}$: Set of dangling assets, those that no edge leaves.
- $n$: Number of assets, which is the number of vertices of the network.
The three terms are the walk's three moves: it teleports to a uniformly drawn asset, it teleports out of a dangling asset it cannot leave, or it follows one of the edges into asset $i$. Every score is therefore non-negative and the vector sums to one, which is what separates this member from the counting scores of the family.
Every network this library builds is undirected, where $\mathcal{I}_i$ is the neighbourhood of asset $i$ and $k_j$ is its degree. On a connected undirected network the solution approaches the degree vector DegreeCentrality counts, up to a scale, as $\alpha$ approaches one, and a smaller $\alpha$ blends that limit with the uniform distribution.
Fields
n: Number of iterations.Graphs.pagerankraises when the scores have not converged after this many sweeps.
alpha: Damping factor. It is the probability that the walk follows an edge rather than teleporting.
epsilon: Convergence threshold. A sweep converges when the L1 change of the score vector falls below this value multiplied by the number of assets.
Constructors
Pagerank(; n::Integer = 100, alpha::Number = 0.85, epsilon::Number = 1e-6) -> PagerankKeywords correspond to the struct's fields.
Validation
n > 0.0 < alpha < 1.epsilon > 0.
Examples
julia> Pagerank(; alpha = 0.9, n = 200, epsilon = 1e-8)Pagerank n ┼ Int64: 200 alpha ┼ Float64: 0.9 epsilon ┴ Float64: 1.0e-8Related
References
- [67] S. Brin and L. Page. The anatomy of a large-scale hypertextual Web search engine. Computer Networks and ISDN Systems 30, 107–117 (1998).
PortfolioOptimisers.RadialityCentrality — Type
struct RadialityCentrality{__T_ov} <: AbstractCentralityAlgorithmScores each asset by its mean shortest-path distance, measured against the network's diameter.
RadialityCentrality computes the radiality centrality of nodes in a graph, measuring how close a node is to all other nodes, adjusted for the maximum possible distance.
Declares DistancePolarity, unless ov overrides it: it reads shortest-path lengths against the graph's diameter, so its weights must be distances. It reads them on both branches, and its answer moves when they arrive — measured over twenty assets, a maximum absolute change of 0.248 on a triangulated maximally filtered graph and 0.234 on a tree. Set ov to TopologyOnly to withdraw the declaration and read the topology alone.
Mathematical definition
\[\begin{align} \bar{\ell}_i &= \dfrac{1}{n - 1}\sum_{j} \ell_{i,\,j}\,, \\ \mathrm{RC}_i &= \dfrac{D + 1 - \bar{\ell}_i}{D}\,. \end{align}\]
Where:
- $\bar{\ell}_i$: Mean length from asset $i$ to every other asset.
- $\mathrm{RC}_i$: Radiality centrality of asset $i$.
- $D$: Diameter of the network, the largest $\ell_{i,\,j}$ over every pair.
- $\ell_{i,\,j}$: Length of a shortest path between assets $i$ and $j$. It counts the edges on an unweighted network, and sums the edge weights on a weighted one.
- $n$: Number of assets, which is the number of vertices of the network.
The diameter is what separates this score from ClosenessCentrality. Closeness reciprocates the mean length and reads a scale of its own; radiality subtracts it from the longest length the network holds, so the score says how far inside the network's own reach an asset sits.
The score is at most $1$, which an asset one edge away from every other reaches, and at least $1/D$, which an asset whose mean length equals the diameter reaches. Both bounds move with $D$, so two networks give comparable scores only when the two have the same diameter.
Fields
ov: Polarity override.TopologyOnlyasks for the centrality over the network's topology alone, socentrality_polarityanswersnothingandcentrality_graphbuilds the plain graph.nothingleaves the algorithm's declared polarity in force.
Constructors
RadialityCentrality(; ov::Option{TopologyOnly} = nothing) -> RadialityCentralityKeywords correspond to the struct's fields.
Examples
julia> RadialityCentrality()RadialityCentrality ov ┴ nothingRelated
AbstractCentralityAlgorithmcentrality_polarityDistancePolarityTopologyOnlyGraphs.radiality_centrality
References
- [68] T. W. Valente and R. K. Foreman. Integration and radiality: measuring the extent of an individual's connectedness and reachability in a network. Social Networks 20, 89–105 (1998).
PortfolioOptimisers.StressCentrality — Type
struct StressCentrality{__T_args, __T_kwargs, __T_ov} <: AbstractCentralityAlgorithmCounts the shortest paths of the network that pass through each asset.
StressCentrality computes the stress centrality of nodes in a graph, measuring the number of shortest paths passing through each node.
Declares DistancePolarity, unless ov overrides it: it counts shortest paths, so its weights must be distances. Like BetweennessCentrality it is unchanged by them on a tree, where the shortest-path set is fixed by the structure alone, and does move on the similarity branch. Set ov to TopologyOnly to withdraw the declaration and read the topology alone.
Mathematical definition
\[\begin{align} \mathrm{SC}_i &= \sum_{s \neq i \neq t} \sigma_{s,\,t}(i)\,, \end{align}\]
Where:
- $\mathrm{SC}_i$: Stress centrality of asset $i$.
- $\sigma_{s,\,t}(i)$: Number of the shortest paths between assets $s$ and $t$ that pass through asset $i$.
The sum runs over the ordered pairs of distinct assets, so an undirected network counts each pair twice. There is no normalisation, so the score is a count rather than a rate: it grows with the size of the network, and two networks give comparable scores only when the two hold the same number of assets.
It is BetweennessCentrality's sum without the division by $\sigma_{s,\,t}$. A pair joined by many shortest paths therefore contributes many units here and one unit there, so this score reads how much traffic an asset carries and betweenness reads how much of it the asset alone can carry.
Fields
args: Positional arguments for the centrality function.
kwargs: Keyword arguments for the centrality function.
ov: Polarity override.TopologyOnlyasks for the centrality over the network's topology alone, socentrality_polarityanswersnothingandcentrality_graphbuilds the plain graph.nothingleaves the algorithm's declared polarity in force.
Constructors
StressCentrality(; args::Tuple = (), kwargs::NamedTuple = (;), ov::Option{TopologyOnly} = nothing) -> StressCentralityKeywords correspond to the struct's fields.
Validation
- No entry of
argsis anAbstractMatrix. A weight matrix reaches a centrality algorithm throughcentrality_polarity, and never throughargs.
Examples
julia> StressCentrality()StressCentrality args ┼ Tuple{}: () kwargs ┼ @NamedTuple{}: NamedTuple() ov ┴ nothingRelated
References
- [69] A. Shimbel. Structural parameters of communication networks. The Bulletin of Mathematical Biophysics 15, 501–507 (1953).
PortfolioOptimisers.calc_centrality — Function
calc_centrality(ct::AbstractCentralityAlgorithm, g::Graphs.AbstractGraph)Compute node centrality scores for a graph using the specified centrality algorithm.
This function dispatches to the appropriate centrality computation from Graphs.jl based on the type of ct. Supported algorithms include betweenness, closeness, degree, eigenvector, Katz, pagerank, radiality, and stress centrality.
g may be weighted or unweighted, and nothing here inspects which. Graphs.jl weights implicitly — the distmx of every routine that takes one defaults to weights(g) — so the choice is made once, by centrality_graph, and this function only forwards. Handing a weighted graph to an algorithm that declares no polarity is what centrality_graph exists to prevent: Graphs.katz_centrality throws an InexactError on one.
Algorithm
- Select the
Graphs.jlroutine that the type ofctnames, from the list under# Arguments. - Splat the configuration
ctcarries into that call.BetweennessCentrality,ClosenessCentralityandStressCentralitypassargsandkwargs;DegreeCentralitypasseskindandkwargs;KatzCentralitypassesalpha;Pagerankpassesalpha,nandepsilon;EigenvectorCentralityandRadialityCentralitypass nothing. - Return the scores that routine produced, one entry per vertex of
g.
Arguments
ct: Centrality algorithm to use.ct::BetweennessCentrality: Computes betweenness centrality.ct::ClosenessCentrality: Computes closeness centrality.ct::DegreeCentrality: Computes degree centrality.ct::EigenvectorCentrality: Computes eigenvector centrality.ct::KatzCentrality: Computes Katz centrality.ct::Pagerank: Computes PageRank.ct::RadialityCentrality: Computes radiality centrality.ct::StressCentrality: Computes stress centrality.
g: Graph to compute centrality on.
Returns
ct::VecNum: Centrality scores for each node in the graph.
Related
References
- [5]
- D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025).
- [61]
- E. Estrada. The Structure of Complex Networks: Theory and Applications (Oxford University Press, 2011).
- [62]
- L. C. Freeman. A set of measures of centrality based on betweenness. Sociometry 40, 35–41 (1977).
- [63]
- U. Brandes. A faster algorithm for betweenness centrality. The Journal of Mathematical Sociology 25, 163–177 (2001).
- [64]
- L. C. Freeman. Centrality in social networks conceptual clarification. Social Networks 1, 215–239 (1979).
- [65]
- P. Bonacich. Power and centrality: a family of measures. American Journal of Sociology 92, 1170–1182 (1987).
- [66]
- L. Katz. A new status index derived from sociometric analysis. Psychometrika 18, 39–43 (1953).
- [67]
- S. Brin and L. Page. The anatomy of a large-scale hypertextual Web search engine. Computer Networks and ISDN Systems 30, 107–117 (1998).
- [68]
- T. W. Valente and R. K. Foreman. Integration and radiality: measuring the extent of an individual's connectedness and reachability in a network. Social Networks 20, 89–105 (1998).
- [69]
- A. Shimbel. Structural parameters of communication networks. The Bulletin of Mathematical Biophysics 15, 501–507 (1953).