Skip to content

Commit 53b0b87

Browse files
committed
PR #35969: try to clean the branch
1 parent 543f8d6 commit 53b0b87

File tree

2 files changed

+86
-21
lines changed

2 files changed

+86
-21
lines changed

src/sage/combinat/posets/hasse_diagram.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ def dual(self):
574574
sage: H.is_isomorphic( H.dual() ) # optional - sage.combinat
575575
False
576576
"""
577-
H = self.reverse()
577+
H = self.reverse(immutable=False)
578578
H.relabel(perm=list(range(H.num_verts() - 1, -1, -1)), inplace=True)
579579
return HasseDiagram(H)
580580

src/sage/graphs/digraph.py

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -923,8 +923,8 @@ def is_directed(self):
923923
# Properties
924924

925925
def is_directed_acyclic(self, certificate=False):
926-
"""
927-
Return whether the digraph is acyclic or not.
926+
r"""
927+
Check whether the digraph is acyclic or not.
928928
929929
A directed graph is acyclic if for any vertex `v`, there is no directed
930930
path that starts and ends at `v`. Every directed acyclic graph (DAG)
@@ -943,8 +943,8 @@ def is_directed_acyclic(self, certificate=False):
943943
* When ``certificate=True``:
944944
945945
* If the graph is acyclic, returns a pair ``(True, ordering)`` where
946-
``ordering`` is a list of the vertices such that ``u`` appears
947-
before ``v`` in ``ordering`` if ``u, v`` is an edge.
946+
``ordering`` is a list of the vertices such that `u` appears
947+
before `v` in ``ordering`` if `uv` is an edge.
948948
949949
* Else, returns a pair ``(False, cycle)`` where ``cycle`` is a list of
950950
vertices representing a circuit in the graph.
@@ -1272,8 +1272,7 @@ def in_degree(self, vertices=None, labels=False):
12721272
return self._backend.in_degree(vertices)
12731273
elif labels:
12741274
return {v: d for v, d in self.in_degree_iterator(vertices, labels=labels)}
1275-
else:
1276-
return list(self.in_degree_iterator(vertices, labels=labels))
1275+
return list(self.in_degree_iterator(vertices, labels=labels))
12771276

12781277
def in_degree_iterator(self, vertices=None, labels=False):
12791278
"""
@@ -1343,8 +1342,7 @@ def out_degree(self, vertices=None, labels=False):
13431342
return self._backend.out_degree(vertices)
13441343
elif labels:
13451344
return {v: d for v, d in self.out_degree_iterator(vertices, labels=labels)}
1346-
else:
1347-
return list(self.out_degree_iterator(vertices, labels=labels))
1345+
return list(self.out_degree_iterator(vertices, labels=labels))
13481346

