Skip to content

Commit 6b0abb2

Browse files
authored
Merge pull request #2 from sbromberger/sbromberger/no-workie
Sbromberger/no workie
2 parents 633b0f6 + f9df7e8 commit 6b0abb2

File tree

10 files changed

+119
-107
lines changed

10 files changed

+119
-107
lines changed

REQUIRE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
julia 0.6
2-
LightGraphs 0.10.5
2+
LightGraphs 0.11
3+
JLD2

src/StaticGraphs.jl

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module StaticGraphs
22

33
using LightGraphs
4+
using JLD2
45

56
import Base:
67
convert, eltype, show, ==, Pair, Tuple, in, copy, length, start, next, done, issubset, zero, one,
@@ -10,7 +11,7 @@ import LightGraphs:
1011
_NI, _insert_and_dedup!, AbstractEdge, AbstractEdgeIter,
1112
src, dst, edgetype, nv, ne, vertices, edges, is_directed,
1213
has_vertex, has_edge, in_neighbors, out_neighbors,
13-
indegree, outdegree, degree, insorted,
14+
indegree, outdegree, degree, insorted, squash,
1415

1516
AbstractGraphFormat, loadgraph, savegraph
1617

@@ -39,9 +40,8 @@ export
3940

4041
include("utils.jl")
4142

42-
const StaticEdgeIter{G} = LightGraphs.SimpleGraphs.SimpleEdgeIter{G}
43-
const AbstractStaticEdge = AbstractSimpleEdge
44-
const StaticEdge = SimpleEdge
43+
const AbstractStaticEdge{T} = AbstractSimpleEdge{T}
44+
const StaticEdge{T} = SimpleEdge{T}
4545

4646
"""
4747
AbstractStaticGraph
@@ -50,7 +50,11 @@ An abstract type representing a simple graph structure.
5050
AbstractStaticGraphs must have the following elements:
5151
- weightmx::AbstractSparseMatrix{Real}
5252
"""
53-
abstract type AbstractStaticGraph <: AbstractSimpleGraph end
53+
abstract type AbstractStaticGraph{T<:Integer, U<:Integer} <: AbstractSimpleGraph{T} end
54+
55+
vectype(g::AbstractStaticGraph{T, U}) where T where U = T
56+
indtype(g::AbstractStaticGraph{T, U}) where T where U = U
57+
eltype(x::AbstractStaticGraph) = vectype(x)
5458

5559
function show(io::IO, g::AbstractStaticGraph)
5660
if is_directed(g)
@@ -59,9 +63,9 @@ function show(io::IO, g::AbstractStaticGraph)
5963
dir = "undirected"
6064
end
6165
if nv(g) == 0
62-
print(io, "empty $dir simple static $(eltype(g)) graph")
66+
print(io, "empty $dir simple static {$(vectype(g)), $(indtype(g))} graph")
6367
else
64-
print(io, "{$(nv(g)), $(ne(g))} $dir simple static $(eltype(g)) graph")
68+
print(io, "{$(nv(g)), $(ne(g))} $dir simple static {$(vectype(g)), $(indtype(g))} graph")
6569
end
6670
end
6771

@@ -76,14 +80,14 @@ end
7680
return fastview(g.f_vec, r)
7781
end
7882

79-
nv(g::AbstractStaticGraph) = length(g.f_ind) - 1
80-
vertices(g::AbstractStaticGraph) = one(eltype(g)):nv(g)
81-
eltype(x::AbstractStaticGraph) = eltype(x.f_vec)
83+
nv(g::AbstractStaticGraph{T, U}) where T where U = T(length(g.f_ind) - 1)
84+
vertices(g::AbstractStaticGraph{T, U}) where T where U = one(T):nv(g)
85+
8286

8387
has_edge(g::AbstractStaticGraph, e::AbstractStaticEdge) =
84-
insorted(dst(e), neighbors(g, src(e)))
88+
insorted(dst(e), out_neighbors(g, src(e)))
8589

