Skip to content

Commit da6864e

Browse files
ffloresbritowilfwilson
authored andcommitted
attr: add VertexConnectivity
1 parent d9f060c commit da6864e

File tree

6 files changed

+218
-0
lines changed

6 files changed

+218
-0
lines changed

doc/attr.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,3 +2371,39 @@ gap> Length(M);
23712371
</Description>
23722372
</ManSection>
23732373
<#/GAPDoc>
2374+
2375+
<#GAPDoc Label="VertexConnectivity">
2376+
<ManSection>
2377+
<Attr Name="VertexConnectivity" Arg="digraph"/>
2378+
<Returns>An non-negative integer.</Returns>
2379+
<Description>
2380+
For a digraph <A>digraph</A> with set of vertices <C>V</C>, the attribute
2381+
<C>VertexConnectivity(<A>digraph</A>)</C> returns the least cardinality
2382+
<C>|S|</C> of a subset <C>S</C> of <C>V</C> such that the induced subdigraph
2383+
of <A>digraph</A> on <C>V \ S</C> is disconnected, or has at most one
2384+
vertex. <P/>
2385+
2386+
The algorithm makes <C>n - d - 1 + d * (d - 1) / 2</C> calls to a max-flow
2387+
algorithm which itself has complexity <C>O((n ^ 2) * e)</C>, where <C>n</C>
2388+
is the number of vertices of <A>digraph</A>, and <C>e, d</C> are the number
2389+
of edges and the minimum degree (respectively) of the underlying undirected
2390+
graph of <A>digraph</A>.
2391+
2392+
<Example><![CDATA[
2393+
gap> J := JohnsonDigraph(9, 2);
2394+
<immutable symmetric digraph with 36 vertices, 504 edges>
2395+
gap> VertexConnectivity(J);
2396+
14
2397+
gap> D := Digraph([[2, 4, 5], [1, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2398+
> [1, 4], [4, 7], [3, 4, 6]]);
2399+
<immutable digraph with 7 vertices, 20 edges>
2400+
gap> VertexConnectivity(D);
2401+
1
2402+
gap> T := Digraph([]);
2403+
<immutable empty digraph with 0 vertices>
2404+
gap> VertexConnectivity(T);
2405+
0
2406+
]]></Example>
2407+
</Description>
2408+
</ManSection>
2409+
<#/GAPDoc>

doc/z-chap4.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
<#Include Label="HamiltonianPath">
7878
<#Include Label="NrSpanningTrees">
7979
<#Include Label="DigraphDijkstra">
80+
<#Include Label="VertexConnectivity">
8081
</Section>
8182

8283
<Section><Heading>Cayley graphs of groups</Heading>

gap/attr.gd

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

6666
DeclareAttribute("CharacteristicPolynomial", IsDigraph);
6767
DeclareAttribute("NrSpanningTrees", IsDigraph);
68+
DeclareAttribute("VertexConnectivity", IsDigraph);
6869

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

gap/attr.gi

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2434,3 +2434,146 @@ function(D)
24342434
M := List(DigraphLoops(D), x -> [x, x]);
24352435
return Union(M, DIGRAPHS_MateToMatching(D, mateD));
24362436
end);
2437+
2438+
InstallMethod(VertexConnectivity, "for a digraph", [IsDigraph],
2439+
function(digraph)
2440+
local kappas, newnetw, edmondskarp, mat, degs, mindegv, mindeg, Nv, outn, k,
2441+
i, j, x, y;
2442+
2443+
if DigraphNrVertices(digraph) <= 1 or not IsConnectedDigraph(digraph) then
2444+
return 0;
2445+
fi;
2446+
2447+
if IsMultiDigraph(digraph) then
2448+
digraph := DigraphRemoveAllMultipleEdges(digraph);
2449+
fi;
2450+
2451+
kappas := [DigraphNrVertices(digraph) - 1];
2452+
2453+
# The function newnetw is an implementation of Algorithm Nine from
2454+
# Abdol-Hossein Esfahanian's ``Connectivity Algorithms'' which can be found at
2455+
# https://www.cse.msu.edu/~cse835/Papers/Graph_connectivity_revised.pdf
2456+
newnetw := function(digraph, source, sink)
2457+
local n, mat, outn, x, y;
2458+
n := DigraphNrVertices(digraph);
2459+
mat := List([1 .. 2 * n], x -> BlistList([1 .. 2 * n], []));
2460+
outn := OutNeighbours(digraph);
2461+
for x in [1 .. DigraphNrVertices(digraph)] do
2462+
if x <> source and x <> sink then
2463+
mat[x + n][x] := true;
2464+
fi;
2465+
for y in outn[x] do
2466+
if x = source or x = sink then
2467+
mat[x][y + n] := true;
2468+
mat[y][x] := true;
2469+
elif y = source or y = sink then
2470+
mat[y][x + n] := true;
2471+
mat[x][y] := true;
2472+
else
2473+
mat[y][x + n] := true;
2474+
mat[x][y + n] := true;
2475+
fi;
2476+
od;
2477+
od;
2478+
return List(mat, x -> ListBlist([1 .. 2 * n], x));
2479+
end;
2480+
2481+
# The following function is an implementation of the Edmonds-Karp algorithm
2482+
# with some minor adjustments that take into account the fact that the
2483+
# capacity of all edges is 1.
2484+
edmondskarp := function(netw, source, sink)
2485+
local flow, capacity, queue, m, predecessor, edgeindex, stop, current, n, v;
2486+
2487+
flow := 0;
2488+
capacity := List(netw, x -> BlistList(x, x));
2489+
# nredges := Sum(List(netw, Length));
2490+
2491+
while true do
2492+
queue := [source];
2493+
m := 1;
2494+
predecessor := List(netw, x -> 0);
2495+
edgeindex := List(netw, x -> 0);
2496+
stop := false;
2497+
while m <= Size(queue) and not stop do
2498+
current := queue[m];
2499+
n := 0;
2500+
for v in netw[current] do
2501+
n := n + 1;
2502+
if predecessor[v] = 0 and v <> source and capacity[current][n] then
2503+
predecessor[v] := current;
2504+
edgeindex[v] := n;
2505+
Add(queue, v);
2506+
fi;
2507+
if v = sink then
2508+
stop := true;
2509+
break;
2510+
fi;
2511+
od;
2512+
m := m + 1;
2513+
od;
2514+
2515+
if predecessor[sink] <> 0 then
2516+
v := predecessor[sink];
2517+
n := edgeindex[sink];
2518+
while v <> 0 do
2519+
capacity[v][n] := false;
2520+
n := edgeindex[v];
2521+
v := predecessor[v];
2522+
od;
2523+
flow := flow + 1;
2524+
else
2525+
return flow;
2526+
fi;
2527+
od;
2528+
end;
2529+
2530+
# Referring once again to Abdol-Hossein Esfahanian's paper (see newnetw, above)
2531+
# the following lines implement Algorithm Eleven of that paper.
2532+
mat := BooleanAdjacencyMatrix(digraph);
2533+
degs := ListWithIdenticalEntries(DigraphNrVertices(digraph), 0);
2534+
for i in DigraphVertices(digraph) do
2535+
for j in [i + 1 .. DigraphNrVertices(digraph)] do
2536+
if mat[i][j] or mat[j][i] then
2537+
degs[i] := degs[i] + 1;
2538+
degs[j] := degs[j] + 1;
2539+
fi;
2540+
od;
2541+
od;
2542+
2543+
mindegv := 0;
2544+
mindeg := DigraphNrVertices(digraph) + 1;
2545+
for i in DigraphVertices(digraph) do
2546+
if degs[i] < mindeg then
2547+
mindeg := degs[i];
2548+
mindegv := i;
2549+
fi;
2550+
od;
2551+
2552+
Nv := OutNeighboursOfVertex(digraph, mindegv);
2553+
outn := OutNeighbours(digraph);
2554+
2555+
for x in DigraphVertices(digraph) do
2556+
if x <> mindegv and not mat[x][mindegv] and not mat[mindegv][x] then
2557+
k := edmondskarp(newnetw(digraph, mindegv, x), mindegv, x);
2558+
if k = 0 then
2559+
return 0;
2560+
else
2561+
AddSet(kappas, k);
2562+
fi;
2563+
fi;
2564+
od;
2565+
2566+
for x in [1 .. Size(Nv) - 1] do
2567+
for y in [x + 1 .. Size(Nv)] do
2568+
if not mat[Nv[x]][Nv[y]] and not mat[Nv[y]][Nv[x]] then
2569+
k := edmondskarp(newnetw(digraph, Nv[x], Nv[y]), Nv[x], Nv[y]);
2570+
if k = 0 then
2571+
return 0;
2572+
else
2573+
AddSet(kappas, k);
2574+
fi;
2575+
fi;
2576+
od;
2577+
od;
2578+
return kappas[1];
2579+
end);

