Skip to content

Commit 155fd3e

Browse files
finnbuckwilfwilson
authored andcommitted
Introduce AmalgamDigraphs
1 parent 1231e19 commit 155fd3e

File tree

5 files changed

+350
-1
lines changed

5 files changed

+350
-1
lines changed

doc/oper.xml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,6 +2381,64 @@ true
23812381
</ManSection>
23822382
<#/GAPDoc>
23832383

2384+
<#GAPDoc Label="AmalgamDigraphs">
2385+
<ManSection>
2386+
<Oper Name="AmalgamDigraphs" Arg="D1, D2,
2387+
S[, map1[, map2]]"/>
2388+
<Returns>An immutable digraph and a transformation.</Returns>
2389+
<Description>
2390+
2391+
<C>AmalgamDigraphs</C> takes as input two digraphs <A>D1</A> and <A>D2</A>
2392+
and a digraph <A>S</A> for which there is an embedding into both
2393+
<A>D1</A> and <A>D2</A>. Additional optional arguments <A>map1</A> and
2394+
<A>map2</A> are transformation objects which can force specific
2395+
embeddings of <A>S</A> into <A>D1</A> and <A>D2</A> respectively. If
2396+
<A>map1</A> and <A>map2</A> are not given then arbitrary embeddings
2397+
will be found using <C>DigraphEmbedding</C>. If no embeddings can be found
2398+
the function will throw an error.<P/>
2399+
2400+
If <A>D1</A>, <A>D2</A> and <A>S</A> are not multidigraphs then
2401+
<C>AmalgamDigraphs</C> calculates a new digraph, the <E>amalgam digraph</E>
2402+
<M>D_A</M>. <M>D_A</M> is an amalgam of <A>D1</A> and <A>D2</A> over
2403+
<A>S</A> with respect to embeddings (where the embeddings of <A>S</A> into
2404+
<A>D1</A> and <A>D2</A> can be specified by <A>map1</A> and <A>map2</A>).
2405+
The embedding of <A>D1</A> into <M>D_A</M> is set to always be the
2406+
<C>IdentityTransformation</C>.<P/>
2407+
2408+
Note that <C>AmalgamDigraphs</C> does not necessarily return the smallest
2409+
possible digraph satisfying these properties. For examble, when
2410+
<A>D1</A> and <A>D2</A> are equal, the embedding from <A>D2</A>
2411+
to <M>D_A</M> will not be the <C>IdentityTransformation</C> and so
2412+
<M>D_A</M> could have many more vertices than the smallest possible amalgam
2413+
of <A>D1</A> and <A>D2</A> over <A>S</A>. A less formal way to picture
2414+
the exact form of <M>D_A</M> is to think of it as <A>D1</A> and <A>D2</A>
2415+
'joined together' by the common subdigraph <A>S</A>.<P/>
2416+
2417+
<C>AmalgamDigraphs</C> returns a <E>tuple</E> of size two, with the first
2418+
element being the digraph <M>A_D</M> and the second element being a
2419+
transformation object which describes the embedding of <A>D2</A> into
2420+
<M>A_D</M>.
2421+
2422+
<Example><![CDATA[
2423+
gap> D := CycleGraph(3);;
2424+
gap> S := PathGraph(2);;
2425+
gap> AmalgamDigraphs(D, D, S);
2426+
[ <immutable digraph with 4 vertices, 10 edges>,
2427+
Transformation( [ 1, 2, 4, 4 ] ) ]
2428+
gap> D1 := Digraph([[2, 3], [1, 3, 4], [1, 2, 4], [2, 3, 5], [4]]);;
2429+
gap> D2 := Digraph(
2430+
> [[2, 3], [1, 3, 4], [1, 2, 4, 5], [2, 3, 5], [3, 4]]);;
2431+
gap> S := CycleGraph(3);;
2432+
gap> map1 := Transformation([2, 4, 3, 4]);;
2433+
gap> map2 := Transformation([2, 3, 4, 4]);;
2434+
gap> AmalgamDigraphs(D1, D2, S, map1, map2);
2435+
[ <immutable digraph with 7 vertices, 20 edges>,
2436+
Transformation( [ 6, 2, 4, 3, 7, 6, 7 ] ) ]
2437+
]]></Example>
2438+
</Description>
2439+
</ManSection>
2440+
<#/GAPDoc>
2441+
23842442
<#GAPDoc Label="DigraphCycleBasis">
23852443
<ManSection>
23862444
<Oper Name="DigraphCycleBasis" Arg="digraph"/>

