Index

MaxEntropyGraphs.BiCMType
BiCM

Maximum entropy model for the Undirected Bipartite Configuration Model (BiCM).

The object holds the maximum likelihood parameters of the model (θ), the expected bi-adjacency matrix (Ĝ), and the variance for the elements of the adjacency matrix (σ).

source
MaxEntropyGraphs.BiCMMethod
BiCM(G::T; precision::N=Float64, kwargs...) where {T<:Graphs.AbstractGraph, N<:Real}
BiCM(;d⊥::Vector{T}, d⊤::Vector{T}, precision::Type{<:AbstractFloat}=Float64, kwargs...)

Constructor function for the BiCM type. The graph you provide should be bipartite

By default and dependng on the graph type T, the definition of degree from $Graphs.jl$ is applied. If you want to use a different definition of degrees, you can pass vectors of degrees sequences as keyword arguments (d⊥, d⊤). If you want to generate a model directly from degree sequences without an underlying graph , you can simply pass the degree sequences as arguments (d⊥, d⊤). If you want to work from an adjacency matrix, or edge list, you can use the graph constructors from the $JuliaGraphs$ ecosystem.

Zero degree nodes have a zero probability of being connected to other nodes, so they are skipped in the computation of the model.

Examples

# generating a model from a graph
julia> G = corporateclub();

julia> model =  BiCM(G)
BiCM{Graphs.SimpleGraphs.SimpleGraph{Int64}, Float64} (25 + 15 vertices, 6 + 6 unique degrees, 0.30 compression ratio)
# generating a model directly from a degree sequence
julia> model = model = BiCM(d⊥=[1,1,2,2,2,3,3,1,1,2], d⊤=[3,4,5,2,5,6,6,1,1,2])
BiCM{Nothing, Float64} (10 + 10 vertices, 3 + 6 unique degrees, 0.45 compression ratio)
# generating a model directly from a degree sequence with a different precision
julia> model = model = BiCM(d⊥=[1,1,2,2,2,3,3,1,1,2], d⊤=[3,4,5,2,5,6,6,1,1,2], precision=Float32)
BiCM{Nothing, Float32} (10 + 10 vertices, 3 + 6 unique degrees, 0.45 compression ratio)
# generating a model from an adjacency matrix
julia> A = [0 0 0 1 0;0 0 0 1 0;0 0 0 0 1;1 1 0 0 0;0 0 1 0 0];

julia> G = MaxEntropyGraphs.Graphs.SimpleGraph(A);

julia> @assert MaxEntropyGraphs.Graphs.is_bipartite(G); # check if the graph is bipartite

julia> model = BiCM(G) # generating the model
BiCM{Graphs.SimpleGraphs.SimpleGraph{Int64}, Float64} (3 + 2 vertices, 1 + 2 unique degrees, 0.60 compression ratio)
# generating a model from a biadjacency matrix
julia> biadjacency = [1 0;1 0; 0 1];

julia> N⊥,N⊤ = size(biadjacency); # layer dimensions

