Skip to content

Commit 4081fe3

Browse files
author
Release Manager
committed
gh-40110: Fix "NotImplementedError: an immutable graph does not change name" Certain methods related to TSP (Travelling salesman problem) fail on immutable graphs: ```sage sage: Graph('EJ~w', immutable=True).longest_cycle().order() NotImplementedError: an immutable graph does not change name sage: graphs.ChvatalGraph().copy(immutable=True).is_hamiltonian() NotImplementedError: an immutable graph does not change name ``` This PR fixes this by setting the `_name` attribute directly instead of setting it via [`name()`](https://doc-develop--sagemath.netlify.app/html /en/reference/graphs/sage/graphs/generic_graph.html#sage.graphs.generic_ graph.GenericGraph.name). Another fix would be to allow changing the name of immutable graphs by removing these two lines from `name()`: ```py if self.is_immutable(): raise NotImplementedError("an immutable graph does not change name") ``` This check was introduced in #15681 and [has bitten us in the past](http s://github.com/sagemath/sage/commit/82f6e161dfedebdc31d09f507a0686f5bf15 c10a). While it seems counterintuitive for *immutable* graphs to have mutable attributes, the `_embedding` attribute can already be mutated via `set_embedding()`. ### 📝 Checklist - [x] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. URL: #40110 Reported by: Lennard Hofmann Reviewer(s): David Coudert
2 parents ab921ad + 3513dc4 commit 4081fe3

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

src/sage/graphs/generic_graph.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8410,6 +8410,9 @@ def longest_cycle(self, induced=False, use_edge_labels=False,
84108410
True
84118411
sage: D.longest_cycle(induced=False, use_edge_labels=True, immutable=False)[1].is_immutable()
84128412
False
8413+
sage: # check that https://houseofgraphs.org/graphs/752 has circumference 6:
8414+
sage: Graph('EJ~w', immutable=True).longest_cycle().order()
8415+
6
84138416
"""
84148417
self._scream_if_not_simple()
84158418
G = self
@@ -8565,7 +8568,7 @@ def F(e):
85658568
hh = h.subgraph(vertices=c)
85668569
if total_weight(hh) > best_w:
85678570
best = hh
8568-
best.name(name)
8571+
best._name = name
85698572
best_w = total_weight(best)
85708573

85718574
# Add subtour elimination constraints
@@ -9304,7 +9307,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False,
93049307
return (0, None) if use_edge_labels else None
93059308

93069309
tsp.delete_vertices(extra_vertices)
9307-
tsp.name("Hamiltonian path from {}".format(self.name()))
9310+
tsp._name = "Hamiltonian path from {}".format(self.name())
93089311
if immutable:
93099312
tsp = tsp.copy(immutable=True)
93109313

@@ -9579,7 +9582,7 @@ def weight(label):
95799582
(vv, uu, self.edge_label(vv, uu))]
95809583
answer = self.subgraph(edges=edges, immutable=self.is_immutable())
95819584
answer.set_pos(self.get_pos())
9582-
answer.name("TSP from "+self.name())
9585+
answer._name = "TSP from "+self.name()
95839586
return answer
95849587
else:
95859588
if self.allows_multiple_edges() and len(self.edge_label(uu, vv)) > 1:
@@ -9589,7 +9592,7 @@ def weight(label):
95899592
edges = self.edges(sort=True, key=weight)[:2]
95909593
answer = self.subgraph(edges=edges, immutable=self.is_immutable())
95919594
answer.set_pos(self.get_pos())
9592-
answer.name("TSP from " + self.name())
9595+
answer._name = "TSP from " + self.name()
95939596
return answer
95949597

95959598
raise EmptySetError("the given graph is not Hamiltonian")
@@ -9738,7 +9741,7 @@ def weight(label):
97389741
# We can now return the TSP !
97399742
answer = self.subgraph(edges=h.edges(sort=False), immutable=self.is_immutable())
97409743
answer.set_pos(self.get_pos())
9741-
answer.name("TSP from "+g.name())
9744+
answer._name = "TSP from "+g.name()
97429745
return answer
97439746

97449747
#################################################
@@ -9810,7 +9813,7 @@ def weight(label):
98109813
f_val = p.get_values(f, convert=bool, tolerance=integrality_tolerance)
98119814
tsp.add_vertices(g.vertex_iterator())
98129815
tsp.set_pos(g.get_pos())
9813-
tsp.name("TSP from " + g.name())
9816+
tsp._name= "TSP from " + g.name()
98149817
if g.is_directed():
98159818
tsp.add_edges((u, v, l) for u, v, l in g.edge_iterator() if f_val[u, v] == 1)
98169819
else:
@@ -24896,7 +24899,7 @@ def is_hamiltonian(self, solver=None, constraint_generation=None,
2489624899

2489724900
TESTS::
2489824901

24899-
sage: g = graphs.ChvatalGraph()
24902+
sage: g = graphs.ChvatalGraph().copy(immutable=True)
2490024903
sage: g.is_hamiltonian() # needs sage.numerical.mip
2490124904
True
2490224905

0 commit comments

Comments
 (0)