Skip to content

Commit 980aa72

Browse files
author
Release Manager
committed
gh-36924: add interface to nauty's genktreeg Nauty has a generator of k-trees. We add an interface to this generator. This is a complement of #36587. ### 📝 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. - [x] 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: #36924 Reported by: David Coudert Reviewer(s): Matthias Köppe
2 parents 5eb7aae + 5ad350c commit 980aa72

File tree

5 files changed

+130
-17
lines changed

5 files changed

+130
-17
lines changed

build/pkgs/nauty/package-version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.8.8
1+
2.8.8.p0

build/pkgs/nauty/spkg-configure.m4

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
# We don't use the "converseg" program, but we need to ensure that we
2-
# only detect nauty >= 2.6 because we use the digraph6 format from
3-
# that version -- and converseg was added in nauty-2.6.
4-
#
5-
# We also don't use the "genposetg" program (added in nauty 2.8) yet.
6-
# We require it here to prepare Sage for the use of the major new features
7-
# added in 2.7 and 2.8 (https://pallini.di.uniroma1.it/changes24-28.txt).
1+
# We use the "genktreeg" program (added in nauty 2.8.8). This ensures that we
2+
# detect nauty >= 2.8.8 and so we can use the major new features added in nauty
3+
# since version 2.6. For instance, we use the digraph6 format from nauty >= 2.6
4+
# (https://pallini.di.uniroma1.it/changes24-28.txt).
85
AC_DEFUN([SAGE_TEST_NAUTY_PROGS], [
9-
m4_foreach([nautyprog], [directg, gentourng, geng, genbg, gentreeg, converseg, genposetg], [
6+
m4_foreach([nautyprog], [directg, gentourng, geng, genbg, gentreeg, genktreeg, genposetg], [
107
AC_PATH_PROG([$2]nautyprog, [[$1]nautyprog])
118
AS_IF([test x$[$2]nautyprog = x], [sage_spkg_install_nauty=yes])
129
])

build/pkgs/nauty/spkg-install.in

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ sdh_make
1313

1414
# No install target so we resort to manual copy
1515
PROGRAMS="
16-
addedgeg addptg amtog ancestorg assembleg biplabg catg complg converseg copyg countg cubhamg deledgeg
17-
delptg dimacs2g directg dreadnaut dretodot dretog edgetransg genbg genbgL geng gengL genposetg genquarticg genrang
18-
genspecialg gentourng gentreeg hamheuristic labelg linegraphg listg multig nbrhoodg
19-
newedgeg pickg planarg productg ranlabg shortg showg subdivideg twohamg underlyingg vcolg
20-
watercluster2 NRswitchg"
16+
addedgeg addptg amtog ancestorg assembleg biplabg catg complg converseg copyg
17+
countg countneg cubhamg deledgeg delptg dimacs2g directg dreadnaut dretodot
18+
dretog edgetransg genbg genbgL geng gengL genposetg genquarticg genrang
19+
genspecialg gentourng gentreeg genktreeg hamheuristic labelg linegraphg listg
20+
multig nbrhoodg newedgeg pickg planarg productg ranlabg ransubg shortg showg
21+
subdivideg twohamg underlyingg vcolg watercluster2 NRswitchg"
2122
sdh_install $PROGRAMS "$SAGE_LOCAL/bin"
2223

2324
sdh_install nauty.h "$SAGE_LOCAL/include/nauty"

src/sage/features/nauty.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class NautyExecutable(Executable):
2424
EXAMPLES::
2525
2626
sage: from sage.features.nauty import NautyExecutable
27-
sage: NautyExecutable('converseg').is_present() # optional - nauty
27+
sage: NautyExecutable('converseg').is_present() # needs nauty
2828
FeatureTestResult('nauty_converseg', True)
2929
"""
3030
def __init__(self, name):
@@ -49,7 +49,7 @@ class Nauty(JoinFeature):
4949
EXAMPLES::
5050
5151
sage: from sage.features.nauty import Nauty
52-
sage: Nauty().is_present() # optional - nauty
52+
sage: Nauty().is_present() # needs nauty
5353
FeatureTestResult('nauty', True)
5454
"""
5555
def __init__(self):
@@ -62,7 +62,7 @@ def __init__(self):
6262
"""
6363
JoinFeature.__init__(self, "nauty",
6464
[NautyExecutable(name)
65-
for name in ('directg', 'gentourng', 'geng', 'genbg', 'gentreeg', 'converseg')])
65+
for name in ('directg', 'gentourng', 'geng', 'genbg', 'gentreeg', 'genktreeg')])
6666

6767

6868
def all_features():

src/sage/graphs/graph_generators.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,121 @@ def nauty_genbg(self, options="", debug=False):
11921192
G = BipartiteGraph(s[:-1], format='graph6', partition=partition)
11931193
yield G
11941194

1195+
def nauty_genktreeg(self, options="", debug=False):
1196+
r"""
1197+
Return a generator which creates all `k`-trees using nauty..
1198+
1199+
A `k`-tree is an undirected graph formed by starting with a complete
1200+
graph on `k + 1` vertices and then repeatedly add vertices in such a
1201+
way that each added vertex `v` has exactly `k` neighbors `U` such that,
1202+
together, the `k + 1` vertices formed by `v` and `U` form a clique.
1203+
See the :wikipedia:`K-tree` for more details.
1204+
1205+
INPUT:
1206+
1207+
- ``options`` -- string (default: ``""``); a string passed to
1208+
``genktreeg`` as if it was run at a system command line. At a minimum,
1209+
you *must* pass the number of vertices you desire. Sage expects the
1210+
graphs to be in nauty's "graph6" format, do not set an option to
1211+
change this default or results will be unpredictable.
1212+
1213+
- ``debug`` -- boolean (default: ``False``); if ``True`` the first line
1214+
of ``genktreeg``'s output to standard error is captured and the first
1215+
call to the generator's ``next()`` function will return this line as a
1216+
string. A line leading with ">A" indicates a successful initiation of
1217+
the program with some information on the arguments, while a line
1218+
beginning with ">E" indicates an error with the input.
1219+
1220+
The possible options, obtained as output of ``genktreeg --help``::
1221+
1222+
n : the number of vertices
1223+
-k<int> : the value of `k`(default: 2)
1224+
res/mod : only generate subset res out of subsets 0..mod-1
1225+
-l : canonically label output graphs
1226+
1227+
Options which cause ``genktreeg`` to use an output format different than
1228+
the graph6 format are not listed above (-u, -s, -h) as they will confuse
1229+
the creation of a Sage graph. The res/mod option can be useful when
1230+
using the output in a routine run several times in parallel.
1231+
1232+
OUTPUT:
1233+
1234+
A generator which will produce the graphs as Sage graphs.
1235+
These will be simple graphs: no loops, no multiple edges, no
1236+
directed edges.
1237+
1238+
EXAMPLES:
1239+
1240+
A `k`-tree is a maximal graph with treewidth `k`::
1241+
1242+
sage: # needs nauty
1243+
sage: gen = graphs.nauty_genktreeg("10 -k4")
1244+
sage: G = next(gen); G
1245+
Graph on 10 vertices
1246+
sage: G.treewidth()
1247+
4
1248+
1249+
A list of all 2-trees with 6, 7 and 8 vertices. This agrees with
1250+
:oeis:`A054581`::
1251+
1252+
sage: # needs nauty
1253+
sage: gen = graphs.nauty_genktreeg("6")
1254+
sage: len(list(gen))
1255+
5
1256+
sage: gen = graphs.nauty_genktreeg("7")
1257+
sage: len(list(gen))
1258+
12
1259+
sage: gen = graphs.nauty_genktreeg("8")
1260+
sage: len(list(gen))
1261+
39
1262+
1263+
The ``debug`` switch can be used to examine ``geng``'s reaction to the
1264+
input in the ``options`` string. We illustrate success. (A failure
1265+
will be a string beginning with ">E".) Passing the "-q" switch to
1266+
``geng`` will suppress the indicator of a successful initiation, and so
1267+
the first returned value might be an empty string if ``debug`` is
1268+
``True``::
1269+
1270+
sage: gen = graphs.nauty_genktreeg("7", debug=True) # needs nauty
1271+
sage: print(next(gen)) # needs nauty
1272+
>A ...genktreeg k=2 n=7
1273+
1274+
TESTS:
1275+
1276+
Wrong input::
1277+
1278+
sage: # needs nauty
1279+
sage: list(graphs.nauty_genktreeg("4 -k5", debug=True))
1280+
['>E genktreeg: n cannot be less than k\n']
1281+
sage: list(graphs.nauty_genktreeg("10 -k 4", debug=True))
1282+
['>E genktreeg -k: missing argument value\n']
1283+
sage: list(graphs.nauty_genktreeg("-c3", debug=False))
1284+
Traceback (most recent call last):
1285+
...
1286+
ValueError: wrong format of parameter option
1287+
"""
1288+
import shlex
1289+
from sage.features.nauty import NautyExecutable
1290+
geng_path = NautyExecutable("genktreeg").absolute_filename()
1291+
sp = subprocess.Popen(shlex.quote(geng_path) + " {0}".format(options), shell=True,
1292+
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
1293+
stderr=subprocess.PIPE, close_fds=True,
1294+
encoding='latin-1')
1295+
msg = sp.stderr.readline()
1296+
if debug:
1297+
yield msg
1298+
elif msg.startswith('>E'):
1299+
raise ValueError('wrong format of parameter option')
1300+
gen = sp.stdout
1301+
while True:
1302+
try:
1303+
s = next(gen)
1304+
except StopIteration:
1305+
# Exhausted list of graphs from nauty geng
1306+
return
1307+
G = graph.Graph(s[:-1], format='graph6')
1308+
yield G
1309+
11951310
def cospectral_graphs(self, vertices, matrix_function=None, graphs=None):
11961311
r"""
11971312
Find all sets of graphs on ``vertices`` vertices (with

0 commit comments

Comments
 (0)