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

Commit

Permalink
added a parameter 'closed' to neighbor_iterator to get rid of closed_…
Browse files Browse the repository at this point in the history
…neighborhood_iterator + fixed my own failing doctests + simplified is_dominating
  • Loading branch information
Jean-Florent Raymond committed Apr 4, 2019
1 parent 822cefa commit f66030c
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 74 deletions.
26 changes: 15 additions & 11 deletions src/sage/graphs/domination.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def _parent(G, dom, V_prev):
EXAMPLES:
sage: from sage.graphs.domination import _parent
sage: G = graphs.PathGraph(4)
sage: G.add_vertices([4, 5])
sage: G.add_edges([(4, 1), (5, 2)])
Expand All @@ -67,12 +68,12 @@ def _parent(G, dom, V_prev):

while D_start:
v = D_start.pop() # element of min index
priv = set(G.closed_neighbor_iterator(v))
priv = set(G.neighbor_iterator(v, closed=True))
# We remove the vertices already dominated
# by other vertices of (D_end union D_start)
priv.difference_update(*(G.closed_neighbor_iterator(u)
priv.difference_update(*(G.neighbor_iterator(u, closed=True)
for u in D_start if u != v))
priv.difference_update(*(G.closed_neighbor_iterator(u)
priv.difference_update(*(G.neighbor_iterator(u, closed=True)
for u in D_end if u != v))
# Now priv is the private neighborhood of v
# in G wrt D_start + D_end
Expand Down Expand Up @@ -105,6 +106,7 @@ def _peel(G, A):
EXAMPLES:
sage: from sage.graphs.domination import _peel
sage: G = Graph(10); _peel(G, range(5))
[(None, set()),
(4, {4}),
Expand All @@ -114,6 +116,8 @@ def _peel(G, A):
(0, {0, 1, 2, 3, 4}),
(None, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])]
sage: from sage.graphs.domination import _peel
sage: G = graphs.PathGraph(10); _peel(G, (i for i in range(10) if i%2==0))
[(None, set()),
(8, {8}),
Expand All @@ -135,7 +139,7 @@ def _peel(G, A):
ui = next(H.vertex_iterator()) # pick some vertex of H
Vi = set(H.vertex_iterator())
peeling.append((ui, Vi))
H.delete_vertices(H.closed_neighbor_iterator(ui))
H.delete_vertices(H.neighbor_iterator(ui, closed=True))
peeling.append((None, set()))
peeling.reverse()
return peeling
Expand Down Expand Up @@ -184,7 +188,7 @@ def _aux_with_rep(G, dom, u_next, V_next):

# True iff u_next is dominated by dom:
u_next_dom_by_dom = any(
v in dom for v in G.closed_neighbor_iterator(u_next))
v in dom for v in G.neighbor_iterator(u_next, closed=True))

if u_next_dom_by_dom:
# In this case, u_next is already dominated by dom,
Expand All @@ -199,7 +203,7 @@ def _aux_with_rep(G, dom, u_next, V_next):
elif not S:
# In this case, only u_next has to be dominated
cand_ext_index = 0
for w in G.closed_neighbor_iterator(u_next):
for w in G.neighbor_iterator(u_next, closed=True):
# Notice that the case w = u_next is included
yield ({w}, cand_ext_index)
cand_ext_index += 1
Expand All @@ -219,15 +223,15 @@ def _aux_with_rep(G, dom, u_next, V_next):
# as we are not in the first case of the if statement

S_minus = set.difference(
S, set(G.closed_neighbor_iterator(w)))
S, set(G.neighbor_iterator(w, closed=True)))
# S_minus: vertices of S that still need to be
# dominated, assuming w is included in the DS

for Q in minimal_dominating_sets(G, S_minus):
sQ = set(Q)
NQ = set(G.closed_vertex_boundary(sQ))
Nw_minus = set.intersection(
set(G.closed_neighbor_iterator(w)), S_plus)
set(G.neighbor_iterator(w, closed=True)), S_plus)
if not NQ >= Nw_minus:
# If Nw_minus is not included in i.e. if w has
# a private neighbor in V_next wrt Q + {w}:
Expand Down Expand Up @@ -272,12 +276,12 @@ def minimal_dominating_sets(G, vertices_to_dominate=None):
sage: G = Graph()
sage: for ds in minimal_dominating_sets(G):
.. print(ds)
sage: set([])
....: print(ds)
set()
sage: G = graphs.ButterflyGraph()
sage: sorted(list(minimal_dominating_sets(G)))
sage: [{0, 1}, {1, 3}, {0, 2}, {2, 3}, {4}]
[{0, 1}, {1, 3}, {0, 2}, {2, 3}, {4}]
sage: sorted(list(minimal_dominating_sets(G, [0,3])))
[{0}, {3}, {4}]
sage: sorted(list(minimal_dominating_sets(G, [4])))
Expand Down
106 changes: 43 additions & 63 deletions src/sage/graphs/generic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -9830,7 +9830,7 @@ def closed_vertex_boundary(self, vertex_subset):
EXAMPLES::

sage: G = graphs.PathGraph(5)
sage: G.neighbors_of_a_set({2,3})
sage: G.closed_vertex_boundary({2,3})
{1, 2, 3, 4}
"""

Expand All @@ -9847,7 +9847,7 @@ def closed_vertex_boundary(self, vertex_subset):
return list(output)

def private_neighbors(self, vertex, vertex_subset):
r'''
r"""
Return the private neighbors of a vertex with repect to an iterable.

INPUT:
Expand All @@ -9871,19 +9871,18 @@ def private_neighbors(self, vertex, vertex_subset):

sage: list(g.private_neighbors(1, [3, 4, 0]))
[]

'''
"""

closed_neighborhood_vs = set(self.closed_vertex_boundary(
u for u in vertex_subset if u!=vertex))


return (neighbor for neighbor in self.closed_neighbor_iterator(vertex)
return (neighbor for neighbor in self.neighbor_iterator(vertex, closed=True)
if neighbor not in closed_neighborhood_vs)


def is_dominating(self, p_dominating, p_dominated=None):
r'''
r"""
Return whether the first set dominates the second one.

We say that as set `D` of vertices of a graph `G`dominated a set `S`
Expand All @@ -9894,7 +9893,7 @@ def is_dominating(self, p_dominating, p_dominated=None):

- ``p_dominating`` -- an iterable of vertices of ``self``
- ``vertex_subset`` -- (default: `None`) an iterable of vertices of
``self``
``self``

OUTPUT:

Expand All @@ -9915,40 +9914,30 @@ def is_dominating(self, p_dominating, p_dominated=None):

sage: g.is_dominating([0,1], {2, 42})
LookupError: vertex (42) is not a vertex of the graph
'''
if p_dominated is None:
sp_dominated = set(self.vertex_iterator())
else:
sp_dominated = set(p_dominated)

# using a set to check membership repeatedly faster
all_vertices = set(self.vertex_iterator())

# check that sp_dominated is a subset of self.vertices
try:
bad_boy = next(v for v in sp_dominated if v not in all_vertices)
raise LookupError(
'vertex ({0}) is not a vertex of the graph'.format(bad_boy))
except StopIteration:
pass

actually_dominated = set(self.closed_vertex_boundary(p_dominating))
return sp_dominated <= actually_dominated
"""
closed_neighb = set()
# Construct the closed neighborhood of p_dominating
for v in p_dominating:
closed_neighb.update(self.neighbor_iterator(v, closed=True))

if p_dominated is None:
p_dominated = set(self)

return closed_neighb >= set(p_dominated)


def is_redundant(self, dom, focus=None):
r'''
r"""
Return whether a vertex iterable has redundant vertices.

Let `G` be a graph and `D` be a subset of its vertices. A vertex `v`
of `D` is said to be redundant in `S` if every closed neighbors of
`v` that belongs to `S` is dominated by `D \ {v}`.
Let ``G`` be a graph and ``D`` be a subset of its vertices. A vertex
``v`` of ``D`` is said to be redundant in ``S`` if every closed
neighbors of ``v`` that belongs to ``S`` is dominated by ``D \ {v}``.

INPUT:

- ``dom`` -- an iterable of vertices of ``self``
- ``focus`` -- (default: `None`) an iterable of vertices of
``self``
- ``focus`` -- (default: ``None``) an iterable of vertices of ``self``

OUTPUT:

Expand All @@ -9963,7 +9952,7 @@ def is_redundant(self, dom, focus=None):
True
sage: G.is_redundant(['000', '101'])
False
'''
"""

if focus is None:
focus = self.vertices()
Expand All @@ -9984,7 +9973,7 @@ def is_redundant(self, dom, focus=None):

for x in dom:
has_private[x] = False # Initialization
for v in self.closed_neighbor_iterator(x):
for v in self.neighbor_iterator(x, closed=True):
if v in focus:
# x dominates all its closed neighbors:
dominator[v].append(x)
Expand Down Expand Up @@ -10158,10 +10147,13 @@ def vertex_iterator(self, vertices=None):

__iter__ = vertex_iterator

def neighbor_iterator(self, vertex):
def neighbor_iterator(self, vertex, closed=False):
"""
Return an iterator over neighbors of ``vertex``.

When ``closed`` is set to ``True``, the returned iterator also
contains ``vertex``.

EXAMPLES::

sage: G = graphs.PetersenGraph()
Expand All @@ -10182,22 +10174,10 @@ def neighbor_iterator(self, vertex):
sage: D = DiGraph({0: [1, 2], 3: [0]})
sage: list(D.neighbor_iterator(0))
[1, 2, 3]
"""
return self._backend.iterator_nbrs(vertex)

def closed_neighbor_iterator(self, vertex):
r'''
Return an iterator over the closed neighbors of ``vertex``.

INPUT:

- ``vertex`` -- the vertex of ``self``, the closed neighborhood of
which we want to iterate over.

EXAMPLES::

::
sage: g = graphs.CubeGraph(3)
sage: for i in g.closed_neighbor_iterator('010'):
sage: for i in g.neighbor_iterator('010', closed=True):
....: print(i)
010
011
Expand All @@ -10209,28 +10189,28 @@ def closed_neighbor_iterator(self, vertex):
sage: g = Graph(3, loops = True)
sage: g.add_edge(0,1)
sage: g.add_edge(0,0)
sage: list(g.closed_neighbor_iterator(0))
sage: list(g.neighbor_iterator(0, closed=True))
[0, 1]
sage: list(g.closed_neighbor_iterator(2))
sage: list(g.neighbor_iterator(2, closed=True))
[2]

TESTS::

sage: G = graphs.CubeGraph(3)
sage: list(G.closed_neighbor_iterator('013'))
sage: list(G.neighbor_iterator('013', closed=True))
LookupError: vertex (013) is not a vertex of the graph
'''

if not self.has_vertex(vertex):
raise LookupError(
'vertex ({0}) is not a vertex of the graph'.format(vertex))

if not self.has_edge(vertex, vertex):
yield vertex
"""

for neighbor in self.neighbor_iterator(vertex):
yield neighbor
return
if not closed:
return self._backend.iterator_nbrs(vertex)
else:
if not self.has_vertex(vertex):
raise LookupError(
'vertex ({0}) is not a vertex of the graph'.format(vertex))
if not self.has_edge(vertex, vertex):
yield vertex
yield from self._backend.iterator_nbrs(vertex)


def vertices(self, sort=True, key=None):
r"""
Expand Down

0 comments on commit f66030c

Please sign in to comment.