diff --git a/doc/oper.xml b/doc/oper.xml
index 54d8d0ed7..324951db2 100644
--- a/doc/oper.xml
+++ b/doc/oper.xml
@@ -257,6 +257,56 @@ gap> OutNeighbours(D2);
<#/GAPDoc>
+<#GAPDoc Label="OnTuplesDigraphs">
+
+
+
+ A list or set of digraphs.
+
+ If list is a list of digraphs, and perm is a
+ permutation of the vertices of the digraphs in list, then
+
+ returns a new list constructed by applying perm via
+
+ to a copy (with the same mutability) of each entry of list in turn.
+
+
+ More precisely, OnTuplesDigraphs(list,perm) is a list
+ of length Length(list), whose i-th entry is
+ OnDigraphs(DigraphCopy(list[i]), perm).
+
+
+ If list is moreover a &GAP; set (i.e. a duplicate-free sorted list),
+ then
+ returns the sorted output of
+ ,
+ which is therefore again a set.
+ list := [CycleDigraph(IsMutableDigraph, 6),
+> DigraphReverse(CycleDigraph(6))];
+[ ,
+ ]
+gap> p := (1, 6)(2, 5)(3, 4);;
+gap> result_tuples := OnTuplesDigraphs(list, p);
+[ ,
+ ]
+gap> result_tuples[2] = OnDigraphs(list[2], p);
+true
+gap> result_tuples = list;
+false
+gap> result_tuples = Reversed(list);
+true
+gap> result_sets := OnSetsDigraphs(list, p);
+[ ,
+ ]
+gap> result_sets = list;
+true]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="DigraphAddVertex">
diff --git a/doc/z-chap6.xml b/doc/z-chap6.xml
index c4aaad204..d9b2369d8 100644
--- a/doc/z-chap6.xml
+++ b/doc/z-chap6.xml
@@ -11,6 +11,7 @@ from} $E_a$ \emph{to} $E_b$. In this case we say that $E_a$ and $E_b$ are
Acting on digraphs
<#Include Label="OnDigraphs">
<#Include Label="OnMultiDigraphs">
+ <#Include Label="OnTuplesDigraphs">
diff --git a/gap/digraph.gd b/gap/digraph.gd
index 8c3924bc6..d93389b46 100644
--- a/gap/digraph.gd
+++ b/gap/digraph.gd
@@ -14,6 +14,7 @@ DeclareCategory("IsDigraphWithAdjacencyFunction", IsDigraph);
DeclareCategory("IsCayleyDigraph", IsDigraph);
DeclareCategory("IsImmutableDigraph", IsDigraph);
DeclareSynonym("IsMutableDigraph", IsDigraph and IsMutable);
+DeclareCategoryCollections("IsDigraph");
DeclareAttribute("DigraphMutabilityFilter", IsDigraph);
diff --git a/gap/oper.gd b/gap/oper.gd
index e8fa1f176..45c48ea3c 100644
--- a/gap/oper.gd
+++ b/gap/oper.gd
@@ -59,6 +59,8 @@ DeclareOperation("DIGRAPHS_GraphProduct", [IsDigraph, IsDigraph, IsFunction]);
# 4. Actions . . .
DeclareOperation("OnDigraphs", [IsDigraph, IsPerm]);
DeclareOperation("OnDigraphs", [IsDigraph, IsTransformation]);
+DeclareOperation("OnTuplesDigraphs", [IsDigraphCollection, IsPerm]);
+DeclareOperation("OnSetsDigraphs", [IsDigraphCollection, IsPerm]);
DeclareOperation("OnMultiDigraphs", [IsDigraph, IsPermCollection]);
DeclareOperation("OnMultiDigraphs", [IsDigraph, IsPerm, IsPerm]);
diff --git a/gap/oper.gi b/gap/oper.gi
index 4d7e7057c..a8f3f65d9 100644
--- a/gap/oper.gi
+++ b/gap/oper.gi
@@ -826,6 +826,21 @@ function(D, t)
return MakeImmutable(OnDigraphs(DigraphMutableCopy(D), t));
end);
+InstallMethod(OnTuplesDigraphs,
+"for list of digraphs and a perm",
+[IsDigraphCollection and IsHomogeneousList, IsPerm],
+{L, p} -> List(L, D -> OnDigraphs(DigraphMutableCopyIfMutable(D), p)));
+
+InstallMethod(OnSetsDigraphs,
+"for a list of digraphs and a perm",
+[IsDigraphCollection and IsHomogeneousList, IsPerm],
+function(S, p)
+ if not IsSet(S) then
+ ErrorNoReturn("the first argument must be a set (a strictly sorted list),");
+ fi;
+ return Set(S, D -> OnDigraphs(DigraphMutableCopyIfMutable(D), p));
+end);
+
# Not revising the following because multi-digraphs are being withdrawn in the
# near future.
diff --git a/tst/standard/oper.tst b/tst/standard/oper.tst
index e5549a3e2..4c4aedf0a 100644
--- a/tst/standard/oper.tst
+++ b/tst/standard/oper.tst
@@ -149,6 +149,55 @@ gap> gr := OnDigraphs(gr, t);
gap> OutNeighbours(gr);
[ [ 2 ], [ 1, 1 ], [ ] ]
+# OnTuplesDigraphs: for a digraph and a permutation
+gap> D := [ChainDigraph(3), CycleDigraph(4)];;
+gap> List(D, OutNeighbours);
+[ [ [ 2 ], [ 3 ], [ ] ], [ [ 2 ], [ 3 ], [ 4 ], [ 1 ] ] ]
+gap> List(OnTuplesDigraphs(D, (1, 3)), OutNeighbours);
+[ [ [ ], [ 1 ], [ 2 ] ], [ [ 4 ], [ 1 ], [ 2 ], [ 3 ] ] ]
+gap> D := [ChainDigraph(3), DigraphReverse(ChainDigraph(3))];;
+gap> List(D, OutNeighbours);
+[ [ [ 2 ], [ 3 ], [ ] ], [ [ ], [ 1 ], [ 2 ] ] ]
+gap> List(OnTuplesDigraphs(D, (1, 3)), OutNeighbours);
+[ [ [ ], [ 1 ], [ 2 ] ], [ [ 2 ], [ 3 ], [ ] ] ]
+gap> OnTuplesDigraphs(D, (1, 3)) = Permuted(D, (1, 2));
+true
+gap> D := EmptyDigraph(IsMutableDigraph, 3);;
+gap> DigraphAddEdge(D, 1, 1);;
+gap> out := OnTuplesDigraphs([D, D], (1, 2, 3));;
+gap> List(out, DigraphEdges);
+[ [ [ 2, 2 ] ], [ [ 2, 2 ] ] ]
+
+# OnSetsDigraphs: for a digraph and a permutation
+gap> D := [DigraphReverse(ChainDigraph(3)), ChainDigraph(3)];;
+gap> IsSet(D);
+false
+gap> OnSetsDigraphs(D, (1, 2));
+Error, the first argument must be a set (a strictly sorted list),
+gap> D := Reversed(D);;
+gap> OnSetsDigraphs(D, (1, 3)) = D;
+true
+gap> OnSetsDigraphs(D, (1, 3)) = OnTuplesDigraphs(D, (1, 3));
+false
+gap> MinimalGeneratingSet(Stabilizer(SymmetricGroup(3), D, OnSetsDigraphs));
+[ (1,3) ]
+
+# Set of orbital graphs of G := TransitiveGroup(6, 4)
+# The stabiliser of this set is the normaliser of G in S_6
+gap> x := Set(["&ECA@_OG", "&EQHcQHc", "&EHcQHcQ"], DigraphFromDigraph6String);
+[ ,
+ ,
+ ]
+gap> Stabiliser(SymmetricGroup(6), x, OnSetsDigraphs)
+> = Group([(1, 2, 3, 4, 5, 6), (1, 5)(2, 4)(3, 6)]);
+true
+gap> OnTuplesDigraphs(x, (2, 3)(5, 6)) = x;
+false
+gap> OnTuplesDigraphs(x, (2, 3)(5, 6)) = [x[1], x[3], x[2]];
+true
+gap> OnSetsDigraphs(x, (2, 3)(5, 6)) = x;
+true
+
# OnMultiDigraphs: for a pair of permutations
gap> gr1 := CompleteDigraph(3);