Skip to content

Commit 28b1ae9

Browse files
finnbuckjames-d-mitchell
authored andcommitted
oper: add various graph products
1 parent dd79ecb commit 28b1ae9

File tree

6 files changed

+440
-28
lines changed

6 files changed

+440
-28
lines changed

doc/oper.xml

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,7 +1932,7 @@ gap> DigraphDijkstra(D, 1, 2);
19321932
<Description>
19331933
If <A>D1</A> and <A>D2</A> are digraphs without multiple edges, then
19341934
<C>ModularProduct</C> calculates the <E>modular product digraph</E>
1935-
(<C>MPD</C>) of <A>D1</A>and <A>D2</A>.
1935+
(<C>MPD</C>) of <A>D1</A> and <A>D2</A>.
19361936

19371937
<C>MPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
19381938
<A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
@@ -1958,7 +1958,8 @@ gap> ModularProduct(Digraph([[1], [1, 2]]), Digraph([[], [2]]));
19581958
<immutable digraph with 4 vertices, 4 edges>
19591959
gap> OutNeighbours(last);
19601960
[ [ 4 ], [ 2, 3 ], [ ], [ 4 ] ]
1961-
gap> ModularProduct(PetersenGraph(), DigraphSymmetricClosure(CycleDigraph(5)));
1961+
gap> ModularProduct(PetersenGraph(),
1962+
> DigraphSymmetricClosure(CycleDigraph(5)));
19621963
<immutable digraph with 50 vertices, 950 edges>
19631964
gap> ModularProduct(NullDigraph(0), CompleteDigraph(10));
19641965
<immutable empty digraph with 0 vertices>
@@ -1967,6 +1968,164 @@ gap> ModularProduct(NullDigraph(0), CompleteDigraph(10));
19671968
</ManSection>
19681969
<#/GAPDoc>
19691970

