Skip to content

Commit 5a561ab

Browse files
author
Release Manager
committed
gh-37181: Fix subtour elimination constraints in `longest_cycle` An issue has been raised (see #37028 (comment)) on the formulation used to find the longest (induced) cycle. This was due to the subtour elimination constraints that were not correct. We change these constraints to fix this issue. The new constraints force to use edges from the boundary of a subtour only when a vertex of that subtour is selected. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> <!-- Feel free to remove irrelevant items. --> - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [ ] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - #12345: short description why this is a dependency - #34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: #37181 Reported by: David Coudert Reviewer(s): Travis Scrimshaw
2 parents b5f69b0 + ebb7584 commit 5a561ab

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

src/sage/graphs/generic_graph.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7976,6 +7976,17 @@ def longest_cycle(self, induced=False, use_edge_labels=False,
79767976

79777977
TESTS:
79787978

7979+
Check that the example from :issue:`37028` is fixed::
7980+
7981+
sage: d = {0: [4, 6, 10, 11], 1: [5, 7, 10, 11], 2: [8, 9, 10, 11],
7982+
....: 3: [8, 9, 11], 4: [6, 10, 11], 5: [7, 10, 11],
7983+
....: 6: [10, 11], 7: [10], 8: [10], 9: [11]}
7984+
sage: Z = Graph(d)
7985+
sage: Z.longest_cycle()
7986+
longest cycle: Graph on 9 vertices
7987+
sage: Z.longest_cycle(induced=True)
7988+
longest induced cycle: Graph on 5 vertices
7989+
79797990
Small cases::
79807991

79817992
sage: Graph().longest_cycle()
@@ -8085,8 +8096,8 @@ def F(e):
80858096
constraint_generation=True)
80868097

80878098
# We need one binary variable per vertex and per edge
8088-
vertex = p.new_variable(binary=True)
8089-
edge = p.new_variable(binary=True)
8099+
vertex = p.new_variable(binary=True, name='vertex')
8100+
edge = p.new_variable(binary=True, name='edge')
80908101

80918102
# Objective function: maximize the size of the cycle
80928103
p.set_objective(p.sum(weight(e) * edge[F(e)] for e in G.edge_iterator()))
@@ -8165,12 +8176,14 @@ def F(e):
81658176

81668177
# Add subtour elimination constraints
81678178
if directed:
8168-
p.add_constraint(p.sum(edge[F(e)] for e in G.edge_boundary(c)), min=1)
81698179
c = set(c)
81708180
cbar = (v for v in G if v not in c)
8171-
p.add_constraint(p.sum(edge[F(e)] for e in G.edge_boundary(cbar, c)), min=1)
8181+
for u in c:
8182+
p.add_constraint(vertex[u] <= p.sum(edge[F(e)] for e in G.edge_boundary(c)))
8183+
p.add_constraint(vertex[u] <= p.sum(edge[F(e)] for e in G.edge_boundary(cbar, c)))
81728184
else:
8173-
p.add_constraint(p.sum(edge[F(e)] for e in G.edge_boundary(c)), min=2)
8185+
for u in c:
8186+
p.add_constraint(2*vertex[u] <= p.sum(edge[F(e)] for e in G.edge_boundary(c)))
81748187

81758188
if induced:
81768189
# We eliminate this cycle

0 commit comments

Comments
 (0)