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

Commit

Permalink
Merge pull request #332 from CarloLucibello/visit
Browse files Browse the repository at this point in the history
updates in graph_traversal
  • Loading branch information
sbromberger committed Apr 24, 2016
2 parents 452a38a + e8d7351 commit 0cf3103
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 204 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ save("mygraph.jgz", g, "mygraph", compress=true)

- **distance:** eccentricity, diameter, periphery, radius, center

- **connectivity:** strongly- and weakly-connected components, bipartite checks, condensation, attracting components
- **connectivity:** strongly- and weakly-connected components, bipartite checks, condensation, attracting components, neighborhood

- **operators:** complement, reverse, reverse!, union, join, intersect, difference,
symmetric difference, blkdiag, induced subgraphs, products (cartesian/scalar)
Expand Down
14 changes: 14 additions & 0 deletions doc/basicmeasures.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,17 @@ common_neighbors(g::Union{LightGraphs.DiGraph,LightGraphs.Graph}, u::Int64, v::I
```
Returns the neighbors common to vertices `u` and `v` in `g`.

### neighborhood
```julia
neighborhood(g, v::Int, d::Int; dir=:out)
```

Returns a vector of the vertices in `g` at distance less or equal to `d` from `v`. If `g` is a `DiGraph` the `dir` optional argument specifies the edge direction the edge direction with respect to `v` (i.e. `:in` or `:out`) to be considered.

### egonet
```julia
egonet(g, v::Int, d::Int; dir=:out)
```

Returns the subgraph of `g` induced by the neighbors of `v` up to distance `d`. If `g` is a `DiGraph` the `dir` optional argument specifies the edge direction the edge direction with respect to `v` (i.e. `:in` or `:out`) to be considered. This is equivalent to `induced_subgraph(g, neighborhood(g, v, d, dir=dir)).`

7 changes: 5 additions & 2 deletions doc/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ types:
## Neighbors and Degree
{{degree, indegree, outdegree, Δ, δ, Δout, δout, δin, Δin, degree_histogram, density, neighbors, in_neighbors, all_neighbors, common_neighbors}}
{{degree, indegree, outdegree, Δ, δ, Δout, δout, δin, Δin, degree_histogram, density, neighbors,
in_neighbors, all_neighbors, common_neighbors, neighborhood, egonet}}
"""

@file "centrality.md" """
Expand Down Expand Up @@ -354,7 +355,9 @@ Any graph traversal will traverse an edge only if it is present in the graph. W
## Connectivity / Bipartiteness
`Graph connectivity` functions are defined on both undirected and directed graphs:
{{is_connected, is_strongly_connected, is_weakly_connected, connected_components, strongly_connected_components, weakly_connected_components, has_self_loop, attracting_components, is_bipartite, condensation, period}}
{{is_connected, is_strongly_connected, is_weakly_connected, connected_components,
strongly_connected_components, weakly_connected_components, has_self_loop,
attracting_components, is_bipartite, condensation, period, neighborhood}}
## Cycle Detection
In graph theory, a cycle is defined to be a path that starts from some vertex
Expand Down
2 changes: 1 addition & 1 deletion doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ save("mygraph.jgz", g, "mygraph", compress=true)

- **distance:** eccentricity, diameter, periphery, radius, center

- **connectivity:** strongly- and weakly-connected components, bipartite checks, condensation, attracting components
- **connectivity:** strongly- and weakly-connected components, bipartite checks, condensation, attracting components, neighborhood

- **operators:** complement, reverse, reverse!, union, join, intersect, difference,
symmetric difference, blkdiag, induced subgraphs, products (cartesian/scalar)
Expand Down
38 changes: 25 additions & 13 deletions doc/pathing.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ This function is a high level wrapper around bfs_tree!, use that function for mo

### dfs_tree
```julia
dfs_tree(g::Union{LightGraphs.DiGraph,LightGraphs.Graph}, s::Int64)
dfs_tree(g, s::Int)
```

Provides a depth-first traversal of the graph `g` starting with source vertex `s`, and returns a directed acyclic graph of vertices in the order they were discovered.

### maximum_adjacency_visit
Expand Down Expand Up @@ -62,9 +63,9 @@ Performs a [self-avoiding walk](https://en.wikipedia.org/wiki/Self-avoiding_walk
`Graph connectivity` functions are defined on both undirected and directed graphs:
### is_connected
```julia
is_connected(g::LightGraphs.Graph)
is_connected(g::LightGraphs.DiGraph)
is_connected(g)
```

Returns `true` if `g` is connected. For DiGraphs, this is equivalent to a test of weak connectivity.

### is_strongly_connected
Expand All @@ -83,7 +84,8 @@ Returns `true` if the undirected graph of `g` is connected.
```julia
connected_components(g)
```
Returns the [connected components](https://en.wikipedia.org/wiki/Connectivity_(graph_theory)) of an undirected graph `g` as a vector of components, each represented by a vector of vectors of vertices belonging to the component.

Returns the [connected components](https://en.wikipedia.org/wiki/Connectivity_(graph_theory)) of `g` as a vector of components, each represented by a vector of vertices belonging to the component.

### strongly_connected_components
```julia
Expand Down Expand Up @@ -111,10 +113,11 @@ Returns a vector of vectors of integers representing lists of attracting compone

### is_bipartite
```julia
is_bipartite(g::Union{LightGraphs.DiGraph,LightGraphs.Graph})
is_bipartite(g::Union{LightGraphs.DiGraph,LightGraphs.Graph}, s::Int64)
is_bipartite(g)
is_bipartite(g, v)
```
Will return `true` if graph `g` is [bipartite](https://en.wikipedia.org/wiki/Bipartite_graph).

Will return `true` if graph `g` is [bipartite](https://en.wikipedia.org/wiki/Bipartite_graph). If a node `v` is specified, only the connected component to which it belongs is considered.

### condensation
```julia
Expand All @@ -131,13 +134,21 @@ period(g::LightGraphs.DiGraph)
```
Computes the (common) period for all nodes in a strongly connected graph.

### neighborhood
```julia
neighborhood(g, v::Int, d::Int; dir=:out)
```

Returns a vector of the vertices in `g` at distance less or equal to `d` from `v`. If `g` is a `DiGraph` the `dir` optional argument specifies the edge direction the edge direction with respect to `v` (i.e. `:in` or `:out`) to be considered.

## Cycle Detection
In graph theory, a cycle is defined to be a path that starts from some vertex
`v` and ends up at `v`.
### is_cyclic
```julia
is_cyclic(graph::Union{LightGraphs.DiGraph,LightGraphs.Graph})
is_cyclic(g)
```

Tests whether a graph contains a cycle through depth-first search. It returns `true` when it finds a cycle, otherwise `false`.

## Shortest-Path Algorithms
Expand Down Expand Up @@ -184,16 +195,17 @@ Note that this algorithm may return a large amount of data (it will allocate on
## Path discovery / enumeration
### gdistances
```julia
gdistances(graph::Union{LightGraphs.DiGraph,LightGraphs.Graph}, sources)
gdistances(g, source) -> dists
```
Returns the geodesic distances of graph `g` from source vertex `s` or a set of source vertices `ss`.

Returns a vector filled with the geodesic distances of vertices in `g` from vertex/vertices `source`. For vertices in disconnected components the default distance is -1.

### gdistances!
```julia
gdistances!{DMap}(graph::Union{LightGraphs.DiGraph,LightGraphs.Graph}, s::Int64, dists::DMap)
gdistances!{DMap}(graph::Union{LightGraphs.DiGraph,LightGraphs.Graph}, sources::AbstractArray{Int64,1}, dists::DMap)
gdistances!(g, source, dists) -> dists
```
Returns the geodesic distances of graph `g` from source vertex `s` or a set of source vertices `ss`.

Fills `dists` with the geodesic distances of vertices in `g` from vertex/vertices `source`. `dists` can be either a vector or a dictionary.

### enumerate_paths
```julia
Expand Down
10 changes: 5 additions & 5 deletions src/LightGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ catch
end

import Base: write, ==, <, *, isless, issubset, complement, union, intersect,
reverse, reverse!, blkdiag, getindex, show, print, copy, in,
reverse, reverse!, blkdiag, getindex, setindex!, show, print, copy, in,
sum, size, sparse, eltype, length, ndims, issym, transpose,
ctranspose, join, start, next, done, eltype
ctranspose, join, start, next, done, eltype, get


# core
Expand All @@ -48,7 +48,7 @@ crosspath,
# graph visit
SimpleGraphVisitor, TrivialGraphVisitor, LogGraphVisitor,
discover_vertex!, open_vertex!, close_vertex!,
examine_neighbor!, visited_vertices, traverse_graph, traverse_graph_withlog,
examine_neighbor!, visited_vertices, traverse_graph!, traverse_graph_withlog,

# bfs
BreadthFirst, gdistances, gdistances!, bfs_tree, is_bipartite, bipartite_map,
Expand All @@ -62,7 +62,7 @@ randomwalk, saw, non_backtracking_randomwalk,
# connectivity
connected_components, strongly_connected_components, weakly_connected_components,
is_connected, is_strongly_connected, is_weakly_connected, period,
condensation, attracting_components,
condensation, attracting_components, neighborhood, egonet,

# cliques
maximal_cliques,
Expand Down Expand Up @@ -100,7 +100,7 @@ maximum_weight_maximal_matching, MatchingResult,
# randgraphs
erdos_renyi, watts_strogatz, random_regular_graph, random_regular_digraph, random_configuration_model,
StochasticBlockModel, make_edgestream, nearbipartiteSBM, blockcounts, blockfractions,
stochastic_block_model,
stochastic_block_model,

#community
modularity, community_detection_nback, core_periphery_deg,
Expand Down
93 changes: 73 additions & 20 deletions src/connectivity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
# licensing details.


"""connected_components! produces a label array of components
"""
connected_components!(label::Vector{Int}, g::SimpleGraph)
Fills `label` with the `id` of the connected component to which it belongs.
Arguments:
label: a place to store the output
Expand All @@ -21,14 +24,14 @@ function connected_components!(label::Vector{Int}, g::SimpleGraph)
# passed to components(a)
nvg = nv(g)
visitor = LightGraphs.ComponentVisitorVector(label, 0)
colormap = zeros(Int,nvg)
que = Vector{Int}()
sizehint!(que, nvg)
colormap = fill(0, nvg)
queue = Vector{Int}()
sizehint!(queue, nvg)
for v in 1:nvg
if label[v] == 0
visitor.labels[v] = v
visitor.seed = v
traverse_graph(g, BreadthFirst(), v, visitor; colormap=colormap, que=que)
traverse_graph!(g, BreadthFirst(), v, visitor; vertexcolormap=colormap, queue=queue)
end
end
return label
Expand All @@ -51,25 +54,25 @@ function components_dict(labels::Vector{Int})
return d
end

"""components(labels) converts an array of labels to a Vector{Vector{Int}} of components
"""
components(labels::Vector{Int})
Converts an array of labels to a Vector{Vector{Int}} of components
Arguments:
c = labels[i] => vertex i belongs to component c.
Output:
vs = c[i] => vertices in vs belong to component i.
a = d[i] => if label[v[j]]==i then j in c[a] end
a = d[i] => if labels[v]==i then v in c[a] end
"""
function components(labels::Vector{Int})
d = Dict{Int, Int}()
c = Vector{Vector{Int}}()
i = 1
for (v,l) in enumerate(labels)
index = get(d, l, i)
d[l] = index
index = get!(d, l, i)
if length(c) >= index
vec = c[index]
push!(vec, v)
c[index] = vec
push!(c[index], v)
else
push!(c, [v])
i += 1
Expand All @@ -78,19 +81,26 @@ function components(labels::Vector{Int})
return c, d
end

"""Returns the [connected components](https://en.wikipedia.org/wiki/Connectivity_(graph_theory))
of an undirected graph `g` as a vector of components, each represented by a
vector of vectors of vertices belonging to the component.
"""
function connected_components(g)
connected_components(g)
Returns the [connected components](https://en.wikipedia.org/wiki/Connectivity_(graph_theory))
of `g` as a vector of components, each represented by a
vector of vertices belonging to the component.
"""
function connected_components(g::SimpleGraph)
label = zeros(Int, nv(g))
connected_components!(label, g)
c, d = components(label)
return c
end

"""Returns `true` if `g` is connected.
For DiGraphs, this is equivalent to a test of weak connectivity."""
"""
is_connected(g)
Returns `true` if `g` is connected.
For DiGraphs, this is equivalent to a test of weak connectivity.
"""
is_connected(g::Graph) = length(connected_components(g)) == 1
is_connected(g::DiGraph) = is_weakly_connected(g)

Expand Down Expand Up @@ -123,7 +133,7 @@ function discover_vertex!(vis::TarjanVisitor, v)
end

function examine_neighbor!(vis::TarjanVisitor, v, w, w_color::Int, e_color::Int)
if w_color > 0 # 1 means added seen, but not explored; 2 means closed
if w_color != 0 # != 0 means seen
while vis.index[w] > 0 && vis.index[w] < vis.lowlink[end]
pop!(vis.lowlink)
end
Expand All @@ -150,7 +160,7 @@ function strongly_connected_components(g::DiGraph)
for v in vertices(g)
if cmap[v] == 0 # 0 means not visited yet
visitor = TarjanVisitor(nvg)
traverse_graph(g, DepthFirst(), v, visitor, vertexcolormap=cmap)
traverse_graph!(g, DepthFirst(), v, visitor, vertexcolormap=cmap)
for component in visitor.components
push!(components, component)
end
Expand Down Expand Up @@ -227,3 +237,46 @@ function attracting_components(g::DiGraph)
end
return scc[attracting]
end

type NeighborhoodVisitor <: SimpleGraphVisitor
d::Int
neigs::Vector{Int}
end

NeighborhoodVisitor(d::Int) = NeighborhoodVisitor(d, Vector{Int}())

function examine_neighbor!(visitor::NeighborhoodVisitor, u::Int, v::Int, ucolor::Int, vcolor::Int, ecolor::Int)
-ucolor > visitor.d && return false # color is negative for not-closed vertices
if vcolor == 0
push!(visitor.neigs, v)
end
return true
end


"""
neighborhood(g, v::Int, d::Int; dir=:out)
Returns a vector of the vertices in `g` at distance less or equal to `d`
from `v`. If `g` is a `DiGraph` the `dir` optional argument specifies the edge direction
the edge direction with respect to `v` (i.e. `:in` or `:out`) to be considered.
"""
function neighborhood(g::SimpleGraph, v::Int, d::Int; dir=:out)
@assert d >= 0 "Distance has to be greater then zero."
visitor = NeighborhoodVisitor(d)
push!(visitor.neigs, v)
traverse_graph!(g, BreadthFirst(), v, visitor,
vertexcolormap=Dict{Int,Int}(), dir=dir)
return visitor.neigs
end


"""
egonet(g, v::Int, d::Int; dir=:out)
Returns the subgraph of `g` induced by the neighbors of `v` up to distance
`d`. If `g` is a `DiGraph` the `dir` optional argument specifies
the edge direction the edge direction with respect to `v` (i.e. `:in` or `:out`)
to be considered. This is equivalent to `induced_subgraph(g, neighborhood(g, v, d, dir=dir)).`
"""
egonet(g::SimpleGraph, v::Int, d::Int; dir=:out) = induced_subgraph(g, neighborhood(g, v, d, dir=dir))
Loading

0 comments on commit 0cf3103

Please sign in to comment.