1971+
<#GAPDoc Label="StrongProduct">
1972+
<ManSection>
1973+
<Oper Name="StrongProduct" Arg="D1, D2"/>
1974+
<Returns>A digraph.</Returns>
1975+
<Description>
1976+
If <A>D1</A> and <A>D2</A> are digraphs without multiple edges,
1977+
then <C>StrongProduct</C> calculates the <E>strong product digraph</E>
1978+
(<C>SPD</C>) of <A>D1</A> and <A>D2</A>.
1979+
1980+
<C>SPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
1981+
<A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
1982+
<C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the output). There is
1983+
an edge from <C>[a, b]</C> to <C>[c, d]</C> when at least one of the
1984+
following three conditions are satisfied:
1985+
<List>
1986+
<Item>
1987+
The vertices <C>a</C> and <C>c</C> of <A>D1</A> are equal and there is
1988+
an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
1989+
</Item>
1990+
<Item>
1991+
The vertices <C>b</C> and <C>d</C> of <A>D2</A> are equal and there is
1992+
an edge from <C>a</C> to <C>c</C> in <A>D1</A>.
1993+
</Item>
1994+
<Item>
1995+
There is an edge from <C>a</C> to <C>c</C> in <A>D1</A> and there is
1996+
an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
1997+
</Item>
1998+
</List>
1999+
2000+
The SPD of two paths of lengths <C>m</C> and <C>n</C> is also the king's graph
2001+
for an <C>m</C> by <C>n</C> board.
2002+
2003+
<Example><![CDATA[
2004+
gap> D1 := Digraph([[2], [1, 3, 4], [2, 5], [2, 5], [3, 4]]);
2005+
<immutable digraph with 5 vertices, 10 edges>
2006+
gap> D2 := Digraph([[2], [1, 3, 4], [2], [2]]);
2007+
<immutable digraph with 4 vertices, 6 edges>
2008+
gap> StrongProduct(D1, D2);
2009+
<immutable digraph with 20 vertices, 130 edges>
2010+
gap> StrongProduct(DigraphSymmetricClosure(ChainDigraph(3)),
2011+
> DigraphSymmetricClosure(ChainDigraph(4)));
2012+
<immutable digraph with 12 vertices, 58 edges>
2013+
]]></Example>
2014+
</Description>
2015+
</ManSection>
2016+
<#/GAPDoc>
2017+
2018+
<#GAPDoc Label="ConormalProduct">
2019+
<ManSection>
2020+
<Oper Name="ConormalProduct" Arg="D1, D2"/>
2021+
<Returns>A digraph.</Returns>
2022+
<Description>
2023+
If <A>D1</A> and <A>D2</A> are digraphs without multiple edges,
2024+
then <C>ConormalProduct</C> calculates the <E>co-normal product digraph</E>
2025+
(<C>CNPD</C>) of <A>D1</A> and <A>D2</A>.
2026+
2027+
<C>CNPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
2028+
<A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
2029+
<C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the output). There is
2030+
an edge from <C>[a, b]</C> to <C>[c, d]</C> when at least one of the
2031+
following two conditions are satisfied:
2032+
<List>
2033+
<Item>
2034+
There is an edge from <C>a</C> to <C>c</C> in <A>D1</A>.
2035+
</Item>
2036+
<Item>
2037+
There is an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
2038+
</Item>
2039+
</List>
2040+
2041+
<Example><![CDATA[
2042+
gap> ConormalProduct(DigraphSymmetricClosure(CycleDigraph(7)),
2043+
> DigraphSymmetricClosure(CycleDigraph(4)));
2044+
<immutable digraph with 28 vertices, 504 edges>
2045+
gap> ConormalProduct(NullDigraph(0), CompleteDigraph(10));
2046+
<immutable empty digraph with 0 vertices>
2047+
]]></Example>
2048+
</Description>
2049+
</ManSection>
2050+
<#/GAPDoc>
2051+
2052+
<#GAPDoc Label="HomomorphicProduct">
2053+
<ManSection>
2054+
<Oper Name="HomomorphicProduct" Arg="D1, D2"/>
2055+
<Returns>A digraph.</Returns>
2056+
<Description>
2057+
If <A>D1</A> and <A>D2</A> are digraphs without multiple edges,
2058+
then <C>HomomorphicProduct</C> calculates the <E>homomorphic product digraph</E>
2059+
(<C>HPD</C>) of <A>D1</A> and <A>D2</A>.
2060+
2061+
<C>HPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
2062+
<A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
2063+
<C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the output). There is
2064+
an edge from <C>[a, b]</C> to <C>[c, d]</C> when at least one of the
2065+
following two conditions are satisfied:
2066+
<List>
2067+
<Item>
2068+
The vertices <C>a</C> and <C>c</C> of <A>D1</A> are equal.
2069+
</Item>
2070+
<Item>
2071+
There is an edge from <C>a</C> to <C>c</C> in <A>D1</A> and no edge from
2072+
<C>b</C> to <C>d</C> in <A>D2</A>.
2073+
</Item>
2074+
</List>
2075+
2076+
<Example><![CDATA[
2077+
gap> HomomorphicProduct(PetersenGraph(),
2078+
> DigraphSymmetricClosure(ChainDigraph(4)));
2079+
<immutable digraph with 40 vertices, 460 edges>
2080+
gap> D1 := Digraph([[2], [1, 3, 4], [2, 5], [2, 5], [3, 4]]);
2081+
<immutable digraph with 5 vertices, 10 edges>
2082+
gap> D2 := Digraph([[2], [1, 3], [2, 4], [3]]);
2083+
<immutable digraph with 4 vertices, 6 edges>
2084+
gap> HomomorphicProduct(D1, D2);
2085+
<immutable digraph with 20 vertices, 180 edges>
2086+
]]></Example>
2087+
</Description>
2088+
</ManSection>
2089+
<#/GAPDoc>
2090+
2091+
<#GAPDoc Label="LexicographicProduct">
2092+
<ManSection>
2093+
<Oper Name="LexicographicProduct" Arg="D1, D2"/>
2094+
<Returns>A digraph.</Returns>
2095+
<Description>
2096+
If <A>D1</A> and <A>D2</A> are digraphs without multiple edges,
2097+
then <C>LexicographicProduct</C> calculates the <E>lexicographic product digraph</E>
2098+
(<C>LPD</C>) of <A>D1</A> and <A>D2</A>.
2099+
2100+
<C>LPD</C> has vertex set <C>V1 x V2</C> where <C>V1</C> is the vertex set of
2101+
<A>D1</A> and <C>V2</C> is the vertex set of <A>D2</A> (a vertex
2102+
<C>[a, b]</C> has label <C>(a - 1) * |V2| + b</C> in the output). There is
2103+
an edge from <C>[a, b]</C> to <C>[c, d]</C> when at least one of the
2104+
following two conditions are satisfied:
2105+
<List>
2106+
<Item>
2107+
There is an edge from <C>a</C> to <C>c</C> in <A>D1</A>.
2108+
</Item>
2109+
<Item>
2110+
The vertices <C>a</C> and <C>c</C> of <A>D1</A> are equal and there is
2111+
an edge from <C>b</C> to <C>d</C> in <A>D2</A>.
2112+
</Item>
2113+
</List>
2114+
2115+
<Example><![CDATA[
2116+
gap> LexicographicProduct(DigraphSymmetricClosure(CycleDigraph(3)),
2117+
> DigraphSymmetricClosure(ChainDigraph(2)));
2118+
<immutable digraph with 6 vertices, 30 edges>
2119+
gap> OutNeighbours(last);
2120+
[ [ 2, 3, 4, 5, 6 ], [ 1, 3, 4, 5, 6 ], [ 1, 2, 4, 5, 6 ],
2121+
[ 1, 2, 3, 5, 6 ], [ 1, 2, 3, 4, 6 ], [ 1, 2, 3, 4, 5 ] ]
2122+
gap> LexicographicProduct(NullDigraph(0), CompleteDigraph(10));
2123+
<immutable empty digraph with 0 vertices>
2124+
]]></Example>
2125+
</Description>
2126+
</ManSection>
2127+
<#/GAPDoc>
2128+
19702129
<#GAPDoc Label="NewDFSRecord">
19712130
<ManSection>
19722131
<Oper Name="NewDFSRecord" Arg="digraph"/>