doc/z-chap2.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
<#Include Label="DistanceDigraph">
7676
<#Include Label="DigraphClosure">
7777
<#Include Label="DigraphMycielskian">
78+
<#Include Label="AmalgamDigraphs">
7879
</Section>
7980

8081
<Section><Heading>Random digraphs</Heading>

gap/oper.gd

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ DeclareOperation("StrongProduct", [IsDigraph, IsDigraph]);
4949
DeclareOperation("ConormalProduct", [IsDigraph, IsDigraph]);
5050
DeclareOperation("HomomorphicProduct", [IsDigraph, IsDigraph]);
5151
DeclareOperation("LexicographicProduct", [IsDigraph, IsDigraph]);
52+
DeclareOperation("AmalgamDigraphs",
53+
[IsDigraph, IsDigraph, IsDigraph,
54+
IsTransformation, IsTransformation]);
55+
DeclareOperation("AmalgamDigraphs",
56+
[IsDigraph, IsDigraph, IsDigraph, IsTransformation]);
57+
DeclareOperation("AmalgamDigraphs",
58+
[IsDigraph, IsDigraph, IsDigraph]);
5259

5360
DeclareSynonym("DigraphModularProduct", ModularProduct);
5461
DeclareSynonym("DigraphStrongProduct", StrongProduct);
@@ -58,6 +65,9 @@ DeclareSynonym("DigraphLexicographicProduct", LexicographicProduct);
5865

5966
DeclareGlobalFunction("DIGRAPHS_CombinationOperProcessArgs");
6067
DeclareOperation("DIGRAPHS_GraphProduct", [IsDigraph, IsDigraph, IsFunction]);
68+
DeclareOperation("NOCHECKS_AmalgamDigraphs",
69+
[IsDigraph, IsDigraph, IsDigraph,
70+
IsTransformation, IsTransformation]);
6171

6272
# 4. Actions . . .
6373
DeclareOperation("OnDigraphs", [IsDigraph, IsPerm]);

gap/oper.gi

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,170 @@ function(D1, D2, edge_function)
989989
return Digraph(edges);
990990
end);
991991

