10
10
11
11
# Permutation groups
12
12
13
+ # FIXME: Currently, if ValueOptions are set, then this can set the wrong value
14
+ # of this attribute!
13
15
InstallMethod(OrbitalGraphs, " for a permutation group" , [ IsPermGroup] ,
14
16
{ G} -> OrbitalGraphs(G, MovedPoints(G)));
15
17
30
32
InstallMethod(OrbitalGraphs, " for a permutation group and a homogeneous list" ,
31
33
[ IsPermGroup, IsHomogeneousList] ,
32
34
function (G, points )
33
- local orb, orbitsG, iorb, graph, graphlist, val, p, i, orbsizes, D,
35
+ local orb, orbitsG, iorb, graph, graphlist, val, p, i, orbsizes, D, cutoff,
36
+ biggestOrbit, shouldSkipOneLargeOrbit, allowLoopyGraphs, search,
34
37
orbpos, innerorblist, orbitsizes, orbreps, fillRepElts, maxval, moved;
35
38
36
39
if IsEmpty(points) then
@@ -48,6 +51,15 @@ function(G, points)
48
51
fi ;
49
52
moved := Intersection(points, MovedPoints(G));
50
53
54
+ # Optimisation from BacktrackKit
55
+ # Warning: in the future, if we wish to allow supporting orbital graphs
56
+ # with loops, and choosing base points that are allowed to be fixed, then
57
+ # this would mean that a trivial group could have some orbital graphs to
58
+ # return, and so this optimisation would be invalid.
59
+ if IsTrivial(G) then
60
+ return [] ;
61
+ fi ;
62
+
51
63
fillRepElts := function (G, orb )
52
64
local val, g, reps, buildorb, gens;
53
65
reps := [] ;
@@ -65,49 +77,101 @@ function(G, points)
65
77
return reps;
66
78
end ;
67
79
68
- orbitsG := Orbits(G, moved);
80
+ # Option `cutoff`:
81
+ # Have a limit for the number of edges that an orbital graph that this
82
+ # function will create. The default is infinity.
83
+ if IsPosInt(ValueOption(" cutoff" )) then
84
+ cutoff := ValueOption(" cutoff" );
85
+ else
86
+ cutoff := infinity;
87
+ fi ;
69
88
70
- # FIXME: Currently unused
71
- orbsizes := [] ;
72
- # FIXME: Currently unused
73
- orbpos := [] ;
89
+ # TODO: Implement this
90
+ # Option `loops`:
91
+ # Create OrbitalGraphs with base pair is a loop (i.e. a repeated vertex).
92
+ # People do not normally want these kinds of orbital graphs, since they
93
+ # only tell you about the orbit of that point.
94
+ # allowLoopyGraphs := ValueOption("loops") = true;
95
+
96
+ # Option `search`:
97
+ # If `true`, then OrbitalGraphs will not create some orbital graphs
98
+ # that are useless from the point of view of a backtrack search algorithm.
99
+ search := ValueOption(" search" ) = true ;
100
+
101
+ # Option `skipone`
102
+ # If `true`, then OrbitalGraphs will not create one of the orbital graphs
103
+ # that has the largest possible number of edges. In a backtrack search,
104
+ # one such orbital graph can be ignored without losing anything.
105
+ shouldSkipOneLargeOrbit := search or ValueOption(" skipone" ) = true ;
106
+
107
+ # Make sure that the orbits of G are stably sorted, so that the resulting
108
+ # list of orbital graphs for a group always comes in the same order,
109
+ # with the same base pairs.
110
+ orbitsG := Set(Orbits(G, moved), Set);
74
111
75
112
# Efficently store size of orbits of values
113
+ orbsizes := [] ;
114
+ orbpos := [] ;
76
115
for orb in [ 1 .. Length(orbitsG)] do
77
116
for i in orbitsG[ orb] do
78
117
orbsizes[ i] := Length(orbitsG[ orb] );
79
118
orbpos[ i] := orb;
80
119
od ;
81
120
od ;
82
121
83
- innerorblist := List(orbitsG, o -> Orbits(Stabilizer(G, o[ 1 ] ), moved));
84
- # FIXME: Currently unused
122
+ # FIXME: In the following line, BacktrackKit uses [1..LargestMovedPoint(G)]
123
+ # instead of moved (which omits non-moved points). Is this a problem?
124
+ innerorblist := List(orbitsG, o -> Set(Orbits(Stabilizer(G, o[ 1 ] ), moved), Set));
85
125
orbitsizes := List([ 1 .. Length(orbitsG)] ,
86
126
x -> List(innerorblist[ x] , y -> Length(orbitsG[ x] ) * Length(y)));
127
+ biggestOrbit := Maximum(List(orbitsizes, Maximum));
87
128
88
129
graphlist := [] ;
89
130
for i in [ 1 .. Length(orbitsG)] do
90
131
orb := orbitsG[ i] ;
91
132
orbreps := [] ;
92
-
93
133
for iorb in innerorblist[ i] do
94
- if not (Size(iorb) = 1 and orb[ 1 ] = iorb[ 1 ] ) # No loopy orbitals
95
- then
96
- graph := List([ 1 .. maxval] , x -> [] );
97
- if IsEmpty(orbreps) then
98
- orbreps := fillRepElts(G, orb);
99
- fi ;
100
- for val in orb do
101
- p := orbreps[ val] ;
102
- graph[ val] := List(iorb, x -> x^ p);
103
- od ;
104
- D := Digraph(graph);
105
- SetUnderlyingGroup(D, G);
106
- AddSet(graphlist, D);
134
+ # Find reasons to not construct this orbital graph...
135
+ # (These conditions are split to allow for future Info statements
136
+ # explaining what is happening, and also to make sure we have
137
+ # good code coverage, and therefore that we have good tests.)
138
+ if Size(orb) * Size(iorb) > cutoff then
139
+ # orbital graph is too big
140
+ continue ;
141
+ elif search and orbpos[ orb[ 1 ]] = orbpos[ iorb[ 1 ]] and Size(iorb) + 1 = orbsizes[ iorb[ 1 ]] then
142
+ # orbit size only removed one point
143
+ # TODO: Is this only relevant to 2-or-more-transitive groups, in which case there is just a unique orbital graph?
144
+ continue ;
145
+ elif Length(iorb) = 1 and orb[ 1 ] = iorb[ 1 ] then
146
+ # don't want to take the fixed point orbit
147
+ continue ;
148
+ elif search and Size(iorb) = orbsizes[ iorb[ 1 ]] then
149
+ # orbit size unchanged
150
+ # TODO: Give an explanation of what this means
151
+ continue ;
152
+ elif shouldSkipOneLargeOrbit and Size(orb) * Size(iorb) = biggestOrbit then
153
+ # FIXME: Is it safe putting this here, not as the first check?
154
+ # largest possible; skip
155
+ shouldSkipOneLargeOrbit := false ;
156
+ continue ;
107
157
fi ;
158
+
159
+ # Construct the orbital graph as a Digraphs package object
160
+ if IsEmpty(orbreps) then
161
+ orbreps := fillRepElts(G, orb);
162
+ fi ;
163
+ graph := List([ 1 .. maxval] , x -> [] );
164
+ for val in orb do
165
+ p := orbreps[ val] ;
166
+ graph[ val] := List(iorb, x -> x ^ p);
167
+ od ;
168
+ D := Digraph(graph);
169
+ SetFilterObj(D, IsOrbitalGraphOfGroup);
170
+ SetUnderlyingGroup(D, G);
171
+ Add(graphlist, D);
108
172
od ;
109
173
od ;
110
- Perform( graphlist, function ( x ) SetFilterObj(x, IsOrbitalGraphOfGroup); end );
174
+ # Note: ` graphlist` should already be stably ordered because of the uses of `Set`
111
175
return graphlist;
112
176
end );
113
177
0 commit comments