Skip to content

Commit c498734

Browse files
committed
DigraphEdgeConnectivity and additional functions (Dominating Set functions) added
1 parent c6dabf9 commit c498734

File tree

5 files changed

+260
-0
lines changed

5 files changed

+260
-0
lines changed

gap/oper.gd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ DeclareOperation("IsOrderIdeal", [IsDigraph, IsList]);
154154
DeclareOperation("IsOrderFilter", [IsDigraph, IsList]);
155155
DeclareOperation("Dominators", [IsDigraph, IsPosInt]);
156156
DeclareOperation("DominatorTree", [IsDigraph, IsPosInt]);
157+
DeclareOperation("DigraphDominatingSet", [IsDigraph]);
158+
DeclareOperation("DigraphGetNeighbourhood", [IsDigraph, IsList]);
157159
DeclareOperation("DigraphCycleBasis", [IsDigraph]);
158160

159161
# 10. Operations for vertices . . .

gap/oper.gi

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,6 +2522,43 @@ function(D, root)
25222522
return result;
25232523
end);
25242524

2525+
# For calculating a dominating set for a digraph
2526+
InstallMethod(DigraphDominatingSet, "for a digraph",
2527+
[IsDigraph],
2528+
function(digraph)
2529+
local D, neighbourhood, VerticesLeft, Vertices;
2530+
2531+
Vertices := [1 .. DigraphNrVertices(digraph)];
2532+
Shuffle(Vertices);
2533+
2534+
# Shuffling not technically necessary - may be better to just do D := [1]?
2535+
D := [Vertices[1]];
2536+
neighbourhood := DigraphGetNeighbourhood(digraph, D);
2537+
VerticesLeft := Difference(Vertices, Union(neighbourhood, D));
2538+
2539+
while not IsEmpty(VerticesLeft) do;
2540+
Append(D, [VerticesLeft[1]]);
2541+
neighbourhood := DigraphGetNeighbourhood(digraph, D);
2542+
VerticesLeft := Difference(Vertices, Union(neighbourhood, D));
2543+
od;
2544+
2545+
return D;
2546+
end);
2547+
2548+
# For getting the neighbourhood for a given List of Vertices in a Digraph
2549+
InstallMethod(DigraphGetNeighbourhood, "for a digraph and a List of vertices",
2550+
[IsDigraph, IsList],
2551+
function(digraph, vertices)
2552+
local v, neighbourhood;
2553+
neighbourhood := [];
2554+
for v in vertices do
2555+
neighbourhood := Difference(Union(neighbourhood,
2556+
OutNeighbours(digraph)[v]), vertices);
2557+
od;
2558+
2559+
return neighbourhood;
2560+
end);
2561+
25252562
# Computes the fundamental cycle basis of a symmetric digraph
25262563
# First, notice that the cycle space is composed of orthogonal subspaces
25272564
# corresponding to the cycle spaces of the connected components.

gap/weights.gd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ DeclareGlobalFunction("DIGRAPHS_Edge_Weighted_Dijkstra");
3939
DeclareOperation("DigraphMaximumFlow",
4040
[IsDigraph and HasEdgeWeights, IsPosInt, IsPosInt]);
4141

42+
# Digraph Edge Connectivity
43+
DeclareOperation("DigraphEdgeConnectivity", [IsDigraph]);
44+
DeclareOperation("DigraphEdgeConnectivityDS", [IsDigraph]);
45+
4246
# 6. Random edge weighted digraphs
4347
DeclareOperation("RandomUniqueEdgeWeightedDigraph", [IsPosInt]);
4448
DeclareOperation("RandomUniqueEdgeWeightedDigraph", [IsPosInt, IsFloat]);

gap/weights.gi

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,200 @@ function(D, start, destination)
772772
return flows;
773773
end);
774774