doc/z-chap2.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@
5959
<#Include Label="DigraphJoin">
6060
<#Include Label="DigraphCartesianProduct">
6161
<#Include Label="DigraphDirectProduct">
62+
<#Include Label="ConormalProduct">
63+
<#Include Label="HomomorphicProduct">
64+
<#Include Label="LexicographicProduct">
65+
<#Include Label="ModularProduct">
66+
<#Include Label="StrongProduct">
6267
<#Include Label="DigraphCartesianProductProjections">
6368
<#Include Label="DigraphDirectProductProjections">
6469
<#Include Label="LineDigraph">

gap/oper.gd

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,19 @@ DeclareGlobalFunction("DigraphEdgeUnion");
4242
DeclareGlobalFunction("DigraphCartesianProduct");
4343
DeclareGlobalFunction("DigraphDirectProduct");
4444
DeclareOperation("ModularProduct", [IsDigraph, IsDigraph]);
45+
DeclareOperation("StrongProduct", [IsDigraph, IsDigraph]);
46+
DeclareOperation("ConormalProduct", [IsDigraph, IsDigraph]);
47+
DeclareOperation("HomomorphicProduct", [IsDigraph, IsDigraph]);
48+
DeclareOperation("LexicographicProduct", [IsDigraph, IsDigraph]);
49+
50+
DeclareSynonym("DigraphModularProduct", ModularProduct);
51+
DeclareSynonym("DigraphStrongProduct", StrongProduct);
52+
DeclareSynonym("DigraphConormalProduct", ConormalProduct);
53+
DeclareSynonym("DigraphHomomorphicProduct", HomomorphicProduct);
54+
DeclareSynonym("DigraphLexicographicProduct", LexicographicProduct);
4555

4656
DeclareGlobalFunction("DIGRAPHS_CombinationOperProcessArgs");
57+
DeclareOperation("DIGRAPHS_GraphProduct", [IsDigraph, IsDigraph, IsFunction]);
4758

4859
# 4. Actions . . .
4960
DeclareOperation("OnDigraphs", [IsDigraph, IsPerm]);

gap/oper.gi

Lines changed: 130 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -616,46 +616,152 @@ end);
616616
InstallMethod(ModularProduct, "for a digraph and digraph",
617617
[IsDigraph, IsDigraph],
618618
function(D1, D2)
619-
local m, n, E1, E2, edges, next, map, u, v, w, x;
619+
local edge_function;
620+
621+
edge_function := function(u, v, m, n, map)
622+
local w, x, connections;
623+
connections := [];
624+
for w in OutNeighbours(D1)[u] do
625+
for x in OutNeighbours(D2)[v] do
626+
if (u = w) = (v = x) then
627+
Add(connections, map(w, x));
628+
fi;
629+
od;
630+
od;
631+
for w in OutNeighbours(DigraphDual(D1))[u] do
632+
for x in OutNeighbours(DigraphDual(D2))[v] do
633+
if (u = w) = (v = x) then
634+
Add(connections, map(w, x));
635+
fi;
636+
od;
637+
od;
638+
return connections;
639+
end;
640+
641+
return DIGRAPHS_GraphProduct(D1, D2, edge_function);
642+
end);
643+
644+
InstallMethod(StrongProduct, "for a digraph and digraph",
645+
[IsDigraph, IsDigraph],
646+
function(D1, D2)
647+
local edge_function;
648+
649+
edge_function := function(u, v, m, n, map)
650+
local w, x, connections;
651+
connections := [];
652+
for x in OutNeighbours(D2)[v] do
653+
AddSet(connections, map(u, x));
654+
for w in OutNeighbours(D1)[u] do
655+
AddSet(connections, map(w, x));
656+
od;
657+
od;
658+
for w in OutNeighbours(D1)[u] do
659+
AddSet(connections, map(w, v));
660+
od;
661+
return connections;
662+
end;
663+
664+
return DIGRAPHS_GraphProduct(D1, D2, edge_function);
665+
end);
666+
667+
InstallMethod(ConormalProduct, "for a digraph and digraph",
668+
[IsDigraph, IsDigraph],
669+
function(D1, D2)
670+
local edge_function;
671+
672+
edge_function := function(u, v, m, n, map)
673+
local w, x, connections;
674+
connections := [];
675+
for w in OutNeighbours(D1)[u] do
676+
for x in [1 .. n] do
677+
AddSet(connections, map(w, x));
678+
od;
679+
od;
680+
for x in OutNeighbours(D2)[v] do
681+
for w in [1 .. m] do
682+
AddSet(connections, map(w, x));
683+
od;
684+
od;
685+
return connections;
686+
end;
687+
688+
return DIGRAPHS_GraphProduct(D1, D2, edge_function);
689+
end);
620690

