Skip to content

Commit bc0ffc7

Browse files
author
Release Manager
committed
sagemathgh-39802: Module and Graph method for Projective planarity via forbidden minors <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> Addresses sagemath#37937 (to enable checking if a graph in projective planar) by 1. creating a new module, `src/sage/graphs/projective_planarity.py`, that holds the relevant forbidden minors and a function to search for them in another graph. 2. adding `is_projective_planar` method to `Graph`. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [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. - [x] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#39802 Reported by: Juan M. Lazaro Ruiz Reviewer(s): David Coudert, Dima Pasechnik, steveschluchter
2 parents f6e08ba + 52ddf4d commit bc0ffc7

File tree

5 files changed

+144
-2
lines changed

5 files changed

+144
-2
lines changed

src/doc/en/reference/graphs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,5 @@ Libraries of algorithms
125125
sage/graphs/cycle_enumeration
126126

127127
.. include:: ../footer.txt
128+
129+

src/doc/en/reference/references/index.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5219,6 +5219,9 @@ REFERENCES:
52195219
Swinnerton-Dyer*,
52205220
Inventiones Mathematicae **84**, (1986), 1-48.
52215221
5222+
.. [MT2001] B. Mojar and C. Thomassen. *Graphs on Surfaces*.
5223+
Johns Hopkins University Press, (2001). ISBN 9780801866890.
5224+
52225225
.. [Mu1997] Murty, M. Ram. *Congruences between modular forms*. In "Analytic
52235226
Number Theory" (ed. Y. Motohashi), London Math. Soc. Lecture Notes
52245227
247 (1997), 313-320, Cambridge Univ. Press.
@@ -6808,6 +6811,8 @@ REFERENCES:
68086811

68096812
**W**
68106813

6814+
.. [WA2025] https://mathworld.wolfram.com/ProjectivePlanarGraph.html.
6815+
68116816
.. [Wac2003] Wachs, "Topology of Matching, Chessboard and General
68126817
Bounded Degree Graph Complexes" (Algebra Universalis
68136818
Special Issue in Memory of Gian-Carlo Rota, Algebra

src/sage/graphs/generators/families.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
# Emily A. Kirkman
1010
# 2009 Michael C. Yurko <myurko@gmail.com>
1111
# 2016 Rowan Schrecker <rowan.schrecker@hertford.ox.ac.uk>
12+
# 2025 Juan M. Lazaro Ruiz, Steve Schluchter, and
13+
# Kristina Obrenovic Gilmour: is_projective_planar
14+
# in graph.py and associated method p2_forbidden_minors
15+
# in sage.graphs.generators.families module.
1216
#
1317
# This program is free software: you can redistribute it and/or modify
1418
# it under the terms of the GNU General Public License as published by
@@ -3162,6 +3166,61 @@ def YDeltaTrans(G, v):
31623166
return [Graph(x) for x in l]
31633167

31643168

