Skip to content

Commit

Permalink
sagemathgh-36924: add interface to nauty's genktreeg
Browse files Browse the repository at this point in the history
    
Nauty has a generator of k-trees. We add an interface to this generator.
This is a complement of sagemath#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
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#36924
Reported by: David Coudert
Reviewer(s): Matthias Köppe
  • Loading branch information
Release Manager committed Dec 24, 2023
2 parents 8c04fa9 + 5ad350c commit 1172a7a
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 17 deletions.
2 changes: 1 addition & 1 deletion build/pkgs/nauty/package-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.8.8
2.8.8.p0
13 changes: 5 additions & 8 deletions build/pkgs/nauty/spkg-configure.m4
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
# We don't use the "converseg" program, but we need to ensure that we
# only detect nauty >= 2.6 because we use the digraph6 format from
# that version -- and converseg was added in nauty-2.6.
#
# We also don't use the "genposetg" program (added in nauty 2.8) yet.
# We require it here to prepare Sage for the use of the major new features
# added in 2.7 and 2.8 (https://pallini.di.uniroma1.it/changes24-28.txt).
# We use the "genktreeg" program (added in nauty 2.8.8). This ensures that we
# detect nauty >= 2.8.8 and so we can use the major new features added in nauty
# since version 2.6. For instance, we use the digraph6 format from nauty >= 2.6
# (https://pallini.di.uniroma1.it/changes24-28.txt).
AC_DEFUN([SAGE_TEST_NAUTY_PROGS], [
m4_foreach([nautyprog], [directg, gentourng, geng, genbg, gentreeg, converseg, genposetg], [
m4_foreach([nautyprog], [directg, gentourng, geng, genbg, gentreeg, genktreeg, genposetg], [
AC_PATH_PROG([$2]nautyprog, [[$1]nautyprog])
AS_IF([test x$[$2]nautyprog = x], [sage_spkg_install_nauty=yes])
])
Expand Down
11 changes: 6 additions & 5 deletions build/pkgs/nauty/spkg-install.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ sdh_make

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

sdh_install nauty.h "$SAGE_LOCAL/include/nauty"
Expand Down
6 changes: 3 additions & 3 deletions src/sage/features/nauty.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class NautyExecutable(Executable):
EXAMPLES::
sage: from sage.features.nauty import NautyExecutable
sage: NautyExecutable('converseg').is_present() # optional - nauty
sage: NautyExecutable('converseg').is_present() # needs nauty
FeatureTestResult('nauty_converseg', True)
"""
def __init__(self, name):
Expand All @@ -49,7 +49,7 @@ class Nauty(JoinFeature):
EXAMPLES::
sage: from sage.features.nauty import Nauty
sage: Nauty().is_present() # optional - nauty
sage: Nauty().is_present() # needs nauty
FeatureTestResult('nauty', True)
"""
def __init__(self):
Expand All @@ -62,7 +62,7 @@ def __init__(self):
"""
JoinFeature.__init__(self, "nauty",
[NautyExecutable(name)
for name in ('directg', 'gentourng', 'geng', 'genbg', 'gentreeg', 'converseg')])
for name in ('directg', 'gentourng', 'geng', 'genbg', 'gentreeg', 'genktreeg')])


def all_features():
Expand Down
115 changes: 115 additions & 0 deletions src/sage/graphs/graph_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,121 @@ def nauty_genbg(self, options="", debug=False):
G = BipartiteGraph(s[:-1], format='graph6', partition=partition)
yield G

def nauty_genktreeg(self, options="", debug=False):
r"""
Return a generator which creates all `k`-trees using nauty..
A `k`-tree is an undirected graph formed by starting with a complete
graph on `k + 1` vertices and then repeatedly add vertices in such a
way that each added vertex `v` has exactly `k` neighbors `U` such that,
together, the `k + 1` vertices formed by `v` and `U` form a clique.
See the :wikipedia:`K-tree` for more details.
INPUT:
- ``options`` -- string (default: ``""``); a string passed to
``genktreeg`` as if it was run at a system command line. At a minimum,
you *must* pass the number of vertices you desire. Sage expects the
graphs to be in nauty's "graph6" format, do not set an option to
change this default or results will be unpredictable.
- ``debug`` -- boolean (default: ``False``); if ``True`` the first line
of ``genktreeg``'s output to standard error is captured and the first
call to the generator's ``next()`` function will return this line as a
string. A line leading with ">A" indicates a successful initiation of
the program with some information on the arguments, while a line
beginning with ">E" indicates an error with the input.
The possible options, obtained as output of ``genktreeg --help``::
n : the number of vertices
-k<int> : the value of `k`(default: 2)
res/mod : only generate subset res out of subsets 0..mod-1
-l : canonically label output graphs
Options which cause ``genktreeg`` to use an output format different than
the graph6 format are not listed above (-u, -s, -h) as they will confuse
the creation of a Sage graph. The res/mod option can be useful when
using the output in a routine run several times in parallel.
OUTPUT:
A generator which will produce the graphs as Sage graphs.
These will be simple graphs: no loops, no multiple edges, no
directed edges.
EXAMPLES:
A `k`-tree is a maximal graph with treewidth `k`::
sage: # needs nauty
sage: gen = graphs.nauty_genktreeg("10 -k4")
sage: G = next(gen); G
Graph on 10 vertices
sage: G.treewidth()
4
A list of all 2-trees with 6, 7 and 8 vertices. This agrees with
:oeis:`A054581`::
sage: # needs nauty
sage: gen = graphs.nauty_genktreeg("6")
sage: len(list(gen))
5
sage: gen = graphs.nauty_genktreeg("7")
sage: len(list(gen))
12
sage: gen = graphs.nauty_genktreeg("8")
sage: len(list(gen))
39
The ``debug`` switch can be used to examine ``geng``'s reaction to the
input in the ``options`` string. We illustrate success. (A failure
will be a string beginning with ">E".) Passing the "-q" switch to
``geng`` will suppress the indicator of a successful initiation, and so
the first returned value might be an empty string if ``debug`` is
``True``::
sage: gen = graphs.nauty_genktreeg("7", debug=True) # needs nauty
sage: print(next(gen)) # needs nauty
>A ...genktreeg k=2 n=7
TESTS:
Wrong input::
sage: # needs nauty
sage: list(graphs.nauty_genktreeg("4 -k5", debug=True))
['>E genktreeg: n cannot be less than k\n']
sage: list(graphs.nauty_genktreeg("10 -k 4", debug=True))
['>E genktreeg -k: missing argument value\n']
sage: list(graphs.nauty_genktreeg("-c3", debug=False))
Traceback (most recent call last):
...
ValueError: wrong format of parameter option
"""
import shlex
from sage.features.nauty import NautyExecutable
geng_path = NautyExecutable("genktreeg").absolute_filename()
sp = subprocess.Popen(shlex.quote(geng_path) + " {0}".format(options), shell=True,
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, close_fds=True,
encoding='latin-1')
msg = sp.stderr.readline()
if debug:
yield msg
elif msg.startswith('>E'):
raise ValueError('wrong format of parameter option')
gen = sp.stdout
while True:
try:
s = next(gen)
except StopIteration:
# Exhausted list of graphs from nauty geng
return
G = graph.Graph(s[:-1], format='graph6')
yield G

def cospectral_graphs(self, vertices, matrix_function=None, graphs=None):
r"""
Find all sets of graphs on ``vertices`` vertices (with
Expand Down

0 comments on commit 1172a7a

Please sign in to comment.