Skip to content

Commit 1cb644a

Browse files
authored
WIP: LightGraphs Abstraction (#541)
* benchmarks * add edgetype benchmark katz centrality is broken. * simplegraphs abstraction * Edge is no longer a Pair * pkgbenchmarks * f * remove data files from benchmarks * simplegraphs, take 2 * more changes * reshuffle * fix tests * more tests * abstractions * more tests * tests and fixes * trait fixes and tests - unrolling * persistence and floyd-warshall * make(di)graphs, through spanningtrees * moved cliques, testing through connectivity.jl * @jpfairbanks first round of review * another fix * all tests * new simpletraits * first cut at 0.6 compat * squash * update randgraphs.jl to use Channels over Tasks Fixes deprecation warnings introduced in: JuliaLang/julia#19841 Changes an API interface: -function Graph(nvg::Int, neg::Int, edgestream::Task) +function Graph(nvg::Int, neg::Int, edgestream::Channel) Iteration over Tasks is deprecated so now we iterate over the Channel. * got rid of tasks in randgraphs * graph -> g * Add tutorials to section on docs (#547) * Update README.md * Update README.md Made tutorials separate line and consistent with the other lines. * type -> mutable struct * more type -> mutable struct, plus OF detection for add_vertex! * foo{T}(x::T) -> foo(x::T) where T * test negative cycles * test coverage * manual cherry-pick of #551 * simplegraph/ -> simplegraphs, optimization for is_connected, some type simplifications * re-add b-f tests * Inferred (#554) * core * @inferred wherever possible * empty -> zero * test grid periodic=true * oops * redo graphmatrices tests * linalg test fix * loosen type restrictions in randgraphs functions * readall -> readstring, and comment rationalization in randgraphs * Fixes #555: graphmatrices convert incorrect on CA (#560) CombinatorialAdjacency(CombinatorialAdjacency(g)) was returning the backing storage. Fix includes tests. * fixes #564 * one more test * removed nv() and vertices() (#565) * simpleedge tests * test coverage * short circuit B-F negative cycles, plus tests * more test coverage * more test coverage * Docs (#567) * docs, plus some various fixes (see blocking_flow). * nodes -> vertices, node -> vertex, and more doc consistency * doc fixes * 1.0 -> 0.8 * docfix and benchmarks * doc fixes
1 parent b85a6cf commit 1cb644a

File tree

122 files changed

+5689
-4622
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+5689
-4622
lines changed

.travis.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ os:
55
# - osx
66

77
julia:
8-
- 0.5
9-
# - nightly
8+
# - 0.5
9+
- nightly
1010

1111
notifications:
1212
email: false

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function f(g::AbstractGraph, v::Integer)
4040
return inner!(storage, g, v)
4141
end
4242

43-
function inner!(storage::AbstractArray{Int,1}, g::AbstractGraph, v::Integer)
43+
function inner!(storage::AbstractVector{Int}, g::AbstractGraph, v::Integer)
4444
# some code operating on storage, g, and v.
4545
for i in 1:nv(g)
4646
storage[i] = v-i

README.md

+36-93
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ better-optimized mechanisms.
2828

2929
Additional functionality may be found in the companion package [LightGraphsExtras.jl](https://github.com/JuliaGraphs/LightGraphsExtras.jl).
3030

31+
3132
## Documentation
3233
Full documentation is available at [GitHub Pages](https://juliagraphs.github.io/LightGraphs.jl/latest).
3334
Documentation for methods is also available via the Julia REPL help system.
@@ -38,91 +39,26 @@ A graph *G* is described by a set of vertices *V* and edges *E*:
3839
*G = {V, E}*. *V* is an integer range `1:n`; *E* is represented as forward
3940
(and, for directed graphs, backward) adjacency lists indexed by vertices. Edges
4041
may also be accessed via an iterator that yields `Edge` types containing
41-
`(src::Int, dst::Int)` values.
42+
`(src<:Integer, dst<:Integer)` values. Both vertices and edges may be integers
43+
of any type, and the smallest type that fits the data is recommended in order
44+
to save memory.
4245

4346
*LightGraphs.jl* provides two graph types: `Graph` is an undirected graph, and
4447
`DiGraph` is its directed counterpart.
4548

4649
Graphs are created using `Graph()` or `DiGraph()`; there are several options
47-
(see below for examples).
48-
49-
Edges are added to a graph using `add_edge!(g, e)`. Instead of an edge type
50-
integers may be passed denoting the source and destination vertices (e.g.,
51-
`add_edge!(g, 1, 2)`).
50+
(see the tutorials for examples).
5251

5352
Multiple edges between two given vertices are not allowed: an attempt to
5453
add an edge that already exists in a graph will result in a silent failure.
5554

56-
Edges may be removed using `rem_edge!(g, e)`. Alternately, integers may be passed
57-
denoting the source and destination vertices (e.g., `rem_edge!(g, 1, 2)`). Note
58-
that, particularly for very large graphs, edge removal is a (relatively)
59-
expensive operation. An attempt to remove an edge that does not exist in the graph will result in an
60-
error.
61-
62-
Use `nv(g)` and `ne(g)` to compute the number of vertices and edges respectively.
63-
64-
`rem_vertex!(g, v)` alters the vertex identifiers. In particular, calling `n=nv(g)`, it swaps `v` and `n` and then removes `n`.
65-
66-
`edges(g)` returns an iterator to the edge set. Use `collect(edge(set))` to fill
67-
an array with all edges in the graph.
6855

6956
## Installation
7057
Installation is straightforward:
7158
```julia
7259
julia> Pkg.add("LightGraphs")
7360
```
7461

75-
## Usage Examples
76-
(all examples apply equally to `DiGraph` unless otherwise noted):
77-
78-
```julia
79-
# create an empty undirected graph
80-
g = Graph()
81-
82-
# create a 10-node undirected graph with no edges
83-
g = Graph(10)
84-
@assert nv(g) == 10
85-
86-
# create a 10-node undirected graph with 30 randomly-selected edges
87-
g = Graph(10,30)
88-
89-
# add an edge between vertices 4 and 5
90-
add_edge!(g, 4, 5)
91-
92-
# remove an edge between vertices 9 and 10
93-
rem_edge!(g, 9, 10)
94-
95-
# create vertex 11
96-
add_vertex!(g)
97-
98-
# remove vertex 2
99-
# attention: this changes the id of vertex nv(g) to 2
100-
rem_vertex!(g, 2)
101-
102-
# get the neighbors of vertex 4
103-
neighbors(g, 4)
104-
105-
# iterate over the edges
106-
m = 0
107-
for e in edges(g)
108-
m += 1
109-
end
110-
@assert m == ne(g)
111-
112-
# show distances between vertex 4 and all other vertices
113-
dijkstra_shortest_paths(g, 4).dists
114-
115-
# as above, but with non-default edge distances
116-
distmx = zeros(10,10)
117-
distmx[4,5] = 2.5
118-
distmx[5,4] = 2.5
119-
dijkstra_shortest_paths(g, 4, distmx).dists
120-
121-
# graph I/O
122-
g = loadgraph("mygraph.jgz", :lg)
123-
savegraph("mygraph.gml", g, :gml)
124-
```
125-
12662
## Current functionality
12763
- **core functions:** vertices and edges addition and removal, degree (in/out/histogram), neighbors (in/out/all/common)
12864

@@ -155,44 +91,50 @@ symmetric difference, blkdiag, induced subgraphs, products (cartesian/scalar)
15591

15692
- **community:** modularity, community detection, core-periphery, clustering coefficients
15793

158-
- **persistence formats:** proprietary compressed, [GraphML](http://en.wikipedia.org/wiki/GraphML), [GML](https://en.wikipedia.org/wiki/Graph_Modelling_Language), [Gexf](http://gexf.net/format), [DOT](https://en.wikipedia.org/wiki/DOT_(graph_description_language)), [Pajek NET](http://gephi.org/users/supported-graph-formats/pajek-net-format/)
94+
- **persistence formats:** proprietary compressed, [GraphML](http://en.wikipedia.org/wiki/GraphML), [GML](https://en.wikipedia.org/wiki/Graph_Modelling_Language), [Gexf](http://gexf.net/format), [DOT](https://en.wikipedia.org/wiki/DOT_(graph_description_language)), [Pajek NET](http://gephi.org/users/supported-graph-formats/pajek-net-format/), [Graph6](http://users.cecs.anu.edu.au/~bdm/data/formats.html)
15995

160-
- **visualization:** integration with [GraphLayout](https://github.com/IainNZ/GraphLayout.jl), [TikzGraphs](https://github.com/sisl/TikzGraphs.jl), [GraphPlot](https://github.com/JuliaGraphs/GraphPlot.jl), [NetworkViz](https://github.com/abhijithanilkumar/NetworkViz.jl/)
96+
- **visualization:** integration with
97+
[GraphPlot](https://github.com/JuliaGraphs/GraphPlot.jl),
98+
[Plots](https://github.com/JuliaPlots/Plots.jl) via [PlotRecipes](https://github.com/JuliaPlots/PlotRecipes.jl), [GraphLayout](https://github.com/IainNZ/GraphLayout.jl), [TikzGraphs](https://github.com/sisl/TikzGraphs.jl), [NetworkViz](https://github.com/abhijithanilkumar/NetworkViz.jl/)
16199

162100

163101
## Core API
164-
These functions are defined as the public contract of the LightGraphs.AbstractGraph interface.
102+
These functions are defined as the public contract of the `LightGraphs.AbstractGraph` interface.
165103

166104
### Constructing and modifying the graph
167-
168-
- add_edge!
169-
- rem_edge!
170-
- add_vertex!
171-
- add_vertices!
172-
- rem_vertex!
105+
- `Graph`
106+
- `DiGraph`
107+
- `add_edge!`
108+
- `rem_edge!`
109+
- `add_vertex!`, `add_vertices!`
110+
- `rem_vertex!`
111+
- `zero`
173112

174113
### Edge/Arc interface
175-
- src
176-
- dst
114+
- `src`
115+
- `dst`
116+
- `reverse`
117+
- `==`
118+
- Pair / Tuple conversion
177119

178120
### Accessing state
179-
- nv::Int
180-
- ne::Int
181-
- vertices (Iterable)
182-
- edges (Iterable)
183-
- neighbors
184-
- in_edges
185-
- out_edges
186-
- has_vertex
187-
- has_edge
188-
- has_self_loops (though this might be a trait or an abstract graph type)
121+
- `nv`
122+
- `ne`
123+
- `vertices` (Iterable)
124+
- `edges` (Iterable)
125+
- `neighbors`, `in_neighbors`, `out_neighbors`
126+
- `in_edges`
127+
- `out_edges`
128+
- `has_vertex`
129+
- `has_edge`
130+
- `has_self_loops` (though this might be a trait or an abstract graph type)
189131

190132

191133
### Non-Core APIs
192134
These functions can be constructed from the Core API functions but can be given specialized implementations in order to improve performance.
193135

194-
- adjacency_matrix
195-
- degree
136+
- `adjacency_matrix`
137+
- `degree`
196138

197139
This can be computed from neighbors by default `degree(g,v) = length(neighbors(g,v))` so you don't need to implement this unless your type can compute degree faster than this method.
198140

@@ -202,7 +144,8 @@ This can be computed from neighbors by default `degree(g,v) = length(neighbors(g
202144
* Julia 0.3: LightGraphs v0.3.7 is the last version guaranteed to work with Julia 0.3.
203145
* Julia 0.4: LightGraphs versions in the 0.6 series are designed to work with Julia 0.4.
204146
* Julia 0.5: LightGraphs versions in the 0.7 series are designed to work with Julia 0.5.
205-
* Julia 0.6: Some functionality might not work with prerelease / unstable / nightly versions of Julia. If you run into a problem on 0.6, please file an issue.
147+
* Julia 0.6: LightGraphs versions in the 0.8 series are designed to work with Julia 0.6.
148+
* Later versions: Some functionality might not work with prerelease / unstable / nightly versions of Julia. If you run into a problem, please file an issue.
206149

207150
# Contributing and Reporting Bugs
208151
We welcome contributions and bug reports! Please see [CONTRIBUTING.md](https://github.com/JuliaGraphs/LightGraphs.jl/blob/master/CONTRIBUTING.md)

REQUIRE

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
julia 0.5
1+
julia 0.6-
22
GZip 0.2.20
33
EzXML 0.3.0
44
ParserCombinator 1.7.11
55
JLD 0.6.3
66
Distributions 0.10.2
77
StatsBase 0.9.0
88
DataStructures 0.5.0
9+
SimpleTraits 0.4.0

benchmark/edges.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Base: convert
2-
typealias P Pair{Int, Int}
2+
3+
const P = Pair{Int, Int}
34

45
convert(::Type{Tuple}, e::Pair) = (e.first, e.second)
56

benchmark/max-flow.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
p = 8.0 / n
55
A = sprand(n,n,p)
66
g = DiGraph(A)
7-
cap = round(A*100)
7+
cap = round.(A*100)
88
@bench "n = $n" LightGraphs.maximum_flow($g, 1, $n, $cap)
99
end
1010
end # max-flow

benchmarks/core.jl

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
bg = BenchmarkGroup()
2+
SUITE["core"] = bg
3+
4+
function bench_iteredges(g::AbstractGraph)
5+
i = 0
6+
for e in edges(g)
7+
i += 1
8+
end
9+
return i
10+
end
11+
12+
function bench_has_edge(g::AbstractGraph)
13+
srand(1)
14+
nvg = nv(g)
15+
srcs = rand([1:nvg;], cld(nvg, 4))
16+
dsts = rand([1:nvg;], cld(nvg, 4))
17+
i = 0
18+
for (s, d) in zip(srcs, dsts)
19+
if has_edge(g, s, d)
20+
i += 1
21+
end
22+
end
23+
return i
24+
end
25+
26+
27+
EDGEFNS = [
28+
bench_iteredges,
29+
bench_has_edge
30+
]
31+
32+
for fun in EDGEFNS
33+
for (name, g) in GRAPHS
34+
bg["edges","$fun","graph","$name"] = @benchmarkable $fun($g)
35+
end
36+
37+
for (name, g) in DIGRAPHS
38+
bg["edges","$fun","digraph","$name"] = @benchmarkable $fun($g)
39+
end
40+
41+
end

src/LightGraphs.jl

+30-16
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,25 @@ using DataStructures
77
using EzXML
88
using ParserCombinator: Parsers.DOT, Parsers.GML
99
using StatsBase: fit, Histogram
10+
using SimpleTraits
1011

1112
import Base: write, ==, <, *, , convert, isless, issubset, union, intersect,
12-
reverse, reverse!, blkdiag, getindex, setindex!, show, print, copy, in,
13-
sum, size, sparse, eltype, length, ndims, transpose,
14-
ctranspose, join, start, next, done, eltype, get, issymmetric, A_mul_B!
15-
13+
reverse, reverse!, blkdiag, isassigned, getindex, setindex!, show,
14+
print, copy, in, sum, size, sparse, eltype, length, ndims, transpose,
15+
ctranspose, join, start, next, done, eltype, get, issymmetric, A_mul_B!,
16+
Pair, Tuple, zero
17+
export
18+
# Interface
19+
AbstractGraph, AbstractDiGraph, AbstractEdge, AbstractEdgeInter,
20+
Edge, Graph, DiGraph, vertices, edges, edgetype, nv, ne, src, dst,
21+
is_directed, add_vertex!, add_edge!, rem_vertex!, rem_edge!,
22+
has_vertex, has_edge, in_neighbors, out_neighbors,
1623

1724
# core
18-
export AbstractGraph, Edge, Graph, DiGraph, vertices, edges, src, dst,
19-
fadj, badj, in_edges, out_edges, has_vertex, has_edge, is_directed,
20-
nv, ne, add_edge!, rem_edge!, add_vertex!, add_vertices!,
21-
indegree, outdegree, degree, degree_histogram, density, Δ, δ,
22-
Δout, Δin, δout, δin, neighbors, in_neighbors, out_neighbors,
23-
common_neighbors, all_neighbors, has_self_loops, num_self_loops,
24-
rem_vertex!,
25+
is_ordered, add_vertices!, indegree, outdegree, degree,
26+
Δout, Δin, δout, δin, Δ, δ, degree_histogram,
27+
neighbors, all_neighbors, common_neighbors,
28+
has_self_loops, num_self_loops, density, squash,
2529

2630
# distance
2731
eccentricity, diameter, periphery, radius, center,
@@ -113,7 +117,10 @@ kruskal_mst, prim_mst,
113117
#biconnectivity and articulation points
114118
articulation, biconnected_components
115119

116-
"""An optimized graphs package.
120+
"""
121+
LightGraphs
122+
123+
An optimized graphs package.
117124
118125
Simple graphs (not multi- or hypergraphs) are represented in a memory- and
119126
time-efficient manner with adjacency lists and edge sets. Both directed and
@@ -127,14 +134,21 @@ explicit design decision that any data not required for graph manipulation
127134
(attributes and other information, for example) is expected to be stored
128135
outside of the graph structure itself. Such data lends itself to storage in
129136
more traditional and better-optimized mechanisms.
137+
138+
[Full documentation](http://codecov.io/github/JuliaGraphs/LightGraphs.jl) is available,
139+
and tutorials are available at the
140+
[JuliaGraphsTutorials repository](https://github.com/JuliaGraphs/JuliaGraphsTutorials).
130141
"""
131142
LightGraphs
132-
143+
include("interface.jl")
144+
include("deprecations.jl")
133145
include("core.jl")
134-
include("digraph.jl")
146+
include("graphtypes/simplegraphs/SimpleGraphs.jl")
147+
const Graph = SimpleGraphs.SimpleGraph
148+
const DiGraph = SimpleGraphs.SimpleDiGraph
149+
const Edge = SimpleGraphs.SimpleEdge
150+
135151
include("digraph-transitivity.jl")
136-
include("graph.jl")
137-
include("edgeiter.jl")
138152
include("traversals/graphvisit.jl")
139153
include("traversals/bfs.jl")
140154
include("traversals/dfs.jl")

0 commit comments

Comments
 (0)