Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add parameter immutable to generators in sage/graphs/digraph_generators.py (part 2) #39266

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 71 additions & 44 deletions src/sage/graphs/digraph_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ def Circulant(self, n, integers, immutable=False):
G._circle_embedding(list(range(n)))
return G

def DeBruijn(self, k, n, vertices='strings'):
def DeBruijn(self, k, n, vertices='strings', immutable=False):
r"""
Return the De Bruijn digraph with parameters `k,n`.

Expand All @@ -1021,6 +1021,9 @@ def DeBruijn(self, k, n, vertices='strings'):
are words over an alphabet (default) or integers
(``vertices='string'``)

- ``immutable`` -- boolean (default: ``False``); whether to return
an immutable or mutable digraph.

EXAMPLES:

de Bruijn digraph of degree 2 and diameter 2::
Expand Down Expand Up @@ -1074,40 +1077,48 @@ def DeBruijn(self, k, n, vertices='strings'):
"""
from sage.rings.integer import Integer

name = f"De Bruijn digraph (k={k}, n={n})"
if vertices == 'strings':
from sage.combinat.words.words import Words

W = Words(list(range(k)) if isinstance(k, Integer) else k, n)
A = Words(list(range(k)) if isinstance(k, Integer) else k, 1)
g = DiGraph(loops=True)

if not n:
g.allow_multiple_edges(True)
v = W[0]
vs = v.string_rep()
for a in A:
g.add_edge(vs, vs, a.string_rep())
multiedges = True

def edges():
v = W[0]
vs = v.string_rep()
return ((vs, vs, a.string_rep()) for a in A)

else:
for w in W:
ww = w[1:]
ws = w.string_rep()
for a in A:
g.add_edge(ws, (ww * a).string_rep(), a.string_rep())
multiedges = False

def edges():
for w in W:
ww = w[1:]
ws = w.string_rep()
yield from ((ws, (ww * a).string_rep(), a.string_rep())
for a in A)

return DiGraph(edges(), format='list_of_edges', name=name,
loops=True, multiedges=multiedges,
immutable=immutable)

elif vertices == 'integers':
d = k if isinstance(k, Integer) else len(list(k))
if not d:
g = DiGraph(loops=True, multiedges=True)
else:
g = digraphs.GeneralizedDeBruijn(d ** n, d)
return DiGraph(loops=True, multiedges=True, name=name,
immutable=immutable)

return digraphs.GeneralizedDeBruijn(d ** n, d, immutable=immutable,
name=name)

else:
raise ValueError('unknown type for vertices')

g.name("De Bruijn digraph (k={}, n={})".format(k, n))
return g

def GeneralizedDeBruijn(self, n, d):
def GeneralizedDeBruijn(self, n, d, immutable=False, name=None):
r"""
Return the generalized de Bruijn digraph of order `n` and degree `d`.

Expand All @@ -1126,6 +1137,12 @@ def GeneralizedDeBruijn(self, n, d):

- ``d`` -- integer; degree of the digraph (must be at least one)

- ``immutable`` -- boolean (default: ``False``); whether to return
an immutable or mutable digraph.

- ``name`` -- string (default: ``None``); when set, the specified name
is used instead of the default one.

.. SEEALSO::

* :meth:`sage.graphs.generic_graph.GenericGraph.is_circulant` --
Expand Down Expand Up @@ -1159,15 +1176,15 @@ def GeneralizedDeBruijn(self, n, d):
raise ValueError("order must be greater than or equal to one")
if d < 1:
raise ValueError("degree must be greater than or equal to one")
if name is None:
name = f"Generalized de Bruijn digraph (n={n}, d={d})"

GB = DiGraph(n, loops=True, multiedges=True,
name="Generalized de Bruijn digraph (n={}, d={})".format(n, d))
for u in range(n):
for a in range(u * d, u * d + d):
GB.add_edge(u, a % n)
return GB
edges = ((u, a % n) for u in range(n) for a in range(u * d, u * d + d))
return DiGraph([range(n), edges], format='vertices_and_edges',
loops=True, multiedges=True, immutable=immutable,
name=name)

def ImaseItoh(self, n, d):
def ImaseItoh(self, n, d, immutable=False, name=None):
r"""
Return the Imase-Itoh digraph of order `n` and degree `d`.

Expand All @@ -1189,6 +1206,12 @@ def ImaseItoh(self, n, d):
- ``d`` -- integer; degree of the digraph (must be greater than or
equal to one)

- ``immutable`` -- boolean (default: ``False``); whether to return
an immutable or mutable digraph.

- ``name`` -- string (default: ``None``); when set, the specified name
is used instead of the default one.

EXAMPLES::

sage: II = digraphs.ImaseItoh(8, 2)
Expand Down Expand Up @@ -1225,15 +1248,15 @@ def ImaseItoh(self, n, d):
raise ValueError("order must be greater than or equal to two")
if d < 1:
raise ValueError("degree must be greater than or equal to one")
if name is None:
name = f"Imase and Itoh digraph (n={n}, d={d})"

II = DiGraph(n, loops=True, multiedges=True,
name="Imase and Itoh digraph (n={}, d={})".format(n, d))
for u in range(n):
for a in range(-u * d - d, -u * d):
II.add_edge(u, a % n)
return II
edges = ((u, a % n) for u in range(n) for a in range(-u * d - d, -u * d))
return DiGraph([range(n), edges], format='vertices_and_edges',
loops=True, multiedges=True, immutable=immutable,
name=name)

def Kautz(self, k, D, vertices='strings'):
def Kautz(self, k, D, vertices='strings', immutable=False):
r"""
Return the Kautz digraph of degree `d` and diameter `D`.

Expand Down Expand Up @@ -1268,6 +1291,9 @@ def Kautz(self, k, D, vertices='strings'):
are words over an alphabet (default) or integers
(``vertices='strings'``)

- ``immutable`` -- boolean (default: ``False``); whether to return
an immutable or mutable digraph.

EXAMPLES::

sage: # needs sage.combinat
Expand Down Expand Up @@ -1342,6 +1368,8 @@ def Kautz(self, k, D, vertices='strings'):

from sage.rings.integer import Integer

name = f"Kautz digraph (k={k}, D={D})"

if vertices == 'strings':
from sage.combinat.words.words import Words

Expand All @@ -1359,26 +1387,25 @@ def Kautz(self, k, D, vertices='strings'):
V = VV

# We now build the set of arcs
G = DiGraph()
for u in V:
us = u.string_rep()
for a in my_alphabet:
if not u.has_suffix(a):
G.add_edge(us, (u[1:] * a).string_rep(),
a.string_rep())
def edges():
for u in V:
us = u.string_rep()
yield from ((us, (u[1:] * a).string_rep(), a.string_rep())
for a in my_alphabet if not u.has_suffix(a))

return DiGraph(edges(), format='list_of_edges',
name=name, immutable=immutable)

elif vertices == 'integers':
d = k if isinstance(k, Integer) else (len(list(k)) - 1)
if d < 1:
raise ValueError("degree must be greater than or equal to one")
G = digraphs.ImaseItoh((d + 1) * (d ** (D - 1)), d)
return digraphs.ImaseItoh((d + 1) * (d ** (D - 1)), d,
name=name, immutable=immutable)

else:
raise ValueError('unknown type for vertices')

G.name("Kautz digraph (k={}, D={})".format(k, D))
return G

def RandomDirectedAcyclicGraph(self, n, p, weight_max=None):
r"""
Return a random (weighted) directed acyclic graph of order `n`.
Expand Down
Loading