Skip to content

Commit 28946b8

Browse files
Add Min/MaximalCommonSubdigraph
1 parent e097454 commit 28946b8

File tree

5 files changed

+185
-0
lines changed

5 files changed

+185
-0
lines changed

doc/grahom.xml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,3 +798,66 @@ false
798798
</Description>
799799
</ManSection>
800800
<#/GAPDoc>
801+
802+
<#GAPDoc Label="MaximalCommonSubdigraph">
803+
<ManSection>
804+
<Oper Name="MaximalCommonSubdigraph" Arg="D1, D2"/>
805+
<Returns>A list containing a digraph and two transformations.</Returns>
806+
<Description>
807+
If <A>D1</A> and <A>D2</A> are digraphs without multiple edges, then
808+
<C>MaximalCommonSubdigraph</C> returns a maximal common subgraph <C>M</C> of
809+
<A>D1</A> and <A>D2</A> with the maximum number of vertices. So <C>M</C> is a
810+
digraph which embeds into both <A>D1</A> and <A>D2</A> and has the largest
811+
number of vertices amoung such digraphs.
812+
813+
It returns a list <C>[M, t1, t2]</C> where <C>M</C> is the maximal common
814+
subdigraph and <C>t1, t2</C> are transformations embedding <C>M</C> into
815+
<A>D1</A> and <A>D2</A> respectively.
816+
817+
<Example><![CDATA[
818+
gap> MaximalCommonSubdigraph(PetersenGraph(), CompleteDigraph(10));
819+
[ <immutable digraph with 2 vertices, 2 edges>,
820+
IdentityTransformation, IdentityTransformation ]
821+
gap> MaximalCommonSubdigraph(PetersenGraph(),
822+
> DigraphSymmetricClosure(CycleDigraph(5)));
823+
[ <immutable digraph with 5 vertices, 10 edges>,
824+
IdentityTransformation, IdentityTransformation ]
825+
gap> MaximalCommonSubdigraph(NullDigraph(0), CompleteDigraph(10));
826+
[ <immutable empty digraph with 0 vertices>, IdentityTransformation,
827+
IdentityTransformation ]
828+
]]></Example>
829+
</Description>
830+
</ManSection>
831+
<#/GAPDoc>
832+
833+
<#GAPDoc Label="MinimalCommonSuperdigraph">
834+
<ManSection>
835+
<Oper Name="MinimalCommonSuperdigraph" Arg="D1, D2"/>
836+
<Returns>A list containing a digraph and two transformations.</Returns>
837+
<Description>
838+
If <A>D1</A> and <A>D2</A> are digraphs without multiple edges, then
839+
<C>MinimalCommonSuperdigraph</C> returns a minimal common superdigraph
840+
<C>M</C> of <A>D1</A> and <A>D2</A> with the minimum number of vertices.
841+
So <C>M</C> is a digraph into which both <A>D1</A> and <A>D2</A> embed and
842+
has the smallest number of vertices amoung such digraphs.
843+
844+
It returns a list <C>[M, t1, t2]</C> where <C>M</C> is the minimal common
845+
superdigraph and <C>t1, t2</C> are transformations embedding <A>D1</A> and
846+
<A>D2</A> respectively into <C>M</C>.
847+
<Example><![CDATA[
848+
gap> MinimalCommonSuperdigraph(PetersenGraph(), CompleteDigraph(10));
849+
[ <immutable digraph with 18 vertices, 118 edges>,
850+
IdentityTransformation,
851+
Transformation( [ 1, 2, 11, 12, 13, 14, 15, 16, 17, 18, 11, 12, 13,
852+
14, 15, 16, 17, 18 ] ) ]
853+
gap> MinimalCommonSuperdigraph(PetersenGraph(),
854+
> DigraphSymmetricClosure(CycleDigraph(5)));
855+
[ <immutable digraph with 10 vertices, 30 edges>,
856+
IdentityTransformation, IdentityTransformation ]
857+
gap> MinimalCommonSuperdigraph(NullDigraph(0), CompleteDigraph(10));
858+
[ <immutable digraph with 10 vertices, 90 edges>,
859+
IdentityTransformation, IdentityTransformation ]
860+
]]></Example>
861+
</Description>
862+
</ManSection>
863+
<#/GAPDoc>

