Skip to content

Commit 95916d7

Browse files
Add manual documentation and tidy comments
Document the previously-undocumented user-facing API in the manual: - Introduction chapter explaining graph backtracking and its relationship to BacktrackKit and vole, with cross-references into the BacktrackKit manual rather than duplicating its framework docs. - "Executing a search" chapter for InfoGB and the GB_Simple* search functions, plus GB_CheckInitial{Group,Coset}. - "Refiners" chapter describing the GB_Con refiner families (group, coset, transporter, normaliser/conjugacy) with worked examples, and a section on the experimental normaliser variants with the canonical-safety warning. - Flesh out the Equitable Graphs chapter: a description for each of the None/Weak/Strong/Full consolidators. makedoc.g now loads the package (so cross-book references resolve) and fixes the chapter order via autodoc.files. Tidy comments: remove commented-out debug Print statements, drop two dangling references to files that were never committed, and rewrite the graph-merge comment in ApplyFilters to explain why pos is forced to fail without the leftover code fragment. Fix two tests that loaded "graphbacktrack" instead of the full package name.
1 parent 5346e14 commit 95916d7

12 files changed

Lines changed: 317 additions & 36 deletions

README.md

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,6 @@ This algorithm can be used to perform calculations in permutation groups, such a
1111

1212
This package is intended for learning and exploring the graph backtracking algorithm. The performance is **extremely poor**. For a modern, high-performance version of this algorithm, please see the [**vole**](https://github.com/peal/vole) package.
1313

14-
`GraphBacktracking` requires GAP version >= 4.13.0, and recent versions of the following packages (see the `PackageInfo.g` file for specific versions):
15-
* BacktrackKit
16-
* datastructures
17-
* digraphs
18-
* images
19-
* primgrp
20-
21-
Additionally, [the QuickCheck package](https://github.com/ChrisJefferson/QuickCheck) is required to run all of the tests.
22-
2314
## Contact
2415

2516
This package is a work in progress, both in terms of code and documentation.

gap/Equitable.gd

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,53 @@
22
#
33
#! @Chapter Equitable Graphs
44
#!
5+
#! @Section Making a partition equitable
56
#!
7+
#! During search, the partition must be refined with respect to the
8+
#! current graph stack until it is <E>equitable</E>: informally, until no
9+
#! cell can be split by looking at how its points connect to the cells of
10+
#! the partition. &GraphBacktracking; offers several methods of differing
11+
#! strength and cost. A stronger method splits the partition at least as
12+
#! much as a weaker one, prunes the search tree more, but costs more per
13+
#! node. Which one is used is controlled by the <C>consolidator</C> field
14+
#! of the configuration record passed to the search functions (see
15+
#! <Ref Chap="Chapter_Executing_a_search"/>); the default is
16+
#! <Ref Oper="GB_MakeEquitableStrong" Label="for IsPartitionStack, IsTracer, IsList"/>.
617
#!
7-
#! @Section Example Methods
8-
#!
9-
#! This section will describe the methods which can
10-
#! be used to make equitable partitions
18+
#! Each method takes a partition stack <A>ps</A>, a tracer <A>tracer</A>
19+
#! (see <Ref Chap="Ordered tracers" BookName="BacktrackKit"/>), and a list
20+
#! <A>graphs</A> of digraphs. It refines <A>ps</A> in place, recording the
21+
#! splits in <A>tracer</A>, and returns <K>true</K> on success or
22+
#! <K>false</K> if a split contradicted the tracer (a dead branch).
1123

24+
#! @Arguments ps, tracer, graphs
1225
#! @Description
13-
#! Given a partition stack, and a list of graphs,
14-
#! make the partition equitable.
26+
#! Does nothing and returns <K>true</K>: the partition is left
27+
#! unchanged. Provided as a baseline (it makes graph backtracking behave
28+
#! like ordinary backtracking with respect to the graphs).
1529
DeclareOperation("GB_MakeEquitableNone", [IsPartitionStack, IsTracer, IsList]);
30+
31+
#! @Arguments ps, tracer, graphs
32+
#! @Description
33+
#! Refines <A>ps</A> by repeatedly splitting each cell according to the
34+
#! multiset of cells reached along out- and in-edges of each graph,
35+
#! iterating to a fixed point. This is the classical equitable-partition
36+
#! refinement applied to each graph in turn.
1637
DeclareOperation("GB_MakeEquitableWeak", [IsPartitionStack, IsTracer, IsList]);
38+
39+
#! @Arguments ps, tracer, graphs
40+
#! @Description
41+
#! A stronger refinement than <Ref Oper="GB_MakeEquitableWeak" Label="for IsPartitionStack, IsTracer, IsList"/>: it
42+
#! distinguishes points using the combined edge information across all
43+
#! graphs simultaneously, rather than one graph at a time. This is the
44+
#! default consolidator.
1745
DeclareOperation("GB_MakeEquitableStrong", [IsPartitionStack, IsTracer, IsList]);
46+
47+
#! @Arguments ps, tracer, graphs
48+
#! @Description
49+
#! The strongest (and most expensive) refinement: it builds a single
50+
#! digraph encoding the whole graph stack, computes its automorphism
51+
#! group and orbits, and splits the partition by those orbits. This can
52+
#! prune branches the cheaper methods miss, at a substantial cost per
53+
#! node.
1854
DeclareOperation("GB_MakeEquitableFull", [IsPartitionStack, IsTracer, IsList]);

gap/Equitable.gi

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,18 @@ InstallMethod(GB_MakeEquitableWeak, [IsPartitionStack, IsTracer, IsList],
1313
while cellcount <> PS_Cells(ps) and PS_Cells(ps) <> PS_ExtendedPoints(ps) do
1414
cellcount := PS_Cells(ps);
1515
for graph in graphlist do
16-
#Print(graph,"\n");
1716
hm := [];
1817
for v in [1..PS_ExtendedPoints(ps)] do
1918
hm[v] := List(_BTKit.OutNeighboursSafe(graph, v), {x} -> PS_CellOfPoint(ps, x));
20-
# We negate to distinguish in and out neighbours ---------v
19+
# Negate the in-neighbour cells to distinguish them from out-neighbours.
2120
Append(hm[v], List(_BTKit.InNeighboursSafe(graph, v), {x} -> -PS_CellOfPoint(ps, x)));
22-
#Print(v,":",hm[v],"\n");
2321
Sort(hm[v]);
2422
od;
25-
#Print(hm,"\n");
2623
if not PS_SplitCellsByFunction(ps, tracer, {x} -> hm[x]) then
2724
Info(InfoGB, 2, "EquitableWeak trace violation");
2825
return false;
2926
fi;
3027
od;
31-
#Print(hm,"\n");
3228
od;
3329
return true;
3430
end);
@@ -62,7 +58,6 @@ InstallMethod(GB_MakeEquitableStrong, [IsPartitionStack, IsTracer, IsList],
6258
Info(InfoGB, 2, "EquitableStrong trace violation");
6359
return false;
6460
fi;
65-
#Print(hm,"\n");
6661
od;
6762
return true;
6863
end);

gap/GraphBacktracking.gd

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,71 @@
11
#
22
# GraphBacktracking
33
#
4-
# Implementations
4+
# Declarations
55
#
66

7-
#! @Description
8-
#! Information about backtrack search
7+
#! @Chapter Introduction
8+
#!
9+
#! @Section What is &GraphBacktracking;?
10+
#!
11+
#! &GraphBacktracking; implements the graph backtracking algorithm
12+
#! described in the paper <Q>Computing canonical images in permutation
13+
#! groups with Graph Backtracking</Q>, by Christopher Jefferson, Rebecca
14+
#! Waldecker and Wilf A. Wilson
15+
#! (<URL>https://arxiv.org/abs/2209.02534</URL>). Graph backtracking
16+
#! generalises
17+
#! Leon's partition backtrack: instead of refining only an ordered
18+
#! partition of the points, the search also accumulates a stack of
19+
#! vertex- and edge-labelled graphs, which can capture constraints that a
20+
#! partition alone cannot. This makes it possible to solve problems such
21+
#! as normaliser computation and the canonical image of a graph under an
22+
#! arbitrary group.
23+
#!
24+
#! This package builds directly on the <Package>BacktrackKit</Package>
25+
#! package, and reuses its framework essentially unchanged: ordered
26+
#! partition stacks, tracers, constraints, the refiner protocol, and the
27+
#! top-level search loop. Those concepts are documented in the
28+
#! <Package>BacktrackKit</Package> manual and are not repeated here. This
29+
#! manual assumes you are familiar with them, in particular with
30+
#! <Ref Sect="The concept of constraints" BookName="BacktrackKit"/> and
31+
#! <Ref Chap="Refiners" BookName="BacktrackKit"/>, and documents only what
32+
#! &GraphBacktracking; adds on top.
33+
#!
34+
#! @Section Relationship to BacktrackKit and Vole
35+
#!
36+
#! Like <Package>BacktrackKit</Package>, this package exists for
37+
#! <E>learning and exploring</E> the algorithms. Its performance is
38+
#! <E>extremely poor</E> — often orders of magnitude slower than the
39+
#! built-in &GAP; functions for the same task. For a modern,
40+
#! high-performance implementation of graph backtracking, use the
41+
#! <Package>vole</Package> package
42+
#! (<URL>https://github.com/peal/vole</URL>) instead.
43+
#!
44+
#! The one substantive extension to the <Package>BacktrackKit</Package>
45+
#! refiner protocol is that a &GraphBacktracking; refiner may, in addition
46+
#! to splitting cells of the partition, emit <E>graphs</E>. A value
47+
#! returned by a refiner's <C>refine</C> functions (see
48+
#! <Ref Sect="The record refine" BookName="BacktrackKit"/>) may be a
49+
#! record with the components:
50+
#! * <C>graph</C> — a <Package>Digraphs</Package> digraph that is added to
51+
#! the graph stack; and/or
52+
#! * <C>vertlabels</C> — a list giving an initial colour for each vertex.
53+
#!
54+
#! The graph stack is then made equitable (see
55+
#! <Ref Chap="Chapter_Equitable_Graphs"/>) and contributes to the branching and
56+
#! pruning of the search in the same way the partition does.
57+
58+
#! @Chapter Executing a search
59+
#!
60+
#! @Section Information and diagnostics
61+
#!
62+
#! &GraphBacktracking; reports diagnostic information through the info
63+
#! class <C>InfoGB</C>, which is set equal to the
64+
#! <Package>BacktrackKit</Package> info class
65+
#! <Ref InfoClass="InfoBTKit" BookName="BacktrackKit"/>; raising the level
66+
#! of either (with <C>SetInfoLevel</C>) therefore raises both. Higher
67+
#! levels print progressively more detail about the progress of the
68+
#! search.
969
InfoGB := InfoBTKit;
1070

1171
# From init.g

gap/GraphBacktracking.gi

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,12 @@ InstallMethod(ApplyFilters, [IsGBState, IsTracer, IsObject],
8686
fi;
8787
fi;
8888
if IsBound(f.graph) then
89-
# TODO (maybe) -- this skipping of merged graphs ignores
90-
# vertex colourings.
91-
pos := fail; # This isn't valid for normalisers (and others): Position(state!.raw_graphs, f.graph);
89+
# We never merge a repeated graph: refiners such as the
90+
# normaliser push graphs that must all be kept, and
91+
# deduplicating by Position would also ignore vertex
92+
# colourings. So pos is always fail; the merge branch
93+
# below is kept for the day we can merge safely.
94+
pos := fail;
9295
if pos = fail then
9396
Add(state!.raw_graphs, f.graph);
9497
if PS_Points(state!.ps) < DigraphNrVertices(f.graph) then

gap/constraints/canonicalconstraints.g

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ GB_Con.InCosetSimple := function(group, perm)
1515
array[j] := i;
1616
od;
1717
od;
18-
#Print(group, pointlist, orbs, array, "\n");
1918
return rec(points := array, graphs := graphs);
2019
end;
2120

gap/constraints/normaliser.g

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ _BTKit.findRegularCharacteristicSubgroup := function(group, sizeCap)
477477
# uniqueness check fails. Skipping early also dodges a GAP-internal
478478
# performance pathology in which CharacteristicSubgroups hangs
479479
# after Size/Orbits have been called on Derived/Fitting/Centre
480-
# subgroups (reproducer in tst/benchmarks/refiner-sweep-slow.g).
480+
# subgroups.
481481
# This is a heuristic: there exist exotic H where two equal-length
482482
# orbits have non-isomorphic H-actions and no Aut(H)-swap exists,
483483
# in which case we may miss a usable F. But those cases are rare
@@ -544,7 +544,7 @@ end;
544544
# regOrbit, fp_R = g(fp_L), and the deduction-set D_R = g(D_L). The
545545
# labels match between sides because BFS-position(p) on the left
546546
# equals BFS-position(g(p)) on the right (the generator-correspondence
547-
# h_i^g = h_i' under conjugation by g — see notes/phase-c-notes.md).
547+
# h_i^g = h_i' under conjugation by g).
548548
# The branch-point proposal points to corresponding cells (same cell
549549
# index) on both sides since cell indices are g-equivariant for valid
550550
# candidates.

0 commit comments

Comments
 (0)