Centrality: private API

PortfolioOptimisers.assert_no_weight_channel_argsFunction
assert_no_weight_channel_args(::Type{T}, args::Tuple, S::Type, shape::AbstractString,
                              channel::AbstractString) where {T}

Refuse an entry of args that would reach a second weighting channel.

The one refusal both splat guards make. A Graphs.jl entry point takes its weights in a positional slot, so an entry of args with that shape is a second channel answering a question the declared one already answered. assert_centrality_args and assert_tree_args differ only in which shape reaches a channel and in which declared channel they name, so both call this with their own S, shape and channel.

The index of the offending entry is reported with its type, because args is splatted and the caller sees no argument names.

Algorithm

  1. Find the index of the first entry of args that is an S, giving idx.
  2. Throw a ConflictingArgumentError when idx is an index rather than nothing. The message carries T, shape, channel, idx and the type of the offending entry.

Arguments

  • T: Algorithm type, named in the error message.
  • args: Positional arguments destined for the Graphs.jl function.
  • S: The shape that reaches a weight slot, e.g. AbstractMatrix.
  • shape: Name of that shape, used in the error message.
  • channel: Sentence naming the declared channel the caller must use instead.

Validation

Returns

  • nothing.

Related

source
PortfolioOptimisers.assert_centrality_argsFunction
assert_centrality_args(::Type{T}, args::Tuple) where {T}

Refuse a matrix inside a centrality algorithm's args.

args is splatted straight into the Graphs.jl centrality function, so a matrix in it is a distmx — a second, undeclared way to weight the graph. centrality_polarity is the declared one, and it picks the weights the algorithm's own mathematics needs, from the structure that was actually built. Two channels answering the same question is one too many, and this one was never safe:

  • Graphs.betweenness_centrality's distmx is its third positional argument, so a matrix in args binds to vs instead and the call overflows the stack inside Graphs.degree. The StackOverflowError is catchable and the process survives it, so what is lost is the call and not the session.
  • Graphs.closeness_centrality's is its second, so that one worked — silently overriding the polarity, and reporting a wrong-sized matrix as a BoundsError rather than a DimensionMismatch.
  • Graphs.stress_centrality has no distmx at all.

Non-matrix entries are untouched: a vertex list or a sample count is a genuine positional argument of those functions and says nothing about weights.

kwargs needs no companion guard. A keyword binds by name, so a matrix there cannot reach a positional slot: none of the four functions declares a matrix-valued keyword, and every one of normalize, endpoints, rng and seed refuses a matrix on its own. The whole family fails closed with a MethodError or a TypeError.

Algorithm

  1. Refuse an AbstractMatrix in args with assert_no_weight_channel_args, naming centrality_polarity as the declared weight channel.

Arguments

  • T: Centrality algorithm type, named in the error message.
  • args: Positional arguments destined for the Graphs.jl centrality function.

Validation

Returns

  • nothing.

Related

source
PortfolioOptimisers.assert_tree_argsFunction
assert_tree_args(::Type{T}, args::Tuple, kwargs::NamedTuple) where {T}

Refuse a second weighting channel inside a spanning-tree algorithm's args and kwargs.

Both fields are splatted straight into the Graphs.jl spanning-tree function, and every channel they can reach re-weights or re-orients a tree that calc_weighted_adjacency_graph has already weighted. The graph it hands to calc_mst carries the distances the estimator's de and ce produced, and Graphs.jl defaults distmx to exactly those weights. A caller who fills these fields therefore answers a question that was already answered, and the wrong answer is silent:

  • kruskal_mst, boruvka_mst and prim_mst all take distmx as their second positional argument, so a matrix in args replaces the estimator's distances outright. It is correctly sized often enough to succeed, and the tree it builds is a legitimate-looking tree of the wrong graph.
  • kruskal_mst also takes a weight_vector there, which is the same override in the other shape.
  • minimize in kwargs inverts the sense of the search. The tree branch is defined by minimising a distance — calc_weighted_adjacency_graph and SimilarityPolarity both say so — and minimize = false yields a maximum spanning tree while everything downstream still reads it as a minimum one.

Non-matrix, non-vector entries are untouched, and so is every other keyword. Those reach no weighting channel, and the three functions declare none, so they fail closed at the call.

Algorithm

  1. Refuse an AbstractMatrix or an AbstractVector in args with assert_no_weight_channel_args, naming the graph calc_weighted_adjacency_graph built as the declared weight channel.
  2. Throw a ConflictingArgumentError when kwargs carries the key minimize. The message carries T and the value of that key.

Arguments

  • T: Spanning-tree algorithm type, named in the error message.
  • args: Positional arguments destined for the Graphs.jl spanning-tree function.
  • kwargs: Keyword arguments destined for the same function.

Validation

Returns

  • nothing.

Related

source