doc/z-chap6.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ from} $E_a$ \emph{to} $E_b$. In this case we say that $E_a$ and $E_b$ are
4242
<#Include Label="RepresentativeOutNeighbours">
4343
<#Include Label="IsDigraphAutomorphism">
4444
<#Include Label="IsDigraphColouring">
45+
<#Include Label="MaximalCommonSubdigraph">
46+
<#Include Label="MinimalCommonSuperdigraph">
4547
</Section>
4648

4749
<Section><Heading>Homomorphisms of digraphs</Heading>

gap/grahom.gd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,6 @@ DeclareOperation("DigraphsRespectsColouring",
9292
[IsDigraph, IsDigraph, IsTransformation, IsList, IsList]);
9393
DeclareOperation("DigraphsRespectsColouring",
9494
[IsDigraph, IsDigraph, IsPerm, IsList, IsList]);
95+
96+
DeclareOperation("MaximalCommonSubdigraph", [IsDigraph, IsDigraph]);
97+
DeclareOperation("MinimalCommonSuperdigraph", [IsDigraph, IsDigraph]);

gap/grahom.gi

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,80 @@ function(D, t)
678678
n := DigraphNrVertices(D);
679679
return IsDigraphColouring(D, ImageListOfTransformation(t, n));
680680
end);
681+
682+
InstallMethod(MaximalCommonSubdigraph, "for a pair of digraphs",
683+
[IsDigraph, IsDigraph],
684+
function(A, B)
685+
local D1, D2, MPG, nonloops, Clqus, M, l, n, m, embedding1, embedding2, iso;
686+
687+
D1 := DigraphImmutableCopy(A);
688+
D2 := DigraphImmutableCopy(B);
689+
690+
# If the digraphs are isomorphic then we return the first one as the answer
691+
iso := IsomorphismDigraphs(D1, D2);
692+
if iso <> fail then
693+
return [D1, IdentityTransformation, AsTransformation(iso)];
694+
fi;
695+
696+
n := DigraphNrVertices(D1);
697+
m := DigraphNrVertices(D2);
698+
699+
# The algorithm works as follows: We construct the modular product digraph
700+
# MPG (see https://en.wikipedia.org/wiki/Modular_product_of_graphs for the
701+
# undirected version) a maximal partial isomorphism between D1 and D2 is
702+
# equal to a maximal clique this digraph. We then search for cliques using the
703+
# DigraphMaximalCliquesReps function.
704+
705+
MPG := ModularProduct(D1, D2);
706+
707+
nonloops := Filtered([1 .. n * m], x -> not x in OutNeighbours(MPG)[x]);
708+
# We find a big clique
709+
Clqus := DigraphMaximalCliquesReps(MPG, [], nonloops);
710+
M := 1;
711+
for l in [1 .. Size(Clqus)] do
712+
if Size(Clqus[l]) > Size(Clqus[M]) then
713+
M := l;
714+
fi;
715+
od;
716+
717+
embedding1 := List(Clqus[M], x -> QuoInt(x - 1, m) + 1);
718+
embedding2 := List(Clqus[M], x -> RemInt(x - 1, m) + 1);
719+
return [InducedSubdigraph(D1, embedding1),
720+
Transformation([1 .. Size(embedding1)], embedding1),
721+
Transformation([1 .. Size(embedding2)], embedding2)];
722+
723+
end);
724+
725+
InstallMethod(MinimalCommonSuperdigraph, "for a pair of digraphs",
726+
[IsDigraph, IsDigraph],
727+
function(D1, D2)
728+
local out, L, v, e, embfunc, embedding1, embedding2, newvertices;
729+
L := MaximalCommonSubdigraph(D1, D2);
730+
L[2] := List([1 .. DigraphNrVertices(L[1])], x -> x ^ L[2]);
731+
L[3] := List([1 .. DigraphNrVertices(L[1])], x -> x ^ L[3]);
732+
out := List(OutNeighbours(D1), x -> ShallowCopy(x));
733+
newvertices := Filtered(DigraphVertices(D2), x -> not x in L[3]);
734+
embedding1 := [1 .. DigraphNrVertices(D1)];
735+
736+
embfunc := function(v)
737+
if v in L[3] then
738+
return L[2][Position(L[3], v)];
739+
fi;
740+
return Position(newvertices, v) + DigraphNrVertices(D1);
741+
end;
742+
embedding2 := List(DigraphVertices(D2), embfunc);
743+
744+
for v in newvertices do
745+
Add(out, []);
746+
od;
747+
748+
for e in DigraphEdges(D2) do
749+
if (not e[1] in L[3]) or (not e[2] in L[3]) then
750+
Add(out[embedding2[e[1]]], embedding2[e[2]]);
751+
fi;
752+
od;
753+
754+
return [Digraph(out), Transformation([1 .. Size(embedding1)], embedding1),
755+
Transformation([1 .. Size(embedding2)], embedding2)];
756+
757+
end);

