Skip to content

Commit 1ec2be4

Browse files
ffloresbritoreiniscirpons
authored andcommitted
attr: add VertexConnectivity
1 parent 1305081 commit 1ec2be4

File tree

6 files changed

+219
-1
lines changed

6 files changed

+219
-1
lines changed

doc/attr.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,6 +2510,42 @@ gap> Length(M);
25102510
</ManSection>
25112511
<#/GAPDoc>
25122512

2513+
<#GAPDoc Label="VertexConnectivity">
2514+
<ManSection>
2515+
<Attr Name="VertexConnectivity" Arg="digraph"/>
2516+
<Returns>An non-negative integer.</Returns>
2517+
<Description>
2518+
For a digraph <A>digraph</A> with set of vertices <C>V</C>, the attribute
2519+
<C>VertexConnectivity(<A>digraph</A>)</C> returns the least cardinality
2520+
<C>|S|</C> of a subset <C>S</C> of <C>V</C> such that the induced subdigraph
2521+
of <A>digraph</A> on <C>V \ S</C> is disconnected, or has at most one
2522+
vertex. <P/>
2523+
2524+
The algorithm makes <C>n - d - 1 + d * (d - 1) / 2</C> calls to a max-flow
2525+
algorithm which itself has complexity <C>O((n ^ 2) * e)</C>, where <C>n</C>
2526+
is the number of vertices of <A>digraph</A>, and <C>e, d</C> are the number
2527+
of edges and the minimum degree (respectively) of the underlying undirected
2528+
graph of <A>digraph</A>.
2529+
2530+
<Example><![CDATA[
2531+
gap> J := JohnsonDigraph(9, 2);
2532+
<immutable symmetric digraph with 36 vertices, 504 edges>
2533+
gap> VertexConnectivity(J);
2534+
14
2535+
gap> D := Digraph([[2, 4, 5], [1, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2536+
> [1, 4], [4, 7], [3, 4, 6]]);
2537+
<immutable digraph with 7 vertices, 20 edges>
2538+
gap> VertexConnectivity(D);
2539+
1
2540+
gap> T := Digraph([]);
2541+
<immutable empty digraph with 0 vertices>
2542+
gap> VertexConnectivity(T);
2543+
0
2544+
]]></Example>
2545+
</Description>
2546+
</ManSection>
2547+
<#/GAPDoc>
2548+
25132549
<#GAPDoc Label="NonUpperSemimodularPair">
25142550
<ManSection>
25152551
<Attr Name="NonUpperSemimodularPair" Arg="D"/>

doc/z-chap4.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<#Include Label="DegreeMatrix">
3939
<#Include Label="LaplacianMatrix">
4040
</Section>
41-
41+
4242
<Section><Heading>Orders</Heading>
4343
<#Include Label="PartialOrderDigraphMeetOfVertices">
4444
<#Include Label="NonUpperSemimodularPair">
@@ -83,6 +83,7 @@
8383
<#Include Label="HamiltonianPath">
8484
<#Include Label="NrSpanningTrees">
8585
<#Include Label="DigraphDijkstra">
86+
<#Include Label="VertexConnectivity">
8687
<#Include Label="DigraphCycleBasis">
8788
</Section>
8889

gap/attr.gd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ DeclareAttribute("DigraphCore", IsDigraph);
7070

7171
DeclareAttribute("CharacteristicPolynomial", IsDigraph);
7272
DeclareAttribute("NrSpanningTrees", IsDigraph);
73+
DeclareAttribute("VertexConnectivity", IsDigraph);
7374

7475
# AsGraph must be mutable for grape to function properly
7576
DeclareAttribute("AsGraph", IsDigraph, "mutable");

gap/attr.gi

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2868,6 +2868,149 @@ function(D)
28682868
return Union(M, DIGRAPHS_MateToMatching(D, mateD));
28692869
end);
28702870