775+
# DigraphEdgeConnectivity calculated using Spanning Trees
776+
InstallMethod(DigraphEdgeConnectivity, "for a digraph",
777+
[IsDigraph],
778+
function(digraph)
779+
local w, weights, EdgeD, VerticesED, min, u, v,
780+
sum, a, b, st, added, NeighboursV, Edges, notadded,
781+
max, NextVertex, notAddedNeighbours, non_leaf;
782+
783+
if DigraphNrVertices(digraph) = 1 then
784+
return 0;
785+
fi;
786+
787+
if DigraphNrStronglyConnectedComponents(digraph) > 1 then
788+
return 0;
789+
fi;
790+
791+
weights := List([1 .. DigraphNrVertices(digraph)],
792+
x -> List([1 .. Length(OutNeighbours(digraph)[x])],
793+
y -> 1));
794+
EdgeD := EdgeWeightedDigraph(digraph, weights);
795+
VerticesED := [1 .. DigraphNrVertices(EdgeD)];
796+
797+
min := -1;
798+
799+
# Algorithm 4: Constructing a Spanning Tree with a large numbers of leaves
800+
801+
st := EmptyDigraph(DigraphNrVertices(EdgeD));
802+
v := 1;
803+
added := [v];
804+
805+
while DigraphNrEdges(st) < DigraphNrVertices(EdgeD) - 1 do
806+
807+
# Add all edges incident from v
808+
NeighboursV := OutNeighbors(EdgeD)[v];
809+
810+
Edges := List([1 .. Length(NeighboursV)],
811+
x -> [v, OutNeighbours(EdgeD)[v][x]]);
812+
813+
Edges := Difference(Edges, [[v, v]]);
814+
815+
st := DigraphAddEdges(st, Edges);
816+
Append(added, Difference(OutNeighbours(EdgeD)[v], added));
817+
818+
# Select the neighbour to v with the highest number of not-added neighbours:
819+
820+
notadded := Difference(VerticesED, added);
821+
max := 0;
822+
NextVertex := v;
823+
824+
# Preventing infinite iteration if the current vertex has no neighbours
825+
if (Length(NeighboursV) = 0) then
826+
# Pick from a vertex that hasn't been added yet
827+
NextVertex := notadded[1];
828+
fi;
829+
830+
for w in Difference(NeighboursV, [v]) do;
831+
notAddedNeighbours := Intersection(notadded, OutNeighbours(EdgeD)[w]);
832+
if (Length(notAddedNeighbours) > max) then
833+
max := Length(notAddedNeighbours);
834+
NextVertex := w;
835+
fi;
836+
od;
837+
838+
v := NextVertex;
839+
840+
od;
841+
842+
# Algorithm 5: Using Algorithm 4 to find the Edge Connectivity
843+
844+
non_leaf := [];
845+
for b in VerticesED do
846+
if not IsEmpty(OutNeighbours(st)[b]) then
847+
Append(non_leaf, [b]);
848+
fi;
849+
od;
850+
851+
# Get the smaller of non_leaf and Difference(Vertices in EdgeD, non_leaf)
852+
853+
if (Length(non_leaf) > 1) then
854+
u := non_leaf[1];
855+
856+
for v in [2 .. Length(non_leaf)] do
857+
a := DigraphMaximumFlow(EdgeD, u, non_leaf[v])[u];
858+
b := DigraphMaximumFlow(EdgeD, non_leaf[v], u)[non_leaf[v]];
859+
860+
sum := Minimum(Sum(a), Sum(b));
861+
if (sum < min or min = -1) then
862+
min := sum;
863+
fi;
864+
865+
if (sum = 0) then
866+
return 0;
867+
fi;
868+
od;
869+
870+
min := Minimum(min, Minimum(Minimum(OutDegrees(EdgeD)),
871+
Minimum(InDegrees(EdgeD))));
872+
else
873+
# In the case of spanning trees with only one non-leaf node,
874+
# the above algorithm does not work
875+
876+
u := 1;
877+
for v in [2 .. DigraphNrVertices(EdgeD)] do
878+
a := DigraphMaximumFlow(EdgeD, u, v)[u];
879+
b := DigraphMaximumFlow(EdgeD, v, u)[v];
880+
881+
sum := Minimum(Sum(a), Sum(b));
882+
if (sum < min or min = -1) then
883+
min := sum;
884+
fi;
885+
886+
if (sum = 0) then
887+
return 0;
888+
fi;
889+
890+
od;
891+
fi;
892+
893+
if (min = -1) then
894+
return 0;
895+
fi;
896+
897+
return min;
898+
end);
899+
900+
# Digraph EdgeConnectivity calculated with Dominating Sets
901+
InstallMethod(DigraphEdgeConnectivityDS, "for a digraph",
902+
[IsDigraph],
903+
function(digraph)
904+
# Form an identical but edge weighted digraph with all edge weights as 1:
905+
local weights, i, u, v, w, neighbourhood, EdgeD,
906+
maxFlow, min, sum, a, b, V, added, st, non_leaf, max,
907+
notAddedNeighbours, notadded, NextVertex, NeighboursV,
908+
neighbour, Edges, D, VerticesLeft, VerticesED;
909+
910+
if DigraphNrVertices(digraph) = 1 then
911+
return 0;
912+
fi;
913+
914+
if DigraphNrStronglyConnectedComponents(digraph) > 1 then
915+
return 0;
916+
fi;
917+
918+
weights := List([1 .. DigraphNrVertices(digraph)],
919+
x -> List([1 .. Length(OutNeighbours(digraph)[x])],
920+
y -> 1));
921+
EdgeD := EdgeWeightedDigraph(digraph, weights);
922+
923+
min := -1;
924+
925+
# Algorithm 7: Creating a dominating set of the digraph
926+
927+
D := DigraphDominatingSet(digraph);
928+
929+
# Algorithm 6:
930+
931+
if Length(D) > 1 then
932+
933+
v := D[1];
934+
for i in [2 .. Length(D)] do
935+
w := D[i];
936+
a := DigraphMaximumFlow(EdgeD, v, w)[v];
937+
b := DigraphMaximumFlow(EdgeD, w, v)[w];
938+
939+
sum := Minimum(Sum(a), Sum(b));
940+
if (sum < min or min = -1) then
941+
min := sum;
942+
fi;
943+
od;
944+
945+
else
946+
# If the dominating set of EdgeD is of Length 1,
947+
# the above algorithm will not work
948+
949+
u := 1;
950+
951+
for v in [2 .. DigraphNrVertices(EdgeD)] do
952+
a := DigraphMaximumFlow(EdgeD, u, v)[u];
953+
b := DigraphMaximumFlow(EdgeD, v, u)[v];
954+
955+
sum := Minimum(Sum(a), Sum(b));
956+
if (sum < min or min = -1) then
957+
min := sum;
958+
fi;
959+
960+
od;
961+
fi;
962+
963+
return Minimum(min,
964+
Minimum(Minimum(OutDegrees(EdgeD)),
965+
Minimum(InDegrees(EdgeD))));
966+
967+
end);
968+
775969
#############################################################################
776970
# 6. Random edge weighted digraphs
777971
#############################################################################

