Skip to content

Commit 529beeb

Browse files
committed
DigraphEdgeConnectivity and additional functions (Dominating Set functions) added
1 parent c113340 commit 529beeb

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
@@ -152,6 +152,8 @@ DeclareOperation("IsOrderIdeal", [IsDigraph, IsList]);
152152
DeclareOperation("IsOrderFilter", [IsDigraph, IsList]);
153153
DeclareOperation("Dominators", [IsDigraph, IsPosInt]);
154154
DeclareOperation("DominatorTree", [IsDigraph, IsPosInt]);
155+
DeclareOperation("DigraphDominatingSet", [IsDigraph]);
156+
DeclareOperation("DigraphGetNeighbourhood", [IsDigraph, IsList]);
155157
DeclareOperation("DigraphCycleBasis", [IsDigraph]);
156158

157159
# 10. Operations for vertices . . .

gap/oper.gi

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,6 +2512,43 @@ function(D, root)
25122512
return result;
25132513
end);
25142514

2515+
# For calculating a dominating set for a digraph
2516+
InstallMethod(DigraphDominatingSet, "for a digraph",
2517+
[IsDigraph],
2518+
function(digraph)
2519+
local D, neighbourhood, VerticesLeft, Vertices;
2520+
2521+
Vertices := [1 .. DigraphNrVertices(digraph)];
2522+
Shuffle(Vertices);
2523+
2524+
# Shuffling not technically necessary - may be better to just do D := [1]?
2525+
D := [Vertices[1]];
2526+
neighbourhood := DigraphGetNeighbourhood(digraph, D);
2527+
VerticesLeft := Difference(Vertices, Union(neighbourhood, D));
2528+
2529+
while not IsEmpty(VerticesLeft) do;
2530+
Append(D, [VerticesLeft[1]]);
2531+
neighbourhood := DigraphGetNeighbourhood(digraph, D);
2532+
VerticesLeft := Difference(Vertices, Union(neighbourhood, D));
2533+
od;
2534+
2535+
return D;
2536+
end);
2537+
2538+
# For getting the neighbourhood for a given List of Vertices in a Digraph
2539+
InstallMethod(DigraphGetNeighbourhood, "for a digraph and a List of vertices",
2540+
[IsDigraph, IsList],
2541+
function(digraph, vertices)
2542+
local v, neighbourhood;
2543+
neighbourhood := [];
2544+
for v in vertices do
2545+
neighbourhood := Difference(Union(neighbourhood,
2546+
OutNeighbours(digraph)[v]), vertices);
2547+
od;
2548+
2549+
return neighbourhood;
2550+
end);
2551+
25152552
# Computes the fundamental cycle basis of a symmetric digraph
25162553
# First, notice that the cycle space is composed of orthogonal subspaces
25172554
# 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
@@ -781,6 +781,200 @@ function(digraph, start, destination)
781781
return flows;
782782
end);
783783

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

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)