86-
edgetype(g::AbstractStaticGraph) = StaticEdge
90+
edgetype(g::AbstractStaticGraph{T}) where T = StaticEdge{T}
8791
edges(g::AbstractStaticGraph) = StaticEdgeIter(g)
8892

8993
has_vertex(g::AbstractStaticGraph, v::Integer) = v in vertices(g)
@@ -104,4 +108,10 @@ include("persistence.jl")
104108
const SGraph = StaticGraph
105109
const SDiGraph = StaticDiGraph
106110

111+
const StaticEdgeIter{G} = LightGraphs.SimpleGraphs.SimpleEdgeIter{G}
112+
113+
eltype(::Type{StaticEdgeIter{StaticGraph{T, U}}}) where T where U = StaticGraphEdge{T}
114+
eltype(::Type{StaticEdgeIter{StaticDiGraph{T, U}}}) where T where U = StaticDiGraphEdge{T}
115+
116+
107117
end # module

src/persistence.jl

Lines changed: 22 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,37 @@
11
# StaticGraphs are binary files with the following format:
2-
# f_vec, 0, f_ind
2+
# sizeof(T), sizeU, f_vec, 0, f_ind
33
# StaticDiGraphs have the following format:
4-
# f_vec, 0, f_ind, 0, b_vec, 0, b_ind
4+
# bits in T, bits in U, f_vec, 0, f_ind, 0, b_vec, 0, b_ind
55

66
abstract type StaticGraphFormat <: AbstractGraphFormat end
7-
struct SGFormat{T<:Integer} <: StaticGraphFormat end
8-
struct SDGFormat{T<:Integer} <: StaticGraphFormat end
7+
struct SGFormat <: StaticGraphFormat end
8+
struct SDGFormat <: StaticGraphFormat end
99

10-
SGFormat() = SGFormat{Int64}()
11-
SGFormat(T::DataType) = SGFormat{T}()
12-
13-
SDGFormat() = SDGFormat{Int64}()
14-
SDGFormat(T::DataType) = SDGFormat{T}()
15-
16-
17-
function savesg(fn::AbstractString, g::StaticGraph, T::DataType)
18-
open(fn, "w+") do io
19-
arr = vcat(g.f_vec, [0], g.f_ind)
20-
v = Mmap.mmap(io, Vector{T}, length(arr))
21-
for i = 1:length(arr)
22-
@inbounds v[i] = arr[i]
23-
end
24-
Mmap.sync!(v)
25-
end
10+
function savesg(fn::AbstractString, g::StaticGraph)
11+
f_ind = g.f_ind
12+
f_vec = g.f_vec
13+
@save fn f_vec f_ind
2614
return 1
2715
end
2816

29-
function savesg(fn::AbstractString, g::StaticDiGraph, T::DataType)
30-
open(fn, "w+") do io
31-
farr = vcat(g.f_vec, [0], g.f_ind)
32-
barr = vcat(g.b_vec, [0], g.b_ind)
33-
arr = vcat(farr, [0], barr)
34-
v = Mmap.mmap(io, Vector{T}, length(arr))
35-
for i = 1:length(arr)
36-
@inbounds v[i] = arr[i]
37-
end
38-
Mmap.sync!(v)
39-
end
17+
function savesg(fn::AbstractString, g::StaticDiGraph)
18+
f_ind = g.f_ind
19+
f_vec = g.f_vec
20+
b_ind = g.b_ind
21+
b_vec = g.b_vec
22+
@save fn f_vec f_ind b_vec b_ind
4023
return 1
4124
end
4225

43-
function loadsg(fn::AbstractString, ::SGFormat{T}) where T <: Integer
44-
open(fn, "r") do io
45-
arr = Mmap.mmap(io, Vector{T})
46-
zeroind = findfirst(arr, 0)
47-
StaticGraph{T}(arr[1:zeroind-1], arr[zeroind+1:end])
48-
end
26+
function loadsg(fn::AbstractString, ::SGFormat)
27+
@load fn f_vec f_ind
28+
return StaticGraph(f_vec, f_ind)
4929
end
5030

