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

Overwrote methods concerning loops for a matching covered graph #38955

Open
wants to merge 112 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
16eb322
Introduced graphs/matching_covered_graph.py
janmenjayap Sep 29, 2024
81bed22
updated the doc
janmenjayap Sep 30, 2024
5189a41
rectified _upgrade_from_graph()
janmenjayap Sep 30, 2024
71ac39a
overwrote allow_loops()
janmenjayap Sep 30, 2024
82d918c
updated a method description
janmenjayap Sep 30, 2024
b164e17
added a test case for disconnected graphs
janmenjayap Sep 30, 2024
2efb686
added a test case for unknown data type
janmenjayap Sep 30, 2024
c6db6fc
restored matching.py
janmenjayap Sep 30, 2024
d65de1e
removed * as functional argument in matching.py
janmenjayap Oct 1, 2024
4c0583e
corrected the problem due to *
janmenjayap Oct 2, 2024
cc18b20
removed spaces around keyword / parameter equals
janmenjayap Oct 2, 2024
3c51d8a
corrected the test with igraph
janmenjayap Oct 2, 2024
a5b3efd
Merge branch 'develop' into mcg
janmenjayap Oct 2, 2024
dfe569a
moved matching_covered_graph to Graph objects and methods
janmenjayap Oct 2, 2024
5ecd500
updated the doc
janmenjayap Oct 2, 2024
9220a9d
updated the documentation
janmenjayap Oct 2, 2024
9b8ab78
updated the code
janmenjayap Oct 2, 2024
e283d1e
updated the code
janmenjayap Oct 2, 2024
55a416a
introduced self.matching
janmenjayap Oct 13, 2024
34bef53
updated the documentation
janmenjayap Oct 13, 2024
adc35e0
introduced get_matching()
janmenjayap Oct 13, 2024
f2b2b3d
made self.matching private
janmenjayap Oct 13, 2024
cce4063
rearranged the methods in lexicographical order
janmenjayap Oct 13, 2024
d83be12
added add_vertex()
janmenjayap Oct 13, 2024
1367acf
added add_vertices()
janmenjayap Oct 13, 2024
f6bbd32
added delete_vertex()
janmenjayap Oct 13, 2024
26deafe
added delete_vertices()
janmenjayap Oct 13, 2024
a90aa33
added update_matching()
janmenjayap Oct 13, 2024
9c2252a
added a doctest
janmenjayap Oct 13, 2024
eec57ab
updated exception statement
janmenjayap Oct 13, 2024
3106204
updated the doctests
janmenjayap Oct 14, 2024
1e18bb2
Merge branch 'develop' into mcg
janmenjayap Oct 14, 2024
46f067a
corrected the use of bare 'except'
janmenjayap Oct 14, 2024
fb94e50
rearranged the methods in lexicographical order
janmenjayap Oct 14, 2024
264bb9a
updated the documentation
janmenjayap Oct 14, 2024
99b8faa
updated the documentation
janmenjayap Oct 15, 2024
7133a28
removed _upgrade_from_graph()
janmenjayap Oct 15, 2024
b19e4db
updated the code
janmenjayap Oct 15, 2024
57670f1
added add_edge()
janmenjayap Oct 15, 2024
f0f7bae
corrected the use of bare 'except'
janmenjayap Oct 15, 2024
c0d90d5
updated the doctests
janmenjayap Oct 15, 2024
7efae8d
removed redundant backslashes
janmenjayap Oct 15, 2024
928bfa5
removed an unnecessary blank line
janmenjayap Oct 15, 2024
a92e227
updated the documentation
janmenjayap Oct 18, 2024
addfe08
made doctests more concise
janmenjayap Oct 18, 2024
c0b1493
updated the doc
janmenjayap Oct 18, 2024
ba1164b
updated the doc and the code
janmenjayap Oct 25, 2024
67b315a
updated the doctests
janmenjayap Oct 25, 2024
c595f43
updated the code and the doc
janmenjayap Oct 27, 2024
ef66f81
added add_edges()
janmenjayap Oct 27, 2024
02154a7
updated delete_vertices()
janmenjayap Oct 27, 2024
0cd3db1
updated add_edges()
janmenjayap Oct 27, 2024
1eaa5ad
updated delete_vertices()
janmenjayap Oct 27, 2024
338f7e9
updated update_matching()
janmenjayap Oct 27, 2024
bddd230
added whitespaces around modulo operator
janmenjayap Oct 27, 2024
c4870d5
Merge branch 'develop' into mcg
janmenjayap Oct 27, 2024
11fc7c8
added TODO methods
janmenjayap Oct 29, 2024
3de9015
changed the description of get_matching()
janmenjayap Oct 29, 2024
adce272
added _subgraph_by_adding()
janmenjayap Oct 29, 2024
a4e8851
corrected a class name
janmenjayap Oct 29, 2024
37c1834
added allows_loops()
janmenjayap Oct 30, 2024
509cfd0
added REFERENCES
janmenjayap Oct 30, 2024
2b49ba0
updated the TODO list
janmenjayap Oct 30, 2024
021ef7c
added doc_index
janmenjayap Oct 30, 2024
58739ef
added _upgrade_from_graph()
janmenjayap Oct 30, 2024
f6c188b
added the file to sage/graphs/meson.build
janmenjayap Oct 30, 2024
aa5d41d
added the book name
janmenjayap Oct 31, 2024
350bba3
added has_perfect_matching()
janmenjayap Nov 4, 2024
d594178
Merge branch 'develop' into mcg
janmenjayap Nov 4, 2024
722d0ce
corrected the indentation
janmenjayap Nov 4, 2024
61c9140
added index of methods
janmenjayap Nov 4, 2024
05dd74a
added one more blankline after the class definition
janmenjayap Nov 4, 2024
2233158
updated the documentation
janmenjayap Nov 4, 2024
27e6536
updated the description of has_perfect_matching()
janmenjayap Nov 5, 2024
1484670
updated the todo list
janmenjayap Nov 5, 2024
b67546e
updated delete_vertex()
janmenjayap Nov 5, 2024
b70350d
added doctests for delete_vertex()
janmenjayap Nov 5, 2024
6a68edf
updated the doctests for _subgraph_by_adding()
janmenjayap Nov 5, 2024
abb1b56
added doctests for _subgraph_by_adding()
janmenjayap Nov 5, 2024
41e46b4
updated the doctests for add_edges()
janmenjayap Nov 5, 2024
17b6e3b
updated the todo list
janmenjayap Nov 5, 2024
a4cc208
Updated the statement for doc index
janmenjayap Nov 6, 2024
91d517a
Updated the doc index for get_matching()
janmenjayap Nov 6, 2024
ba562c9
Updated the import statement for Graph
janmenjayap Nov 6, 2024
62a7a88
updated the description of get_matching()
janmenjayap Nov 6, 2024
0cd4391
updated the todo list
janmenjayap Nov 6, 2024
8f011a7
added doctests for **kwds
janmenjayap Nov 8, 2024
7a2793b
updated __init__()
janmenjayap Nov 8, 2024
83a1be9
added doctests for add_edge()
janmenjayap Nov 8, 2024
7c5c047
updated M_alternating_even_mark()
janmenjayap Nov 8, 2024
bcfe65e
updated is_matching_covered()
janmenjayap Nov 8, 2024
9f32514
updated is_bicritical()
janmenjayap Nov 8, 2024
c63a2bb
removed an unnecessary blank line
janmenjayap Nov 8, 2024
b116347
Overwrote methods concerning loops
janmenjayap Nov 10, 2024
f6ad99c
Overwrote has_loops()
janmenjayap Nov 10, 2024
7de0b7b
Overwrote loop_edges()
janmenjayap Nov 10, 2024
a5a332f
Overwrote loop_vertices()
janmenjayap Nov 10, 2024
8979db1
Overwrote loops()
janmenjayap Nov 10, 2024
7acc34d
Overwrote number_of_loops()
janmenjayap Nov 10, 2024
d247848
Overwrote remove_loops()
janmenjayap Nov 10, 2024
369eeba
updated allow_loops()
janmenjayap Nov 10, 2024
cca3d45
updated allows_loops()
janmenjayap Nov 10, 2024
0a88de6
updated remove_loops()
janmenjayap Nov 10, 2024
d78f604
corrected a typo
janmenjayap Nov 10, 2024
cc07061
corrected the indentation
janmenjayap Nov 10, 2024
e98aae7
updated the indentation
janmenjayap Nov 10, 2024
3272227
updated the doctest of loop_edges()
janmenjayap Nov 10, 2024
023b05a
updated the doctest of loop_vertices()
janmenjayap Nov 10, 2024
a2b4a9d
updated the doctest of number_of_loops()
janmenjayap Nov 10, 2024
ca0f5cc
updated the doctest of remove_loops()
janmenjayap Nov 10, 2024
6fe61f8
updated the doctest of has_loops()
janmenjayap Nov 10, 2024
d8beed1
removed whitespaces from a blankline
janmenjayap Nov 10, 2024
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
1 change: 1 addition & 0 deletions src/doc/en/reference/graphs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Graph objects and methods
sage/graphs/graph
sage/graphs/digraph
sage/graphs/bipartite_graph
sage/graphs/matching_covered_graph
sage/graphs/views

