Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

Commit

Permalink
Sbromberger/parameterization (#744)
Browse files Browse the repository at this point in the history
* performance improvements

* get rid of eltype checks, use parameterization instead - currently only on non-traitfns

* remove more eltypes

* fixed adjacency matrix (#745)

* insorted

* more parameterization, plus a random test fix
  • Loading branch information
sbromberger authored Sep 17, 2017
1 parent 30a423b commit 27baf04
Show file tree
Hide file tree
Showing 34 changed files with 116 additions and 153 deletions.
5 changes: 3 additions & 2 deletions src/community/cliques.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ julia> maximal_cliques(g)
```
"""
function maximal_cliques end
@traitfn function maximal_cliques(g::::(!IsDirected))
T = eltype(g)
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function maximal_cliques{T, AG<:AbstractGraph{T}}(g::AG::(!IsDirected))
# Cache nbrs and find first pivot (highest degree)
maxconn = -1
# uncomment this when https://github.com/JuliaLang/julia/issues/23618 is fixed
# nnbrs = [Set{T}() for n in vertices(g)]
nnbrs = Vector{Set{T}}()
for n in vertices(g)
Expand Down
3 changes: 1 addition & 2 deletions src/community/label_propagation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ the second is the convergence history for each node. Will return after
### References
- [Raghavan et al.](http://arxiv.org/abs/0709.2938)
"""
function label_propagation(g::AbstractGraph, maxiter=1000)
T = eltype(g)
function label_propagation(g::AbstractGraph{T}, maxiter=1000) where T
n = nv(g)
label = collect(one(T):n)
active_vs = IntSet(vertices(g))
Expand Down
23 changes: 11 additions & 12 deletions src/connectivity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ to each vertex. The component value is the smallest vertex ID in the component.
This algorithm is linear in the number of edges of the graph.
"""
function connected_components! end
@traitfn function connected_components!(label::AbstractVector, g::::(!IsDirected))
T = eltype(g)
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function connected_components!{T, AG<:AbstractGraph{T}}(label::AbstractVector, g::AG::(!IsDirected))
nvg = nv(g)

for u in vertices(g)
Expand Down Expand Up @@ -84,8 +84,8 @@ For directed graphs, see [`strongly_connected_components`](@ref) and
[`weakly_connected_components`](@ref).
"""
function connected_components end
@traitfn function connected_components(g::::(!IsDirected))
T = eltype(g)
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function connected_components{T, AG<:AbstractGraph{T}}(g::AG::(!IsDirected))
label = zeros(T, nv(g))
connected_components!(label, g)
c, d = components(label)
Expand Down Expand Up @@ -125,8 +125,8 @@ function is_weakly_connected end
Compute the strongly connected components of a directed graph `g`.
"""
function strongly_connected_components end
@traitfn function strongly_connected_components(g::::IsDirected)
T = eltype(g)
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function strongly_connected_components{T, AG<:AbstractGraph{T}}(g::AG::IsDirected)
zero_t = zero(T)
one_t = one(T)
nvg = nv(g)
Expand Down Expand Up @@ -213,8 +213,8 @@ Return the (common) period for all vertices in a strongly connected directed gra
Will throw an error if the graph is not strongly connected.
"""
function period end
@traitfn function period(g::::IsDirected)
T = eltype(g)
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function period{T, AG<:AbstractGraph{T}}(g::AG::IsDirected)
!is_strongly_connected(g) && error("Graph must be strongly connected")

# First check if there's a self loop
Expand Down Expand Up @@ -272,8 +272,8 @@ The attracting components are a subset of the strongly
connected components in which the components do not have any leaving edges.
"""
function attracting_components end
@traitfn function attracting_components(g::::IsDirected)
T = eltype(g)
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function attracting_components{T, AG<:AbstractGraph{T}}(g::AG::IsDirected)
scc = strongly_connected_components(g)
cond = condensation(g, scc)

Expand All @@ -300,9 +300,8 @@ with respect to `v` of the edges to be considered. Possible values: `:in` or `:o
neighborhood(g::AbstractGraph, v::Integer, d::Integer; dir=:out) = (dir == :out) ?
_neighborhood(g, v, d, out_neighbors) : _neighborhood(g, v, d, in_neighbors)

function _neighborhood(g::AbstractGraph, v::Integer, d::Integer, neighborfn::Function)
function _neighborhood(g::AbstractGraph{T}, v::Integer, d::Integer, neighborfn::Function) where T
@assert d >= 0 "Distance has to be greater then zero."
T = eltype(g)
neighs = Vector{T}()
push!(neighs, v)

Expand Down
4 changes: 2 additions & 2 deletions src/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ represented by the key.
Degree function (for example, `indegree` or `outdegree`) may be specified by
overriding `degfn`.
"""
function degree_histogram(g::AbstractGraph, degfn=degree)
hist = Dict{eltype(g),Int}()
function degree_histogram(g::AbstractGraph{T}, degfn=degree) where T
hist = Dict{T,Int}()
for v in vertices(g) # minimize allocations by
for d in degfn(g, v) # iterating over vertices
hist[d] = get(hist, d, 0) + 1
Expand Down
3 changes: 1 addition & 2 deletions src/degeneracy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ Not implemented for graphs with self loops.
Vladimir Batagelj and Matjaz Zaversnik, 2003.
http://arxiv.org/abs/cs.DS/0310049
"""
function core_number(g::AbstractGraph)
function core_number(g::AbstractGraph{T}) where T
has_self_loops(g) && error("This function does not work on graphs with self-loops")
T = eltype(g)
degrees = degree(g)
vs = sortperm(degrees)
bin_boundaries = [1]
Expand Down
6 changes: 3 additions & 3 deletions src/digraph/cycles/hadwick-james.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ of Hadwick & James.
- Hadwick & James, "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs", 2008
"""
function simplecycles_hadwick_james end
@traitfn function simplecycles_hadwick_james(g::::IsDirected)
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function simplecycles_hadwick_james{T, AG<:AbstractGraph{T}}(g::AG::IsDirected)
nvg = nv(g)
T = eltype(g)
B = [Vector{T}() for i in vertices(g)]
B = Vector{T}[Vector{T}() for i in vertices(g)]
blocked = zeros(Bool, nvg)
stack = Vector{T}()
cycles = Vector{Vector{T}}()
Expand Down
23 changes: 10 additions & 13 deletions src/flow/boykov_kolmogorov.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@ Min-Cut/Max-Flow Algorithms for Energy Minimization in Vision.
- Júlio Hoffimann Mendes ([email protected])
"""
function boykov_kolmogorov_impl end
@traitfn function boykov_kolmogorov_impl(
residual_graph::::IsDirected, # the input graph
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function boykov_kolmogorov_impl{T, U, AG<:AbstractGraph{U}}(
residual_graph::AG::IsDirected, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
capacity_matrix::AbstractMatrix # edge flow capacities
capacity_matrix::AbstractMatrix{T} # edge flow capacities
)

T = eltype(capacity_matrix)
U = eltype(residual_graph)

n = nv(residual_graph)

flow = 0
Expand Down Expand Up @@ -55,8 +52,9 @@ function boykov_kolmogorov_impl end
return flow, flow_matrix, TREE
end

@traitfn function find_path!(
residual_graph::::IsDirected, # the input graph
# see https://github.com/mauro3/SimpleTraits.jl/issues/47#issuecomment-327880153 for syntax
@traitfn function find_path!{T, AG<:AbstractGraph{T}}(
residual_graph::AG::IsDirected, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
flow_matrix::AbstractMatrix, # the current flow matrix
Expand All @@ -65,7 +63,7 @@ end
TREE::Vector, # tree table
A::Vector # active set
)
T = eltype(residual_graph)

tree_cap(p, q) = TREE[p] == one(T) ? capacity_matrix[p, q] - flow_matrix[p, q] :
capacity_matrix[q, p] - flow_matrix[q, p]
while !isempty(A)
Expand Down Expand Up @@ -149,8 +147,8 @@ function augment!(
return Δ
end

@traitfn function adopt!(
residual_graph::::IsDirected, # the input graph
@traitfn function adopt!{T, AG<:AbstractGraph{T}}(
residual_graph::AG::IsDirected, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
flow_matrix::AbstractMatrix, # the current flow matrix
Expand All @@ -161,7 +159,6 @@ end
O::Vector # orphan set
)

T = eltype(residual_graph)
tree_cap(p, q) = TREE[p] == 1 ? capacity_matrix[p, q] - flow_matrix[p, q] :
capacity_matrix[q, p] - flow_matrix[q, p]
while !isempty(O)
Expand Down
10 changes: 4 additions & 6 deletions src/flow/dinic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ with edge flow capacities in `capacity_matrix` using
Return the value of the maximum flow as well as the final flow matrix.
"""
function dinic_impl end
@traitfn function dinic_impl(
@traitfn function dinic_impl{T}(
residual_graph::::IsDirected, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
capacity_matrix::AbstractMatrix # edge flow capacities
capacity_matrix::AbstractMatrix{T} # edge flow capacities
)
n = nv(residual_graph) # number of vertexes
T = eltype(capacity_matrix)
flow_matrix = zeros(T, n, n) # initialize flow matrix
P = zeros(Int, n) # Sharable parent vector

Expand All @@ -37,16 +36,15 @@ end
Like `blocking_flow`, but requires a preallocated parent vector `P`.
"""
function blocking_flow! end
@traitfn function blocking_flow!(
@traitfn function blocking_flow!{T}(
residual_graph::::IsDirected, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
capacity_matrix::AbstractMatrix, # edge flow capacities
capacity_matrix::AbstractMatrix{T}, # edge flow capacities
flow_matrix::AbstractMatrix, # the current flow matrix
P::AbstractVector{Int} # Parent vector to store Level Graph
)
n = nv(residual_graph) # number of vertexes
T = eltype(capacity_matrix)
fill!(P, -1)
P[source] = -2

Expand Down
10 changes: 4 additions & 6 deletions src/flow/edmonds_karp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ Compute the maximum flow in flow graph `residual_graph` between `source` and
Return the value of the maximum flow as well as the final flow matrix.
"""
function edmonds_karp_impl end
@traitfn function edmonds_karp_impl(
@traitfn function edmonds_karp_impl{T}(
residual_graph::::IsDirected, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
capacity_matrix::AbstractMatrix # edge flow capacities
capacity_matrix::AbstractMatrix{T} # edge flow capacities
)
T = eltype(capacity_matrix)
n = nv(residual_graph) # number of vertexes
flow = 0
flow_matrix = zeros(T, n, n) # initialize flow matrix
Expand Down Expand Up @@ -58,10 +57,9 @@ Augment the flow and returns the augment value.
"""
function augment_path!(
path::Vector{Int}, # input path
flow_matrix::AbstractMatrix, # the current flow matrix
flow_matrix::AbstractMatrix{T}, # the current flow matrix
capacity_matrix::AbstractMatrix # edge flow capacities
)
T = eltype(flow_matrix)
) where T
augment = typemax(T) # initialize augment
for i in 1:(length(path) - 1) # calculate min capacity along path
u = path[i]
Expand Down
10 changes: 4 additions & 6 deletions src/flow/ext_multiroute_flow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,15 @@ Calculates the breaking of the restricted max-flow from a set of auxiliary point
for `flow_graph` from `source to `target` using capacities in `capacity_matrix`.
"""
function breakingPoints end
@traitfn function breakingPoints(
@traitfn function breakingPoints{T}(
flow_graph::::IsDirected, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
capacity_matrix::AbstractMatrix # edge flow capacities
capacity_matrix::AbstractMatrix{T} # edge flow capacities
)
auxpoints = auxiliaryPoints(flow_graph, source, target, capacity_matrix)
λ = length(auxpoints) - 1
left_index = 1
T = eltype(capacity_matrix)
breakingpoints = Vector{Tuple{T,T,Int}}()

for (id, point) in enumerate(auxpoints)
Expand Down Expand Up @@ -145,9 +144,8 @@ since we have to ignore zero values.
# note: this is more efficient than maximum() / minimum() / extrema()
# since we have to ignore zero values.
function minmaxCapacity(
capacity_matrix::AbstractMatrix # edge flow capacities
)
T = eltype(capacity_matrix)
capacity_matrix::AbstractMatrix{T} # edge flow capacities
) where T
cmin, cmax = typemax(T), typemin(T)
for c in capacity_matrix
if c > zero(T)
Expand Down
10 changes: 4 additions & 6 deletions src/flow/multiroute_flow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,12 @@ function multiroute_flow(
flow_graph::AbstractGraph, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
capacity_matrix::AbstractMatrix = # edge flow capacities
capacity_matrix::AbstractMatrix{T2} = # edge flow capacities
DefaultCapacity(flow_graph);
flow_algorithm::AbstractFlowAlgorithm = # keyword argument for algorithm
PushRelabelAlgorithm()
) where T1<:Real where R<:Real
) where T2 where T1<:Real where R<:Real
x, f = intersection(breakingpoints, routes)
T2 = eltype(capacity_matrix)
# For other cases, capacities need to be Floats
if !(T2<:AbstractFloat)
capacity_matrix = convert(AbstractMatrix{Float64}, capacity_matrix)
Expand Down Expand Up @@ -191,14 +190,14 @@ function multiroute_flow(
flow_graph::AbstractGraph, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
capacity_matrix::AbstractMatrix = # edge flow capacities
capacity_matrix::AbstractMatrix{T} = # edge flow capacities
DefaultCapacity(flow_graph);
flow_algorithm::AbstractFlowAlgorithm = # keyword argument for algorithm
PushRelabelAlgorithm(),
mrf_algorithm::AbstractMultirouteFlowAlgorithm = # keyword argument for algorithm
KishimotoAlgorithm(),
routes::R = 0 # keyword argument for number of routes (0 = all values)
) where R <: Real
) where T where R <: Real

# a flow with a set of 1-disjoint paths is a classical max-flow
(routes == 1) &&
Expand All @@ -210,7 +209,6 @@ function multiroute_flow(
(routes > λ) && return empty_flow(capacity_matrix, flow_algorithm)

# For other cases, capacities need to be Floats
T = eltype(capacity_matrix)
if !(T<:AbstractFloat)
capacity_matrix = convert(AbstractMatrix{Float64}, capacity_matrix)
end
Expand Down
5 changes: 2 additions & 3 deletions src/flow/push_relabel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ FIFO push relabel algorithm with gap heuristic.
Takes approximately ``\\mathcal{O}(|V|^{3})`` time.
"""
function push_relabel end
@traitfn function push_relabel(
@traitfn function push_relabel{T}(
residual_graph::::IsDirected, # the input graph
source::Integer, # the source vertex
target::Integer, # the target vertex
capacity_matrix::AbstractMatrix # edge flow capacities
capacity_matrix::AbstractMatrix{T} # edge flow capacities
)

n = nv(residual_graph)
T = eltype(capacity_matrix)
flow_matrix = zeros(T, n, n)

height = zeros(Int, n)
Expand Down
15 changes: 7 additions & 8 deletions src/graphtypes/simplegraphs/SimpleGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,23 @@ AbstractSimpleGraphs must have the following elements:
- fadjlist::Vector{Vector{Integer}}
- ne::Integer
"""
abstract type AbstractSimpleGraph <: AbstractGraph end
abstract type AbstractSimpleGraph{T<:Integer} <: AbstractGraph{T} end

function show(io::IO, g::AbstractSimpleGraph)
function show(io::IO, g::AbstractSimpleGraph{T}) where T
if is_directed(g)
dir = "directed"
else
dir = "undirected"
end
if nv(g) == 0
print(io, "empty $dir simple $(eltype(g)) graph")
print(io, "empty $dir simple $T graph")
else
print(io, "{$(nv(g)), $(ne(g))} $dir simple $(eltype(g)) graph")
print(io, "{$(nv(g)), $(ne(g))} $dir simple $T graph")
end
end

nv(g::AbstractSimpleGraph) = eltype(g)(length(fadj(g)))
vertices(g::AbstractSimpleGraph) = one(eltype(g)):nv(g)
nv(g::AbstractSimpleGraph{T}) where T = T(length(fadj(g)))
vertices(g::AbstractSimpleGraph{T}) where T = one(T):nv(g)


edges(g::AbstractSimpleGraph) = SimpleEdgeIter(g)
Expand Down Expand Up @@ -74,8 +74,7 @@ has_vertex(g::AbstractSimpleGraph, v::Integer) = v in vertices(g)

ne(g::AbstractSimpleGraph) = g.ne

function rem_edge!(g::AbstractSimpleGraph, u::Integer, v::Integer)
T = eltype(g)
function rem_edge!(g::AbstractSimpleGraph{T}, u::Integer, v::Integer) where T
rem_edge!(g, edgetype(g)(T(u), T(v)))
end

Expand Down
Loading

0 comments on commit 27baf04

Please sign in to comment.