Separation: private API
PortfolioOptimisers.separation_graph — Function
separation_graph(sep::HopCount, G::Graphs.AbstractGraph)
separation_graph(sep::HopCount, nte::AbstractNetworkEstimator, X::MatNum;
dims::Int = 1, kwargs...)
separation_graph(sep::PathLength, nte::AbstractNetworkEstimator, X::MatNum;
dims::Int = 1, kwargs...)Build the structure a separation measures over.
One third of the extension contract of AbstractSeparationAlgorithm; separation_matrix and separation_budget are the other two. It exists as a kernel of its own so that the structure is built once per consumer call: separation_matrix and resolve_separation both take the graph, and a consumer that needs the separations and a budget rule answered would otherwise build the same structure twice, through two estimator-taking kernels that each derive it privately.
What each member measures over
HopCount:calc_adjacency's structure as aGraphs.SimpleGraph. Binary, because a hop count ignores the weights and its consumers do not —_phylogeny_matrixreadsGraphs.adjacency_matrixoff this graph for a power sum, where a weight would makeA^isum products of distances instead of counting walks.PathLength:calc_distance_weighted_graph's structure. The same edge set, weighted by distance on either branch, because a shortest path over the PMFG's similarities seeks the route through the weakest links.
Two entry points, and why only the hop count gets the graph-taking one
The estimator-taking methods derive the structure from X. The graph-taking method is for a caller that already holds it: both clusterise methods build the structure from the selecting quantity they already paid for, through calc_weighted_adjacency_graph's own two-argument entry point, and would otherwise re-derive the distance — 98% of clusterise's runtime under VariationInfoDistance — to answer a budget rule.
PathLength has no graph-taking method, and cannot: a graph carries no polarity tag, so G is a distance-weighted structure on the tree branch and a similarity-weighted one on the PMFG branch, and nothing in the argument distinguishes them. Handing the PMFG's similarities to a shortest path returns an answer instead of raising — see calc_distance_weighted_graph. The hop count is exempt because it discards the weights.
Algorithm
Build the structure
Ximplies, through the branch thatsepselects.HopCount:calc_adjacency's binary matrix.PathLength:calc_distance_weighted_graph's distance-weighted structure, which is already the answer.
Rebuild a
HopCount's structure as aGraphs.SimpleGraph, which discards the weights. The graph-taking method is handedGand starts here.
Arguments
sep: Separation algorithm. Dispatched on, and its budget is not read — a member whose budget is still a rule measures over the same structure as one whose budget is a number, which is what letsresolve_separationbe handed this graph.G: Network structure a caller already holds, in either polarity.nte: Network estimator.X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.dims: Dimension along which to perform the computation.kwargs...: Additional keyword arguments.
Returns
g::Graphs.AbstractGraph: The structuresepmeasures over.
Related
PortfolioOptimisers.separation_quantile — Function
separation_quantile(
sep::AbstractSeparationAlgorithm,
d::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
q::Number
) -> Number
Quantile of the reachable off-diagonal entries of a separation matrix.
The population is the pairs a budget can be about: the diagonal is zero by construction and an unreachable pair carries separation_matrix's sentinel, so neither is a separation. It is also the population phylogeny_matrix selects from, which is what makes q read as the fraction of pairs the resulting budget relates.
The sentinel test is the family's
The population excludes an unreachable pair through is_reachable rather than through a test written out here. isfinite alone would not do it: it is true for every Integer, so it admits HopCount's typemax(Int).
Algorithm
- Collect the off-diagonal entries of
dthatis_reachableadmits, givingv, the population of the quantile. - Throw an
ArgumentErrorwhenvis empty. - Take the
q-quantile ofvwithStatistics.quantile.
Arguments
sep: Separation algorithm the matrix was measured under, forwarded tois_reachable.d: Separation matrix fromseparation_matrix.q: Quantile in[0, 1].
Validation
- Throws an
ArgumentErrorif no off-diagonal entry ofdis reachable, because a budget cannot be placed at a quantile of an empty population.
Returns
dmax::Number: Theq-quantile of the reachable off-diagonal separations.
Related