Constructors and databases
Expand Down
1 change: 1 addition & 0 deletions src/sage/graphs/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from sage.graphs.graph import Graph
from sage.graphs.digraph import DiGraph
from sage.graphs.bipartite_graph import BipartiteGraph
from sage.graphs.matching_covered_graph import MatchingCoveredGraph
import sage.graphs.weakly_chordal
import sage.graphs.lovasz_theta
import sage.graphs.partial_cube
Expand Down
2 changes: 1 addition & 1 deletion src/sage/graphs/generic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -14285,7 +14285,7 @@ def _subgraph_by_adding(self, vertices=None, edges=None, edge_property=None, imm
or (v, u) in edges_to_keep_unlabeled)):
edges_to_keep.append((u, v, l))
else:
s_vertices = set(vertices)
s_vertices = set(G.vertices()) if vertices is None else set(vertices)
edges_to_keep = [e for e in self.edges(vertices=vertices, sort=False, sort_vertices=False)
if e[0] in s_vertices and e[1] in s_vertices]

Expand Down
74 changes: 36 additions & 38 deletions src/sage/graphs/matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
def has_perfect_matching(G, algorithm='Edmonds', solver=None, verbose=0,
*, integrality_tolerance=1e-3):
r"""
Return whether the graph has a perfect matching
Return whether the graph has a perfect matching.

INPUT:

Expand Down Expand Up @@ -162,7 +162,7 @@ def has_perfect_matching(G, algorithm='Edmonds', solver=None, verbose=0,
def is_bicritical(G, matching=None, algorithm='Edmonds', coNP_certificate=False,
solver=None, verbose=0, *, integrality_tolerance=0.001):
r"""
Check if the graph is bicritical
Check if the graph is bicritical.

