Skip to content

Commit 0101a73

Browse files
Speed up OnDigraphs for a digraph and a permutation (#267)
* Speed up OnDigraphs for a graph and a permutation * Instead of checking if the permutation fixes the vertices, check if it is the identity (which is much cheaper, although catches less cases) * Do not check explictly if the permutation maps the vertices of the graph to itself, do the mapping then check afterwards. * Use SmallestMovedPoint optimization, move error checking to make Permuted safe. * No commas or dots in error messages for OnDigraphs (directions from above) * Roll back change * Add OnDigraphsNC * Fix lint * Use OnDigraphsNC internally * Try with identity perm check --------- Co-authored-by: reiniscirpons <rc234@st-andrews.ac.uk>
1 parent 14637bb commit 0101a73

6 files changed

Lines changed: 65 additions & 33 deletions

File tree

gap/attr.gi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,10 +2744,10 @@ function(D)
27442744
p := Permutation(Transformation(topo), topo);
27452745

27462746
C := DigraphMutableCopyIfImmutable(D);
2747-
OnDigraphs(C, p ^ -1); # changes C in-place
2748-
DIGRAPH_TRANS_REDUCTION(C); # changes C in-place
2747+
OnDigraphsNC(C, p ^ -1); # changes C in-place
2748+
DIGRAPH_TRANS_REDUCTION(C); # changes C in-place
27492749
ClearDigraphEdgeLabels(C);
2750-
OnDigraphs(C, p); # changes C in-place
2750+
OnDigraphsNC(C, p); # changes C in-place
27512751
if IsImmutableDigraph(D) then
27522752
MakeImmutable(C);
27532753
SetDigraphTransitiveReductionAttr(D, C);

gap/grahom.gi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,7 @@ function(L1, L2)
819819
in1, in2, mask, defined, not_in_image, FindNextAmong, Recurse;
820820

821821
p := PermList(Reversed(DigraphWelshPowellOrder(L1)));
822-
L1 := OnDigraphs(L1, p ^ -1);
822+
L1 := OnDigraphsNC(L1, p ^ -1);
823823

824824
# We compute the join/meet table to avoid having to do this twice if L1 or L2
825825
# is mutable

gap/isomorph.gi

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ function(D)
214214
if IsMultiDigraph(D) then
215215
return OnMultiDigraphs(D, BlissCanonicalLabelling(D));
216216
fi;
217-
return OnDigraphs(D, BlissCanonicalLabelling(D));
217+
return OnDigraphsNC(D, BlissCanonicalLabelling(D));
218218
end);
219219

220220
InstallMethod(BlissCanonicalDigraph, "for a digraph and vertex coloring",
@@ -223,7 +223,7 @@ function(D, colors)
223223
if IsMultiDigraph(D) then
224224
return OnMultiDigraphs(D, BlissCanonicalLabelling(D, colors));
225225
fi;
226-
return OnDigraphs(D, BlissCanonicalLabelling(D, colors));
226+
return OnDigraphsNC(D, BlissCanonicalLabelling(D, colors));
227227
end);
228228

229229
InstallMethodThatReturnsDigraph(NautyCanonicalDigraph, "for a digraph",
@@ -233,7 +233,7 @@ function(D)
233233
Info(InfoWarning, 1, "NautyTracesInterface is not available");
234234
return fail;
235235
fi;
236-
return OnDigraphs(D, NautyCanonicalLabelling(D));
236+
return OnDigraphsNC(D, NautyCanonicalLabelling(D));
237237
end);
238238

239239
InstallMethod(NautyCanonicalDigraph, "for a digraph and vertex coloring",
@@ -243,7 +243,7 @@ function(D, colors)
243243
Info(InfoWarning, 1, "NautyTracesInterface is not available");
244244
return fail;
245245
fi;
246-
return OnDigraphs(D, NautyCanonicalLabelling(D, colors));
246+
return OnDigraphsNC(D, NautyCanonicalLabelling(D, colors));
247247
end);
248248

249249
# Automorphism group
@@ -349,7 +349,7 @@ function(C, D)
349349
if IsMultiDigraph(C) then
350350
act := OnMultiDigraphs;
351351
else
352-
act := OnDigraphs;
352+
act := OnDigraphsNC;
353353
fi;
354354

355355
if HasBlissCanonicalLabelling(C) and HasBlissCanonicalLabelling(D)
@@ -400,7 +400,7 @@ function(C, D, c1, c2)
400400
elif IsMultiDigraph(C) then
401401
act := OnMultiDigraphs;
402402
else
403-
act := OnDigraphs;
403+
act := OnDigraphsNC;
404404
fi;
405405

406406
if DIGRAPHS_UsingBliss or IsMultiDigraph(C) then
@@ -489,7 +489,7 @@ function(C, D, c1, c2)
489489
return [label1[1] / label2[1], label1[2] / label2[2]];
490490
fi;
491491

492-
if OnDigraphs(C, label1) <> OnDigraphs(D, label2) then
492+
if OnDigraphsNC(C, label1) <> OnDigraphsNC(D, label2) then
493493
return fail;
494494
fi;
495495
return label1 / label2;

