Skip to content

Commit 7b3e7b3

Browse files
ffloresbritowilfwilson
authored andcommitted
attr: add VertexConnectivity
1 parent 1231e19 commit 7b3e7b3

File tree

6 files changed

+282
-1
lines changed

6 files changed

+282
-1
lines changed

doc/attr.xml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,6 +2680,47 @@ gap> Length(M);
26802680
</ManSection>
26812681
<#/GAPDoc>
26822682

2683+
<#GAPDoc Label="VertexConnectivity">
2684+
<ManSection>
2685+
<Attr Name="VertexConnectivity" Arg="digraph"/>
2686+
<Returns>An non-negative integer.</Returns>
2687+
<Description>
2688+
For a digraph <A>digraph</A> with set of vertices <C>V</C>, the attribute
2689+
<C>VertexConnectivity(<A>digraph</A>)</C> returns the least cardinality
2690+
<C>|S|</C> of a subset <C>S</C> of <C>V</C> such that the induced subdigraph
2691+
of <A>digraph</A> on <C>V \ S</C> is disconnected, or has at most one
2692+
vertex. <P/>
2693+
2694+
Note, in particular, that empty digraphs, and disconnected digraphs, have
2695+
vertex connectivity zero. <P/>
2696+
2697+
The algorithm makes <C>n - d - 1 + d * (d - 1) / 2</C> calls to a max-flow
2698+
algorithm which itself has complexity <C>O((n ^ 2) * e)</C>, where <C>n</C>
2699+
is the number of vertices of <A>digraph</A>, and <C>e, d</C> are the number
2700+
of edges and the minimum degree (respectively) of the underlying undirected
2701+
graph of <A>digraph</A>.
2702+
2703+
<Example><![CDATA[
2704+
gap> J := JohnsonDigraph(9, 2);
2705+
<immutable symmetric digraph with 36 vertices, 504 edges>
2706+
gap> VertexConnectivity(J);
2707+
14
2708+
gap> D := CompleteBipartiteDigraph(4, 5);
2709+
<immutable complete bipartite digraph with bicomponent sizes 4 and 5>
2710+
gap> VertexConnectivity(D);
2711+
4
2712+
gap> VertexConnectivity(PancakeGraph(4));
2713+
3
2714+
gap> D := Digraph([[2, 4, 5], [1, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2715+
> [1, 4], [4, 7], [3, 4, 6]]);
2716+
<immutable digraph with 7 vertices, 20 edges>
2717+
gap> VertexConnectivity(D);
2718+
1
2719+
]]></Example>
2720+
</Description>
2721+
</ManSection>
2722+
<#/GAPDoc>
2723+
26832724
<#GAPDoc Label="NonUpperSemimodularPair">
26842725
<ManSection>
26852726
<Attr Name="NonUpperSemimodularPair" Arg="D"/>

doc/z-chap4.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
<#Include Label="DegreeMatrix">
4141
<#Include Label="LaplacianMatrix">
4242
</Section>
43-
43+
4444
<Section><Heading>Orders</Heading>
4545
<#Include Label="PartialOrderDigraphMeetOfVertices">
4646
<#Include Label="NonUpperSemimodularPair">
@@ -88,6 +88,7 @@
8888
<#Include Label="HamiltonianPath">
8989
<#Include Label="NrSpanningTrees">
9090
<#Include Label="DigraphDijkstra">
91+
<#Include Label="VertexConnectivity">
9192
<#Include Label="DigraphCycleBasis">
9293
<#Include Label="DigraphIsKing">
9394
<#Include Label="DigraphKings">

gap/attr.gd

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

7878
DeclareAttribute("CharacteristicPolynomial", IsDigraph);
7979
DeclareAttribute("NrSpanningTrees", IsDigraph);
80+
DeclareAttribute("VertexConnectivity", IsDigraph);
8081

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

gap/attr.gi

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3358,6 +3358,150 @@ function(D)
33583358
return Union(M, DIGRAPHS_MateToMatching(D, mateD));
33593359
end);
33603360