2871+
InstallMethod(VertexConnectivity, "for a digraph", [IsDigraph],
2872+
function(digraph)
2873+
local kappas, newnetw, edmondskarp, mat, degs, mindegv, mindeg, Nv, outn, k,
2874+
i, j, x, y;
2875+
2876+
if DigraphNrVertices(digraph) <= 1 or not IsConnectedDigraph(digraph) then
2877+
return 0;
2878+
fi;
2879+
2880+
if IsMultiDigraph(digraph) then
2881+
digraph := DigraphRemoveAllMultipleEdges(digraph);
2882+
fi;
2883+
2884+
kappas := [DigraphNrVertices(digraph) - 1];
2885+
2886+
# The function newnetw is an implementation of Algorithm Nine from
2887+
# Abdol-Hossein Esfahanian's ``Connectivity Algorithms'' which can be found at
2888+
# https://www.cse.msu.edu/~cse835/Papers/Graph_connectivity_revised.pdf
2889+
newnetw := function(digraph, source, sink)
2890+
local n, mat, outn, x, y;
2891+
n := DigraphNrVertices(digraph);
2892+
mat := List([1 .. 2 * n], x -> BlistList([1 .. 2 * n], []));
2893+
outn := OutNeighbours(digraph);
2894+
for x in [1 .. DigraphNrVertices(digraph)] do
2895+
if x <> source and x <> sink then
2896+
mat[x + n][x] := true;
2897+
fi;
2898+
for y in outn[x] do
2899+
if x = source or x = sink then
2900+
mat[x][y + n] := true;
2901+
mat[y][x] := true;
2902+
elif y = source or y = sink then
2903+
mat[y][x + n] := true;
2904+
mat[x][y] := true;
2905+
else
2906+
mat[y][x + n] := true;
2907+
mat[x][y + n] := true;
2908+
fi;
2909+
od;
2910+
od;
2911+
return List(mat, x -> ListBlist([1 .. 2 * n], x));
2912+
end;
2913+
2914+
# The following function is an implementation of the Edmonds-Karp algorithm
2915+
# with some minor adjustments that take into account the fact that the
2916+
# capacity of all edges is 1.
2917+
edmondskarp := function(netw, source, sink)
2918+
local flow, capacity, queue, m, predecessor, edgeindex, stop, current, n, v;
2919+
2920+
flow := 0;
2921+
capacity := List(netw, x -> BlistList(x, x));
2922+
# nredges := Sum(List(netw, Length));
2923+
2924+
while true do
2925+
queue := [source];
2926+
m := 1;
2927+
predecessor := List(netw, x -> 0);
2928+
edgeindex := List(netw, x -> 0);
2929+
stop := false;
2930+
while m <= Size(queue) and not stop do
2931+
current := queue[m];
2932+
n := 0;
2933+
for v in netw[current] do
2934+
n := n + 1;
2935+
if predecessor[v] = 0 and v <> source and capacity[current][n] then
2936+
predecessor[v] := current;
2937+
edgeindex[v] := n;
2938+
Add(queue, v);
2939+
fi;
2940+
if v = sink then
2941+
stop := true;
2942+
break;
2943+
fi;
2944+
od;
2945+
m := m + 1;
2946+
od;
2947+
2948+
if predecessor[sink] <> 0 then
2949+
v := predecessor[sink];
2950+
n := edgeindex[sink];
2951+
while v <> 0 do
2952+
capacity[v][n] := false;
2953+
n := edgeindex[v];
2954+
v := predecessor[v];
2955+
od;
2956+
flow := flow + 1;
2957+
else
2958+
return flow;
2959+
fi;
2960+
od;
2961+
end;
2962+
2963+
# Referring once again to Abdol-Hossein Esfahanian's paper (see newnetw, above)
2964+
# the following lines implement Algorithm Eleven of that paper.
2965+
mat := BooleanAdjacencyMatrix(digraph);
2966+
degs := ListWithIdenticalEntries(DigraphNrVertices(digraph), 0);
2967+
for i in DigraphVertices(digraph) do
2968+
for j in [i + 1 .. DigraphNrVertices(digraph)] do
2969+
if mat[i][j] or mat[j][i] then
2970+
degs[i] := degs[i] + 1;
2971+
degs[j] := degs[j] + 1;
2972+
fi;
2973+
od;
2974+
od;
2975+
2976+
mindegv := 0;
2977+
mindeg := DigraphNrVertices(digraph) + 1;
2978+
for i in DigraphVertices(digraph) do
2979+
if degs[i] < mindeg then
2980+
mindeg := degs[i];
2981+
mindegv := i;
2982+
fi;
2983+
od;
2984+
2985+
Nv := OutNeighboursOfVertex(digraph, mindegv);
2986+
outn := OutNeighbours(digraph);
2987+
2988+
for x in DigraphVertices(digraph) do
2989+
if x <> mindegv and not mat[x][mindegv] and not mat[mindegv][x] then
2990+
k := edmondskarp(newnetw(digraph, mindegv, x), mindegv, x);
2991+
if k = 0 then
2992+
return 0;
2993+
else
2994+
AddSet(kappas, k);
2995+
fi;
2996+
fi;
2997+
od;
2998+
2999+
for x in [1 .. Size(Nv) - 1] do
3000+
for y in [x + 1 .. Size(Nv)] do
3001+
if not mat[Nv[x]][Nv[y]] and not mat[Nv[y]][Nv[x]] then
3002+
k := edmondskarp(newnetw(digraph, Nv[x], Nv[y]), Nv[x], Nv[y]);
3003+
if k = 0 then
3004+
return 0;
3005+
else
3006+
AddSet(kappas, k);
3007+
fi;
3008+
fi;
3009+
od;
3010+
od;
3011+
return kappas[1];
3012+
end);
3013+
28713014
# The following function is a transliteration from python to GAP of
28723015
# the function find_nonsemimodular_pair
28733016
# in sage/src/sage/combinat/posets/hasse_diagram.py