621-
if IsMultiDigraph(D1) or IsMultiDigraph(D2) then
622-
ErrorNoReturn("ModularProduct does not support multidigraphs,");
691+
InstallMethod(HomomorphicProduct, "for a digraph and digraph",
692+
[IsDigraph, IsDigraph],
693+
function(D1, D2)
694+
local edge_function;
695+
696+
edge_function := function(u, v, m, n, map)
697+
local w, x, connections;
698+
connections := [];
699+
for x in [1 .. n] do
700+
AddSet(connections, map(u, x));
701+
od;
702+
for w in OutNeighbours(D1)[u] do
703+
for x in OutNeighbours(DigraphDual(D2))[v] do
704+
AddSet(connections, map(w, x));
705+
od;
706+
od;
707+
return connections;
708+
end;
709+
710+
return DIGRAPHS_GraphProduct(D1, D2, edge_function);
711+
end);
712+
713+
InstallMethod(LexicographicProduct, "for a digraph and digraph",
714+
[IsDigraph, IsDigraph],
715+
function(D1, D2)
716+
local edge_function;
717+
718+
edge_function := function(u, v, m, n, map)
719+
local w, x, connections;
720+
connections := [];
721+
for w in OutNeighbours(D1)[u] do
722+
for x in [1 .. n] do
723+
AddSet(connections, map(w, x));
724+
od;
725+
od;
726+
for x in OutNeighbours(D2)[v] do
727+
AddSet(connections, map(u, x));
728+
od;
729+
return connections;
730+
end;
731+
732+
return DIGRAPHS_GraphProduct(D1, D2, edge_function);
733+
end);
734+
735+
InstallMethod(DIGRAPHS_GraphProduct,
736+
"for a digraph, a digraph, and a function",
737+
[IsDigraph, IsDigraph, IsFunction],
738+
function(D1, D2, edge_function)
739+
local m, n, edges, u, v, map;
740+
741+
if IsMultiDigraph(D1) then
742+
ErrorNoReturn(
743+
"the 1st argument (a digraph) must not satisfy IsMultiDigraph");
744+
elif IsMultiDigraph(D2) then
745+
ErrorNoReturn(
746+
"the 2nd argument (a digraph) must not satisfy IsMultiDigraph");
623747
fi;
624748

625749
m := DigraphNrVertices(D1);
626750
n := DigraphNrVertices(D2);
627751

628-
E1 := DigraphDual(D1);
629-
E2 := DigraphDual(D2);
630-
631752
edges := EmptyPlist(m * n);
632-
next := 0;
633753

634754
map := function(a, b)
635755
return (a - 1) * n + b;
636756
end;
637757

638758
for u in [1 .. m] do
639759
for v in [1 .. n] do
640-
next := next + 1;
641-
edges[next] := [];
642-
for w in OutNeighbours(D1)[u] do
643-
for x in OutNeighbours(D2)[v] do
644-
if (u = w) = (v = x) then
645-
Add(edges[next], map(w, x));
646-
fi;
647-
od;
648-
od;
649-
for w in OutNeighbours(E1)[u] do
650-
for x in OutNeighbours(E2)[v] do
651-
if (u = w) = (v = x) then
652-
Add(edges[next], map(w, x));
653-
fi;
654-
od;
655-
od;
760+
edges[map(u, v)] := edge_function(u, v, m, n, map);
656761
od;
657762
od;
658-
return DigraphNC(edges);
763+
764+
return Digraph(edges);
659765
end);
660766

661767
###############################################################################

0 commit comments

Comments
 (0)