51-
function loadsg(fn::AbstractString, ::SDGFormat{T}) where T <: Integer
52-
open(fn, "r") do io
53-
arr = Mmap.mmap(io, Vector{T})
54-
(z1, z2, z3) = findin(arr, 0)
55-
f_arr = fastview(arr, 1:(z1 - 1))
56-
f_ind = fastview(arr, (z1 + 1):(z2 - 1))
57-
b_arr = fastview(arr, (z2 + 1):(z3 - 1))
58-
b_ind = fastview(arr, (z3 + 1):length(arr))
59-
StaticDiGraph{T}(f_arr, f_ind, b_arr, b_ind)
60-
end
31+
function loadsg(fn::AbstractString, ::SDGFormat)
32+
@load fn f_vec f_ind b_vec b_ind
33+
return StaticDiGraph(f_vec, f_ind, b_vec, b_ind)
6134
end
6235

63-
loadgraph(fn::AbstractString, gname::String, s::T) where T <: StaticGraphFormat = loadsg(fn, s)
64-
savegraph(fn::AbstractString, g::AbstractStaticGraph) = savesg(fn, g, eltype(g))
36+
loadgraph(fn::AbstractString, gname::String, s::StaticGraphFormat) = loadsg(fn, s)
37+
savegraph(fn::AbstractString, g::AbstractStaticGraph) = savesg(fn, g)

src/staticdigraph.jl

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
"""
2-
StaticDiGraph{T}
2+
StaticDiGraph{T, U}
33
44
A type representing a static directed graph.
55
"""
6-
struct StaticDiGraph{T<:Integer} <: AbstractStaticGraph
6+
struct StaticDiGraph{T<:Integer, U<:Integer} <: AbstractStaticGraph{T, U}
77
f_vec::Vector{T}
8-
f_ind::Vector{T}
8+
f_ind::Vector{U}
99
b_vec::Vector{T}
10-
b_ind::Vector{T}
10+
b_ind::Vector{U}
1111
end
1212

1313
@inline function _bvrange(g::StaticDiGraph, s)
@@ -21,17 +21,24 @@ end
2121
return fastview(g.b_vec, r)
2222
end
2323

24-
ne(g::StaticDiGraph) = length(g.f_vec)
24+
ne(g::StaticDiGraph{T, U}) where T where U = U(length(g.f_vec))
2525

2626
# sorted src, dst vectors for forward and backward edgelists.
27-
function StaticDiGraph(n_v, f_ss::Vector{T}, f_ds::Vector{T}, b_ss::Vector{T}, b_ds::Vector{T}) where T <: Integer
27+
function StaticDiGraph(n_v, f_ss::AbstractVector, f_ds::AbstractVector, b_ss::AbstractVector, b_ds::AbstractVector)
2828
length(f_ss) == length(f_ds) == length(b_ss) == length(b_ds) || error("source and destination vectors must be equal length")
29-
(n_v == 0 || length(f_ss) == 0) && return StaticDiGraph(T[], T[1], T[], T[1])
29+
(n_v == 0 || length(f_ss) == 0) && return StaticDiGraph(UInt8[], UInt8[1], UInt8[], UInt8[1])
3030
f_ind = [searchsortedfirst(f_ss, x) for x in 1:n_v]
3131
push!(f_ind, length(f_ss)+1)
3232
b_ind = [searchsortedfirst(b_ss, x) for x in 1:n_v]
3333
push!(b_ind, length(b_ss)+1)
34-
return StaticDiGraph{T}(f_ds, f_ind, b_ds, b_ind)
34+
T = mintype(f_ds)
35+
U = mintype(f_ind)
36+
return StaticDiGraph{T, U}(
37+
convert(Vector{T}, f_ds),
38+
convert(Vector{U}, f_ind),
39+
convert(Vector{T}, b_ds),
40+
convert(Vector{U}, b_ind)
41+
)
3542
end
3643

3744
# sorted src, dst tuples for forward and backward