gap/examples.gi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,11 @@ function(_, n, k)
286286
D := MakeImmutable(JohnsonDigraphCons(IsMutableDigraph, n, k));
287287
SetIsMultiDigraph(D, false);
288288
SetIsSymmetricDigraph(D, true);
289+
if k > n then
290+
SetVertexConnectivity(D, 0);
291+
else
292+
SetVertexConnectivity(D, (n - k) * k);
293+
fi;
289294
return D;
290295
end);
291296

tst/standard/attr.tst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2794,6 +2794,38 @@ gap> D := DigraphRemoveEdge(D, 1, 3);
27942794
gap> D := DigraphRemoveEdge(D, 1, 3);
27952795
<immutable digraph with 6 vertices, 11 edges>
27962796

2797+
# VertexConnectivity
2798+
gap> D := CompleteDigraph(10);
2799+
<immutable complete digraph with 10 vertices>
2800+
gap> VertexConnectivity(D);
2801+
9
2802+
gap> D := JohnsonDigraph(9, 2);
2803+
<immutable symmetric digraph with 36 vertices, 504 edges>
2804+
gap> VertexConnectivity(D);
2805+
14
2806+
gap> D := Digraph([]);
2807+
<immutable empty digraph with 0 vertices>
2808+
gap> VertexConnectivity(D);
2809+
0
2810+
gap> D := Digraph([[]]);
2811+
<immutable empty digraph with 1 vertex>
2812+
gap> VertexConnectivity(D);
2813+
0
2814+
gap> D := Digraph([[2, 4, 5], [1, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2815+
> [1, 4], [4, 7], [3, 4, 6]]);
2816+
<immutable digraph with 7 vertices, 20 edges>
2817+
gap> VertexConnectivity(D);
2818+
1
2819+
gap> D := Digraph([[2, 4, 5], [1, 3, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2820+
> [1, 4], [4, 7], [3, 4, 6]]);
2821+
<immutable digraph with 7 vertices, 21 edges>
2822+
gap> VertexConnectivity(D);
2823+
2
2824+
gap> D := Digraph([[2, 3], [3, 5], [1, 2, 4], [2, 3], [3]]);
2825+
<immutable digraph with 5 vertices, 10 edges>
2826+
gap> VertexConnectivity(D);
2827+
2
2828+
27972829
# Semimodular lattices
27982830
gap> D := DigraphFromDigraph6String("&C[o?");
27992831
<immutable digraph with 4 vertices, 5 edges>

0 commit comments

Comments
 (0)