3361+
InstallMethod(VertexConnectivity, "for a digraph", [IsDigraph],
3362+
function(digraph)
3363+
local kappas, newnetw, edmondskarp, mat, degs, mindegv, mindeg, Nv, outn, k,
3364+
i, j, x, y;
3365+
3366+
if DigraphNrVertices(digraph) <= 1 or not IsConnectedDigraph(digraph) then
3367+
return 0;
3368+
fi;
3369+
3370+
if IsMultiDigraph(digraph) then
3371+
digraph := DigraphRemoveAllMultipleEdges(digraph);
3372+
fi;
3373+
3374+
kappas := [DigraphNrVertices(digraph) - 1];
3375+
3376+
# The function newnetw is an implementation of Algorithm Nine from
3377+
# Abdol-Hossein Esfahanian's ``Connectivity Algorithms'' which can be found at
3378+
# https://www.cse.msu.edu/~cse835/Papers/Graph_connectivity_revised.pdf
3379+
newnetw := function(digraph, source, sink)
3380+
local n, mat, outn, x, y;
3381+
n := DigraphNrVertices(digraph);
3382+
mat := List([1 .. 2 * n], x -> BlistList([1 .. 2 * n], []));
3383+
outn := OutNeighbours(digraph);
3384+
for x in [1 .. DigraphNrVertices(digraph)] do
3385+
if x <> source and x <> sink then
3386+
mat[x + n][x] := true;
3387+
fi;
3388+
for y in outn[x] do
3389+
if x = source or x = sink then
3390+
mat[x][y + n] := true;
3391+
mat[y][x] := true;
3392+
elif y = source or y = sink then
3393+
mat[y][x + n] := true;
3394+
mat[x][y] := true;
3395+
else
3396+
mat[y][x + n] := true;
3397+
mat[x][y + n] := true;
3398+
fi;
3399+
od;
3400+
od;
3401+
return List(mat, x -> ListBlist([1 .. 2 * n], x));
3402+
end;
3403+
3404+
# The following function is an implementation of the Edmonds-Karp algorithm
3405+
# with some minor adjustments that take into account the fact that the
3406+
# capacity of all edges is 1.
3407+
edmondskarp := function(netw, source, sink)
3408+
local flow, capacity, queue, m, predecessor, edgeindex, stop, current, n, v;
3409+
3410+
flow := 0;
3411+
capacity := List(netw, x -> BlistList(x, x));
3412+
# nredges := Sum(List(netw, Length));
3413+
3414+
while true do
3415+
queue := [source];
3416+
m := 1;
3417+
predecessor := List(netw, x -> 0);
3418+
edgeindex := List(netw, x -> 0);
3419+
stop := false;
3420+
while m <= Size(queue) and not stop do
3421+
current := queue[m];
3422+
n := 0;
3423+
for v in netw[current] do
3424+
n := n + 1;
3425+
if predecessor[v] = 0 and v <> source and capacity[current][n] then
3426+
predecessor[v] := current;
3427+
edgeindex[v] := n;
3428+
Add(queue, v);
3429+
fi;
3430+
if v = sink then
3431+
stop := true;
3432+
break;
3433+
fi;
3434+
od;
3435+
m := m + 1;
3436+
od;
3437+
3438+
if predecessor[sink] <> 0 then
3439+
v := predecessor[sink];
3440+
n := edgeindex[sink];
3441+
while v <> 0 do
3442+
capacity[v][n] := false;
3443+
n := edgeindex[v];
3444+
v := predecessor[v];
3445+
od;
3446+
flow := flow + 1;
3447+
else
3448+
return flow;
3449+
fi;
3450+
od;
3451+
end;
3452+
3453+
# Referring once again to Abdol-Hossein Esfahanian's paper
3454+
# (see newnetw, above).
3455+
# The following lines implement Algorithm Eleven of that paper.
3456+
mat := BooleanAdjacencyMatrix(digraph);
3457+
degs := ListWithIdenticalEntries(DigraphNrVertices(digraph), 0);
3458+
for i in DigraphVertices(digraph) do
3459+
for j in [i + 1 .. DigraphNrVertices(digraph)] do
3460+
if mat[i][j] or mat[j][i] then
3461+
degs[i] := degs[i] + 1;
3462+
degs[j] := degs[j] + 1;
3463+
fi;
3464+
od;
3465+
od;
3466+
3467+
mindegv := 0;
3468+
mindeg := DigraphNrVertices(digraph) + 1;
3469+
for i in DigraphVertices(digraph) do
3470+
if degs[i] < mindeg then
3471+
mindeg := degs[i];
3472+
mindegv := i;
3473+
fi;
3474+
od;
3475+
3476+
Nv := OutNeighboursOfVertex(digraph, mindegv);
3477+
outn := OutNeighbours(digraph);
3478+
3479+
for x in DigraphVertices(digraph) do
3480+
if x <> mindegv and not mat[x][mindegv] and not mat[mindegv][x] then
3481+
k := edmondskarp(newnetw(digraph, mindegv, x), mindegv, x);
3482+
if k = 0 then
3483+
return 0;
3484+
else
3485+
AddSet(kappas, k);
3486+
fi;
3487+
fi;
3488+
od;
3489+
3490+
for x in [1 .. Size(Nv) - 1] do
3491+
for y in [x + 1 .. Size(Nv)] do
3492+
if not mat[Nv[x]][Nv[y]] and not mat[Nv[y]][Nv[x]] then
3493+
k := edmondskarp(newnetw(digraph, Nv[x], Nv[y]), Nv[x], Nv[y]);
3494+
if k = 0 then
3495+
return 0;
3496+
else
3497+
AddSet(kappas, k);
3498+
fi;
3499+
fi;
3500+
od;
3501+
od;
3502+
return kappas[1];
3503+
end);
3504+
33613505
# The following function is a transliteration from python to GAP of
33623506
# the function find_nonsemimodular_pair
33633507
# 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
@@ -296,6 +296,11 @@ function(_, n, k)
296296
D := MakeImmutable(JohnsonDigraphCons(IsMutableDigraph, n, k));
297297
SetIsMultiDigraph(D, false);
298298
SetIsSymmetricDigraph(D, true);
299+
if k > n then
300+
SetVertexConnectivity(D, 0);
301+
else
302+
SetVertexConnectivity(D, (n - k) * k);
303+
fi;
299304
return D;
300305
end);
301306

