-
Notifications
You must be signed in to change notification settings - Fork 184
[WIP] Lighter graphs with edge iterators #163
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import Base: start, next, done, length, show, | ||
in, == | ||
|
||
type EdgeItState | ||
it::Int | ||
v::Int | ||
k::Int | ||
end | ||
|
||
type EdgeIt | ||
m::Int | ||
adj::Vector{Vector{Int}} | ||
start::EdgeItState # =[it, v, k] | ||
directed::Bool | ||
end | ||
|
||
edge_it(g::Graph) = EdgeIt(ne(g), g.fadjlist, EdgeItState(1,1,1), false) | ||
edge_it(g::DiGraph) = EdgeIt(ne(g), g.fadjlist, EdgeItState(1,1,1), true) | ||
|
||
start(eit::EdgeIt) = eit.start | ||
done(eit::EdgeIt, state::EdgeItState) = state.it > eit.m | ||
function next(eit::EdgeIt, state::EdgeItState) | ||
# println("$eit, $state") | ||
assert(state.v <= length(eit.adj)) | ||
u = 0 | ||
while state.k <= length(eit.adj[state.v]) | ||
u = eit.adj[state.v][state.k] | ||
eit.directed && break | ||
u >= state.v && break | ||
state.k += 1 | ||
end | ||
while state.k > length(eit.adj[state.v]) | ||
state.k = 1 | ||
state.v += 1 | ||
while state.k <= length(eit.adj[state.v]) | ||
u = eit.adj[state.v][state.k] | ||
eit.directed && break | ||
u >= state.v && break | ||
state.k += 1 | ||
end | ||
end | ||
e = !eit.directed && u < state.v ? Edge(u, state.v) : Edge(state.v, u) | ||
state.k += 1 | ||
state.it += 1 | ||
return (e, state) | ||
end | ||
length(eit::EdgeIt) = eit.m | ||
|
||
function in(e::Edge, eit::EdgeIt) | ||
s = src(e) | ||
t = dst(e) | ||
n = length(eit.adj) | ||
!(1 <= s <= n) && return false | ||
!(1 <= t <= n) && return false | ||
return t in eit.adj[s] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is O(n) and will be a performance bottleneck. The reason we went with edge sets is so we can do membership tests in O(1). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is O(deg(s)), that is O(1) in sparse graphs and O(n) in dense graphs. Since I usually work with sparse graphs I was not considering the latter case. Here there is a trade-off beetween saving In case maybe we can add this modified Graph as another type in LightGraphs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're quite right about the tradeoffs. It's one of the reasons there are so many different ways to represent graphs. :) Most of my work is in sparse graphs as well, so it won't affect ME too much, but I don't want it to be a surprise for anyone else. If you find calls to |
||
end | ||
|
||
#TODO implement using a loop and ∈, so that no memory is allocated | ||
==(e1::EdgeIt, e2::Set{Edge}) = Set{Edge}(e1) == e2 | ||
==(e1::Set{Edge}, e2::EdgeIt) = e1 == Set{Edge}(e2) | ||
==(e1::EdgeIt, e2::EdgeIt) = Set{Edge}(e1) == Set{Edge}(e2) | ||
|
||
|
||
|
||
show(io::IO, eit::EdgeIt) = write(io, "edgeit $(eit.m)") | ||
show(io::IO, s::EdgeItState) = write(io, "edgeitstate [ $(s.it),$(s.v),$(s.k) ]") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this allocate a ton of memory from a copy of
g.fadjlist
? Test memory allocation on some graph with 10^9 edges and see what happens.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not copying, adj points to the same memory of g.fadjlist