From d802909d2e0ecf14a8bd72b48c0ac3bfb79bcf8a Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Fri, 30 Aug 2024 10:02:22 +0100 Subject: [PATCH] Add SubdigraphsMonomorphisms --- doc/grahom.xml | 212 +++++++++++++++++++++++----------------- doc/z-chap6.xml | 3 +- gap/cliques.gi | 26 +---- gap/grahom.gd | 5 + gap/grahom.gi | 73 ++++++++++++++ gap/orbits.gd | 1 + gap/orbits.gi | 20 ++++ gap/utils.gi | 3 +- tst/standard/grahom.tst | 20 ++++ 9 files changed, 246 insertions(+), 117 deletions(-) diff --git a/doc/grahom.xml b/doc/grahom.xml index 19aae9595..0d5158e0c 100644 --- a/doc/grahom.xml +++ b/doc/grahom.xml @@ -87,7 +87,7 @@ For backwards compatibility, injective can also be false or true which correspond to the values 0 and 1 - described in the previous paragraph, respectively. + described in the previous paragraph, respectively. image @@ -106,28 +106,28 @@ D1. HomomorphismDigraphsFinder only finds homomorphisms extending partial_map (if any). - + colors1 This should be a list representing possible colours of vertices in the - digraph D1; see - + digraph D1; see + for details of the permissible values for this argument. - + colors2 This should be a list representing possible colours of vertices in the - digraph D2; see - + digraph D2; see + for details of the permissible values for this argument. order The optional argument order specifies the order the - vertices in D1 appear in the search for homomorphisms. + vertices in D1 appear in the search for homomorphisms. The value of this parameter can have a large impact on the runtime of the function. It seems in many cases to be a good idea for this to be the , i.e. @@ -149,7 +149,7 @@ gap> D := DigraphSymmetricClosure(D); gap> HomomorphismDigraphsFinder(D, D, fail, [], infinity, 2, 0, > [3, 4], [], fail, fail); -[ Transformation( [ 3, 4, 3, 4, 3, 4, 3, 4, 3, 4 ] ), +[ Transformation( [ 3, 4, 3, 4, 3, 4, 3, 4, 3, 4 ] ), Transformation( [ 4, 3, 4, 3, 4, 3, 4, 3, 4, 3 ] ) ] gap> D2 := CompleteDigraph(6);; gap> HomomorphismDigraphsFinder(D, D2, fail, [], 1, fail, 0, @@ -160,20 +160,20 @@ gap> func := function(user_param, t) > end;; gap> HomomorphismDigraphsFinder(D, D2, func, [Transformation([2, 2])], > 3, fail, 0, [1 .. 6], [1, 2, 1], fail, fail); -[ Transformation( [ 2, 2 ] ), - Transformation( [ 2, 2, 2, 3, 4, 5, 6, 2, 2, 2 ] ), - Transformation( [ 2, 2, 2, 3, 4, 5, 6, 2, 2, 3 ] ), +[ Transformation( [ 2, 2 ] ), + Transformation( [ 2, 2, 2, 3, 4, 5, 6, 2, 2, 2 ] ), + Transformation( [ 2, 2, 2, 3, 4, 5, 6, 2, 2, 3 ] ), Transformation( [ 2, 2, 2, 3, 4, 5, 6, 2, 2, 4 ] ) ] gap> HomomorphismDigraphsFinder(NullDigraph(2), NullDigraph(3), fail, > [], infinity, fail, 1, [1, 2, 3], fail, fail, fail, fail, > Group(())); -[ IdentityTransformation, Transformation( [ 1, 3, 3 ] ), - Transformation( [ 2, 1 ] ), Transformation( [ 2, 3, 3 ] ), +[ IdentityTransformation, Transformation( [ 1, 3, 3 ] ), + Transformation( [ 2, 1 ] ), Transformation( [ 2, 3, 3 ] ), Transformation( [ 3, 1, 3 ] ), Transformation( [ 3, 2, 3 ] ) ] gap> HomomorphismDigraphsFinder(NullDigraph(2), NullDigraph(3), fail, > [], infinity, fail, 1, [1, 2, 3], fail, fail, fail, fail, > Group((1, 2))); -[ IdentityTransformation, Transformation( [ 1, 3, 3 ] ), +[ IdentityTransformation, Transformation( [ 1, 3, 3 ] ), Transformation( [ 3, 1, 3 ] ) ]]]> @@ -232,9 +232,9 @@ gap> gr1 := ChainDigraph(3);; gap> gr2 := Digraph([[3, 5], [2], [3, 1], [], [4]]); gap> HomomorphismsDigraphs(gr1, gr2); -[ Transformation( [ 1, 3, 1 ] ), Transformation( [ 1, 3, 3 ] ), - Transformation( [ 1, 5, 4, 4, 5 ] ), Transformation( [ 2, 2, 2 ] ), - Transformation( [ 3, 1, 3 ] ), Transformation( [ 3, 1, 5, 4, 5 ] ), +[ Transformation( [ 1, 3, 1 ] ), Transformation( [ 1, 3, 3 ] ), + Transformation( [ 1, 5, 4, 4, 5 ] ), Transformation( [ 2, 2, 2 ] ), + Transformation( [ 3, 1, 3 ] ), Transformation( [ 3, 1, 5, 4, 5 ] ), Transformation( [ 3, 3, 1 ] ), Transformation( [ 3, 3, 3 ] ) ] gap> HomomorphismsDigraphsRepresentatives(gr1, CompleteDigraph(3)); [ Transformation( [ 2, 1 ] ), Transformation( [ 2, 1, 2 ] ) ] @@ -278,7 +278,7 @@ gap> gr1 := ChainDigraph(3);; gap> gr2 := Digraph([[3, 5], [2], [3, 1], [], [4]]); gap> MonomorphismsDigraphs(gr1, gr2); -[ Transformation( [ 1, 5, 4, 4, 5 ] ), +[ Transformation( [ 1, 5, 4, 4, 5 ] ), Transformation( [ 3, 1, 5, 4, 5 ] ) ] gap> MonomorphismsDigraphsRepresentatives(gr1, CompleteDigraph(3)); [ Transformation( [ 2, 1 ] ) ] @@ -287,6 +287,34 @@ gap> MonomorphismsDigraphsRepresentatives(gr1, CompleteDigraph(3)); <#/GAPDoc> +<#GAPDoc Label="SubdigraphsMonomorphisms"> + + + + A list of transformations. + + These operations behave the same as and + , except they only return + injective homomorphisms with the following property: the (not + necessarily induced) subdigraphs defined by the images of these + monomorphisms are all of the subdigraphs of digraph2 that are + isomorphic to digraph1. Note that the subdigraphs of the previous + sentence are those obtained by applying the corresponding monomorphism to + 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)); +[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 3, 1 ] ), + Transformation( [ 3, 4, 2, 1 ] ) ] +gap> SubdigraphsMonomorphismsRepresentatives( +> CompleteBipartiteDigraph(2, 2), CompleteDigraph(4)); +[ Transformation( [ 1, 3, 2 ] ) ] +]]> + + +<#/GAPDoc> + <#GAPDoc Label="DigraphEpimorphism"> @@ -324,17 +352,17 @@ gap> gr1 := DigraphReverse(ChainDigraph(4)); gap> gr2 := DigraphSymmetricClosure(CycleDigraph(3)); gap> EpimorphismsDigraphsRepresentatives(gr1, gr2); -[ Transformation( [ 3, 1, 2, 1 ] ), Transformation( [ 3, 1, 2, 3 ] ), +[ Transformation( [ 3, 1, 2, 1 ] ), Transformation( [ 3, 1, 2, 3 ] ), Transformation( [ 2, 1, 2, 3 ] ) ] gap> EpimorphismsDigraphs(gr1, gr2); -[ Transformation( [ 1, 2, 1, 3 ] ), Transformation( [ 1, 2, 3, 1 ] ), - Transformation( [ 1, 2, 3, 2 ] ), Transformation( [ 1, 3, 1, 2 ] ), - Transformation( [ 1, 3, 2, 1 ] ), Transformation( [ 1, 3, 2, 3 ] ), - Transformation( [ 2, 1, 2, 3 ] ), Transformation( [ 2, 1, 3, 1 ] ), - Transformation( [ 2, 1, 3, 2 ] ), Transformation( [ 2, 3, 1, 2 ] ), - Transformation( [ 2, 3, 1, 3 ] ), Transformation( [ 2, 3, 2, 1 ] ), - Transformation( [ 3, 1, 2, 1 ] ), Transformation( [ 3, 1, 2, 3 ] ), - Transformation( [ 3, 1, 3, 2 ] ), Transformation( [ 3, 2, 1, 2 ] ), +[ Transformation( [ 1, 2, 1, 3 ] ), Transformation( [ 1, 2, 3, 1 ] ), + Transformation( [ 1, 2, 3, 2 ] ), Transformation( [ 1, 3, 1, 2 ] ), + Transformation( [ 1, 3, 2, 1 ] ), Transformation( [ 1, 3, 2, 3 ] ), + Transformation( [ 2, 1, 2, 3 ] ), Transformation( [ 2, 1, 3, 1 ] ), + Transformation( [ 2, 1, 3, 2 ] ), Transformation( [ 2, 3, 1, 2 ] ), + Transformation( [ 2, 3, 1, 3 ] ), Transformation( [ 2, 3, 2, 1 ] ), + Transformation( [ 3, 1, 2, 1 ] ), Transformation( [ 3, 1, 2, 3 ] ), + Transformation( [ 3, 1, 3, 2 ] ), Transformation( [ 3, 2, 1, 2 ] ), Transformation( [ 3, 2, 1, 3 ] ), Transformation( [ 3, 2, 3, 1 ] ) ] ]]> @@ -381,16 +409,16 @@ gap> EpimorphismsDigraphs(gr1, gr2); gr := Digraph(List([1 .. 3], x -> [1 .. 3]));; gap> GeneratorsOfEndomorphismMonoid(gr); -[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 1 ] ), - IdentityTransformation, Transformation( [ 1, 2, 1 ] ), - Transformation( [ 1, 2, 2 ] ), Transformation( [ 1, 1, 2 ] ), +[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 1 ] ), + IdentityTransformation, Transformation( [ 1, 2, 1 ] ), + Transformation( [ 1, 2, 2 ] ), Transformation( [ 1, 1, 2 ] ), Transformation( [ 1, 1, 1 ] ) ] gap> GeneratorsOfEndomorphismMonoid(gr, 3); -[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 1 ] ), +[ Transformation( [ 1, 3, 2 ] ), Transformation( [ 2, 1 ] ), IdentityTransformation ] gap> gr := CompleteDigraph(3);; gap> GeneratorsOfEndomorphismMonoid(gr); -[ Transformation( [ 2, 3, 1 ] ), Transformation( [ 2, 1 ] ), +[ Transformation( [ 2, 3, 1 ] ), Transformation( [ 2, 1 ] ), IdentityTransformation ] gap> GeneratorsOfEndomorphismMonoid(gr, [1, 2, 2]); [ Transformation( [ 1, 3, 2 ] ), IdentityTransformation ] @@ -423,7 +451,7 @@ gap> GeneratorsOfEndomorphismMonoid(gr, [[1], [2, 3]]); from digraph onto the complete digraph with n vertices if one exists, else it returns fail.

- See also and + See also and

Note that a digraph with at least two vertices has a 2-colouring if and only @@ -437,7 +465,7 @@ fail gap> D := ChainDigraph(10);; gap> t := DigraphColouring(D, 2); Transformation( [ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 ] ) -gap> IsDigraphColouring(D, t); +gap> IsDigraphColouring(D, t); true gap> DigraphGreedyColouring(D); Transformation( [ 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 ] ) @@ -448,42 +476,42 @@ Transformation( [ 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 ] ) <#GAPDoc Label="DigraphGreedyColouring"> - - - A transformation, or fail. A proper colouring of a digraph is a labelling of its vertices in - such a way that adjacent vertices have different labels. Note that a digraph - with loops () does not have any proper + such a way that adjacent vertices have different labels. Note that a digraph + with loops () does not have any proper colouring.

- - If digraph is a digraph and order is a dense list consisting - of all of the vertices of digraph (in any order), then + + If digraph is a digraph and order is a dense list consisting + of all of the vertices of digraph (in any order), then DigraphGreedyColouring uses a greedy algorithm with the specified order to obtain some proper colouring of digraph, which may not use the minimal number of colours.

- - If digraph is a digraph and func is a function whose argument - is a digraph, and that returns a dense list order, then + + If digraph is a digraph and func is a function whose argument + is a digraph, and that returns a dense list order, then DigraphGreedyColouring(digraph, func) returns DigraphGreedyColouring(digraph, func(digraph)).

- If the optional second argument (either a list or a function), is not - specified, then is used by default. + If the optional second argument (either a list or a function), is not + specified, then is used by default.

- + See also - .

@@ -502,14 +530,14 @@ Transformation( [ 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 ] ) A list of the vertices. - DigraphWelshPowellOrder returns a list of all of the vertices of - the digraph digraph ordered according to the sum of the number of - out- and in-neighbours, from highest to lowest. + DigraphWelshPowellOrder returns a list of all of the vertices of + the digraph digraph ordered according to the sum of the number of + out- and in-neighbours, from highest to lowest.

DigraphWelshPowellOrder(Digraph([[4], [9], [9], [], -> [4, 6, 9], [1], [], [], +gap> DigraphWelshPowellOrder(Digraph([[4], [9], [9], [], +> [4, 6, 9], [1], [], [], > [4, 5], [4, 5]])); [ 5, 9, 4, 1, 6, 10, 2, 3, 7, 8 ] ]]> @@ -567,14 +595,14 @@ gap> D2 := CycleDigraph(5); gap> EmbeddingsDigraphsRepresentatives(D1, D2); [ Transformation( [ 1, 3, 3 ] ), Transformation( [ 1, 4, 3, 4 ] ) ] gap> EmbeddingsDigraphs(D1, D2); -[ Transformation( [ 1, 3, 3 ] ), Transformation( [ 1, 4, 3, 4 ] ), - Transformation( [ 2, 4, 4, 5, 1 ] ), - Transformation( [ 2, 5, 4, 5, 1 ] ), - Transformation( [ 3, 1, 5, 1, 2 ] ), - Transformation( [ 3, 5, 5, 1, 2 ] ), - Transformation( [ 4, 1, 1, 2, 3 ] ), - Transformation( [ 4, 2, 1, 2, 3 ] ), - Transformation( [ 5, 2, 2, 3, 4 ] ), +[ Transformation( [ 1, 3, 3 ] ), Transformation( [ 1, 4, 3, 4 ] ), + Transformation( [ 2, 4, 4, 5, 1 ] ), + Transformation( [ 2, 5, 4, 5, 1 ] ), + Transformation( [ 3, 1, 5, 1, 2 ] ), + Transformation( [ 3, 5, 5, 1, 2 ] ), + Transformation( [ 4, 1, 1, 2, 3 ] ), + Transformation( [ 4, 2, 1, 2, 3 ] ), + Transformation( [ 5, 2, 2, 3, 4 ] ), Transformation( [ 5, 3, 2, 3, 4 ] ) ] ]]> @@ -583,7 +611,7 @@ gap> EmbeddingsDigraphs(D1, D2); <#GAPDoc Label="IsDigraphHomomorphism"> - EmbeddingsDigraphs(D1, D2); If col1 and col2, or col, are given, then they must - represent vertex colourings; see - + represent vertex colourings; see + for details of the permissible values for these argument. The homomorphism must then also have the property: - + col[i] = col[i ^ x] for all vertices i of digraph, @@ -647,7 +675,7 @@ gap> EmbeddingsDigraphs(D1, D2); See also . - + src := Digraph([[1], [1, 2], [1, 3]]); @@ -732,13 +760,13 @@ false]]> <#GAPDoc Label="IsDigraphColouring"> - true or false. - The operation IsDigraphColouring verifies whether or not - the list list describes a proper colouring of the digraph - digraph. + The operation IsDigraphColouring verifies whether or not + the list list describes a proper colouring of the digraph + digraph.

A list list describes a proper colouring of a digraph @@ -750,11 +778,11 @@ false]]> A transformation t describes a proper colouring of a digraph digraph, if ImageListOfTransformation(t, - DigraphNrVertices(digraph)) is a proper colouring of + DigraphNrVertices(digraph)) is a proper colouring of digraph.

See also . - + D := JohnsonDigraph(5, 3); @@ -778,7 +806,7 @@ true true or false. - The operation DigraphsRespectsColouring verifies whether or not + The operation DigraphsRespectsColouring verifies whether or not the permutation or transformation x respects the vertex colourings col1 and col2 of the digraphs src and range. That is, DigraphsRespectsColouring returns true if and only if for @@ -816,14 +844,14 @@ false MaximalCommonSubdigraph(PetersenGraph(), CompleteDigraph(10)); -[ , +[ , IdentityTransformation, IdentityTransformation ] gap> MaximalCommonSubdigraph(PetersenGraph(), > DigraphSymmetricClosure(CycleDigraph(5))); -[ , +[ , IdentityTransformation, IdentityTransformation ] gap> MaximalCommonSubdigraph(NullDigraph(0), CompleteDigraph(10)); -[ , IdentityTransformation, +[ , IdentityTransformation, IdentityTransformation ] ]]> @@ -840,22 +868,22 @@ gap> MaximalCommonSubdigraph(NullDigraph(0), CompleteDigraph(10)); M of D1 and D2 with the minimum number of vertices. So M is a digraph into which both D1 and D2 embed and has the smallest number of vertices among such digraphs. - - It returns a list [M, t1, t2] where M is the minimal common + + It returns a list [M, t1, t2] where M is the minimal common superdigraph and t1, t2 are transformations embedding D1 and D2 respectively into M. MinimalCommonSuperdigraph(PetersenGraph(), CompleteDigraph(10)); -[ , - IdentityTransformation, +[ , + IdentityTransformation, Transformation( [ 1, 2, 11, 12, 13, 14, 15, 16, 17, 18, 11, 12, 13, 14, 15, 16, 17, 18 ] ) ] gap> MinimalCommonSuperdigraph(PetersenGraph(), > DigraphSymmetricClosure(CycleDigraph(5))); -[ , +[ , IdentityTransformation, IdentityTransformation ] gap> MinimalCommonSuperdigraph(NullDigraph(0), CompleteDigraph(10)); -[ , +[ , IdentityTransformation, IdentityTransformation ] ]]> @@ -868,7 +896,7 @@ gap> MinimalCommonSuperdigraph(NullDigraph(0), CompleteDigraph(10)); A transformation, or fail. If L1 and L2 are lattice digraphs ( returns true, then + Prop="IsLatticeDigraph"/> returns true, then LatticeDigraphEmbedding returns a single injective between L1 and L2, with the property that it is a lattice homomorphism. If no such @@ -897,7 +925,7 @@ fail <#GAPDoc Label="IsLatticeHomomorphism"> - @@ -935,7 +963,7 @@ fail IsLatticeEmbedding returns true if the permutation or transformation map is an injective lattice homomorphism from the lattice digraph L1 to the lattice digraph L2. - The function IsLatticeMonomorphism is a synonym of + The function IsLatticeMonomorphism is a synonym of IsLatticeEmbedding.

diff --git a/doc/z-chap6.xml b/doc/z-chap6.xml index 71714bd61..2cbdf04ea 100644 --- a/doc/z-chap6.xml +++ b/doc/z-chap6.xml @@ -20,7 +20,7 @@ from} $E_a$ \emph{to} $E_b$. In this case we say that $E_a$ and $E_b$ are &nauty; (via &NautyTracesInterface;) to calculate canonical labellings and automorphism groups of digraphs; see and for more details about &bliss; and &nauty;, - respectively. + respectively. <#Include Label="DigraphsUseNauty"> <#Include Label="AutomorphismGroupDigraph"> @@ -65,6 +65,7 @@ from} $E_a$ \emph{to} $E_b$. In this case we say that $E_a$ and $E_b$ are <#Include Label="EmbeddingsDigraphs"> <#Include Label="IsDigraphHomomorphism"> <#Include Label="IsDigraphEmbedding"> + <#Include Label="SubdigraphsMonomorphisms"> <#Include Label="DigraphsRespectsColouring"> <#Include Label="GeneratorsOfEndomorphismMonoid"> <#Include Label="DigraphColouring"> diff --git a/gap/cliques.gi b/gap/cliques.gi index 56f58f3ca..12a86617a 100644 --- a/gap/cliques.gi +++ b/gap/cliques.gi @@ -10,26 +10,6 @@ ############################################################################# ## -BindGlobal("AddOrbitToHashMap", -function(G, set, hashmap) - local gens, o, im, pt, g; - - gens := GeneratorsOfGroup(G); - o := [set]; - Assert(1, not set in hashmap); - hashmap[set] := true; - for pt in o do - for g in gens do - im := OnSets(pt, g); - if not im in hashmap then - hashmap[im] := true; - Add(o, im); - fi; - od; - od; - return o; -end); - InstallMethod(CliqueNumber, "for a digraph", [IsDigraph], D -> Maximum(List(DigraphMaximalCliquesReps(D), Length))); @@ -570,7 +550,7 @@ function(arg...) orbits := HashMap(); for c in cliques do if not c in orbits then - AddOrbitToHashMap(G, c, orbits); + DIGRAPHS_AddOrbitToHashMap(G, c, orbits); fi; od; out := Keys(orbits); @@ -729,7 +709,7 @@ function(digraph, hook, user_param, limit, include, exclude, max, size, reps) new_found := 0; if not clique in found_orbits then - orbit := AddOrbitToHashMap(group, clique, found_orbits); + orbit := DIGRAPHS_AddOrbitToHashMap(group, clique, found_orbits); n := Length(orbit); if invariant_include and invariant_exclude then @@ -915,7 +895,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 := AddOrbitToHashMap(grp, c, found_orbits); + orb := DIGRAPHS_AddOrbitToHashMap(grp, c, found_orbits); n := Length(orb); if invariant then # we're not just looking for orbit reps, but inc and diff --git a/gap/grahom.gd b/gap/grahom.gd index 7c0b7ea41..b18ecce70 100644 --- a/gap/grahom.gd +++ b/gap/grahom.gd @@ -21,6 +21,11 @@ DeclareOperation("MonomorphismsDigraphs", [IsDigraph, IsDigraph]); DeclareOperation("MonomorphismsDigraphsRepresentatives", [IsDigraph, IsDigraph]); +DeclareOperation("SubdigraphsMonomorphismsRepresentatives", + [IsDigraph, IsDigraph]); +DeclareOperation("SubdigraphsMonomorphisms", + [IsDigraph, IsDigraph]); + DeclareOperation("DigraphEpimorphism", [IsDigraph, IsDigraph]); DeclareOperation("EpimorphismsDigraphs", [IsDigraph, IsDigraph]); DeclareOperation("EpimorphismsDigraphsRepresentatives", [IsDigraph, IsDigraph]); diff --git a/gap/grahom.gi b/gap/grahom.gi index 34a2f393d..d211c6b19 100644 --- a/gap/grahom.gi +++ b/gap/grahom.gi @@ -330,6 +330,79 @@ function(D1, D2) return Union(List(aut, x -> hom * x)); 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); + + map := HashMap(); + reps := []; + + for set in Combinations(GV, HN) do + if not set in map then + Add(reps, set); + DIGRAPHS_AddOrbitToHashMap(AutomorphismGroup(G), set, 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)); + 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)); + od; + return DigraphNC(new); + 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; + od; + return result; +end); + ################################################################################ # SURJECTIVE HOMOMORPHISMS diff --git a/gap/orbits.gd b/gap/orbits.gd index c41743131..d36b27586 100644 --- a/gap/orbits.gd +++ b/gap/orbits.gd @@ -12,6 +12,7 @@ DeclareGlobalFunction("DIGRAPHS_Orbits"); DeclareGlobalFunction("DIGRAPHS_TraceSchreierVector"); DeclareGlobalFunction("DIGRAPHS_EvaluateWord"); DeclareAttribute("DIGRAPHS_Stabilizers", IsDigraph, "mutable"); +DeclareGlobalFunction("DIGRAPHS_AddOrbitToHashMap"); DeclareAttribute("DigraphGroup", IsDigraph); DeclareAttribute("DigraphOrbits", IsDigraph); diff --git a/gap/orbits.gi b/gap/orbits.gi index eefc39e5c..e1c6cbf08 100644 --- a/gap/orbits.gi +++ b/gap/orbits.gi @@ -68,6 +68,26 @@ function(G, domain) return rec(orbits := orbs, schreier := sch, lookup := lookup); end); +InstallGlobalFunction(DIGRAPHS_AddOrbitToHashMap, +function(G, set, hashmap) + local gens, o, im, pt, g; + + gens := GeneratorsOfGroup(G); + o := [set]; + Assert(1, not set in hashmap); + hashmap[set] := true; + for pt in o do + for g in gens do + im := OnSets(pt, g); + if not im in hashmap then + hashmap[im] := true; + Add(o, im); + fi; + od; + od; + return o; +end); + InstallMethod(RepresentativeOutNeighbours, "for a digraph by out-neighbours", [IsDigraphByOutNeighboursRep], function(D) diff --git a/gap/utils.gi b/gap/utils.gi index e978cecfe..0751fd6fc 100644 --- a/gap/utils.gi +++ b/gap/utils.gi @@ -262,7 +262,8 @@ function(arg...) s := InputTextString(ex[1]); start_time := IO_gettimeofday(); - test := Test(s, rec(ignoreComments := false, + test := Test(s, rec(compareFunction := "uptowhitespace", + ignoreComments := false, width := 72, EQ := EQ, reportDiff := Ignore, diff --git a/tst/standard/grahom.tst b/tst/standard/grahom.tst index f2aea9a35..b1a3106b1 100644 --- a/tst/standard/grahom.tst +++ b/tst/standard/grahom.tst @@ -2739,6 +2739,26 @@ false gap> IsLatticeEpimorphism(D, D, (2, 3)); true +# SubdigraphsMonomorphisms +gap> 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); +[ Transformation( [ 1, 3, 4, 5, 5 ] ), Transformation( [ 2, 3, 4, 5, 5 ] ) ] +gap> Length(SubdigraphsMonomorphisms(CompleteDigraph(4), CompleteDigraph(12))); +495 +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 + # DIGRAPHS_UnbindVariables gap> Unbind(D); gap> Unbind(D1);