Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3fd587f
Added SwapDigraphs and DigraphsRemoveAllEdges functions
rm387 Oct 1, 2025
6a61490
Fixed gaplint errors
rm387 Oct 1, 2025
b27b696
Changes made to SwapDigraphs and DigraphRemoveAllEdges
rm387 Oct 6, 2025
96bdfed
Changes made to DigraphRemoveAllEdges
rm387 Oct 8, 2025
e7544b9
More changes made to DigraphRemoveAllEdges
rm387 Oct 8, 2025
b9f0043
DigraphEdgeConnectivity and additional functions (Dominating Set func…
rm387 Nov 19, 2025
5e5f9a2
Added explanations for each Algorithm and edited gapdocs + tests for …
rm387 Nov 21, 2025
92d5afe
Minor gaplint/test changes made
rm387 Nov 26, 2025
44dc104
Added DigraphEdgeConnectivityDS tests to weights.tst
rm387 Nov 29, 2025
d2e455c
Added tests for DigraphDominatingSet()
rm387 Nov 29, 2025
cd04338
Fixes made to Spanning Tree Algorithm + tests added to weights.tst
rm387 Dec 1, 2025
a3aa6a8
Tests added to testinstall.tst for DigraphEdgeConnectivityDS()
rm387 Dec 3, 2025
960abd9
Removing Spanning Tree Algorithm
rm387 Dec 3, 2025
c01c2f1
Documentation changes + some DigraphsDominatingSet implementation cha…
rm387 Dec 10, 2025
5bb3381
Removing DigraphsOutNeighbourhood
rm387 Dec 10, 2025
3a82b72
Changing DigraphEdgeConnectivity and associated tests to work only fo…
rm387 Jan 28, 2026
9b4fb41
Move EdgeConnectivity to attr
reiniscirpons May 28, 2026
72ff633
Small formatting fixes etc
reiniscirpons May 28, 2026
eb631e0
Improve wording a little
reiniscirpons May 28, 2026
2e91f32
Factor out dominating set and add it as attr
reiniscirpons Aug 26, 2026
335415c
Finish adding tests for dominating set
reiniscirpons Sep 9, 2026
03569c7
Add more tests for EdgeConnectivity, fix mutability bug
reiniscirpons Sep 23, 2026
b544566
Add docs
reiniscirpons Sep 23, 2026
34abdf9
Fix minor issue with testinstall
reiniscirpons Sep 23, 2026
c3f4897
Comments from review
reiniscirpons Oct 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions doc/attr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2703,6 +2703,47 @@ gap> Length(M);
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="AttrDigraphGreedyOutDominatingSet">
<ManSection>
<Attr Name="DigraphGreedyOutDominatingSet" Arg="digraph"/>
<Attr Name="DigraphGreedyInDominatingSet" Arg="digraph"/>
<Returns>A list of positive integers</Returns>
<Description>
<C>DigraphGreedyOutDominatingSet</C> returns the unique <E>greedy
out-dominating set</E> of <A>digraph</A> with respect to the ordering
<M>1 &lt; 2 &lt; ... &lt; n</M> where <M>n</M> is the number of vertices in
<A>digraph</A>. An <E>out-dominating set</E> is a subset <M>S</M> of
vertices of <A>digraph</A> such that every vertex of <A>digraph</A> is
either in <M>S</M> or an out-neighbour of a vertex in <M>S</M>. Such a
set is <E>greedy</E>, if it is obtained by starting with an empty set
<M>S</M> and repeatedly adding to <M>S</M> the least vertex that is not
in <M>S</M> and not and out-neighbour of <M>S</M>.

See also <Ref Oper="IsDigraphOutDominatingSet"/> for further
information on dominating sets, and <Ref
Oper="DigraphGreedyOutDominatingSet"/> for a version of this function
that finds a greedy out-dominating set with respect to an arbitrary
ordering on vertices.

Similarly, <C>DigraphGreedyInDominatingSet</C> returns the unique <E>greedy
in-dominating set</E> of <A>digraph</A> with respect to the ordering
<M>1 &lt; 2 &lt; ... &lt; n</M> where <M>n</M> is the number of vertices in
<A>digraph</A>. This is equivalently the greedy out-dominating set of
the <Ref Attr="DigraphReverse"/> of <A>digraph</A>.

See also <Ref Oper="IsDigraphInDominatingSet"/> and <Ref
Oper="DigraphGreedyInDominatingSet"/>.
<Example><![CDATA[
gap> D := Digraph([[2, 4], [3], [1, 5], [3], [4]]);;
gap> A := DigraphGreedyOutDominatingSet(D);
[ 1, 3 ]
gap> A := DigraphGreedyInDominatingSet(D);
[ 1, 2, 4 ]
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphVertexConnectivity">
<ManSection>
<Attr Name="DigraphVertexConnectivity" Arg="digraph"/>
Expand Down Expand Up @@ -2778,6 +2819,40 @@ gap> DigraphVertexConnectivity(CompleteDigraph(5));
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphEdgeConnectivity">
<ManSection>
<Attr Name="DigraphEdgeConnectivity" Arg="digraph"/>
<Returns>An integer</Returns>
<Description>
This function returns the edge connectivity of a symmetric digraph
<A>digraph</A>.<P/>

The edge connectivity of a symmetric digraph is the size <M>k</M> of the
smallest set of edges whose removal would make the digraph disconnected
(in the sense of <Ref Prop="IsConnectedDigraph"/>).<P/>

The implementation makes use of the
<C>DigraphMaximumFlow(<A>digraph</A>)</C> function, assuming each edge has
weight 1, then using the max-flow min-cut theorem to determine the size of
the minimum cut. See also <Ref Attr="DigraphMaximumFlow"/>.<P/>

The edge connectivity of any symmetric bridgeless digraph is at least 2.
See also <Ref Prop="IsBridgelessDigraph"/>.
<Example><![CDATA[
gap> d := Digraph([[4], [4], [4], [1, 2, 3]]);;
gap> DigraphEdgeConnectivity(d);
1
gap> D := RandomDigraph(1);;
gap> DigraphEdgeConnectivity(D);
0
gap> d := Digraph([[2, 3], [1, 4], [1, 4], [2, 3]]);;
gap> DigraphEdgeConnectivity(d);
2
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="NonUpperSemimodularPair">
<ManSection>
<Attr Name="NonUpperSemimodularPair" Arg="D"/>
Expand Down
86 changes: 86 additions & 0 deletions doc/oper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1954,6 +1954,92 @@ rec( idom := [ 2, fail, 2, 2, 2 ], preorder := [ 2, 1, 3, 4, 5 ] )
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDigraphOutDominatingSet">
<ManSection>
<Oper Name="IsDigraphOutDominatingSet" Arg="digraph, list"/>
<Oper Name="IsDigraphInDominatingSet" Arg="digraph, list"/>
<Returns><K>true</K> or <K>false</K>.</Returns>
<Description>
If <A>digraph</A> is a digraph and <A>list</A> is a strictly sorted list of
vertices of <A>digraph</A>, then <C>IsDigraphOutDominatingSet</C>
returns <K>true</K> if <A>list</A> is an out-dominating set of <A>digraph</A>.
Similarly, the operation <C>IsDigraphInDominatingSet</C> returns <K>true</K>
if <A>list</A> is an in-dominating set of <A>digraph</A>.
Otherwise, each of these operations return <K>false</K>.
<P/>

An <E>out-dominating set</E> of <A>digraph</A> is a subset <M>S</M> of
vertices of <A>digraph</A> such that every vertex of <A>digraph</A> is
either in <M>S</M> or an out-neighbour of a vertex in <M>S</M>.
An <E>in-dominating set</E> of <A>digraph</A> is a subset <M>S</M> of
vertices of <A>digraph</A> such that every vertex of <A>digraph</A> is
either in <M>S</M> or an in-neighbour of a vertex in <M>S</M>.

<Example><![CDATA[
gap> D := Digraph([[2, 4], [3], [1, 5], [3], [4]]);;
gap> IsDigraphOutDominatingSet(D, [1, 3]);
true
gap> IsDigraphOutDominatingSet(D, [1, 3, 5]);
true
gap> IsDigraphOutDominatingSet(D, [3, 5]);
false
gap> IsDigraphOutDominatingSet(D, [3, 1, 5, 2, 4]);
false
gap> IsDigraphInDominatingSet(D, [3, 4]);
true
gap> IsDigraphInDominatingSet(D, [1, 3, 5]);
true
gap> IsDigraphInDominatingSet(D, [3, 5]);
false
gap> IsDigraphInDominatingSet(D, [3, 1, 5, 2, 4]);
false
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="OperDigraphGreedyOutDominatingSet">
<ManSection>
<Oper Name="DigraphGreedyOutDominatingSet" Arg="digraph, order"/>
<Oper Name="DigraphGreedyInDominatingSet" Arg="digraph, order"/>
<Returns>A list of positive integers</Returns>
<Description>
<C>DigraphGreedyOutDominatingSet</C> returns the unique <E>greedy
out-dominating set</E> of <A>digraph</A> with respect to the ordering
that the list <A>order</A> induced on the vertices in
<A>digraph</A>. An <E>out-dominating set</E> is a subset <M>S</M> of
vertices of <A>digraph</A> such that every vertex of <A>digraph</A> is
either in <M>S</M> or an out-neighbour of a vertex in <M>S</M>. Such a
set is <E>greedy</E>, if it is obtained by starting with an empty set
<M>S</M> and repeatedly adding to <M>S</M> the least (with respect to the
ordering <A>order</A>) vertex that is not in <M>S</M> and not and
out-neighbour of <M>S</M>.

See also <Ref Oper="IsDigraphOutDominatingSet"/> for further
information on dominating sets, and <Ref
Attr="DigraphGreedyOutDominatingSet"/> for the attribute version of this
function that finds a greedy out-dominating set with respect to the
ordering <M>1 &lt; 2 &lt; ... &lt; n </M> on the vertices of <A>digraph</A>.

Similarly, <C>DigraphGreedyInDominatingSet</C> returns the unique <E>greedy
in-dominating set</E> of <A>digraph</A> with respect to the ordering
that the list <A>order</A> induces on the vertices in
<A>digraph</A>. This is equivalently the greedy out-dominating set of
the <Ref Attr="DigraphReverse"/> of <A>digraph</A>.

See also <Ref Oper="IsDigraphInDominatingSet"/> and <Ref
Attr="DigraphGreedyInDominatingSet"/>.
<Example><![CDATA[
gap> D := Digraph([[2, 4], [3], [1, 5], [3], [4]]);;
gap> DigraphGreedyOutDominatingSet(D, [2, 1, 3, 4, 5]);
[ 1, 2, 5 ]
gap> DigraphGreedyInDominatingSet(D, [5, 1, 3, 4, 2]);
[ 1, 2, 4, 5 ]
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="PartialOrderDigraphMeetOfVertices">
<ManSection>
<Oper Name="PartialOrderDigraphMeetOfVertices"
Expand Down
4 changes: 4 additions & 0 deletions doc/z-chap4.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
<#Include Label="DigraphAbsorptionExpectedSteps">
<#Include Label="Dominators">
<#Include Label="DominatorTree">
<#Include Label="IsDigraphOutDominatingSet">
<#Include Label="AttrDigraphGreedyOutDominatingSet">
<#Include Label="OperDigraphGreedyOutDominatingSet">
<#Include Label="IteratorOfPaths">
<#Include Label="DigraphAllSimpleCircuits">
<#Include Label="DigraphLongestSimpleCircuit">
Expand All @@ -89,6 +92,7 @@
<#Include Label="NrSpanningTrees">
<#Include Label="DigraphDijkstra">
<#Include Label="DigraphVertexConnectivity">
<#Include Label="DigraphEdgeConnectivity">
<#Include Label="DigraphCycleBasis">
<#Include Label="DigraphIsKing">
<#Include Label="DigraphKings">
Expand Down
4 changes: 4 additions & 0 deletions gap/attr.gd
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ DeclareAttribute("DigraphCore", IsDigraph);
DeclareAttribute("CharacteristicPolynomial", IsDigraph);
DeclareAttribute("NrSpanningTrees", IsDigraph);
DeclareAttribute("DigraphVertexConnectivity", IsDigraph);
DeclareAttribute("DigraphEdgeConnectivity", IsDigraph);

# AsGraph must be mutable for grape to function properly
DeclareAttribute("AsGraph", IsDigraph, "mutable");
Expand Down Expand Up @@ -135,6 +136,9 @@ DeclareAttribute("DigraphMaximumMatching", IsDigraph);
DeclareAttribute("Bridges", IsDigraph);
DeclareAttributeThatReturnsDigraph("StrongOrientation", IsDigraph);

DeclareAttribute("DigraphGreedyOutDominatingSet", IsDigraph);
DeclareAttribute("DigraphGreedyInDominatingSet", IsDigraph);

DeclareAttribute("NonUpperSemimodularPair", IsDigraph);
DeclareAttribute("NonLowerSemimodularPair", IsDigraph);

Expand Down
137 changes: 137 additions & 0 deletions gap/attr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -3504,6 +3504,143 @@ function(D)
return kappa_min;
end);

#############################################################################
# Digraph Edge Connectivity
#############################################################################

# Algorithms constructed off the algorithms detailed in:
# https://www.cse.msu.edu/~cse835/Papers/Graph_connectivity_revised.pdf
# Each Algorithm uses a different method to decrease the time complexity,
# of calculating Edge Connectivity, though all make use of DigraphMaximumFlow()
# due to the Max-Flow, Min-Cut Theorem

# Algorithm 1: Calculating the Maximum Flow of every possible source and sink
# Algorithm 2: Calculating the Maximum Flow to all sinks of an arbitrary source
# Algorithm 3: Finding Maximum Flow within the non-leaves of a Spanning Tree
# Algorithm 4: Constructing a spanning tree with a high number of leaves
# Algorithm 5: Using the spanning tree^ to find Maximum Flow within non-leaves
# Algorithm 6: Finding Maximum Flow within a dominating set of the digraph
# Algorithm 7: Constructing a dominating set for use in Algorithm 6

# This function computes the greedy dominating set for the subdigraph
# of a digraph induced by a set of vertices. The neighbour_fun function
# determines if in or out-edges are used. Pass OutNeighboursOfVertex
# for out-edges and InNeighboursOfVertex for in-edges.
#
# In other words, we find a subset S of the vertices in the parameter vertices
# such that every vertex in vertices is in S or adjacent to a vertex in S. This
# is done in a greedy manner by including every vertex in vertices in order, if
# it is not already adjacent to some vertex in the current dominating set. The
# vertices are processed in the same order as they occur in the parameter
# vertices.
#
# Implements Algorithm 7 in :
# https://www.cse.msu.edu/~cse835/Papers/Graph_connectivity_revised.pdf
BindGlobal("DIGRAPHS_GreedyDominatingSet",
function(digraph, vertices, neighbour_fun)
local S, seen, neighbour, vertex;

Assert(1,
neighbour_fun = OutNeighboursOfVertex or
neighbour_fun = InNeighboursOfVertex);

seen := BlistList(DigraphVertices(digraph), []);
S := [];
for vertex in vertices do
if not seen[vertex] then
seen[vertex] := true;
Add(S, vertex);
for neighbour in neighbour_fun(digraph, vertex) do
seen[neighbour] := true;
od;
fi;
od;

return S;
end);

InstallMethod(DigraphGreedyOutDominatingSet, "for a digraph", [IsDigraph],
digraph ->
DIGRAPHS_GreedyDominatingSet(
digraph,
DigraphVertices(digraph),
OutNeighboursOfVertex));

InstallMethod(DigraphGreedyInDominatingSet, "for a digraph", [IsDigraph],
digraph ->
DIGRAPHS_GreedyDominatingSet(
digraph,
DigraphVertices(digraph),
InNeighboursOfVertex));
# Algorithms 4-7 are used below:

# Digraph EdgeConnectivity calculated with Dominating Sets (Algorithm 6-7)
InstallMethod(DigraphEdgeConnectivity, "for a symmetric digraph",
[IsDigraph],
function(digraph)
# Form an identical but edge weighted digraph with all edge weights as 1:
local weights, i, u, v, w, neighbourhood, EdgeD,
maxFlow, min, sum, a, b, V, added, st, non_leaf, max,
notAddedNeighbours, notadded, NextVertex, NeighboursV,
neighbour, Edges, D, VerticesLeft, VerticesED;

# check for symmetric digraph
if not IsSymmetricDigraph(digraph) then
ErrorNoReturn("the argument <digraph> must be a symmetric digraph,");
fi;

if DigraphNrVertices(digraph) = 1 or
DigraphNrConnectedComponents(digraph) > 1 then
return 0;
fi;

min := -1;

# Algorithm 7: Creating a dominating set of the digraph
D := DIGRAPHS_GreedyDominatingSet(
digraph,
Shuffle([1 .. DigraphNrVertices(digraph)]),
OutNeighboursOfVertex);

# Algorithm 6: Using the dominating set created to determine the Maximum Flow

EdgeD := UnitEdgeWeightedDigraph(DigraphImmutableCopyIfMutable(digraph));
if Length(D) > 1 then

v := D[1];
for i in [2 .. Length(D)] do
w := D[i];
a := DigraphMaximumFlow(EdgeD, v, w)[v];
b := DigraphMaximumFlow(EdgeD, w, v)[w];

sum := Minimum(Sum(a), Sum(b));
if (sum < min or min = -1) then
min := sum;
fi;
od;

else
# If the dominating set of EdgeD is of Length 1,
# the above algorithm will not work
# Revert to iterating through all vertices of the original digraph

u := 1;

for v in [2 .. DigraphNrVertices(EdgeD)] do
a := DigraphMaximumFlow(EdgeD, u, v)[u];
b := DigraphMaximumFlow(EdgeD, v, u)[v];

sum := Minimum(Sum(a), Sum(b));
if (sum < min or min = -1) then
min := sum;
fi;

od;
fi;

return Minimum(min, Minimum(OutDegrees(EdgeD)), Minimum(InDegrees(EdgeD)));
end);

# The following function is a transliteration from python to GAP of
# the function find_nonsemimodular_pair
# in sage/src/sage/combinat/posets/hasse_diagram.py
Expand Down
6 changes: 6 additions & 0 deletions gap/oper.gd
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ DeclareOperation("IsDigraphPath",
[IsDigraph, IsHomogeneousList, IsHomogeneousList]);
DeclareOperation("IsDigraphPath", [IsDigraph, IsList]);

DeclareOperation("IsDigraphOutDominatingSet", [IsDigraph, IsList]);
DeclareSynonym("IsDigraphDominatingSet", IsDigraphOutDominatingSet);
DeclareOperation("IsDigraphInDominatingSet", [IsDigraph, IsList]);

# 9. Connectivity . . .
DeclareOperation("DigraphIsKing", [IsDigraph, IsPosInt, IsPosInt]);
DeclareOperation("DigraphKings", [IsDigraph, IsPosInt]);
Expand Down Expand Up @@ -154,6 +158,8 @@ DeclareOperation("IsOrderIdeal", [IsDigraph, IsList]);
DeclareOperation("IsOrderFilter", [IsDigraph, IsList]);
DeclareOperation("Dominators", [IsDigraph, IsPosInt]);
DeclareOperation("DominatorTree", [IsDigraph, IsPosInt]);
DeclareOperation("DigraphGreedyOutDominatingSet", [IsDigraph, IsList]);
DeclareOperation("DigraphGreedyInDominatingSet", [IsDigraph, IsList]);
DeclareOperation("DigraphCycleBasis", [IsDigraph]);

DeclareOperation("DigraphColourRefinement", [IsDigraph]);
Expand Down
Loading
Loading