tst/testinstall.tst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,29 @@ gap> OutNeighbours(D);
550550
gap> OutNeighbours(C);
551551
[ [ 2, 3, 4 ], [ 1, 3, 4, 5 ], [ 1, 2 ], [ 5 ], [ 4 ] ]
552552

553+
# DigraphEdgeConnectivity
554+
gap> D := Digraph([[2, 3, 4], [1, 3, 4], [1, 2], [2, 3]]);;
555+
gap> DigraphEdgeConnectivity(D);
556+
2
557+
gap> C := Digraph([[2, 3], [2, 3], [1, 2, 3]]);;
558+
gap> DigraphEdgeConnectivity(C);
559+
1
560+
gap> D := Digraph([[], [1, 2], [2]]);;
561+
gap> DigraphEdgeConnectivity(D);
562+
0
563+
gap> C := Digraph([[3, 4], [1, 3, 4], [2], [3]]);;
564+
gap> DigraphEdgeConnectivity(C);
565+
1
566+
gap> D := RandomDigraph(1);;
567+
gap> DigraphEdgeConnectivity(D);
568+
0
569+
gap> C := Digraph([[2, 4], [3], [1, 5], [3], [4]]);;
570+
gap> DigraphEdgeConnectivity(C);
571+
1
572+
gap> D := Digraph([[ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ], [ 1, 2, 3, 4, 5 ]]);;
573+
gap> DigraphEdgeConnectivity(D);
574+
4
575+
553576
#
554577
gap> DIGRAPHS_StopTest();
555578
gap> STOP_TEST("Digraphs package: testinstall.tst", 0);

0 commit comments

Comments
 (0)