tst/standard/attr.tst

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3114,6 +3114,95 @@ gap> D := DigraphRemoveEdge(D, 1, 3);
31143114
gap> D := DigraphRemoveEdge(D, 1, 3);
31153115
<immutable digraph with 6 vertices, 11 edges>
31163116

3117+
# VertexConnectivity
3118+
gap> D := CompleteDigraph(10);
3119+
<immutable complete digraph with 10 vertices>
3120+
gap> VertexConnectivity(D);
3121+
9
3122+
gap> ForAny(Combinations(DigraphVertices(D), 8),
3123+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3124+
> Difference(DigraphVertices(D), x))));
3125+
false
3126+
gap> D := JohnsonDigraph(9, 2);
3127+
<immutable symmetric digraph with 36 vertices, 504 edges>
3128+
gap> VertexConnectivity(D);
3129+
14
3130+
gap> D := EmptyDigraph(0);
3131+
<immutable empty digraph with 0 vertices>
3132+
gap> VertexConnectivity(D);
3133+
0
3134+
gap> D := EmptyDigraph(1);
3135+
<immutable empty digraph with 1 vertex>
3136+
gap> VertexConnectivity(D);
3137+
0
3138+
gap> D := Digraph([[2, 4, 5], [1, 4], [4, 7], [1, 2, 3, 5, 6, 7],
3139+
> [1, 4], [4, 7], [3, 4, 6]]);
3140+
<immutable digraph with 7 vertices, 20 edges>
3141+
gap> VertexConnectivity(D);
3142+
1
3143+
gap> not IsConnectedDigraph(D);
3144+
false
3145+
gap> ForAny(Combinations(DigraphVertices(D), 1),
3146+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3147+
> Difference(DigraphVertices(D), x))));
3148+
true
3149+
gap> D := Digraph([[2, 4, 5], [1, 3, 4], [4, 7], [1, 2, 3, 5, 6, 7],
3150+
> [1, 4], [4, 7], [3, 4, 6]]);
3151+
<immutable digraph with 7 vertices, 21 edges>
3152+
gap> VertexConnectivity(D);
3153+
2
3154+
gap> ForAny(Combinations(DigraphVertices(D), 1),
3155+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3156+
> Difference(DigraphVertices(D), x))));
3157+
false
3158+
gap> ForAny(Combinations(DigraphVertices(D), 2),
3159+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3160+
> Difference(DigraphVertices(D), x))));
3161+
true
3162+
gap> D := Digraph([[2, 3], [3, 5], [1, 2, 4], [2, 3], [3]]);
3163+
<immutable digraph with 5 vertices, 10 edges>
3164+
gap> VertexConnectivity(D);
3165+
2
3166+
gap> ForAny(Combinations(DigraphVertices(D), 1),
3167+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3168+
> Difference(DigraphVertices(D), x))));
3169+
false
3170+
gap> ForAny(Combinations(DigraphVertices(D), 2),
3171+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3172+
> Difference(DigraphVertices(D), x))));
3173+
true
3174+
gap> D := DigraphFromGraph6String("NoCQ@?EAS_C`QA?c_Kg");;
3175+
gap> VertexConnectivity(D);
3176+
3
3177+
gap> ForAny(Combinations(DigraphVertices(D), 2),
3178+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3179+
> Difference(DigraphVertices(D), x))));
3180+
false
3181+
gap> ForAny(Combinations(DigraphVertices(D), 3),
3182+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3183+
> Difference(DigraphVertices(D), x))));
3184+
true
3185+
gap> D := DigraphFromGraph6String("HoStIv{");;
3186+
gap> VertexConnectivity(D);
3187+
4
3188+
gap> ForAny(Combinations(DigraphVertices(D), 3),
3189+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3190+
> Difference(DigraphVertices(D), x))));
3191+
false
3192+
gap> ForAny(Combinations(DigraphVertices(D), 4),
3193+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3194+
> Difference(DigraphVertices(D), x))));
3195+
true
3196+
gap> D := PancakeGraph(4);
3197+
gap> ForAny(Combinations(DigraphVertices(D), 2),
3198+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3199+
> Difference(DigraphVertices(D), x))));
3200+
false
3201+
gap> ForAny(Combinations(DigraphVertices(D), 3),
3202+
> x -> not IsConnectedDigraph(InducedSubdigraph(D,
3203+
> Difference(DigraphVertices(D), x))));
3204+
true
3205+
31173206
# Semimodular lattices
31183207
gap> D := DigraphFromDigraph6String("&C[o?");
31193208
<immutable digraph with 4 vertices, 5 edges>

0 commit comments

Comments
 (0)