From dfb261276605a2f6457e43348c50c8ed1ba630cd Mon Sep 17 00:00:00 2001 From: Finn Date: Wed, 16 Mar 2022 17:33:50 +0000 Subject: [PATCH] Initial version of AmalgamDigraphs and AmalgamDigraphsIsomorphic. --- gap/oper.gd | 3 ++ gap/oper.gi | 85 +++++++++++++++++++++++++++++++++++++++++++ tst/standard/oper.tst | 35 ++++++++++++++++++ 3 files changed, 123 insertions(+) diff --git a/gap/oper.gd b/gap/oper.gd index 45c48ea3c..35caa5c31 100644 --- a/gap/oper.gd +++ b/gap/oper.gd @@ -46,6 +46,9 @@ DeclareOperation("StrongProduct", [IsDigraph, IsDigraph]); DeclareOperation("ConormalProduct", [IsDigraph, IsDigraph]); DeclareOperation("HomomorphicProduct", [IsDigraph, IsDigraph]); DeclareOperation("LexicographicProduct", [IsDigraph, IsDigraph]); +DeclareOperation("AmalgamDigraphs", [IsDigraph, IsDigraph, IsList, IsList]); +DeclareOperation("AmalgamDigraphsIsomorphic", + [IsDigraph, IsDigraph, IsList, IsList]); DeclareSynonym("DigraphModularProduct", ModularProduct); DeclareSynonym("DigraphStrongProduct", StrongProduct); diff --git a/gap/oper.gi b/gap/oper.gi index 2af8d27ac..b72c5e2f3 100644 --- a/gap/oper.gi +++ b/gap/oper.gi @@ -765,6 +765,91 @@ function(D1, D2, edge_function) return Digraph(edges); end); +InstallMethod(AmalgamDigraphsIsomorphic, +"for a digraph, a digraph, a list, and a list", +[IsDigraph, IsDigraph, IsList, IsList], +function(D1, D2, subdigraphVertices1, subdigraphVertices2) + local subdigraph1, subdigraph2, newSubdigraphVertices2, transformation, vertex; + + subdigraph1 := InducedSubdigraph(D1, subdigraphVertices1); + subdigraph2 := InducedSubdigraph(D2, subdigraphVertices2); + + if not IsIsomorphicDigraph(subdigraph1, subdigraph2) then + ErrorNoReturn( + "the two subdigraphs must be isomorphic."); + fi; + + newSubdigraphVertices2 := []; + transformation := DigraphEmbedding(subdigraph2, subdigraph1); + for vertex in subdigraphVertices2 do + newSubdigraphVertices2[ + Position(subdigraphVertices2, vertex) ^ transformation] := vertex; + od; + + return AmalgamDigraphs(D1, D2, subdigraphVertices1, newSubdigraphVertices2); +end); + +InstallMethod(AmalgamDigraphs, +"for a digraph, a digraph, a list, and a list", +[IsDigraph, IsDigraph, IsList, IsList], +function(D1, D2, subdigraphVertices1, subdigraphVertices2) + local D, map, vertex, vertexList, size, iterator, edgeList, subLength; + + if not InducedSubdigraph(D1, subdigraphVertices1) = + InducedSubdigraph(D2, subdigraphVertices2) then + ErrorNoReturn( + "the two subdigraphs must be equal."); + fi; + + # Create a mutable copy so that the function also works on + # immutable input digraphs. + D := DigraphMutableCopy(D1); + subLength := Length(subdigraphVertices1); + + # 'map' is a mapping from the vertices of D2 to the vertices of the + # final output graph. The idea is to map the subdigraph vertices of D2 + # onto the subdigraph vertices of D1 and then map the rest of the vertices + # of D2 to other (higher) values. The mapping from D1 to the output graph + # can be understood as the identity mapping. + map := rec(); + + for vertex in [1 .. subLength] do + map.(subdigraphVertices2[vertex]) := subdigraphVertices1[vertex]; + od; + + vertexList := Difference(DigraphVertices(D2), subdigraphVertices2); + size := DigraphNrVertices(D1); + iterator := 1; + for vertex in vertexList do + map.(vertex) := iterator + size; + iterator := iterator + 1; + od; + + # The problem with adding edges to the output graph was that the + # edges of of the subdigraph were added twice, creating multiple + # edges between certain pairs of points. A quick and readable fix + # would have been to use DigraphRemoveAllMultipleEdges, but I decided + # to check each of the edges being added to see if they were already + # in the subdigraph. This way the function does not end up adding edges + # only to delete them later. + edgeList := ShallowCopy(DigraphEdges(D2)); + iterator := 1; + while iterator <= Length(edgeList) do + if edgeList[iterator][1] in subdigraphVertices2 and + edgeList[iterator][2] in subdigraphVertices2 then + Remove(edgeList, iterator); + else + edgeList[iterator] := [ + map.(edgeList[iterator][1]), map.(edgeList[iterator][2])]; + iterator := iterator + 1; + fi; + od; + + DigraphAddVertices(D, DigraphNrVertices(D2) - subLength); + DigraphAddEdges(D, edgeList); + return [MakeImmutable(D), map]; +end); + ############################################################################### # 4. Actions ############################################################################### diff --git a/tst/standard/oper.tst b/tst/standard/oper.tst index 4c4aedf0a..48baca7f7 100644 --- a/tst/standard/oper.tst +++ b/tst/standard/oper.tst @@ -2757,6 +2757,41 @@ gap> path := DigraphPath(D, 5, 5);; gap> IsDigraphPath(D, path); true +# AmalgamDigraphs +gap> D1 := Digraph([[2, 3], [1, 3], [1, 2], [2], [3, 4]]);; +gap> D2 := Digraph([[2, 6], [1, 3, 5], [4], [3], [4, 6], [1, 5]]);; +gap> U := AmalgamDigraphs(D1, D2, [2, 3, 4, 5], [4, 3, 5, 2]); +[ , + rec( 1 := 6, 2 := 5, 3 := 3, 4 := 2, 5 := 4, 6 := 7 ) ] +gap> D1 := Digraph([ +> [2, 3], [1, 3, 4, 6], [1, 2, 5, 7], [2, 6], [3, 7], [2, 4, 7, 8], +> [3, 5, 6, 8], [6, 7]]);; +gap> D2 := Digraph([ +> [2, 3], [1, 4], [1, 5], [2, 5, 6], [3, 4, 7], [4, 7], [5, 6]]);; +gap> U := AmalgamDigraphs(D1, D2, [2, 3, 6, 7], [4, 5, 6, 7]); +[ , + rec( 1 := 9, 2 := 10, 3 := 11, 4 := 2, 5 := 3, 6 := 6, 7 := 7 ) ] +gap> AmalgamDigraphs(D1, D2, [3, 6, 2, 7], [4, 5, 7, 6]); +Error, the two subdigraphs must be equal. +gap> D1 := PetersenGraph();; +gap> U := AmalgamDigraphs(D1, D1, [3, 4, 6, 8, 9], [3, 4, 6, 8, 9]); +[ , + rec( 1 := 11, 10 := 15, 2 := 12, 3 := 3, 4 := 4, 5 := 13, 6 := 6, 7 := 14, + 8 := 8, 9 := 9 ) ] + +# AmalgamDigraphsIsomorphic +gap> D1 := PetersenGraph();; +gap> D2 := Digraph([ +> [2, 4], [1, 3, 4, 5], [2, 5], [1, 2, 6], [2, 3, 7], [4, 7, 8], +> [5, 6, 8], [6, 7]]);; +gap> U := AmalgamDigraphsIsomorphic(D1, D2, [3, 4, 6, 8, 9], +> [2, 4, 5, 6, 7]); +[ , + rec( 1 := 11, 2 := 3, 3 := 12, 4 := 4, 5 := 8, 6 := 9, 7 := 6, 8 := 13 ) ] +gap> U := AmalgamDigraphsIsomorphic(D1, D2, [3, 4, 10, 8, 9], +> [2, 4, 5, 6, 7]); +Error, the two subdigraphs must be isomorphic. + #DIGRAPHS_UnbindVariables gap> Unbind(a); gap> Unbind(adj);