Skip to content

Commit 04e645c

Browse files
InterdisciplinaryPhysicsTeamClaudMorpitmonticone
committed
Add disgraphical and update test
Co-Authored-By: Claudio Moroni <[email protected]> Co-Authored-By: Pietro Monticone <[email protected]>
1 parent 599e5dc commit 04e645c

File tree

2 files changed

+39
-23
lines changed

2 files changed

+39
-23
lines changed

src/utilities.jl

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -359,28 +359,40 @@ Check whether `A` is symmetric (within `zero(T)`).
359359
isapproxsymmetric(A::Matrix{T}) where {T<:Integer} = all(abs.(A .- A') .<= zero(T))
360360

361361
"""
362-
isdigraphical(indegree_sequence::Vector{<:Integer}, outdegree_sequence::Vector{<:Integer} )
363-
364-
Return true if the degree sequences `indegree_sequence` and `outdegree_sequence` satisfy the (simple) digraph realization problem.
365-
366-
Two sequences of integers of integers satisfy the (simple) digraph realization problem, if there exists a simple directed graph where the indegrees of its vertices form that first sequence and the outdegrees the second.
362+
isdigraphical(indegree_sequence::AbstractVector{<:Integer}, outdegree_sequence::AbstractVector{<:Integer},)
363+
Check whether the given indegree sequence and outdegree sequence are digraphical, that is whether they can be the indegree and outdegree sequence of a digraph.
367364
368365
### Implementation Notes
369-
According to Fulkerson-Chen-Anstee theorem, a sequence ``\\{(a_1, b_1), ...,(a_n, b_n)\\}`` (sorted in descending order of a) is graphic iff the sum of vertex degrees is even and the sequence obeys the property -
366+
According to Fulkerson-Chen-Anstee theorem, a sequence ``\\{(a_1, b_1), ...,(a_n, b_n)\\}`` (sorted in descending order of a) is graphic iff the sum of vertex degrees is even and ``\\sum_{i = 1}^{n} a_i = \\sum_{i = 1}^{n} b_i\\}`` and the sequence obeys the property -
370367
```math
371368
\\sum_{i=1}^{r} a_i \\leq \\sum_{i=r+1}^n min(r-1,b_i) + \\sum_{i=r+1}^n min(r,b_i)
372369
```
373-
for each integer ``r \\leq n-1``.
374-
"""
375-
function isdigraphical(indegree_sequence::Vector{<:Integer}, outdegree_sequence::Vector{<:Integer} )
370+
for each integer r <= n-1.
371+
"""
372+
function isdigraphical(
373+
indegree_sequence::AbstractVector{<:Integer},
374+
outdegree_sequence::AbstractVector{<:Integer},
375+
)
376+
# Check whether the degree sequences have the same length
377+
length(indegree_sequence) == length(outdegree_sequence) || throw(
378+
ArgumentError("The indegree and outdegree sequences must have the same length.")
379+
)
380+
# Check whether the degree sequence is empty
381+
!(isempty(indegree_sequence) && isempty(outdegree_sequence)) || return true
382+
# Check whether the degree sequences have only non-negative values
383+
all(indegree_sequence .>= 0) || throw(
384+
ArgumentError("The indegree sequence must contain non-negative integers only.")
385+
)
386+
all(outdegree_sequence .>= 0) || throw(
387+
ArgumentError("The outdegree sequence must contain non-negative integers only.")
388+
)
376389

377390
n = length(indegree_sequence)
378-
379391
n == length(outdegree_sequence) || return false
380392

381393
sum(indegree_sequence) == sum(outdegree_sequence) || return false
382394

383-
_sortperm = sortperm(indegree_sequence, rev = true)
395+
_sortperm = sortperm(indegree_sequence; rev=true)
384396

385397
sorted_indegree_sequence = indegree_sequence[_sortperm]
386398
sorted_outdegree_sequence = outdegree_sequence[_sortperm]
@@ -395,27 +407,25 @@ function isdigraphical(indegree_sequence::Vector{<:Integer}, outdegree_sequence:
395407
# with the line
396408
# cum_min -= mindeg[r]
397409
# inside the for loop below, work as well, but the values of `cum_min` at each iteration differ. To be on the safe side we implemented it as in https://en.wikipedia.org/wiki/Fulkerson%E2%80%93Chen%E2%80%93Anstee_theorem
398-
#= mindeg = Vector{Int64}(undef, n)
399-
@inbounds for i = 1:n
400-
mindeg[i] = min(i, sorted_outdegree_sequence[i])
401-
end
402-
cum_min = sum(mindeg) =#
410+
#= mindeg = Vector{Int64}(undef, n)
411+
@inbounds for i = 1:n
412+
mindeg[i] = min(i, sorted_outdegree_sequence[i])
413+
end
414+
cum_min = sum(mindeg) =#
403415
# Similarly for `outdegree_min_sum`.
404416

405-
@inbounds for r = 1:(n - 1)
406-
417+
@inbounds for r in 1:(n - 1)
407418
indegree_sum += sorted_indegree_sequence[r]
408-
outdegree_min_sum = sum([min(sorted_outdegree_sequence[i], r-1) for i in 1:r])
409-
cum_min = sum([min(sorted_outdegree_sequence[i], r) for i in (1+r):n])
410-
419+
outdegree_min_sum = sum([min(sorted_outdegree_sequence[i], r - 1) for i in 1:r])
420+
cum_min = sum([min(sorted_outdegree_sequence[i], r) for i in (1 + r):n])
411421
cond = indegree_sum <= (outdegree_min_sum + cum_min)
412-
413422
cond || return false
414423
end
415424

416425
return true
417426
end
418427

428+
419429
"""
420430
_random_undirected_configuration(empty_mg::M, degree_sequence::Vector{ <: Integer}) where {T,U,M <: MultilayerGraph{T,U}}
421431
@@ -549,6 +559,7 @@ Internal function. Converts `cart_index` to an integer index such that it corres
549559
cartIndexTovecIndex(cart_index::Union{NTuple{N, Integer},CartesianIndex}, tensor_size::NTuple{N, <: Integer} ) where N = cart_index[1] + sum( collect(Tuple(cart_index)[2:end] .- 1) .* cumprod(tensor_size[1:end-1]))
550560

551561

562+
# TODO:
552563
"""
553564
havel_hakimi_(empty_graph::SimpleGraph, degree_sequence::Vector{<:Integer})
554565

test/utilities.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@
22
const A = reshape(rand(1:9, 1000), 10, 10, 10)
33
carts_idxs = CartesianIndices(A)
44
vec_idxs = MultilayerGraphs.cartIndexTovecIndex.(carts_idxs, Ref(size(A)))
5-
@test all(getindex.(Ref(A), carts_idxs) .== getindex.(Ref(A), vec_idxs) )
5+
@test all(getindex.(Ref(A), carts_idxs) .== getindex.(Ref(A), vec_idxs) )
6+
# Test directed simple graphicality
7+
sdg = SimpleDiGraph(10, 90)
8+
@test @inferred(isdigraphical(indegree(sdg), outdegree(sdg)))
9+
@test !@inferred(isdigraphical([1, 1, 1], [1, 1, 0]))
10+
@test @inferred(isdigraphical(Integer[], Integer[]))

0 commit comments

Comments
 (0)