gap/examples.gi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,11 @@ function(filt, 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
@@ -2597,6 +2597,38 @@ true
25972597
gap> DigraphNrLoops(D) = 0;
25982598
true
25992599

2600+
# VertexConnectivity
2601+
gap> D := CompleteDigraph(10);
2602+
<immutable complete digraph with 10 vertices>
2603+
gap> VertexConnectivity(D);
2604+
9
2605+
gap> D := JohnsonDigraph(9, 2);
2606+
<immutable symmetric digraph with 36 vertices, 504 edges>
2607+
gap> VertexConnectivity(D);
2608+
14
2609+
gap> D := Digraph([]);
2610+
<immutable empty digraph with 0 vertices>
2611+
gap> VertexConnectivity(D);
2612+
0
2613+
gap> D := Digraph([[]]);
2614+
<immutable empty digraph with 1 vertex>
2615+
gap> VertexConnectivity(D);
2616+
0
2617+
gap> D := Digraph([[2, 4, 5], [1, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2618+
> [1, 4], [4, 7], [3, 4, 6]]);
2619+
<immutable digraph with 7 vertices, 20 edges>
2620+
gap> VertexConnectivity(D);
2621+
1
2622+
gap> D := Digraph([[2, 4, 5], [1, 3, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2623+
> [1, 4], [4, 7], [3, 4, 6]]);
2624+
<immutable digraph with 7 vertices, 21 edges>
2625+
gap> VertexConnectivity(D);
2626+
2
2627+
gap> D := Digraph([[2, 3], [3, 5], [1, 2, 4], [2, 3], [3]]);
2628+
<immutable digraph with 5 vertices, 10 edges>
2629+
gap> VertexConnectivity(D);
2630+
2
2631+
26002632
# DIGRAPHS_UnbindVariables
26012633
gap> Unbind(adj);
26022634
gap> Unbind(adj1);

0 commit comments

Comments
 (0)