992+
InstallMethod(AmalgamDigraphs,
993+
"for a digraph, a digraph, a digraph, a transformation, and a transformation",
994+
[IsDigraph, IsDigraph, IsDigraph, IsTransformation, IsTransformation],
995+
function(D1, D2, S, map1, map2)
996+
local D, n, imageList1, imageList2, map, edge, T;
997+
998+
if IsMultiDigraph(D1) then
999+
ErrorNoReturn(
1000+
"the 1st argument (a digraph) must not satisfy IsMultiDigraph");
1001+
elif IsMultiDigraph(D2) then
1002+
ErrorNoReturn(
1003+
"the 2nd argument (a digraph) must not satisfy IsMultiDigraph");
1004+
elif IsMultiDigraph(S) then
1005+
ErrorNoReturn(
1006+
"the 3rd argument (a digraph) must not satisfy IsMultiDigraph");
1007+
fi;
1008+
1009+
if not IsDigraphEmbedding(S, D1, map1) then
1010+
ErrorNoReturn(
1011+
"the 4th argument (a transformation) is not ",
1012+
"a digraph embedding from the 3rd argument (a digraph) into ",
1013+
"the 1st argument (a digraph)");
1014+
fi;
1015+
if not IsDigraphEmbedding(S, D2, map2) then
1016+
ErrorNoReturn(
1017+
"the 5th argument (a transformation) is not ",
1018+
"a digraph embedding from the 3rd argument (a digraph) into ",
1019+
"the 2nd argument (a digraph)");
1020+
fi;
1021+
1022+
# Create a mutable copy so that the function also works if
1023+
# D1 is immutable. If D1 is a mutable digraph then
1024+
# D1 will be changed in place.
1025+
D := DigraphMutableCopyIfImmutable(D1);
1026+
1027+
n := DigraphNrVertices(D2) + DigraphNrVertices(D1) - DigraphNrVertices(S);
1028+
1029+
# 'map' is an embedding of D2 into the final output graph.
1030+
# The embedding of D1 into the final output graph is the identity mapping.
1031+
1032+
map := [1 .. n];
1033+
1034+
imageList1 := OnTuples([1 .. DigraphNrVertices(S)], map1);
1035+
imageList2 := OnTuples([1 .. DigraphNrVertices(S)], map2);
1036+
1037+
map{imageList2} := imageList1;
1038+
map{Difference(DigraphVertices(D2), imageList2)} :=
1039+
[DigraphNrVertices(D1) + 1 .. n];
1040+
1041+
T := Transformation(map);
1042+
1043+
DigraphAddVertices(D, DigraphNrVertices(D2) - DigraphNrVertices(S));
1044+
1045+
for edge in DigraphEdges(D2) do
1046+
if not (edge[1] in imageList2
1047+
and edge[2] in imageList2) then
1048+
DigraphAddEdge(D, [edge[1] ^ T, edge[2] ^ T]);
1049+
fi;
1050+
od;
1051+
1052+
return [MakeImmutable(D), T];
1053+
end);
1054+
1055+
InstallMethod(AmalgamDigraphs,
1056+
"for a digraph, a digraph, a digraph, and a transformation",
1057+
[IsDigraph, IsDigraph, IsDigraph, IsTransformation],
1058+
function(D1, D2, S, map1)
1059+
local map2;
1060+
1061+
if IsMultiDigraph(D1) then
1062+
ErrorNoReturn(
1063+
"the 1st argument (a digraph) must not satisfy IsMultiDigraph");
1064+
elif IsMultiDigraph(D2) then
1065+
ErrorNoReturn(
1066+
"the 2nd argument (a digraph) must not satisfy IsMultiDigraph");
1067+
elif IsMultiDigraph(S) then
1068+
ErrorNoReturn(
1069+
"the 3rd argument (a digraph) must not satisfy IsMultiDigraph");
1070+
fi;
1071+
1072+
if not IsDigraphEmbedding(S, D1, map1) then
1073+
ErrorNoReturn(
1074+
"the 4th argument (a transformation) is not ",
1075+
"a digraph embedding from the 3rd argument (a digraph) into ",
1076+
"the 1st argument (a digraph)");
1077+
fi;
1078+
1079+
map2 := DigraphEmbedding(S, D2);
1080+
if map2 = fail then
1081+
ErrorNoReturn(
1082+
"no embeddings could be found from the 3rd argument ",
1083+
"(a digraph) to the 2nd argument (a digraph)");
1084+
fi;
1085+
1086+
return NOCHECKS_AmalgamDigraphs(D1, D2, S, map1, map2);
1087+
end);
1088+
1089+
InstallMethod(AmalgamDigraphs,
1090+
"for a digraph, a digraph, and a digraph",
1091+
[IsDigraph, IsDigraph, IsDigraph],
1092+
function(D1, D2, S)
1093+
local map1, map2;
1094+
1095+
if IsMultiDigraph(D1) then
1096+
ErrorNoReturn(
1097+
"the 1st argument (a digraph) must not satisfy IsMultiDigraph");
1098+
elif IsMultiDigraph(D2) then
1099+
ErrorNoReturn(
1100+
"the 2nd argument (a digraph) must not satisfy IsMultiDigraph");
1101+
elif IsMultiDigraph(S) then
1102+
ErrorNoReturn(
1103+
"the 3rd argument (a digraph) must not satisfy IsMultiDigraph");
1104+
fi;
1105+
1106+
map1 := DigraphEmbedding(S, D1);
1107+
if map1 = fail then
1108+
ErrorNoReturn(
1109+
"no embeddings could be found from the 3rd argument ",
1110+
"(a digraph) to the 1st argument (a digraph)");
1111+
fi;
1112+
1113+
map2 := DigraphEmbedding(S, D2);
1114+
if map2 = fail then
1115+
ErrorNoReturn(
1116+
"no embeddings could be found from the 3rd argument ",
1117+
"(a digraph) to the 2nd argument (a digraph)");
1118+
fi;
1119+
1120+
return NOCHECKS_AmalgamDigraphs(D1, D2, S, map1, map2);
1121+
end);
1122+
1123+
InstallMethod(NOCHECKS_AmalgamDigraphs,
1124+
"for a digraph, a digraph, a digraph, a transformation, and a transformation",
1125+
[IsDigraph, IsDigraph, IsDigraph, IsTransformation, IsTransformation],
1126+
function(D1, D2, S, map1, map2)
1127+
local D, n, imageList1, imageList2, map, edge, T;
1128+
1129+
D := DigraphMutableCopyIfImmutable(D1);
1130+
1131+
n := DigraphNrVertices(D2) + DigraphNrVertices(D1) - DigraphNrVertices(S);
1132+
1133+
map := [1 .. n];
1134+
1135+
imageList1 := OnTuples([1 .. DigraphNrVertices(S)], map1);
1136+
imageList2 := OnTuples([1 .. DigraphNrVertices(S)], map2);
1137+
1138+
map{imageList2} := imageList1;
1139+
map{Difference(DigraphVertices(D2), imageList2)} :=
1140+
[DigraphNrVertices(D1) + 1 .. n];
1141+
1142+
T := Transformation(map);
1143+
1144+
DigraphAddVertices(D, DigraphNrVertices(D2) - DigraphNrVertices(S));
1145+
1146+
for edge in DigraphEdges(D2) do
1147+
if not (edge[1] in imageList2
1148+
and edge[2] in imageList2) then
1149+
DigraphAddEdge(D, [edge[1] ^ T, edge[2] ^ T]);
1150+
fi;
1151+
od;
1152+
1153+
return [MakeImmutable(D), T];
1154+
end);
1155+
9921156
###############################################################################
9931157
# 4. Actions
9941158
###############################################################################

