Skip to content

Commit f5e6563

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

File tree

6 files changed

+354
-5
lines changed

6 files changed

+354
-5
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
###############################################################################

src/digraphs.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,10 +1359,10 @@ static Obj FuncDIGRAPH_REFLEX_TRANS_CLOSURE(Obj self, Obj digraph) {
13591359
}
13601360

13611361
static Obj FuncRANDOM_DIGRAPH(Obj self, Obj nn, Obj pp) {
1362-
UInt n, i, j;
1363-
Double p, q;
1364-
Int len;
1365-
Obj adj, adji;
1362+
UInt n, i, j;
1363+
Double p, q;
1364+
Int len;
1365+
Obj adj, adji;
13661366

13671367
n = INT_INTOBJ(nn);
13681368
p = VAL_MACFLOAT(pp);

0 commit comments

Comments
 (0)