src/staticgraph.jl

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,22 @@
55
66
A type representing an undirected static graph.
77
"""
8-
struct StaticGraph{T<:Integer} <: AbstractStaticGraph
8+
struct StaticGraph{T<:Integer, U<:Integer} <: AbstractStaticGraph{T, U}
99
f_vec::Vector{T}
10-
f_ind::Vector{T}
10+
f_ind::Vector{U}
1111
end
1212

13-
badj(g::StaticGraph, s) = fadj(g, s)
14-
15-
ne(g::StaticGraph) = length(g.f_vec) ÷ 2
16-
1713

1814
# sorted src, dst vectors
1915
# note: this requires reverse edges included in the sorted vector.
20-
function StaticGraph(n_v, ss::Vector{T}, ds::Vector{T}) where T <: Integer
16+
function StaticGraph(n_v, ss::AbstractVector, ds::AbstractVector)
2117
length(ss) != length(ds) && error("source and destination vectors must be equal length")
22-
(n_v == 0 || length(ss) == 0) && return StaticGraph(T[], T[1])
18+
(n_v == 0 || length(ss) == 0) && return StaticGraph(UInt8[], UInt8[1])
2319
f_ind = [searchsortedfirst(ss, x) for x in 1:n_v]
2420
push!(f_ind, length(ss)+1)
25-
return StaticGraph{T}(ds, f_ind)
21+
T = mintype(ds)
22+
U = mintype(f_ind)
23+
return StaticGraph{T, U}(convert(Vector{T},ds), convert(Vector{U}, f_ind))
2624
end
2725

2826
# sorted src, dst tuples
@@ -40,9 +38,21 @@ function StaticGraph(g::LightGraphs.SimpleGraphs.SimpleGraph)
4038
StaticGraph(nv(g), sd)
4139
end
4240

41+
badj(g::StaticGraph, s) = fadj(g, s)
42+
43+
ne(g::StaticGraph{T, U}) where T where U = T(length(g.f_vec) ÷ 2)
44+
45+
function has_edge(g::StaticGraph, e::StaticGraphEdge)
46+
u, v = Tuple(e)
47+
(u > nv(g) || v > nv(g)) && return false
48+
if degree(g, u) > degree(g, v)
49+
u, v = v, u
50+
end
51+
return insorted(v, fadj(g, u))
52+
end
4353
==(g::StaticGraph, h::StaticGraph) = g.f_vec == h.f_vec && g.f_ind == h.f_ind
4454

45-
degree(g::StaticGraph, v::Integer) = length(_fvrange(g, v))
55+
degree(g::StaticGraph{T, U}, v::Integer) where T where U = T(length(_fvrange(g, v)))
4656
degree(g::StaticGraph) = [degree(g, v) for v in vertices(g)]
4757
indegree(g::StaticGraph, v::Integer) = degree(g, v)
4858
indegree(g::StaticGraph) = degree(g)
@@ -56,5 +66,5 @@ outdegree(g::StaticGraph) = degree(g)
5666
Return `true` if `g` is a directed graph.
5767
"""
5868
is_directed(::Type{StaticGraph}) = false
59-
is_directed(::Type{StaticGraph{T}}) where T = false
69+
is_directed(::Type{StaticGraph{T, U}}) where T where U = false
6070
is_directed(g::StaticGraph) = false

src/utils.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,23 @@ From https://github.com/rdeits/NNLS.jl/blob/0a9bf56774595b5735bc738723bd3cb94138
2525
view(parent, range)
2626
end
2727
end
28+
29+
"""
30+
mintype(v)
31+
32+
Returns the minimum integer type required to fit all elements
33+
in sorted vector `v`.
34+
35+
### Implementation Notes
36+
`v` is assumed to be sorted.
37+
"""
38+
function mintype(v::AbstractVector)
39+
validtypes = [UInt8, UInt16, UInt32, UInt64, UInt128]
40+
l = v[end]
41+
for T in validtypes
42+
l <= typemax(T) && return T
43+
end
44+
return eltype(v)
45+
end
46+
47+

0 commit comments

Comments
 (0)