tst/standard/oper.tst

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#############################################################################
1010
##
1111

12-
#@local C, D, D1, D2, D3, D3_edges, DD
12+
#@local C, D, D1, D2, D3, D3_edges, DD, S, T, map1, map2
1313
#@local G, G1, L, TestPartialOrderDigraph
1414
#@local TestPartialOrderDigraph2, TestUnion, a, adj, b, comps, copy, d, e
1515
#@local edges, edges2, func, g, gr, gr1, gr2, gr3, gr4, gri, grrt, grt, h, i
@@ -2869,6 +2869,122 @@ gap> D := CycleDigraph(5);;
28692869
gap> IsOrderIdeal(D, [1]);
28702870
Error, the 1st argument (a digraph) must be a partial order digraph
28712871

2872+
# AmalgamDigraphs
2873+
gap> D1 := Digraph([[2, 3], [1, 3], [1, 2], [2], [3, 4]]);;
2874+
gap> D2 := Digraph([[2, 6], [1, 3, 5], [4], [3], [4, 6], [1, 5]]);;
2875+
gap> S := InducedSubdigraph(D1, [2, 3, 4, 5]);;
2876+
gap> T := DigraphEmbedding(S, D2);;
2877+
gap> AmalgamDigraphs(D2, D1, S, T);
2878+
[ <immutable digraph with 7 vertices, 15 edges>,
2879+
Transformation( [ 7, 4, 3, 5, 2, 6, 7 ] ) ]
2880+
gap> AmalgamDigraphs(D1, D2, S, IdentityTransformation, T);
2881+
Error, the 4th argument (a transformation) is not a digraph embedding from the\
2882+
3rd argument (a digraph) into the 1st argument (a digraph)
2883+
gap> D1 := Digraph([
2884+
> [2, 3], [1, 3, 4, 6], [1, 2, 5, 7], [2, 6], [3, 7], [2, 4, 7, 8],
2885+
> [3, 5, 6, 8], [6, 7]]);;
2886+
gap> D2 := Digraph([
2887+
> [2, 3], [1, 4], [1, 5], [2, 5, 6], [3, 4, 7], [4, 7], [5, 6]]);;
2888+
gap> S := InducedSubdigraph(D1, [2, 3, 6, 7]);;
2889+
gap> T := DigraphEmbedding(S, D1);;
2890+
gap> AmalgamDigraphs(D1, D2, S, T, IdentityTransformation);
2891+
Error, the 5th argument (a transformation) is not a digraph embedding from the\
2892+
3rd argument (a digraph) into the 2nd argument (a digraph)
2893+
gap> D1 := Digraph([[2, 5], [1, 3], [4], [2, 5], [1, 4]]);;
2894+
gap> D2 := Digraph([[2, 3], [1, 4], [1, 2], [3]]);;
2895+
gap> S := Digraph([[2], [3], [1]]);;
2896+
gap> map1 := DigraphEmbedding(S, D1);;
2897+
gap> map2 := DigraphEmbedding(S, D2);;
2898+
gap> AmalgamDigraphs(D1, D2, S, map1, map2);
2899+
[ <immutable digraph with 6 vertices, 13 edges>,
2900+
Transformation( [ 6, 2, 4, 3, 5, 6 ] ) ]
2901+
gap> D1 := DigraphImmutableCopy(D1);
2902+
<immutable digraph with 5 vertices, 9 edges>
2903+
gap> AmalgamDigraphs(D1, D2, S, map1, map2);
2904+
[ <immutable digraph with 6 vertices, 13 edges>,
2905+
Transformation( [ 6, 2, 4, 3, 5, 6 ] ) ]
2906+
gap> D1 := DigraphMutableCopy(D1);
2907+
<mutable digraph with 5 vertices, 9 edges>
2908+
gap> AmalgamDigraphs(D1, D2, S, map1, map2);
2909+
[ <immutable digraph with 6 vertices, 13 edges>,
2910+
Transformation( [ 6, 2, 4, 3, 5, 6 ] ) ]
2911+
gap> D1;
2912+
<immutable digraph with 6 vertices, 13 edges>
2913+
gap> D1 := Digraph([[2, 5], [1, 3], [4], [2, 5], [1, 4]]);;
2914+
gap> D2 := DigraphMutableCopy(D2);
2915+
<mutable digraph with 4 vertices, 7 edges>
2916+
gap> AmalgamDigraphs(D1, D2, S, map1, map2);
2917+
[ <immutable digraph with 6 vertices, 13 edges>,
2918+
Transformation( [ 6, 2, 4, 3, 5, 6 ] ) ]
2919+
gap> D2;
2920+
<mutable digraph with 4 vertices, 7 edges>
2921+
gap> D1 := DigraphImmutableCopy(D1);
2922+
<immutable digraph with 5 vertices, 9 edges>
2923+
gap> AmalgamDigraphs(D1, D2, S, map1, map2);
2924+
[ <immutable digraph with 6 vertices, 13 edges>,
2925+
Transformation( [ 6, 2, 4, 3, 5, 6 ] ) ]
2926+
gap> D1 := PetersenGraph();;
2927+
gap> D2 := Digraph([[], [1, 3, 4], [1, 2, 5], [2, 6], [3, 6], [4, 5]]);;
2928+
gap> S := CycleGraph(5);;
2929+
gap> AmalgamDigraphs(D1, D2, S, IdentityTransformation);
2930+
[ <immutable digraph with 11 vertices, 32 edges>,
2931+
Transformation( [ 11, 1, 2, 5, 3, 4, 7, 8, 9, 10, 11 ] ) ]
2932+
gap> AmalgamDigraphs(D1, D2, S);
2933+
[ <immutable digraph with 11 vertices, 32 edges>,
2934+
Transformation( [ 11, 1, 2, 5, 3, 4, 7, 8, 9, 10, 11 ] ) ]
2935+
gap> D1 := Digraph([[2], [3, 4], [1], [1]]);;
2936+
gap> D2 := Digraph([[3], [1], [2, 4, 5], [], []]);;
2937+
gap> S := Digraph([[2], [3], [1]]);;
2938+
gap> map1 := Transformation([1, 2, 4, 4]);;
2939+
gap> map2 := Transformation([2, 1]);;
2940+
gap> AmalgamDigraphs(D1, D2, S, map1, map2);
2941+
[ <immutable digraph with 6 vertices, 7 edges>,
2942+
Transformation( [ 2, 1, 4, 5, 6, 6 ] ) ]
2943+
gap> AmalgamDigraphs(D1, D2, S, map1);
2944+
[ <immutable digraph with 6 vertices, 7 edges>,
2945+
Transformation( [ 1, 4, 2, 5, 6, 6 ] ) ]
2946+
gap> AmalgamDigraphs(D1, D2, S);
2947+
[ <immutable digraph with 6 vertices, 7 edges>,
2948+
Transformation( [ 1, 3, 2, 5, 6, 6 ] ) ]
2949+
gap> AmalgamDigraphs(D1, D2, S, Transformation([3, 2, 1]));
2950+
Error, the 4th argument (a transformation) is not a digraph embedding from the\
2951+
3rd argument (a digraph) into the 1st argument (a digraph)
2952+
gap> AmalgamDigraphs(D1, D2, D1, IdentityTransformation);
2953+
Error, no embeddings could be found from the 3rd argument (a digraph) to the 2\
2954+
nd argument (a digraph)
2955+
gap> AmalgamDigraphs(D1, D2, D1);
2956+
Error, no embeddings could be found from the 3rd argument (a digraph) to the 2\
2957+
nd argument (a digraph)
2958+
gap> AmalgamDigraphs(D1, D2, D2);
2959+
Error, no embeddings could be found from the 3rd argument (a digraph) to the 1\
2960+
st argument (a digraph)
2961+
gap> D1 := Digraph([[2, 3, 3], [3], []]);;
2962+
gap> D2 := Digraph([[2, 3], [3, 4], [4], []]);;
2963+
gap> S := Digraph([[2, 3], [3], []]);;
2964+
gap> AmalgamDigraphs(D1, D2, S);
2965+
Error, the 1st argument (a digraph) must not satisfy IsMultiDigraph
2966+
gap> AmalgamDigraphs(D1, D2, S, IdentityTransformation);
2967+
Error, the 1st argument (a digraph) must not satisfy IsMultiDigraph
2968+
gap> AmalgamDigraphs(
2969+
> D1, D2, S, IdentityTransformation, IdentityTransformation);
2970+
Error, the 1st argument (a digraph) must not satisfy IsMultiDigraph
2971+
gap> AmalgamDigraphs(D2, D1, S);
2972+
Error, the 2nd argument (a digraph) must not satisfy IsMultiDigraph
2973+
gap> AmalgamDigraphs(D2, D1, S, IdentityTransformation);
2974+
Error, the 2nd argument (a digraph) must not satisfy IsMultiDigraph
2975+
gap> AmalgamDigraphs(
2976+
> D2, D1, S, IdentityTransformation, IdentityTransformation);
2977+
Error, the 2nd argument (a digraph) must not satisfy IsMultiDigraph
2978+
gap> D1 := PetersenGraph();;
2979+
gap> S := Digraph([[2], [3, 3], [1]]);;
2980+
gap> AmalgamDigraphs(D1, D1, S);
2981+
Error, the 3rd argument (a digraph) must not satisfy IsMultiDigraph
2982+
gap> AmalgamDigraphs(D1, D1, S, IdentityTransformation);
2983+
Error, the 3rd argument (a digraph) must not satisfy IsMultiDigraph
2984+
gap> AmalgamDigraphs(
2985+
> D1, D1, S, IdentityTransformation, IdentityTransformation);
2986+
Error, the 3rd argument (a digraph) must not satisfy IsMultiDigraph
2987+
28722988
# IsOrderFilter
28732989
gap> D := DigraphByEdges([[1, 1], [1, 2], [1, 3], [2, 3], [3, 3], [2, 2], [2, 4], [4, 4], [1, 4]]);
28742990
<immutable digraph with 4 vertices, 9 edges>

0 commit comments

Comments
 (0)