Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
trac #25550: deal with multiedges in neighbor iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
dcoudert committed Jul 30, 2018
1 parent fc1b7b0 commit 508cf3e
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/sage/graphs/base/static_sparse_backend.pxd
Expand Up @@ -17,6 +17,7 @@ cdef class StaticSparseBackend(CGraphBackend):
cdef bint _multiedges
cdef list _vertex_to_labels
cdef dict _vertex_to_int
cdef bitset_t _seen

cdef uint32_t simple_BFS(short_digraph g,
uint32_t source,
Expand Down
50 changes: 37 additions & 13 deletions src/sage/graphs/base/static_sparse_backend.pyx
Expand Up @@ -446,6 +446,9 @@ cdef class StaticSparseBackend(CGraphBackend):
self.vertex_labels = {i:v for i,v in enumerate(vertices)}
self._multiple_edges = self._multiedges

# Defining a temporary bitset for neighbors iterators
bitset_init(self._seen, self._order + 1)

def has_vertex(self, v):
r"""
Tests if the vertex belongs to the graph
Expand Down Expand Up @@ -984,28 +987,38 @@ cdef class StaticSparseBackend(CGraphBackend):
Ticket :trac:`25550` is fixed::
sage: g = DiGraph({0: [1]}, immutable=True)
sage: print(g.neighbors(1))
sage: g.neighbors(1)
[0]
sage: g = DiGraph({0: [0, 1, 1]}, loops=True, multiedges=True, immutable=True)
sage: g.neighbors(0)
[0, 1]
"""
try:
v = self._vertex_to_int[v]
except KeyError:
raise LookupError("The vertex does not belong to the graph")

cdef StaticSparseCGraph cg = self._cg
cdef int i
cdef set seen = set()
cdef int i, u
bitset_clear(self._seen)

if cg._directed:
for i in range(out_degree(cg.g, v)):
yield self._vertex_to_labels[cg.g.neighbors[v][i]]
seen.add(cg.g.neighbors[v][i])
u = cg.g.neighbors[v][i]
if not bitset_in(self._seen, u):
yield self._vertex_to_labels[u]
bitset_add(self._seen, u)
for i in range(out_degree(cg.g_rev, v)):
if not cg.g_rev.neighbors[v][i] in seen:
yield self._vertex_to_labels[cg.g_rev.neighbors[v][i]]
u = cg.g_rev.neighbors[v][i]
if not bitset_in(self._seen, u):
yield self._vertex_to_labels[u]
bitset_add(self._seen, u)
else:
for i in range(out_degree(cg.g, v)):
yield self._vertex_to_labels[cg.g.neighbors[v][i]]
u = cg.g.neighbors[v][i]
if not bitset_in(self._seen, u):
yield self._vertex_to_labels[cg.g.neighbors[v][i]]
bitset_add(self._seen, u)

def iterator_out_nbrs(self, v):
r"""
Expand All @@ -1027,10 +1040,14 @@ cdef class StaticSparseBackend(CGraphBackend):
raise LookupError("The vertex does not belong to the graph")

cdef StaticSparseCGraph cg = self._cg
cdef int i
cdef int i, u
bitset_clear(self._seen)

for i in range(out_degree(cg.g, v)):
yield self._vertex_to_labels[cg.g.neighbors[v][i]]
u = cg.g.neighbors[v][i]
if not bitset_in(self._seen, u):
yield self._vertex_to_labels[u]
bitset_add(self._seen, u)

def iterator_in_nbrs(self, v):
r"""
Expand Down Expand Up @@ -1058,14 +1075,21 @@ cdef class StaticSparseBackend(CGraphBackend):
raise LookupError("The vertex does not belong to the graph")

cdef StaticSparseCGraph cg = self._cg
cdef int i
cdef int i, u
bitset_clear(self._seen)

if cg._directed:
for i in range(out_degree(cg.g_rev, v)):
yield self._vertex_to_labels[cg.g_rev.neighbors[v][i]]
u = cg.g_rev.neighbors[v][i]
if not bitset_in(self._seen, u):
yield self._vertex_to_labels[u]
bitset_add(self._seen, u)
else:
for i in range(out_degree(cg.g, v)):
yield self._vertex_to_labels[cg.g.neighbors[v][i]]
u = cg.g.neighbors[v][i]
if not bitset_in(self._seen, u):
yield self._vertex_to_labels[u]
bitset_add(self._seen, u)

def add_vertex(self,v):
r"""
Expand Down

0 comments on commit 508cf3e

Please sign in to comment.