diff --git a/doc/grahom.xml b/doc/grahom.xml
index ac1520148..7f7e2922d 100644
--- a/doc/grahom.xml
+++ b/doc/grahom.xml
@@ -321,8 +321,8 @@ gap> MonomorphismsDigraphsRepresentatives(gr1, CompleteDigraph(3));
the vertices and the edges of digraph1, and are therefore possibly
strictly contained in the induced subdigraph on the same vertex set.
SubdigraphsMonomorphisms(CompleteBipartiteDigraph(2, 2),
-> CompleteDigraph(4));
+gap> Set(SubdigraphsMonomorphisms(CompleteBipartiteDigraph(2, 2),
+> CompleteDigraph(4)));
[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 3, 1 ] ),
Transformation( [ 3, 4, 2, 1 ] ) ]
gap> SubdigraphsMonomorphismsRepresentatives(
diff --git a/gap/attr.gd b/gap/attr.gd
index 47faa5e31..ab8ffcbf8 100644
--- a/gap/attr.gd
+++ b/gap/attr.gd
@@ -87,8 +87,8 @@ DeclareAttributeThatReturnsDigraph("DigraphDual", IsDigraph);
DeclareAttributeThatReturnsDigraph("ReducedDigraph", IsDigraph);
DeclareAttributeThatReturnsDigraph("DigraphRemoveAllMultipleEdges", IsDigraph);
-# TODO replace all DeclareOperations below to DeclareAttributeThatReturnsDigraph,
-# and remove the *Attr versions.
+# TODO replace all DeclareOperations below to
+# DeclareAttributeThatReturnsDigraph, and remove the *Attr versions.
DeclareOperation("DigraphAddAllLoops", [IsDigraph]);
DeclareAttribute("DigraphAddAllLoopsAttr", IsDigraph);
diff --git a/gap/attr.gi b/gap/attr.gi
index aed31b012..c3e5bff2e 100644
--- a/gap/attr.gi
+++ b/gap/attr.gi
@@ -372,7 +372,8 @@ function(D)
fi;
od;
# Iterate over the maximal independent sets of V[S]
- subset_mis := DIGRAPHS_MaximalIndependentSetsSubtractedSet(mis, S, infinity);
+ subset_mis :=
+ DIGRAPHS_MaximalIndependentSetsSubtractedSet(mis, S, infinity);
# Flip the list, as we now need the actual set.
FlipBlist(S);
for I in subset_mis do
@@ -1673,9 +1674,9 @@ function(D, rotationSystem)
if Difference(Union(rotationSystem), DigraphVertices(D))
<> [] then
- Error("the 2nd argument (dense list ) is not a rotation",
- " system for the 1st argument (digraph ), expected the union",
- " to be ", DigraphVertices(D), " but found ",
+ Error("the 2nd argument (dense list ) is not ",
+ "a rotation system for the 1st argument (digraph ), ",
+ "expected the union to be ", DigraphVertices(D), " but found ",
Union(rotationSystem));
fi;
@@ -2953,7 +2954,8 @@ function(D)
# Ensure that InducedSubdigraph is given a digraph with vertex labels equal
# to DigraphVertices(D).
SetDigraphVertexLabels(G, DigraphVertices(G));
- G := InducedSubdigraph(G, Difference(DigraphVertices(G), DigraphLoops(G)));
+ G := InducedSubdigraph(G, Difference(DigraphVertices(G),
+ DigraphLoops(G)));
lab := DigraphVertexLabels(G);
G := DigraphSymmetricClosure(G);
mateG := DIGRAPHS_MaximalMatching(G);
diff --git a/gap/cliques.gi b/gap/cliques.gi
index 12a86617a..df7b3acd0 100644
--- a/gap/cliques.gi
+++ b/gap/cliques.gi
@@ -57,7 +57,8 @@ function(D, set)
return not ForAny(try, x -> IsEmpty(Intersection(set, nbs[x])));
end);
-InstallMethod(IsClique, "for a digraph by out-neighbours and a homogeneous list",
+InstallMethod(IsClique,
+"for a digraph by out-neighbours and a homogeneous list",
[IsDigraphByOutNeighboursRep, IsHomogeneousList],
function(D, clique)
local nbs, v;
@@ -432,7 +433,15 @@ function(arg...)
return DigraphCliquesAttr(D);
fi;
- out := CliquesFinder(D, fail, [], limit, include, exclude, false, size, false);
+ out := CliquesFinder(D,
+ fail,
+ [],
+ limit,
+ include,
+ exclude,
+ false,
+ size,
+ false);
# Store the result if appropriate (not special case due to params)
if IsEmpty(include) and IsEmpty(exclude) and limit = infinity and size = fail
and IsImmutableDigraph(D) then
@@ -550,7 +559,7 @@ function(arg...)
orbits := HashMap();
for c in cliques do
if not c in orbits then
- DIGRAPHS_AddOrbitToHashMap(G, c, orbits);
+ DIGRAPHS_AddOrbitToHashMap(G, c, OnSets, orbits);
fi;
od;
out := Keys(orbits);
@@ -709,7 +718,8 @@ function(digraph, hook, user_param, limit, include, exclude, max, size, reps)
new_found := 0;
if not clique in found_orbits then
- orbit := DIGRAPHS_AddOrbitToHashMap(group, clique, found_orbits);
+ orbit :=
+ DIGRAPHS_AddOrbitToHashMap(group, clique, OnSets, found_orbits);
n := Length(orbit);
if invariant_include and invariant_exclude then
@@ -895,7 +905,7 @@ function(D, hook, param, lim, inc, exc, max, size, reps, inc_var, exc_var)
num := num + 1;
return;
elif not c in found_orbits then
- orb := DIGRAPHS_AddOrbitToHashMap(grp, c, found_orbits);
+ orb := DIGRAPHS_AddOrbitToHashMap(grp, c, OnSets, found_orbits);
n := Length(orb);
if invariant then # we're not just looking for orbit reps, but inc and
diff --git a/gap/digraph.gi b/gap/digraph.gi
index 21ab2bae8..8cd890a3e 100644
--- a/gap/digraph.gi
+++ b/gap/digraph.gi
@@ -859,8 +859,11 @@ function(_, edges, n)
for edge in edges do
pos := pos + 1;
if not IsList(edge) then
- ErrorNoReturn("the 1st argument (list of edges) must be a list of lists, ",
- "but found ", TNAM_OBJ(edge), " in position ", pos);
+ ErrorNoReturn("the 1st argument (list of edges) must be a list of ",
+ "lists, but found ",
+ TNAM_OBJ(edge),
+ " in position ",
+ pos);
elif Length(edge) <> 2 then
ErrorNoReturn("the 1st argument (list of edges) must be a list of lists ",
"of length 2, found ", edge, " (length ", Length(edge),
diff --git a/gap/display.gi b/gap/display.gi
index b578f8d60..44db21e7f 100644
--- a/gap/display.gi
+++ b/gap/display.gi
@@ -144,11 +144,13 @@ InstallMethod(DotDigraph, "for a digraph by out-neighbours",
[IsDigraphByOutNeighboursRep],
D -> DIGRAPHS_DotDigraph(D, [], []));
-InstallMethod(DotColoredDigraph, "for a digraph by out-neighbours and two lists",
+InstallMethod(DotColoredDigraph,
+"for a digraph by out-neighbours and two lists",
[IsDigraphByOutNeighboursRep, IsList, IsList],
function(D, vert, edge)
local vert_func, edge_func;
- if DIGRAPHS_ValidVertColors(D, vert) and DIGRAPHS_ValidEdgeColors(D, edge) then
+ if DIGRAPHS_ValidVertColors(D, vert)
+ and DIGRAPHS_ValidEdgeColors(D, edge) then
vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]);
edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]);
return DIGRAPHS_DotDigraph(D, [vert_func], [edge_func]);
@@ -226,7 +228,8 @@ InstallMethod(DotSymmetricColoredDigraph,
[IsDigraphByOutNeighboursRep, IsList, IsList],
function(D, vert, edge)
local vert_func, edge_func;
- if DIGRAPHS_ValidVertColors(D, vert) and DIGRAPHS_ValidEdgeColors(D, edge) then
+ if DIGRAPHS_ValidVertColors(D, vert)
+ and DIGRAPHS_ValidEdgeColors(D, edge) then
vert_func := i -> StringFormatted("[color={}, style=filled]", vert[i]);
edge_func := {i, j} -> StringFormatted("[color={}]", edge[i][j]);
return DIGRAPHS_DotSymmetricDigraph(D, [vert_func], [edge_func]);
diff --git a/gap/examples.gi b/gap/examples.gi
index 7070e3790..b542fa6fe 100644
--- a/gap/examples.gi
+++ b/gap/examples.gi
@@ -1422,7 +1422,7 @@ InstallMethod(KneserGraphCons, "for IsMutableDigraph and two integers",
function(_, n, k)
local D, vertices, i, j;
if n < k then
- ErrorNoReturn("argument must be greater than or equal to argument ,");
+ ErrorNoReturn("argument must be greater than or equal to argument ");
fi;
vertices := Combinations([1 .. n], k);
D := EmptyDigraph(IsMutableDigraph, Length(vertices));
@@ -1467,7 +1467,8 @@ InstallMethod(KneserGraph, "for two integers", [IsPosInt, IsPosInt],
InstallMethod(KneserGraph, "for a function and two integers",
[IsFunction, IsPosInt, IsPosInt], KneserGraphCons);
-InstallMethod(LindgrenSousselierGraphCons, "for IsMutableDigraph and an integer",
+InstallMethod(LindgrenSousselierGraphCons,
+"for IsMutableDigraph and an integer",
[IsMutableDigraph, IsPosInt],
function(_, n)
local D, central, i, threei;
diff --git a/gap/grahom.gi b/gap/grahom.gi
index 07e8b7c31..c3e433f45 100644
--- a/gap/grahom.gi
+++ b/gap/grahom.gi
@@ -333,75 +333,59 @@ end);
InstallMethod(SubdigraphsMonomorphismsRepresentatives,
"for a digraph and a digraph", [IsDigraph, IsDigraph],
function(H, G)
- local GV, HN, map, reps, result, set, rep;
-
- GV := DigraphVertices(G);
- HN := DigraphNrVertices(H);
+ local AG, map, result, K, rep;
+ AG := AutomorphismGroup(G);
map := HashMap();
- reps := [];
+ result := [];
- for set in Combinations(GV, HN) do
- if not set in map then
- Add(reps, set);
- DIGRAPHS_AddOrbitToHashMap(AutomorphismGroup(G), set, map);
+ for rep in MonomorphismsDigraphsRepresentatives(H, G) do
+ K := OnSetsTuples(DigraphEdges(H), rep);
+ if not K in map then
+ Add(result, rep);
+ DIGRAPHS_AddOrbitToHashMap(AG, K, OnSetsTuples, map);
fi;
od;
- result := [];
- for rep in reps do
- map :=
- HomomorphismDigraphsFinder(H, # domain
- G, # range
- fail, # hook
- [], # user_param
- 1, # max_results
- HN, # hint (i.e. rank)
- true, # injective
- rep, # image
- [], # partial_map
- fail, # colors1
- fail, # colors2
- DigraphWelshPowellOrder(H),
- Group(()));
- if Length(map) <> 0 then
- Add(result, map[1]);
- fi;
- od;
return result;
end);
InstallMethod(SubdigraphsMonomorphisms, "for a digraph and a digraph",
[IsDigraph, IsDigraph],
function(H, G)
- local ApplyHomomorphismNC, reps, AG, result, sub, o, x, rep, i;
-
- ApplyHomomorphismNC := function(D1, D2, t)
- local old, new, v, im;
- old := OutNeighbours(D1);
- new := List([1 .. DigraphNrVertices(D2)], x -> []);
- for v in DigraphVertices(D1) do
- im := v ^ t;
- if not IsBound(new[im]) then
- new[im] := [];
- fi;
- Append(new[im], OnTuples(old[v], t));
+ local AddOrbitToHashMap, AG, map, K, rep;
+
+ AddOrbitToHashMap := function(G, set, act, hashmap, rep)
+ local gens, o, im, pt, g;
+
+ gens := GeneratorsOfGroup(G);
+ o := [set];
+ Assert(1, not set in hashmap);
+ hashmap[set] := rep;
+ for pt in o do
+ for g in gens do
+ im := act(pt, g);
+ if not im in hashmap then
+ hashmap[im] := hashmap[pt] * g;
+ # Assert(0, OnSetsTuples(set, hashmap[im]) = im);
+ Add(o, im);
+ fi;
+ od;
od;
- return DigraphNC(new);
+ return o;
end;
- reps := SubdigraphsMonomorphismsRepresentatives(H, G);
AG := AutomorphismGroup(G);
- result := [];
- for rep in reps do
- sub := ApplyHomomorphismNC(H, G, rep);
- o := Enumerate(Orb(AG, sub, OnDigraphs, rec(schreier := true)));
- for i in [1 .. Length(o)] do
- x := EvaluateWord(GeneratorsOfGroup(AG), TraceSchreierTreeForward(o, i));
- Add(result, rep * x);
- od;
+ map := HashMap();
+
+ for rep in MonomorphismsDigraphsRepresentatives(H, G) do
+ K := OnSetsTuples(DigraphEdges(H), rep);
+ if not K in map then
+ AddOrbitToHashMap(AG, K, OnSetsTuples, map, rep);
+ fi;
od;
- return result;
+
+ return Values(map);
end);
################################################################################
diff --git a/gap/io.gi b/gap/io.gi
index 383f393b4..24a986994 100644
--- a/gap/io.gi
+++ b/gap/io.gi
@@ -695,7 +695,8 @@ DigraphFromGraph6StringCons);
InstallMethod(DigraphFromGraph6String, "for a string", [IsString],
s -> DigraphFromGraph6String(IsImmutableDigraph, s));
-InstallMethod(DigraphFromDigraph6StringCons, "for IsMutableDigraph and a string",
+InstallMethod(DigraphFromDigraph6StringCons,
+"for IsMutableDigraph and a string",
[IsMutableDigraph, IsString],
function(filt, s)
local legacy, list, n, start, i, range, source, pos, len, j, bpos, tabpos;
diff --git a/gap/isomorph.gd b/gap/isomorph.gd
index 0eb05a13c..0792204a7 100644
--- a/gap/isomorph.gd
+++ b/gap/isomorph.gd
@@ -57,10 +57,14 @@ DeclareGlobalFunction("DIGRAPHS_ValidateEdgeColouring");
DeclareGlobalFunction("DIGRAPHS_CollapseMultiColouredEdges");
DeclareGlobalFunction("DIGRAPHS_CollapseMultipleEdges");
-DeclareOperation("IsDigraphAutomorphism", [IsDigraph, IsPerm]);
-DeclareOperation("IsDigraphAutomorphism", [IsDigraph, IsPerm, IsList]);
-DeclareOperation("IsDigraphAutomorphism", [IsDigraph, IsTransformation]);
-DeclareOperation("IsDigraphAutomorphism", [IsDigraph, IsTransformation, IsList]);
+DeclareOperation("IsDigraphAutomorphism",
+ [IsDigraph, IsPerm]);
+DeclareOperation("IsDigraphAutomorphism",
+ [IsDigraph, IsPerm, IsList]);
+DeclareOperation("IsDigraphAutomorphism",
+ [IsDigraph, IsTransformation]);
+DeclareOperation("IsDigraphAutomorphism",
+ [IsDigraph, IsTransformation, IsList]);
DeclareOperation("IsDigraphIsomorphism", [IsDigraph, IsDigraph, IsPerm]);
DeclareOperation("IsDigraphIsomorphism",
diff --git a/gap/orbits.gi b/gap/orbits.gi
index e1c6cbf08..257ae53f9 100644
--- a/gap/orbits.gi
+++ b/gap/orbits.gi
@@ -69,7 +69,7 @@ function(G, domain)
end);
InstallGlobalFunction(DIGRAPHS_AddOrbitToHashMap,
-function(G, set, hashmap)
+function(G, set, act, hashmap)
local gens, o, im, pt, g;
gens := GeneratorsOfGroup(G);
@@ -78,7 +78,7 @@ function(G, set, hashmap)
hashmap[set] := true;
for pt in o do
for g in gens do
- im := OnSets(pt, g);
+ im := act(pt, g);
if not im in hashmap then
hashmap[im] := true;
Add(o, im);
@@ -118,7 +118,8 @@ end);
InstallImmediateMethod(DigraphGroup, IsDigraph and HasAutomorphismGroup, 0,
DIGRAPHS_DigraphGroup);
-InstallMethod(DigraphGroup, "for a digraph", [IsDigraph], DIGRAPHS_DigraphGroup);
+InstallMethod(DigraphGroup, "for a digraph", [IsDigraph],
+DIGRAPHS_DigraphGroup);
InstallMethod(DigraphOrbits, "for a digraph",
[IsDigraph],
diff --git a/gap/weights.gd b/gap/weights.gd
index 071463c21..e2e4d530d 100644
--- a/gap/weights.gd
+++ b/gap/weights.gd
@@ -12,7 +12,8 @@
DeclareAttribute("EdgeWeights", IsDigraph);
DeclareGlobalFunction("EdgeWeightedDigraph");
DeclareProperty("IsNegativeEdgeWeightedDigraph", IsDigraph and HasEdgeWeights);
-DeclareAttribute("EdgeWeightedDigraphTotalWeight", IsDigraph and HasEdgeWeights);
+DeclareAttribute("EdgeWeightedDigraphTotalWeight",
+IsDigraph and HasEdgeWeights);
# 2. Edge Weight Copies
DeclareOperation("EdgeWeightsMutableCopy", [IsDigraph and HasEdgeWeights]);
diff --git a/gap/weights.gi b/gap/weights.gi
index 859b0d3bb..3cb37429e 100644
--- a/gap/weights.gi
+++ b/gap/weights.gi
@@ -230,7 +230,8 @@ end);
InstallMethod(EdgeWeightedDigraphShortestPaths,
"for a digraph with edge weights and known shortest paths and a pos int",
-[IsDigraph and HasEdgeWeights and HasEdgeWeightedDigraphShortestPaths, IsPosInt],
+[IsDigraph and HasEdgeWeights and HasEdgeWeightedDigraphShortestPaths,
+ IsPosInt],
function(digraph, source)
local all_paths;
if not source in DigraphVertices(digraph) then
diff --git a/tst/standard/examples.tst b/tst/standard/examples.tst
index 56d1359d5..24f780db9 100644
--- a/tst/standard/examples.tst
+++ b/tst/standard/examples.tst
@@ -629,7 +629,7 @@ gap> KneserGraph(6, 3);
gap> KneserGraph(3, 4);
-Error, argument must be greater than or equal to argument ,
+Error, argument must be greater than or equal to argument
gap> KneserGraph(3, -1);
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
Error, no 1st choice method found for `KneserGraph' on 2 arguments
diff --git a/tst/standard/grahom.tst b/tst/standard/grahom.tst
index 7b5b56b5c..68c637947 100644
--- a/tst/standard/grahom.tst
+++ b/tst/standard/grahom.tst
@@ -2762,13 +2762,13 @@ gap> IsLatticeEpimorphism(D, D, (2, 3));
true
# SubdigraphsMonomorphisms
-gap> SubdigraphsMonomorphisms(CompleteBipartiteDigraph(2, 2),
-> CompleteDigraph(4));
+gap> Set(SubdigraphsMonomorphisms(CompleteBipartiteDigraph(2, 2),
+> CompleteDigraph(4)));
[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 3, 1 ] ),
Transformation( [ 3, 4, 2, 1 ] ) ]
gap> D := DigraphFromGraph6String("D^{");
-gap> SubdigraphsMonomorphisms(CompleteDigraph(4), D);
+gap> Set(SubdigraphsMonomorphisms(CompleteDigraph(4), D));
[ Transformation( [ 1, 3, 4, 5, 5 ] ), Transformation( [ 2, 3, 4, 5, 5 ] ) ]
gap> Length(SubdigraphsMonomorphisms(CompleteDigraph(4), CompleteDigraph(12)));
495
@@ -2776,10 +2776,12 @@ gap> D := DigraphFromGraph6String("K^vMMF@oM?{@");
gap> Length(SubdigraphsMonomorphisms(CompleteMultipartiteDigraph([2, 5]), D));
252
-gap> D := DigraphFromGraph6String("O^vMMF@oM?w@o@o?w?N?@");
-
-gap> Length(SubdigraphsMonomorphisms(CompleteMultipartiteDigraph([2, 7]), D));
-3432
+
+# The next test is a bit slow
+# gap> D := DigraphFromGraph6String("O^vMMF@oM?w@o@o?w?N?@");
+#
+# gap> Length(SubdigraphsMonomorphisms(CompleteMultipartiteDigraph([2, 7]), D));
+# 3432
#
gap> H := DigraphFromGraph6String("F~CWw");
diff --git a/tst/testinstall.tst b/tst/testinstall.tst
index e7d891de3..183caf656 100644
--- a/tst/testinstall.tst
+++ b/tst/testinstall.tst
@@ -462,6 +462,12 @@ gap> C := DigraphContractEdge(D, 2, 1);
gap> DigraphEdges(C);
[ [ 2, 1 ] ]
+# Issue #704 SubdigraphsMonomorphisms bug
+gap> d := Digraph([[2, 3, 4, 5], [1, 3, 4], [1, 2, 4, 5], [1, 2, 3, 5],
+> [1, 3, 4]]);;
+gap> Length(SubdigraphsMonomorphisms(CompleteMultipartiteDigraph([2, 3]), d));
+4
+
# DIGRAPHS_UnbindVariables
gap> Unbind(C);
gap> Unbind(D);