gap/oper.gd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ DeclareOperation("DIGRAPHS_GraphProduct", [IsDigraph, IsDigraph, IsFunction]);
6262
# 4. Actions . . .
6363
DeclareOperation("OnDigraphs", [IsDigraph, IsPerm]);
6464
DeclareOperation("OnDigraphs", [IsDigraph, IsTransformation]);
65+
DeclareOperation("OnDigraphsNC", [IsDigraph, IsPerm]);
66+
DeclareOperation("OnDigraphsNC", [IsDigraph, IsTransformation]);
6567
DeclareOperation("OnTuplesDigraphs", [IsDigraphCollection, IsPerm]);
6668
DeclareOperation("OnSetsDigraphs", [IsDigraphCollection, IsPerm]);
6769
DeclareOperation("OnMultiDigraphs", [IsDigraph, IsPermCollection]);

gap/oper.gi

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -993,15 +993,25 @@ end);
993993
# 4. Actions
994994
###############################################################################
995995

996-
InstallMethod(OnDigraphs, "for a mutable digraph by out-neighbours and a perm",
997-
[IsMutableDigraph and IsDigraphByOutNeighboursRep, IsPerm],
996+
InstallMethod(OnDigraphs, "for a digraph and a perm",
997+
[IsDigraph, IsPerm],
998998
function(D, p)
999-
local out;
1000999
if ForAll(DigraphVertices(D), i -> i ^ p = i) then
10011000
return D;
10021001
elif ForAny(DigraphVertices(D), i -> i ^ p > DigraphNrVertices(D)) then
10031002
ErrorNoReturn("the 2nd argument <p> must be a permutation that permutes ",
1004-
"the vertices of the digraph <D> that is the 1st argument,");
1003+
"the vertices of the digraph <D> that is the 1st argument");
1004+
fi;
1005+
return OnDigraphsNC(D, p);
1006+
end);
1007+
1008+
InstallMethod(OnDigraphsNC,
1009+
"for a mutable digraph by out-neighbours and a perm",
1010+
[IsMutableDigraph and IsDigraphByOutNeighboursRep, IsPerm],
1011+
function(D, p)
1012+
local out;
1013+
if p = () then
1014+
return D;
10051015
fi;
10061016
out := D!.OutNeighbours;
10071017
out{DigraphVertices(D)} := Permuted(out, p);
@@ -1010,26 +1020,40 @@ function(D, p)
10101020
return D;
10111021
end);
10121022

1013-
InstallMethod(OnDigraphs, "for a immutable digraph and a perm",
1023+
InstallMethod(OnDigraphsNC, "for a immutable digraph and a perm",
10141024
[IsImmutableDigraph, IsPerm],
10151025
function(D, p)
1016-
if ForAll(DigraphVertices(D), i -> i ^ p = i) then
1026+
local out, permed;
1027+
if p = () then
10171028
return D;
10181029
fi;
1019-
return MakeImmutable(OnDigraphs(DigraphMutableCopy(D), p));
1030+
out := D!.OutNeighbours;
1031+
permed := Permuted(out, p);
1032+
Apply(permed, x -> OnTuples(x, p));
1033+
return DigraphNC(IsImmutableDigraph, permed);
10201034
end);
10211035

10221036
InstallMethod(OnDigraphs,
1023-
"for a mutable digraph by out-neighbours and a transformation",
1024-
[IsMutableDigraph and IsDigraphByOutNeighboursRep, IsTransformation],
1037+
"for a digraph and a transformation",
1038+
[IsDigraph, IsTransformation],
10251039
function(D, t)
1026-
local old, new, v;
10271040
if ForAll(DigraphVertices(D), i -> i ^ t = i) then
10281041
return D;
10291042
elif ForAny(DigraphVertices(D), i -> i ^ t > DigraphNrVertices(D)) then
10301043
ErrorNoReturn("the 2nd argument <t> must be a transformation that ",
10311044
"maps every vertex of the digraph <D> that is the 1st ",
1032-
"argument, to another vertex.");
1045+
"argument, to another vertex");
1046+
fi;
1047+
return OnDigraphsNC(D, t);
1048+
end);
1049+
1050+
InstallMethod(OnDigraphsNC,
1051+
"for a mutable digraph by out-neighbours and a transformation",
1052+
[IsMutableDigraph and IsDigraphByOutNeighboursRep, IsTransformation],
1053+
function(D, t)
1054+
local old, new, v;
1055+
if t = IdentityTransformation then
1056+
return D;
10331057
fi;
10341058
old := D!.OutNeighbours;
10351059
new := List(DigraphVertices(D), x -> []);
@@ -1041,13 +1065,19 @@ function(D, t)
10411065
return D;
10421066
end);
10431067