3169+
def p2_forbidden_minors():
3170+
r"""
3171+
Return an array containing the 35 minimal forbidden excluded minors
3172+
of the projective plane.
3173+
3174+
We constructed the graphs given in Theorem 6.5.1 of [MT2001]_,
3175+
which is a result of Archdeacon and encoded them in graph6 format.
3176+
The order of the graphs is the same as they appear in [WA2025]_.
3177+
3178+
TESTS::
3179+
3180+
sage: len(graphs.families.p2_forbidden_minors())
3181+
35
3182+
"""
3183+
3184+
p2_forbidden_minors_graph6 = [
3185+
'KFz_????wF?[',
3186+
'J~{???F@oM?',
3187+
'I~{?GKF@w',
3188+
'JFz_?AB_sE?',
3189+
'I~{?CME`_',
3190+
'H~}CKMF',
3191+
'G^~EMK',
3192+
'H^|ACME',
3193+
'Himp`cr',
3194+
'Iimp_CpKO',
3195+
'IFz@GCdHO',
3196+
'IBz__aB_o',
3197+
'FQ~~w',
3198+
'GlvJ`k',
3199+
'HilKH`J',
3200+
'GjlKJs',
3201+
'HhI]ECZ',
3202+
'HiMIKSp',
3203+
'HFwO]Kf',
3204+
'I]q?a?n@o',
3205+
'IHIWuFGo_',
3206+
'IXJWMC`Eg',
3207+
'GFzfF?',
3208+
'I]o__OF@o',
3209+
'G?^vf_',
3210+
'H?]ufBo',
3211+
'GlrHhs',
3212+
'HhIWuRB',
3213+
'IXCO]FGb?',
3214+
'Fvz~o',
3215+
'GlfH]{',
3216+
'Hl`HGvV',
3217+
'HhcIHmv',
3218+
'IhEGICRiw',
3219+
'JhEIDSD?ga_'
3220+
]
3221+
3222+
return [Graph(graph_str) for graph_str in p2_forbidden_minors_graph6]
3223+
31653224
def SierpinskiGasketGraph(n):
31663225
"""
31673226
Return the Sierpinski Gasket graph of generation `n`.

src/sage/graphs/graph.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,9 @@
426426
from sage.misc.rest_index_of_methods import doc_index, gen_thematic_rest_table_index
427427
from sage.graphs.views import EdgesView
428428
from sage.parallel.decorate import parallel
429-
430429
from sage.misc.lazy_import import lazy_import, LazyImport
431430
from sage.features.mcqd import Mcqd
431+
432432
lazy_import('sage.graphs.mcqd', ['mcqd'],
433433
feature=Mcqd())
434434

@@ -9511,6 +9511,80 @@ def bipartite_double(self, extended=False):
95119511
G.name("%sBipartite Double of %s" % (prefix, self.name()))
95129512
return G
95139513

9514+
@doc_index("Graph properties")
9515+
def is_projective_planar(self, return_map=False):
9516+
r"""
9517+
Check whether ``self`` is projective planar.
9518+
9519+
A graph is projective planar if it can be embedded in the projective
9520+
plane. The approach is to check that the graph does not contain any
9521+
of the known forbidden minors.
9522+
9523+
INPUT:
9524+
9525+
- ``return_map`` -- boolean (default: ``False``); whether to return
9526+
a map indicating one of the forbidden graph minors if in fact the
9527+
graph is not projective planar, or only True/False.
9528+
9529+
OUTPUT:
9530+
9531+
Return ``True`` if the graph is projective planar and ``False`` if not. If the
9532+
parameter ``map_flag`` is ``True`` and the graph is not projective planar, then
9533+
the method returns ``False`` and a map from :meth:`~Graph.minor`
9534+
indicating one of the forbidden graph minors.
9535+
9536+
EXAMPLES:
9537+
9538+
The Peterson graph is a known projective planar graph::
9539+
9540+
sage: P = graphs.PetersenGraph()
9541+
sage: P.is_projective_planar() # long time
9542+
True
9543+
9544+
`K_{4,4}` has a projective plane crossing number of 2. One of the
9545+
minimal forbidden minors is `K_{4,4} - e`, so we get a one-to-one
9546+
dictionary from :meth:`~Graph.minor`::
9547+
9548+
sage: K44 = graphs.CompleteBipartiteGraph(4, 4)
9549+
sage: K44.is_projective_planar(return_map=True)
9550+
(False,
9551+
{0: [0], 1: [1], 2: [2], 3: [3], 4: [4], 5: [5], 6: [6], 7: [7]})
9552+
9553+
.. SEEALSO::
9554+
9555+
- :meth:`~Graph.minor`
9556+
9557+
TESTS::
9558+
9559+
sage: len(graphs.p2_forbidden_minors())
9560+
35
9561+
"""
9562+
9563+
from sage.graphs.generators.families import p2_forbidden_minors
9564+
num_verts_G = self.num_verts()
9565+
num_edges_G = self.num_edges()
9566+
9567+
for forbidden_minor in p2_forbidden_minors():
9568+
# Can't be a minor if it has more vertices or edges than G
9569+
9570+
if (forbidden_minor.num_verts() > num_verts_G
9571+
or forbidden_minor.num_edges() > num_edges_G):
9572+
continue
9573+
9574+
try:
9575+
minor_map = self.minor(forbidden_minor)
9576+
if minor_map is not None:
9577+
if return_map:
9578+
return False, minor_map
9579+
return False
9580+
9581+
# If G has no H minor, then G.minor(H) throws a ValueError
9582+
except ValueError:
9583+
continue
9584+
9585+
return True
9586+
9587+
95149588
# Aliases to functions defined in other modules
95159589
from sage.graphs.weakly_chordal import is_long_hole_free, is_long_antihole_free, is_weakly_chordal
95169590
from sage.graphs.asteroidal_triples import is_asteroidal_triple_free

src/sage/graphs/graph_generators.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def wrap_name(x):
221221
__doc__ += """
222222
**Families of graphs**
223223
224-
A family of graph is an infinite set of graphs which can be indexed by fixed
224+
A family of graphs is a set of graphs, which can be indexed by fixed
225225
number of parameters, e.g. two integer parameters. (A method whose name starts
226226
with a small letter does not return a single graph object but a graph iterator
227227
or a list of graphs or ...)
@@ -284,6 +284,7 @@ def wrap_name(x):
284284
"PaleyGraph",
285285
"PasechnikGraph",
286286
"petersen_family",
287+
"p2_forbidden_minors",
287288
"planar_graphs",
288289
"plantri_gen",
289290
"quadrangulations",
@@ -2775,6 +2776,7 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None
27752776
NKStarGraph = staticmethod(families.NKStarGraph)
27762777
NStarGraph = staticmethod(families.NStarGraph)
27772778
OddGraph = staticmethod(families.OddGraph)
2779+
p2_forbidden_minors = staticmethod(families.p2_forbidden_minors)
27782780
PaleyGraph = staticmethod(families.PaleyGraph)
27792781
PasechnikGraph = staticmethod(families.PasechnikGraph)
27802782
petersen_family = staticmethod(families.petersen_family)

0 commit comments

Comments
 (0)