Skip to content

Commit 5bc0e4d

Browse files
committed
type instability
1 parent 633b0f6 commit 5bc0e4d

File tree

7 files changed

+89
-72
lines changed

7 files changed

+89
-72
lines changed

REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
julia 0.6
22
LightGraphs 0.10.5
3+
JLD2

src/StaticGraphs.jl

Lines changed: 12 additions & 7 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

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

5560
function show(io::IO, g::AbstractStaticGraph)
5661
if is_directed(g)
@@ -59,9 +64,9 @@ function show(io::IO, g::AbstractStaticGraph)
5964
dir = "undirected"
6065
end
6166
if nv(g) == 0
62-
print(io, "empty $dir simple static $(eltype(g)) graph")
67+
print(io, "empty $dir simple static {$(vectype(g)), $(indtype(g))} graph")
6368
else
64-
print(io, "{$(nv(g)), $(ne(g))} $dir simple static $(eltype(g)) graph")
69+
print(io, "{$(nv(g)), $(ne(g))} $dir simple static {$(vectype(g)), $(indtype(g))} graph")
6570
end
6671
end
6772

@@ -76,9 +81,9 @@ end
7681
return fastview(g.f_vec, r)
7782
end
7883

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)
84+
nv(g::AbstractStaticGraph{T, U}) where T where U = T(length(g.f_ind) - 1)
85+
vertices(g::AbstractStaticGraph{T, U}) where T where U = one(T):nv(g)
86+
8287

8388
has_edge(g::AbstractStaticGraph, e::AbstractStaticEdge) =
8489
insorted(dst(e), neighbors(g, src(e)))

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 StaticGraph(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) = 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}(
37+
convert(T, f_ds),
38+
convert(U, f_ind),
39+
convert(T, b_ds),
40+
convert(U, b_ind)
41+
)
3542
end
3643

3744
# sorted src, dst tuples for forward and backward

src/staticgraph.jl

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,26 @@
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

1313
badj(g::StaticGraph, s) = fadj(g, s)
1414

15-
ne(g::StaticGraph) = length(g.f_vec) ÷ 2
15+
ne(g::StaticGraph{T, U}) where T where U = T(length(g.f_vec) ÷ 2)
1616

1717

1818
# sorted src, dst vectors
1919
# note: this requires reverse edges included in the sorted vector.
20-
function StaticGraph(n_v, ss::Vector{T}, ds::Vector{T}) where T <: Integer
20+
function StaticGraph(n_v, ss::AbstractVector, ds::AbstractVector)
2121
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])
22+
(n_v == 0 || length(ss) == 0) && return StaticGraph(UInt8[], UInt8[1])
2323
f_ind = [searchsortedfirst(ss, x) for x in 1:n_v]
2424
push!(f_ind, length(ss)+1)
25-
return StaticGraph{T}(ds, f_ind)
25+
T = mintype(ds)
26+
U = mintype(f_ind)
27+
return StaticGraph{T, U}(convert(Vector{T},ds), convert(Vector{U}, f_ind))
2628
end
2729

2830
# sorted src, dst tuples
@@ -42,7 +44,7 @@ end
4244

4345
==(g::StaticGraph, h::StaticGraph) = g.f_vec == h.f_vec && g.f_ind == h.f_ind
4446

45-
degree(g::StaticGraph, v::Integer) = length(_fvrange(g, v))
47+
degree(g::StaticGraph{T, U}, v::Integer) where T where U = T(length(_fvrange(g, v)))
4648
degree(g::StaticGraph) = [degree(g, v) for v in vertices(g)]
4749
indegree(g::StaticGraph, v::Integer) = degree(g, v)
4850
indegree(g::StaticGraph) = degree(g)
@@ -56,5 +58,5 @@ outdegree(g::StaticGraph) = degree(g)
5658
Return `true` if `g` is a directed graph.
5759
"""
5860
is_directed(::Type{StaticGraph}) = false
59-
is_directed(::Type{StaticGraph{T}}) where T = false
61+
is_directed(::Type{StaticGraph{T, U}}) where T where U = false
6062
is_directed(g::StaticGraph) = false

src/utils.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,32 @@ From https://github.com/rdeits/NNLS.jl/blob/0a9bf56774595b5735bc738723bd3cb94138
2525
view(parent, range)
2626
end
2727
end
28+
29+
"""
30+
squashsorted(v)
31+
32+
Returns the sorted vector `v` converted to the smallest possible
33+
integer type that can fit all values.
34+
35+
### Implementation Notes
36+
`v` is assumed to be sorted.
37+
"""
38+
function squashsorted(v::AbstractVector)
39+
validtypes = [UInt8, UInt16, UInt32, UInt64, UInt128]
40+
l = v[end]
41+
for T in validtypes
42+
l < typemax(T) && return convert(Vector{T}, v)
43+
end
44+
return v
45+
end
46+
47+
function mintype(v::AbstractVector)
48+
validtypes = [UInt8, UInt16, UInt32, UInt64, UInt128]
49+
l = v[end]
50+
for T in validtypes
51+
l < typemax(T) && return T
52+
end
53+
return eltype(v)
54+
end
55+
56+

test/testdata/house.jsg

767 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)