13491347
def out_degree_iterator(self, vertices=None, labels=False):
13501348
"""
@@ -1631,14 +1629,16 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False,
16311629
if self.has_loops():
16321630
# We solve the problem on a copy without loops of the digraph
16331631
D = DiGraph(self.edges(sort=False), multiedges=self.allows_multiple_edges(), loops=True)
1634-
D.allow_loops(False)
1632+
loops = D.loops(labels=None)
1633+
D.delete_edges(loops)
1634+
D.allow_loops(False, check=False)
16351635
FAS = D.feedback_edge_set(constraint_generation=constraint_generation,
16361636
value_only=value_only, solver=solver, verbose=verbose,
16371637
integrality_tolerance=integrality_tolerance)
16381638
if value_only:
1639-
return FAS + self.number_of_loops()
1639+
return FAS + len(loops)
16401640
else:
1641-
return FAS + self.loops(labels=None)
1641+
return FAS + loops
16421642

16431643
if not self.is_strongly_connected():
16441644
# If the digraph is not strongly connected, we solve the problem on
@@ -1647,6 +1647,8 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False,
16471647
FAS = 0 if value_only else []
16481648

16491649
for h in self.strongly_connected_components_subgraphs():
1650+
if not h.size():
1651+
continue
16501652
if value_only:
16511653
FAS += h.feedback_edge_set(constraint_generation=constraint_generation,
16521654
value_only=True, solver=solver, verbose=verbose,
@@ -1691,9 +1693,8 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False,
16911693
if isok:
16921694
if value_only:
16931695
return sum(1 for e in self.edge_iterator(labels=False) if val[e])
1694-
else:
1695-
# listing the edges contained in the MFAS
1696-
return [e for e in self.edge_iterator(labels=False) if val[e]]
1696+
# listing the edges contained in the MFAS
1697+
return [e for e in self.edge_iterator(labels=False) if val[e]]
16971698

16981699
# There is a circuit left. Let's add the corresponding
16991700
# constraint !
@@ -1736,28 +1737,92 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False,
17361737

17371738
if value_only:
17381739
return sum(1 for e in self.edge_iterator(labels=False) if b_sol[e])
1739-
else:
1740-
return [e for e in self.edge_iterator(labels=False) if b_sol[e]]
1740+
return [e for e in self.edge_iterator(labels=False) if b_sol[e]]
17411741

17421742
# Construction
17431743

1744-
def reverse(self):
1744+
def reverse(self, immutable=None):
17451745
"""
17461746
Return a copy of digraph with edges reversed in direction.
17471747
1748+
INPUT:
1749+
1750+
- ``immutable`` -- boolean (default: ``None``); whether to return an
1751+
immutable digraph or not. By default (``None``), the returned digraph
1752+
has the same setting than ``self``. That is, if ``self`` is immutable,
1753+
the returned digraph also is.
1754+
17481755
EXAMPLES::
17491756
1750-
sage: D = DiGraph({0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1]})
1751-
sage: D.reverse()
1757+
sage: adj = {0: [1,2,3], 1: [0,2], 2: [3], 3: [4], 4: [0,5], 5: [1]}
1758+
sage: D = DiGraph(adj)
1759+
sage: R = D.reverse(); R
17521760
Reverse of (): Digraph on 6 vertices
1761+
sage: H = R.reverse()
1762+
sage: adj == H.to_dictionary()
1763+
True
1764+
1765+
TESTS::
1766+
1767+
sage: adj = {0: [1, 1], 1: [1]}
1768+
sage: D = DiGraph(adj, immutable=True, multiedges=True, loops=True)
1769+
sage: R = D.reverse()
1770+
sage: R.is_immutable() and R.allows_loops() and R.allows_multiple_edges()
1771+
True
1772+
sage: adj == R.reverse().to_dictionary(multiple_edges=True)
1773+
True
1774+
1775+
Check the behavior of parameter ``immutable``::
1776+
1777+
sage: D = DiGraph([(0, 1)], immutable=False)
1778+
sage: R = D.reverse()
1779+
sage: R.is_immutable()
1780+
False
1781+
sage: R = D.reverse(immutable=True)
1782+
sage: R.is_immutable()
1783+
True
1784+
sage: H = R.reverse()
1785+
sage: H.is_immutable()
1786+
True
1787+
sage: H = R.reverse(immutable=False)
1788+
sage: H.is_immutable()
1789+
False
17531790
"""
1754-
H = DiGraph(multiedges=self.allows_multiple_edges(), loops=self.allows_loops())
1791+
from sage.graphs.base.dense_graph import DenseGraphBackend
1792+
if isinstance(self._backend, DenseGraphBackend):
1793+
data_structure = "dense"
1794+
else:
1795+
data_structure = "sparse"
1796+
1797+
H = DiGraph(data_structure=data_structure,
1798+
multiedges=self.allows_multiple_edges(), loops=self.allows_loops(),
1799+
pos=copy(self._pos), weighted=self.weighted(),
1800+
hash_labels=self._hash_labels)
17551801
H.add_vertices(self)
17561802
H.add_edges((v, u, d) for u, v, d in self.edge_iterator())
17571803
name = self.name()
17581804
if name is None:
17591805
name = ''
17601806
H.name("Reverse of (%s)" % name)
1807+
1808+
attributes_to_copy = ('_assoc', '_embedding')
1809+
for attr in attributes_to_copy:
1810+
if hasattr(self, attr):
1811+
copy_attr = {}
1812+
old_attr = getattr(self, attr)
1813+
if isinstance(old_attr, dict):
1814+
for v, value in old_attr.items():
1815+
try:
1816+
copy_attr[v] = value.copy()
1817+
except AttributeError:
1818+
copy_attr[v] = copy(value)
1819+
setattr(H, attr, copy_attr)
1820+
else:
1821+
setattr(H, attr, copy(old_attr))
1822+
1823+
if immutable or (immutable is None and self.is_immutable()):
1824+
return H.copy(immutable=True)
1825+
17611826
return H
17621827

17631828
def reverse_edge(self, u, v=None, label=None, inplace=True, multiedges=None):

0 commit comments

Comments
 (0)