A nontrivial graph `G` is *bicritical* if `G - u - v` has a perfect
matching for any two distinct vertices `u` and `v` of `G`. Bicritical
Expand Down Expand Up @@ -270,12 +270,9 @@ def is_bicritical(G, matching=None, algorithm='Edmonds', coNP_certificate=False,

A graph (of order more than two) with more that one component is not bicritical::

sage: cycle1 = graphs.CycleGraph(4)
sage: cycle2 = graphs.CycleGraph(6)
sage: cycle2.relabel(lambda v: v + 4)
sage: G = Graph()
sage: G.add_edges(cycle1.edges() + cycle2.edges())
sage: len(G.connected_components(sort=False))
sage: G = graphs.CycleGraph(4)
sage: G += graphs.CycleGraph(6)
sage: G.connected_components_number()
2
sage: G.is_bicritical()
False
Expand Down Expand Up @@ -449,40 +446,38 @@ def is_bicritical(G, matching=None, algorithm='Edmonds', coNP_certificate=False,
return (False, set(list(A)[:2]))
return (False, set(list(B)[:2]))

# A graph (without a self-loop) is bicritical if and only if the underlying
# simple graph is bicritical
G_simple = G.to_simple()

from sage.graphs.graph import Graph
if matching:
# The input matching must be a valid perfect matching of the graph
M = Graph(matching)
if any(d != 1 for d in M.degree()):
raise ValueError("the input is not a matching")
if any(not G_simple.has_edge(edge) for edge in M.edge_iterator()):

if any(not G.has_edge(edge) for edge in M.edge_iterator()):
raise ValueError("the input is not a matching of the graph")
if (G_simple.order() != M.order()) or (G_simple.order() != 2*M.size()):

if (G.order() != M.order()) or (G.order() != 2*M.size()):
raise ValueError("the input is not a perfect matching of the graph")
else:
# A maximum matching of the graph is computed
M = Graph(G_simple.matching(algorithm=algorithm, solver=solver, verbose=verbose,
M = Graph(G.matching(algorithm=algorithm, solver=solver, verbose=verbose,
integrality_tolerance=integrality_tolerance))

# It must be a perfect matching
if G_simple.order() != M.order():
if G.order() != M.order():
u, v = next(M.edge_iterator(labels=False))
return (False, set([u, v])) if coNP_certificate else False

# G is bicritical if and only if for each vertex u with its M-matched neighbor being v,
# every vertex of the graph distinct from v must be reachable from u through an even length
# M-alternating uv-path starting with an edge not in M and ending with an edge in M

for u in G_simple:
for u in G:
v = next(M.neighbor_iterator(u))

even = M_alternating_even_mark(G_simple, u, M)
even = M_alternating_even_mark(G, u, M)

for w in G_simple:
for w in G:
if w != v and w not in even:
return (False, set([v, w])) if coNP_certificate else False

Expand Down Expand Up @@ -980,27 +975,26 @@ def is_matching_covered(G, matching=None, algorithm='Edmonds', coNP_certificate=
if G.order() == 2:
return (True, None) if coNP_certificate else True

# A graph (without a self-loop) is matching covered if and only if the
# underlying simple graph is matching covered
G_simple = G.to_simple()

from sage.graphs.graph import Graph
if matching:
# The input matching must be a valid perfect matching of the graph
M = Graph(matching)

if any(d != 1 for d in M.degree()):
raise ValueError("the input is not a matching")
if any(not G_simple.has_edge(edge) for edge in M.edge_iterator()):

if any(not G.has_edge(edge) for edge in M.edge_iterator()):
raise ValueError("the input is not a matching of the graph")
if (G_simple.order() != M.order()) or (G_simple.order() != 2*M.size()):

if (G.order() != M.order()) or (G.order() != 2*M.size()):
raise ValueError("the input is not a perfect matching of the graph")
else:
# A maximum matching of the graph is computed
M = Graph(G_simple.matching(algorithm=algorithm, solver=solver, verbose=verbose,
M = Graph(G.matching(algorithm=algorithm, solver=solver, verbose=verbose,
integrality_tolerance=integrality_tolerance))

# It must be a perfect matching
if G_simple.order() != M.order():
if G.order() != M.order():
return (False, next(M.edge_iterator())) if coNP_certificate else False

# Biparite graph:
Expand All @@ -1011,17 +1005,17 @@ def is_matching_covered(G, matching=None, algorithm='Edmonds', coNP_certificate=
# if it is in M or otherwise direct it from B to A. The graph G is
# matching covered if and only if D is strongly connected.

if G_simple.is_bipartite():
A, _ = G_simple.bipartite_sets()
if G.is_bipartite():
A, _ = G.bipartite_sets()
color = dict()

for u in G_simple:
for u in G:
color[u] = 0 if u in A else 1

from sage.graphs.digraph import DiGraph
H = DiGraph()

for u, v in G_simple.edge_iterator(labels=False):
for u, v in G.edge_iterator(labels=False):
if color[u]:
u, v = v, u

Expand Down Expand Up @@ -1075,12 +1069,12 @@ def dfs(J, v, visited, orientation):
# an M-alternating odd length uv-path starting and ending with edges not
# in M.

for u in G_simple:
for u in G:
v = next(M.neighbor_iterator(u))

even = M_alternating_even_mark(G_simple, u, M)
even = M_alternating_even_mark(G, u, M)

for w in G_simple.neighbor_iterator(v):
for w in G.neighbor_iterator(v):
if w != u and w not in even:
return (False, (v, w)) if coNP_certificate else False

Expand All @@ -1092,7 +1086,7 @@ def matching(G, value_only=False, algorithm='Edmonds',
*, integrality_tolerance=1e-3):
r"""
Return a maximum weighted matching of the graph represented by the list
of its edges
of its edges.

For more information, see the :wikipedia:`Matching_(graph_theory)`.

Expand Down Expand Up @@ -1291,7 +1285,7 @@ def weight(x):

def perfect_matchings(G, labels=False):
r"""
Return an iterator over all perfect matchings of the graph
Return an iterator over all perfect matchings of the graph.

ALGORITHM:

Expand Down Expand Up @@ -1404,7 +1398,7 @@ def rec(G):
def M_alternating_even_mark(G, vertex, matching):
r"""
Return the vertices reachable from ``vertex`` via an even alternating path
starting with a non-matching edge
starting with a non-matching edge.

This method implements the algorithm proposed in [LR2004]_. Note that
the complexity of the algorithm is linear in number of edges.
Expand Down Expand Up @@ -1570,7 +1564,8 @@ def M_alternating_even_mark(G, vertex, matching):
M = Graph(matching)
if any(d != 1 for d in M.degree()):
raise ValueError("the input is not a matching")
if any(not G_simple.has_edge(edge) for edge in M.edge_iterator()):

if any(not G.has_edge(edge) for edge in M.edge_iterator()):
raise ValueError("the input is not a matching of the graph")

# Build an M-alternating tree T rooted at vertex
Expand Down Expand Up @@ -1605,8 +1600,10 @@ def M_alternating_even_mark(G, vertex, matching):
while ancestor_x[-1] != ancestor_y[-1]:
if rank[ancestor_x[-1]] > rank[ancestor_y[-1]]:
ancestor_x.append(predecessor[ancestor_x[-1]])

elif rank[ancestor_x[-1]] < rank[ancestor_y[-1]]:
ancestor_y.append(predecessor[ancestor_y[-1]])

else:
ancestor_x.append(predecessor[ancestor_x[-1]])
ancestor_y.append(predecessor[ancestor_y[-1]])
Expand All @@ -1616,6 +1613,7 @@ def M_alternating_even_mark(G, vertex, matching):
# Set t as pred of all vertices of the chains and add
# vertices marked odd to the queue
next_rank_to_lcs_rank = rank[lcs] + 1

for a in itertools.chain(ancestor_x, ancestor_y):
predecessor[a] = lcs
rank[a] = next_rank_to_lcs_rank
Expand Down
Loading
Loading