1044-
InstallMethod(OnDigraphs, "for a immutable digraph and a transformation",
1068+
InstallMethod(OnDigraphsNC, "for a immutable digraph and a transformation",
10451069
[IsImmutableDigraph, IsTransformation],
10461070
function(D, t)
1047-
if ForAll(DigraphVertices(D), i -> i ^ t = i) then
1071+
local old, new, v;
1072+
if t = IdentityTransformation then
10481073
return D;
10491074
fi;
1050-
return MakeImmutable(OnDigraphs(DigraphMutableCopy(D), t));
1075+
old := D!.OutNeighbours;
1076+
new := List(DigraphVertices(D), x -> []);
1077+
for v in DigraphVertices(D) do
1078+
Append(new[v ^ t], OnTuples(old[v], t));
1079+
od;
1080+
return DigraphNC(IsImmutableDigraph, new);
10511081
end);
10521082

10531083
InstallMethod(OnTuplesDigraphs,
@@ -1060,7 +1090,7 @@ InstallMethod(OnSetsDigraphs,
10601090
[IsDigraphCollection and IsHomogeneousList, IsPerm],
10611091
function(S, p)
10621092
if not IsSet(S) then
1063-
ErrorNoReturn("the first argument must be a set (a strictly sorted list),");
1093+
ErrorNoReturn("the first argument must be a set (a strictly sorted list)");
10641094
fi;
10651095
return Set(S, D -> OnDigraphs(DigraphMutableCopyIfMutable(D), p));
10661096
end);
@@ -1081,7 +1111,7 @@ function(D, perms)
10811111
i -> i ^ perms[2] > DigraphNrEdges(D)) then
10821112
ErrorNoReturn("the 2nd entry of the 2nd argument <perms> must ",
10831113
"permute the edges of the digraph <D> that is the 1st ",
1084-
"argument,");
1114+
"argument");
10851115
fi;
10861116

10871117
return OnDigraphs(D, perms[1]);

tst/standard/oper.tst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ gap> h := (1, 2, 3, 4);
9898
(1,2,3,4)
9999
gap> OnDigraphs(gr, h);
100100
Error, the 2nd argument <p> must be a permutation that permutes the vertices o\
101-
f the digraph <D> that is the 1st argument,
101+
f the digraph <D> that is the 1st argument
102102
gap> gr := Digraph([[1, 1, 1, 3, 5], [], [3, 2, 4, 5], [2, 5], [1, 2, 1]]);
103103
<immutable multidigraph with 5 vertices, 14 edges>
104104
gap> DigraphEdges(gr);
@@ -108,7 +108,7 @@ gap> p1 := (2, 4)(3, 6, 5);
108108
(2,4)(3,6,5)
109109
gap> OnDigraphs(gr, p1);
110110
Error, the 2nd argument <p> must be a permutation that permutes the vertices o\
111-
f the digraph <D> that is the 1st argument,
111+
f the digraph <D> that is the 1st argument
112112
gap> p2 := (1, 3, 4, 2);
113113
(1,3,4,2)
114114
gap> OnDigraphs(gr, p2);
@@ -125,7 +125,7 @@ gap> p1 := (1, 5, 4, 2, 3);
125125
(1,5,4,2,3)
126126
gap> OnDigraphs(gr, p1);
127127
Error, the 2nd argument <p> must be a permutation that permutes the vertices o\
128-
f the digraph <D> that is the 1st argument,
128+
f the digraph <D> that is the 1st argument
129129
gap> p2 := (1, 4)(2, 3);
130130
(1,4)(2,3)
131131
gap> OnDigraphs(gr, p2);
@@ -142,7 +142,7 @@ gap> OutNeighbours(gr);
142142
gap> t := Transformation([4, 2, 3, 4]);;
143143
gap> OnDigraphs(gr, t);
144144
Error, the 2nd argument <t> must be a transformation that maps every vertex of\
145-
the digraph <D> that is the 1st argument, to another vertex.
145+
the digraph <D> that is the 1st argument, to another vertex
146146
gap> t := Transformation([1, 2, 1]);;
147147
gap> gr := OnDigraphs(gr, t);
148148
<immutable multidigraph with 3 vertices, 3 edges>
@@ -173,7 +173,7 @@ gap> D := [DigraphReverse(ChainDigraph(3)), ChainDigraph(3)];;
173173
gap> IsSet(D);
174174
false
175175
gap> OnSetsDigraphs(D, (1, 2));
176-
Error, the first argument must be a set (a strictly sorted list),
176+
Error, the first argument must be a set (a strictly sorted list)
177177
gap> D := Reversed(D);;
178178
gap> OnSetsDigraphs(D, (1, 3)) = D;
179179
true
@@ -209,7 +209,7 @@ gap> OnMultiDigraphs(gr1, [(1, 3)]);
209209
Error, the 2nd argument <perms> must be a pair of permutations,
210210
gap> OnMultiDigraphs(gr1, [(1, 3), (1, 7)]);
211211
Error, the 2nd entry of the 2nd argument <perms> must permute the edges of the\
212-
digraph <D> that is the 1st argument,
212+
digraph <D> that is the 1st argument
213213

214214
# DomainForAction
215215
gap> DomainForAction(RandomDigraph(10), SymmetricGroup(10), OnDigraphs);

0 commit comments

Comments
 (0)