tst/standard/grahom.tst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,6 +2453,46 @@ false
24532453
gap> IsDigraphEmbedding(ran, src, (), [2, 1], [1, 1, 2]);
24542454
false
24552455

2456+
# MaximalCommSubdigraph and MinimalCommonSuperDigraph
2457+
gap> MaximalCommonSubdigraph(NullDigraph(0), CompleteDigraph(10));
2458+
[ <immutable empty digraph with 0 vertices>, IdentityTransformation,
2459+
IdentityTransformation ]
2460+
gap> MinimalCommonSuperdigraph(NullDigraph(0), CompleteDigraph(10));
2461+
[ <immutable digraph with 10 vertices, 90 edges>, IdentityTransformation,
2462+
IdentityTransformation ]
2463+
gap> MaximalCommonSubdigraph(PetersenGraph(), CompleteDigraph(10));
2464+
[ <immutable digraph with 2 vertices, 2 edges>, IdentityTransformation,
2465+
IdentityTransformation ]
2466+
gap> MinimalCommonSuperdigraph(PetersenGraph(), CompleteDigraph(10));
2467+
[ <immutable digraph with 18 vertices, 118 edges>, IdentityTransformation,
2468+
Transformation( [ 1, 2, 11, 12, 13, 14, 15, 16, 17, 18, 11, 12, 13, 14, 15,
2469+
16, 17, 18 ] ) ]
2470+
gap> MaximalCommonSubdigraph(NullDigraph(10), CompleteDigraph(10));
2471+
[ <immutable empty digraph with 1 vertex>, IdentityTransformation,
2472+
IdentityTransformation ]
2473+
gap> MinimalCommonSuperdigraph(NullDigraph(10), CompleteDigraph(10));
2474+
[ <immutable digraph with 19 vertices, 90 edges>, IdentityTransformation,
2475+
Transformation( [ 1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 11, 12, 13, 14, 15,
2476+
16, 17, 18, 19 ] ) ]
2477+
gap> MaximalCommonSubdigraph(CompleteDigraph(100), CompleteDigraph(100));
2478+
[ <immutable digraph with 100 vertices, 9900 edges>, IdentityTransformation,
2479+
IdentityTransformation ]
2480+
gap> MinimalCommonSuperdigraph(CompleteDigraph(100), CompleteDigraph(100));
2481+
[ <immutable digraph with 100 vertices, 9900 edges>, IdentityTransformation,
2482+
IdentityTransformation ]
2483+
gap> MaximalCommonSubdigraph(PetersenGraph(),
2484+
> DigraphSymmetricClosure(CycleDigraph(5)));
2485+
[ <immutable digraph with 5 vertices, 10 edges>, IdentityTransformation,
2486+
IdentityTransformation ]
2487+
gap> MinimalCommonSuperdigraph(PetersenGraph(),
2488+
> DigraphSymmetricClosure(CycleDigraph(5)));
2489+
[ <immutable digraph with 10 vertices, 30 edges>, IdentityTransformation,
2490+
IdentityTransformation ]
2491+
gap> MaximalCommonSubdigraph(Digraph([[1, 1]]), Digraph([[1]]));
2492+
Error, ModularProduct does not support multidigraphs,
2493+
gap> MinimalCommonSuperdigraph(Digraph([[1, 1]]), Digraph([[1]]));
2494+
Error, ModularProduct does not support multidigraphs,
2495+
24562496
# DIGRAPHS_UnbindVariables
24572497
gap> Unbind(edges);
24582498
gap> Unbind(epis);

0 commit comments

Comments
 (0)