From b52ce77a2ae81aa1cb8ed76e8c3b5fe9231b7398 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 5 Oct 2025 18:11:11 -0400 Subject: [PATCH 1/6] sage.graphs.graph: make is_projective_planar() a @cached_method The is_projective_planar() function can be very slow. The first example in the documentation is the Petersen graph, on which the method is taking over six minutes to arrive at the answer (True). We mark it as a @cached_method, since that will allow us to pre- fill the cache for graphs that are known to be projective planar, saving the user a lot of time. --- src/sage/graphs/graph.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 41fdabd442f..0891e931670 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -428,6 +428,7 @@ from sage.parallel.decorate import parallel from sage.misc.lazy_import import lazy_import, LazyImport from sage.features.mcqd import Mcqd +from sage.misc.cachefunc import cached_method lazy_import('sage.graphs.mcqd', ['mcqd'], feature=Mcqd()) @@ -9501,6 +9502,7 @@ def bipartite_double(self, extended=False): G.name("%sBipartite Double of %s" % (prefix, self.name())) return G + @cached_method @doc_index("Graph properties") def is_projective_planar(self, return_map=False): r""" @@ -9528,7 +9530,7 @@ def is_projective_planar(self, return_map=False): The Petersen graph is a known projective planar graph:: sage: P = graphs.PetersenGraph() - sage: P.is_projective_planar() # long time + sage: P.is_projective_planar() True `K_{4,4}` has a projective plane crossing number of 2. One of the From c1e015771a9fa88dadd9cca3fdbd443c5e773468 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 5 Oct 2025 18:13:07 -0400 Subject: [PATCH 2/6] sage.graphs.generators.smallgraphs: start caching is_projective_planar() The Petersen graph is known to be projective planar, so we can pre-fill the cache with "True" when it is constructed. --- src/sage/graphs/generators/smallgraphs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index 5c596626125..cd177a99de5 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -4189,6 +4189,7 @@ def PetersenGraph(): from sage.graphs.generators.families import GeneralizedPetersenGraph P = GeneralizedPetersenGraph(5, 2) P.name("Petersen graph") + P.is_projective_planar.set_cache(True) return P From 7ce38c068acef09f0aae4be0a11598e4d1c05f90 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 5 Oct 2025 18:14:29 -0400 Subject: [PATCH 3/6] sage.graphs.is_projective_planar_test: new is_projective_planar() pytests To ensure that is_projective_planar() still works in the absense of the cache (now that it is a @cached_method), we add a new pytest file. For the moment it only tests the Petersen graph, since that is the only graph with the method initially cached. --- src/sage/graphs/is_projective_planar_test.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/sage/graphs/is_projective_planar_test.py diff --git a/src/sage/graphs/is_projective_planar_test.py b/src/sage/graphs/is_projective_planar_test.py new file mode 100644 index 00000000000..5f28e3465a8 --- /dev/null +++ b/src/sage/graphs/is_projective_planar_test.py @@ -0,0 +1,13 @@ +import pytest + + +def test_petersen_graph_is_projective_planar(): + r""" + Ensure that the Petersen graph is projective planar without + using the cache. + """ + from sage.graphs.generators.smallgraphs import PetersenGraph + P = PetersenGraph() + P.is_projective_planar.clear_cache() + assert not P.is_projective_planar.is_in_cache() + assert P.is_projective_planar() From 4082474097ea2ab4a93c1706036e1a651e01f24c Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 5 Oct 2025 18:16:27 -0400 Subject: [PATCH 4/6] src/sage/graphs/meson.build: add new file is_projective_planar_test.py Ultimately we may not want to install these test files, but for now the CI is complaining about it. We can decide later on. --- src/sage/graphs/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/graphs/meson.build b/src/sage/graphs/meson.build index 47d8544d1dd..e30e570d3b5 100644 --- a/src/sage/graphs/meson.build +++ b/src/sage/graphs/meson.build @@ -67,6 +67,7 @@ py.install_sources( 'independent_sets.pyx', 'isgci.py', 'isoperimetric_inequalities.pyx', + 'is_projective_planar_test.py', 'line_graph.pyx', 'lovasz_theta.py', 'matching.py', From 16cfbfd3c6133969331a7564aab7a596e5c1ca06 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 6 Oct 2025 19:03:45 -0400 Subject: [PATCH 5/6] src/sage/graphs: move is_projective_planar() tests to a subdirectory A simple `git mv` with an update of the associated meson.build files. --- src/sage/graphs/meson.build | 3 ++- src/sage/graphs/{ => tests}/is_projective_planar_test.py | 0 src/sage/graphs/tests/meson.build | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) rename src/sage/graphs/{ => tests}/is_projective_planar_test.py (100%) create mode 100644 src/sage/graphs/tests/meson.build diff --git a/src/sage/graphs/meson.build b/src/sage/graphs/meson.build index e30e570d3b5..ce3c85c8cf0 100644 --- a/src/sage/graphs/meson.build +++ b/src/sage/graphs/meson.build @@ -67,7 +67,6 @@ py.install_sources( 'independent_sets.pyx', 'isgci.py', 'isoperimetric_inequalities.pyx', - 'is_projective_planar_test.py', 'line_graph.pyx', 'lovasz_theta.py', 'matching.py', @@ -92,6 +91,7 @@ py.install_sources( subdir: 'sage/graphs', ) + extension_data = { 'asteroidal_triples' : files('asteroidal_triples.pyx'), 'centrality' : files('centrality.pyx'), @@ -179,3 +179,4 @@ py.extension_module( subdir('base') subdir('generators') subdir('graph_decompositions') +subdir('tests') diff --git a/src/sage/graphs/is_projective_planar_test.py b/src/sage/graphs/tests/is_projective_planar_test.py similarity index 100% rename from src/sage/graphs/is_projective_planar_test.py rename to src/sage/graphs/tests/is_projective_planar_test.py diff --git a/src/sage/graphs/tests/meson.build b/src/sage/graphs/tests/meson.build new file mode 100644 index 00000000000..b51e221a723 --- /dev/null +++ b/src/sage/graphs/tests/meson.build @@ -0,0 +1,5 @@ +py.install_sources( + '__init__.py', + 'is_projective_planar_test.py', + subdir: 'sage/graphs/tests', +) From 962a584b6a0c4e9c76704e04d8509d8de6277408 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 6 Oct 2025 19:12:08 -0400 Subject: [PATCH 6/6] meson.build: create __init__.py for sage.graphs.tests, too The "tests" subdirectory is installed, so make it a package for consistency. Add the generated __init__.py to .gitignore while we're at it. --- .gitignore | 1 + meson.build | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 51cf481afa1..d408cdcfe66 100644 --- a/.gitignore +++ b/.gitignore @@ -462,6 +462,7 @@ src/sage/graphs/graph_decompositions/__init__.py src/sage/graphs/generators/__init__.py src/sage/graphs/__init__.py src/sage/graphs/base/__init__.py +src/sage/graphs/tests/__init__.py src/sage/databases/__init__.py src/sage/stats/hmm/__init__.py src/sage/stats/__init__.py diff --git a/meson.build b/meson.build index e470de6ab1f..78cd1f42962 100755 --- a/meson.build +++ b/meson.build @@ -195,6 +195,7 @@ file_paths = [ 'src/sage/graphs/generators/__init__.py', 'src/sage/graphs/__init__.py', 'src/sage/graphs/base/__init__.py', + 'src/sage/graphs/tests/__init__.py', 'src/sage/databases/__init__.py', 'src/sage/stats/hmm/__init__.py', 'src/sage/stats/__init__.py',