julia> adjacency = [zeros(Int, N⊥,N⊥) biadjacency; biadjacency' zeros(Int,N⊤,N⊤)];

julia> G = MaxEntropyGraphs.Graphs.SimpleGraph(adjacency); # generate graph

julia> model = BiCM(G) # generate model
BiCM{Graphs.SimpleGraphs.SimpleGraph{Int64}, Float64} (3 + 2 vertices, 1 + 2 unique degrees, 0.60 compression ratio)
# generating a model from an edge list
julia> edges = MaxEntropyGraphs.Graphs.SimpleEdge.([(1,4); (2,4); (3,5)]);

julia> G = MaxEntropyGraphs.Graphs.SimpleGraph(edges); # generate graph

julia> model = BiCM(G) # generate model
BiCM{Graphs.SimpleGraphs.SimpleGraph{Int64}, Float64} (3 + 2 vertices, 1 + 2 unique degrees, 0.60 compression ratio)
source
MaxEntropyGraphs.solve_model!Method
solve_model!(m::BiCM)

Compute the likelihood maximising parameters of the BiCM model m.

Arguments

  • method::Symbol: solution method to use, can be :fixedpoint (default), or :BFGS, :LBFGS and :Newton.
  • initial::Symbol: initial guess for the parameters $\Theta$, can be :degrees (default), :random, :uniform, or :chung_lu.
  • maxiters::Int: maximum number of iterations for the solver (defaults to 1000).
  • verbose::Bool: set to show log messages (defaults to false).
  • ftol::Union{Real, Nothing}: tolerance for the fixedpoint method (defaults to nothing, i.e. 1e-8). It bounds the fixed-point increment $\|G(\theta) - \theta\|_\infty$ in parameter space; it is not the constraint residual, and it is ignored by every other method. Use constraint_residual to measure how well the expected degrees actually match the observed ones.
  • abstol::Union{Number, Nothing}: absolute function tolerance for convergence with the other methods (defaults to nothing).
  • reltol::Union{Number, Nothing}: relative function tolerance for convergence with the other methods (defaults to nothing).
  • g_tol::Union{Number, Nothing}: gradient tolerance for the gradient-based methods (maps to Optim's g_abstol); set e.g. 1e-5 to stop before over-converging (defaults to nothing, i.e. Optim's tight default). The gradient of this model is its constraint residual (up to the degree multiplicities), but g_abstol is a stopping criterion rather than a guarantee: Optim can also stop on its function or parameter convergence checks and report success without the gradient ever reaching g_tol. Verify what was actually achieved with constraint_residual.
  • AD_method::Symbol: autodiff method to use, can be any of :AutoZygote, :AutoReverseDiff, :AutoForwardDiff and :AutoFiniteDiff. Performance depends on the size of the problem (defaults to :AutoZygote),
  • analytical_gradient::Bool: set the use the analytical gradient instead of the one generated with autodiff (defaults to false)

Examples

# default use
julia> model = BiCM(corporateclub());

julia> solve_model!(model);
# using analytical gradient and uniform initial guess
julia> solve_model!(model, method=:BFGS, analytical_gradient=true, initial=:uniform)
(BiCM{Graphs.SimpleGraphs.SimpleGraph{Int64}, Float64} (25 + 15 vertices, 6 + 6 unique degrees, 0.30 compression ratio), retcode: Success
u: [1.449571644621672, 0.8231752829683303, 0.34755085972479766, -0.04834480708852856, -0.3984299800917503, -0.7223268299919358, 1.6090554004279671, 1.2614196476197532, 0.9762560461922147, 0.11406188481061938, -0.24499004480426345, -2.2646067641037333]
Final objective value:     171.15095803718134
)
source
MaxEntropyGraphs.initial_guessMethod
initial_guess(m::BiCM; method::Symbol=:degrees)

Compute an initial guess for the maximum likelihood parameters of the BiCM model m using the method method.

The methods available are:

  • :degrees (default): the initial guess is computed using the degrees of the graph, i.e. $\theta = [-\log(d_{ot}); -\log(d_{ op})]$
  • :random: the initial guess is computed using random values between 0 and 1, i.e. $\theta_{i} = -\log(r_{i})$ where $r_{i} \sim U(0,1)$
  • :uniform: the initial guess is uniformily set to 0.5, i.e. $\theta_{i} = -\log(0.5)$
  • :chung_lu: the initial guess is computed using the degrees of the graph and the number of edges, i.e. $\theta = [-\log(d_{ot}/(2E)); -\log(d_{ op}/(2E))]$

Examples

julia> model = BiCM(corporateclub());

julia> initial_guess(model, method=:random);

julia> initial_guess(model, method=:uniform);

julia> initial_guess(model, method=:chung_lu);

julia> initial_guess(model);
source
Base.randMethod
rand(m::BiCM; precomputed::Bool=false)

Generate a random graph from the BiCM model m.

Arguments:

  • precomputed::Bool: if true, the precomputed expected biadjacency matrix (m.Ĝ) is used to generate the random graph, otherwise the maximum likelihood parameters are used to generate the random graph on the fly. For larger networks, it is recommended to not precompute the expected adjacency matrix to limit memory pressure.

Note: The generated graph will also be bipartite and respect the layer membership of the original graph used to define the model.

source
Base.randMethod
rand(m::BiCM, n::Int; precomputed::Bool=false)

Generate `n` random graphs from the BiCM model `m`. If multithreading is available, the graphs are generated in parallel.

Arguments:

  • precomputed::Bool: if true, the precomputed expected biadjacency matrix (m.Ĝ) is used to generate the random graph, otherwise the maximum likelihood parameters are used to generate the random graph on the fly. For larger networks, it is recommended to not precompute the expected adjacency matrix to limit memory pressure.

Note: The generated graph will also be bipartite and respect the layer membership of the original graph used to define the model.

source
MaxEntropyGraphs.AICMethod
AIC(m::BiCM)

Compute the Akaike Information Criterion (AIC) for the BiCM model m. The parameters of the models most be computed beforehand. If the number of empirical observations becomes too small with respect to the number of parameters, you will get a warning. In that case, the corrected AIC (AICc) should be used instead.

Examples

julia> model = BiCM(corporateclub());

julia> solve_model!(model);

julia> AIC(model);
[...]

See also AICc, L_BiCM_reduced.

source
MaxEntropyGraphs.AICcMethod
AICc(m::BiCM)

Compute the corrected Akaike Information Criterion (AICc) for the BiCM model m. The parameters of the models most be computed beforehand.

Examples

julia> model = BiCM(corporateclub());

julia> solve_model!(model);

julia> AICc(model)
432.12227535579956

See also AIC, L_BiCM_reduced.

source
MaxEntropyGraphs.BICMethod
BIC(m::BiCM)

Compute the Bayesian Information Criterion (BIC) for the BiCM model m. The parameters of the models most be computed beforehand. BIC is believed to be more restrictive than AIC, as the former favors models with a lower number of parameters than those favored by the latter.

Examples

julia> model = BiCM(corporateclub());

julia> solve_model!(model);

julia> BIC(model)
579.3789571131789

See also AIC, L_BiCM_reduced.

source
MaxEntropyGraphs.L_BiCM_reducedFunction
L_BiCM_reduced(θ::Vector, k⊥::Vector, k⊤::Vector, f⊥::Vector, f⊤::Vector, nz⊥::UnitRange, nz⊤::UnitRange, n⊥ᵣ::Int)

Compute the log-likelihood of the reduced BiCM model using the exponential formulation in order to maintain convexity.

Arguments

  • θ: the maximum likelihood parameters of the model ([α; β])
  • k⊥: the reduced degree sequence of the ⊥ layer
  • k⊤: the reduced degree sequence of the ⊤ layer
  • f⊥: the frequency of each degree in the ⊥ layer
  • f⊤: the frequency of each degree in the ⊤ layer
  • nz⊥: the indices of non-zero elements in the reduced ⊥ layer degree sequence
  • nz⊤: the indices of non-zero elements in the reduced ⊤ layer degree sequence
  • n⊥ᵣ: the number unique values in the reduced ⊥ layer degree sequence

The function returns the log-likelihood of the reduced model. For the optimisation, this function will be used to generate an anonymous function associated with a specific model.

Examples

# Generic use:
julia> k⊥ = [1, 2, 3, 4];

julia> k⊤  = [1, 2, 4];

julia> f⊥  = [1; 3; 1; 1];

julia> f⊤  = [4; 2; 1];

julia> nz⊥ = 1:length(k⊥);

julia> nz⊤ = 1:length(k⊤);

julia> n⊥ᵣ = length(k⊥);

julia> θ   = collect(range(0.1, step=0.1, length=length(k⊥) + length(k⊤)));

julia> L_BiCM_reduced(θ, k⊥, k⊤, f⊥, f⊤, nz⊥, nz⊤, n⊥ᵣ)
-26.7741690720244
# Use with DBCM model:
julia> G = corporateclub();

julia> model = BiCM(G);

julia> model_fun = θ -> L_BiCM_reduced(θ, model.d⊥ᵣ, model.d⊤ᵣ, model.f⊥, model.f⊤, model.d⊥ᵣ_nz, model.d⊤ᵣ_nz, model.status[:d⊥_unique]);

julia> model_fun(ones(size(model.θᵣ)))
-237.5980041411147
source
L_BiCM_reduced(m::BiCM)

Return the log-likelihood of the BiCM model m based on the computed maximum likelihood parameters.

Examples

# Use with DBCM model:
julia> G = corporateclub();

julia> model = BiCM(G);

julia> solve_model!(model);

julia> L_BiCM_reduced(model);

See also L_BiCM_reduced(::Vector, ::Vector, ::Vector, ::Vector, ::Vector, ::UnitRange, ::UnitRange, ::Int)

source
MaxEntropyGraphs.∇L_BiCM_reduced!Function
∇L_BiCM_reduced!(∇L::AbstractVector, θ::AbstractVector, k⊥::Vector, k⊤::Vector, f⊥::Vector, f⊤::Vector,  nz⊥::UnitRange{T}, nz⊤::UnitRange{T}, x::AbstractVector, y::AbstractVector, n⊥::Int) where {T<:Signed}

Compute the gradient of the log-likelihood of the reduced DBCM model using the exponential formulation in order to maintain convexity.

For the optimisation, this function will be used togenerate an anonymous function associated with a specific model. The function will update pre-allocated vectors (∇L,x and y) for speed. The gradient is non-allocating.

Arguments

  • ∇L: the gradient of the log-likelihood of the reduced model
  • θ: the maximum likelihood parameters of the model ([α; β])
  • k⊥: the reduced degree sequence of the ⊥ layer
  • k⊤: the reduced degree sequence of the ⊤ layer
  • f⊥: the frequency of each degree in the ⊥ layer
  • f⊤: the frequency of each degree in the ⊤ layer
  • nz⊥: the indices of non-zero elements in the reduced ⊥ layer degree sequence
  • nz⊤: the indices of non-zero elements in the reduced ⊤ layer degree sequence
  • x: the exponentiated maximum likelihood parameters of the model ( xᵢ = exp(-αᵢ) )
  • y: the exponentiated maximum likelihood parameters of the model ( yᵢ = exp(-βᵢ) )
  • n⊥: the number unique values in the reduced ⊥ layer degree sequence

Examples

# Explicit use with BiCM model:
julia> G = corporateclub();

julia> model = BiCM(G);

julia> ∇L = zeros(Real, length(model.θᵣ));

julia> x  = zeros(Real, length(model.xᵣ));

julia> y  = zeros(Real, length(model.yᵣ));

julia> ∇model_fun! = θ -> ∇L_BiCM_reduced!(∇L, θ, model.d⊥ᵣ, model.d⊤ᵣ, model.f⊥, model.f⊤, model.d⊥ᵣ_nz, model.d⊤ᵣ_nz, x, y, model.status[:d⊥_unique]);

julia> ∇model_fun!(model.θᵣ);
source
MaxEntropyGraphs.BiCM_reduced_iter!Function
BiCM_reduced_iter!(θ::AbstractVector, k⊥::Vector, k⊤::Vector, f⊥::Vector, f⊤::Vector, nz⊥::UnitRange{T}, nz⊤::UnitRange{T}, x::AbstractVector, y::AbstractVector, G::AbstractVector, n⊥::Int) where {T<:Signed}

Compute the next fixed-point iteration for the BiCM model using the exponential formulation in order to maintain convexity. The function is non-allocating and will update pre-allocated vectors (θ, x, y and G) for speed.

Arguments

  • θ: the maximum likelihood parameters of the model ([α; β])
  • k⊥: the reduced degree sequence of the ⊥ layer
  • k⊤: the reduced degree sequence of the ⊤ layer
  • f⊥: the frequency of each degree in the ⊥ layer
  • f⊤: the frequency of each degree in the ⊤ layer
  • nz⊥: the indices of non-zero elements in the reduced ⊥ layer degree sequence
  • nz⊤: the indices of non-zero elements in the reduced ⊤ layer degree sequence
  • x: the exponentiated maximum likelihood parameters of the model ( xᵢ = exp(-αᵢ) )
  • y: the exponentiated maximum likelihood parameters of the model ( yᵢ = exp(-βᵢ) )
  • G: buffer for computations
  • n⊥: the number unique values in the reduced ⊥ layer degree sequence

Examples

# Use with BiCM model:
julia> G = corporateclub();

julia> model = BiCM(G);

julia> G = zeros(eltype(model.θᵣ), length(model.θᵣ));

julia> x = zeros(eltype(model.θᵣ), length(model.xᵣ));

julia> y = zeros(eltype(model.θᵣ), length(model.yᵣ));


julia> BiCM_FP! = θ -> BiCM_reduced_iter!(θ, model.d⊥ᵣ, model.d⊤ᵣ, model.f⊥, model.f⊤, model.d⊥ᵣ_nz, model.d⊤ᵣ_nz, x, y, G, model.status[:d⊥_unique]);

julia> BiCM_FP!(model.θᵣ);
source
MaxEntropyGraphs.ĜMethod
Ĝ(m::BiCM)

Compute the expected biadjacency matrix for the BiCM model m

Note

Please note that this generates a bi-adjacency matrix, not an adjacency matrix.

source
MaxEntropyGraphs.σˣMethod
σˣ(m::BiCM)

Compute the standard deviation for the elements of the biadjacency matrix for the BiCM model m, i.e. sqrt(pᵢα(1 - pᵢα)) (the biadjacency entries are independent Bernoulli distributed variables).

Note: read as "sigma star". The result is an n⊥ × n⊤ matrix, like the biadjacency matrix itself.

source
Base.precisionMethod
precision(m::BiCM)

Determine the compute precision of the BiCM model m.

Examples

julia> model = BiCM(corporateclub());

julia> MaxEntropyGraphs.precision(model)
Float64
julia> model = BiCM(corporateclub(), precision=Float32);

julia> MaxEntropyGraphs.precision(model)
Float32
source
MaxEntropyGraphs.AMethod
A(m::BiCM,i::Int,j::Int)

Return the expected value of the biadjacency matrix for the BiCM model m at the node pair (i,j).

❗ For perfomance reasons, the function does not check:

  • if the node pair is valid.
  • if the parameters of the model have been computed.
source
MaxEntropyGraphs.f_BiCMMethod
f_BiCM(x::T)

Helper function for the BiCM model to compute the expected value of the biadjacency matrix. The function computes the expression x / (1 + x). As an argument you need to pass the product of the maximum likelihood parameters xᵣ[i] * yᵣ[j] from a BiCM model.

source
MaxEntropyGraphs.σₓMethod
σₓ(m::BiCM, X::Function; gradient_method::Symbol=:ReverseDiff)

Compute the standard deviation of metric X for the BiCM model m via error propagation (the delta method of Squartini & Garlaschelli (2011); see also Saracco et al. (2015)).

X must be a function of the biadjacency matrix (n⊥ × n⊤, cf. Ĝ), not of an adjacency matrix. The biadjacency entries are independent Bernoulli variables, so no covariance terms occur:

$σ^{2}[X] = \sum_{i,α} \left( σ[m_{iα}] \frac{∂X}{∂m_{iα}} \right)^{2}$

This requires that both the expected values (m.Ĝ) and standard deviations (m.σ) are computed for m.

For the statistical significance of projection-related quantities, the exact Poisson-binomial machinery (cf. project and V_PB_parameters) is preferable to the delta method.

source
MaxEntropyGraphs.biadjacency_matrixFunction
biadjacency_matrix(G::Graphs.SimpleGraph; skipchecks::Bool=false)

Return the biadjacency matrix of the bipartite graph G.

If the graph is not bipartite, an error is thrown. If the adjacency matrix can be written as: A = [O B; B' O] where O is the null matrix, then the returned biadjacency matrix is B and and B' is the transposed biadjacency matrix.

Arguments

  • skipchecks: if true, skip the check for the graph being bipartite.

Examples

julia> A = [0 0 0 0 1 0 0;
0 0 0 0 1 1 0;
0 0 0 0 0 0 1;
0 0 0 0 0 1 1;
1 1 0 0 0 0 0;
0 1 0 1 0 0 0;
0 0 1 1 0 0 0];

julia> G = MaxEntropyGraphs.Graphs.SimpleGraph(A);

julia> Array(biadjacency_matrix(A))
4x3 Matrix{Int64}:
 1  0  0
 1  1  0
 0  0  1
 0  1  1
source
MaxEntropyGraphs.Vn_motifsFunction
Vn_motifs(A::T, n::Int; layer::Symbol=:bottom, skipchecks::Bool=false) where {T<:AbstractMatrix}

Count the total number of Vn-motifs (n-fold co-occurrences, i.e. n nodes of a layer sharing a common neighbour in the other layer) in the biadjacency matrix A for one of its layers: $N_{Vn} = \sum_α \binom{u_α}{n}$ where the u_α are the degrees of the opposite layer. For n = 2 this is the V-motif count (V_motifs); following Saracco et al. (2015), the family for the bottom (top) layer is also known as the Vn (Λn) family.

Arguments

  • n: motif order (n ≥ 2).
  • layer: the layer between whose nodes the co-occurrences are counted (:bottom or :top).
  • skipchecks: if true, skip the dimension check on A.

Examples

julia> A = [1 1; 1 1; 1 0];

julia> Vn_motifs(A, 2, layer=:bottom)
4.0

julia> Vn_motifs(A, 3, layer=:bottom)
1.0
source
Vn_motifs(m::BiCM, n::Int; layer::Symbol=:bottom, method::Symbol=:exact)

Compute the expected total number of Vn-motifs $⟨N_{Vn}⟩$ between the nodes of layer under the BiCM model m (cf. Vn_motifs(::AbstractMatrix, ::Int) for the definition).

Arguments

  • n: motif order (n ≥ 2).
  • layer: the layer between whose nodes the co-occurrences are counted (:bottom or :top).
  • method:
    • :exact (default): exact expectation from the Poisson-binomial distribution of the random opposite-layer degrees (see _Vn_exact_moments); any n ≥ 2.
    • :delta: closed-form Taylor expansion around the observed degrees (Saracco et al. (2015), SI Eqs. III.9-III.13); only n ∈ {2, 3, 4} (exact for n = 2). Accurate when the opposite-layer degrees are large compared to n; for sparse layers prefer :exact.

Examples

julia> model = BiCM(corporateclub());

julia> solve_model!(model);

julia> Vn_motifs(model, 2, layer=:bottom) ≈ V_motifs(model, layer=:bottom, precomputed=false)
true
source
MaxEntropyGraphs.Vn_sigmaMethod
Vn_sigma(m::BiCM, n::Int; layer::Symbol=:bottom, method::Symbol=:exact)

Compute the standard deviation $σ[N_{Vn}]$ of the total number of Vn-motifs between the nodes of layer under the BiCM model m.

Arguments

  • n: motif order (n ≥ 2).
  • layer: the layer between whose nodes the co-occurrences are counted (:bottom or :top).
  • method:
    • :exact (default): exact variance from the Poisson-binomial distribution of the random opposite-layer degrees (independent across nodes, see _Vn_exact_moments); any n ≥ 2.
    • :delta: first-order delta method around the observed degrees (Saracco et al. (2015), SI Eqs. III.6-III.7): $σ[N_{Vn}] = \sqrt{\sum_α [\binom{u_α}{n}(H_{u_α} - H_{u_α-n})]^2 σ^2[U_α]}$. Accurate when the opposite-layer degrees are large compared to n; it underestimates the variance for sparse layers — prefer :exact.
source
MaxEntropyGraphs.Vn_zscoreMethod
Vn_zscore(m::BiCM, n::Int; layer::Symbol=:bottom, method::Symbol=:exact)

Compute the z-score of the observed total number of Vn-motifs between the nodes of layer with respect to the BiCM model m: $z = (N_{Vn}^{obs} - ⟨N_{Vn}⟩)/σ[N_{Vn}]$. The observed count is obtained from the observed degree sequence stored in the model (no graph needed).

Note

Because the constrained degrees fully determine the observed count, these z-scores have a definite sign (cf. Saracco et al. (2015), SI): under the BiCM, $⟨N_{Vn}⟩ ≥ N_{Vn}^{obs}$. The associated significance tests are one-sided.

Arguments

  • n: motif order (n ≥ 2).
  • layer: the layer between whose nodes the co-occurrences are counted (:bottom or :top).
  • method: :exact (default, any n ≥ 2) or :delta (n ∈ {2, 3, 4}); see Vn_motifs and Vn_sigma.
source
MaxEntropyGraphs._Vn_exact_momentsFunction
_Vn_exact_moments(m::BiCM, n::Int; layer::Symbol=:bottom)

Internal helper computing the exact mean and variance of $N_{Vn} = \sum_α \binom{U_α}{n}$ under the BiCM, where the sum runs over the nodes α of the layer opposite to layer and $U_α = \sum_k a_{kα}$ is the (random) degree of α. Each U_α follows a Poisson-binomial distribution (the biadjacency entries are independent Bernoulli variables) and the U_α of distinct nodes involve disjoint entry sets, hence are independent:

$⟨N_{Vn}⟩ = \sum_α ⟨\binom{U_α}{n}⟩, \qquad Var[N_{Vn}] = \sum_α Var[\binom{U_α}{n}]$

The Poisson-binomial pmf of each U_α is obtained by direct convolution over the connection probabilities, at cost O(n_{opp}^2) per unique degree class.

source
MaxEntropyGraphs._Vn_delta_inputsFunction
_Vn_delta_inputs(m::BiCM, layer::Symbol)

Internal helper for the closed-form (method=:delta) Vn machinery: return (uᵣ, fᵣ, s2ᵣ) with the reduced observed degrees uᵣ of the aggregated (opposite) layer, their frequencies fᵣ and the variance of each random degree $σ^2[U_α] = \sum_k p_{kα}(1 - p_{kα})$ per reduced class.

source
MaxEntropyGraphs.projectFunction
project(G::Graphs.SimpleGraph;  membership::Vector=Graphs.bipartite_map(G), 
                                bottom::Vector=findall(membership .== 1), 
                                top::Vector=findall(membership .== 2); 
                                layer::Symbol=:bottom)

Project the bipartite graph G onto one of its layers and return the projected graph.

Arguments

  • membership: the bipartite mapping of the graphs. This can be computed using Graphs.bipartite_map(G).
  • bottom: the nodes in the bottom layer. This can be computed using findall(membership .== 1).
  • top: the nodes in the top layer. This can be computed using findall(membership .== 2).
  • layer: the layer can be specified by passing layer=:bottom or layer=:top. Layer membership is determined by the bipartite map of the graph.
  • method: the method used to compute the adjacency matrix of the projected graph. This can be :simple or :weighted. Both methods compute the product of the biadjacency matrix with its transposed, but the :weighted method uses the weights of the edges in the projected graph.

Examples

julia> using Graphs

julia> G = SimpleGraph(5); add_edge!(G, 1, 4); add_edge!(G, 2, 4); add_edge!(G, 3, 4); add_edge!(G, 3, 5);

julia> project(G, layer=:bottom)
{3, 3} undirected simple Int64 graph
julia> project(G, layer=:top)
{2, 1} undirected simple Int64 graph
source
project(B::T; layer::Symbol=:bottom, method::Symbol=:simple) where {T<:AbstractMatrix}

Project the biadjacency matrix B onto one of its layers.

Arguments

  • layer: the layer can be specified by passing layer=:bottom or layer=:top. Layer membership is determined by the bipartite map of the graph.
  • method: the method used to compute the adjacency matrix of the projected graph. This can be :simple or :weighted. Both methods compute the product of the biadjacency matrix with its transposed, but the :weighted method uses the weights of the edges in the projected graph.

Examples

julia> B = [0 0 0 1 1; 0 0 0 1 1; 0 0 0 1 0];

julia> project(B, layer=:bottom)
3×3 Matrix{Bool}:
 0  1  1
 1  0  1
 1  1  0
julia> project(B, layer=:top)
5×5 Matrix{Bool}:
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  1
 0  0  0  1  0
julia> B = [0 0 0 1 1; 0 0 0 1 1; 0 0 0 1 0];

julia> project(B, layer=:bottom, method=:weighted)
3×3 Matrix{Int64}:
 0  2  1
 2  0  1
 1  1  0
julia> project(B, layer=:top, method=:weighted)
5×5 Matrix{Int64}:
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  0
 0  0  0  0  2
 0  0  0  2  0
source
project(m::BiCM;   α::Float64=0.05, layer::Symbol=:bottom, precomputed::Bool=true,
                    distribution::Symbol=:Poisson, adjustment::PValueAdjustment=BenjaminiHochberg(),
                        multithreaded::Bool=false)

Obtain the statistically validated projected graph of the BiCM model m onto the layer layer using the V-motifs and the significance level α combined with the p-value adjustment method adjustment.

Arguments

  • α: the significance level.
  • layer: the layer can be specified by passing layer=:bottom or layer=:top.
  • precomputed: if true, the expected values of the biadjacency matrix are used, otherwise the parameters are computed from the model parameters.
  • distribution: the distribution used to compute the p-values. This can be :Poisson or :PoissonBinomial.
  • adjustment: the method used to adjust the p-values for multiple testing. This can be any of the methods in the PValueAdjustment type (see MultipleTesting.jl). By default, the Benjamini-Hochberg method is used.
  • multithreaded: if true, the p-values are computed using multithreading.

Examples

julia> model = BiCM(corporateclub());

julia> solve_model!(model);

julia> project(model, layer=:bottom)
{25, 0} undirected simple Int64 graph
julia> project(model, layer=:top)
{15, 0} undirected simple Int64 graph
source