Skip to content

Commit 1f0981b

Browse files
ffloresbritowilfwilson
authored andcommitted
attr: add VertexConnectivity
1 parent 3e11cbf commit 1f0981b

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
@@ -74,6 +74,7 @@
7474
<#Include Label="HamiltonianPath">
7575
<#Include Label="NrSpanningTrees">
7676
<#Include Label="DigraphDijkstra">
77+
<#Include Label="VertexConnectivity">
7778
</Section>
7879

7980
<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
@@ -2408,3 +2408,146 @@ function(D)
24082408
M := List(DigraphLoops(D), x -> [x, x]);
24092409
return Union(M, DIGRAPHS_MateToMatching(D, mateD));
24102410
end);
2411+
2412+
InstallMethod(VertexConnectivity, "for a digraph", [IsDigraph],
2413+
function(digraph)
2414+
local kappas, newnetw, edmondskarp, mat, degs, mindegv, mindeg, Nv, outn, k,
2415+
i, j, x, y;
2416+
2417+
if DigraphNrVertices(digraph) <= 1 or not IsConnectedDigraph(digraph) then
2418+
return 0;
2419+
fi;
2420+
2421+
if IsMultiDigraph(digraph) then
2422+
digraph := DigraphRemoveAllMultipleEdges(digraph);
2423+
fi;
2424+
2425+
kappas := [DigraphNrVertices(digraph) - 1];
2426+
2427+
# The function newnetw is an implementation of Algorithm Nine from
2428+
# Abdol-Hossein Esfahanian's ``Connectivity Algorithms'' which can be found at
2429+
# https://www.cse.msu.edu/~cse835/Papers/Graph_connectivity_revised.pdf
2430+
newnetw := function(digraph, source, sink)
2431+
local n, mat, outn, x, y;
2432+
n := DigraphNrVertices(digraph);
2433+
mat := List([1 .. 2 * n], x -> BlistList([1 .. 2 * n], []));
2434+
outn := OutNeighbours(digraph);
2435+
for x in [1 .. DigraphNrVertices(digraph)] do
2436+
if x <> source and x <> sink then
2437+
mat[x + n][x] := true;
2438+
fi;
2439+
for y in outn[x] do
2440+
if x = source or x = sink then
2441+
mat[x][y + n] := true;
2442+
mat[y][x] := true;
2443+
elif y = source or y = sink then
2444+
mat[y][x + n] := true;
2445+
mat[x][y] := true;
2446+
else
2447+
mat[y][x + n] := true;
2448+
mat[x][y + n] := true;
2449+
fi;
2450+
od;
2451+
od;
2452+
return List(mat, x -> ListBlist([1 .. 2 * n], x));
2453+
end;
2454+
2455+
# The following function is an implementation of the Edmonds-Karp algorithm
2456+
# with some minor adjustments that take into account the fact that the
2457+
# capacity of all edges is 1.
2458+
edmondskarp := function(netw, source, sink)
2459+
local flow, capacity, queue, m, predecessor, edgeindex, stop, current, n, v;
2460+
2461+
flow := 0;
2462+
capacity := List(netw, x -> BlistList(x, x));
2463+
# nredges := Sum(List(netw, Length));
2464+
2465+
while true do
2466+
queue := [source];
2467+
m := 1;
2468+
predecessor := List(netw, x -> 0);
2469+
edgeindex := List(netw, x -> 0);
2470+
stop := false;
2471+
while m <= Size(queue) and not stop do
2472+
current := queue[m];
2473+
n := 0;
2474+
for v in netw[current] do
2475+
n := n + 1;
2476+
if predecessor[v] = 0 and v <> source and capacity[current][n] then
2477+
predecessor[v] := current;
2478+
edgeindex[v] := n;
2479+
Add(queue, v);
2480+
fi;
2481+
if v = sink then
2482+
stop := true;
2483+
break;
2484+
fi;
2485+
od;
2486+
m := m + 1;
2487+
od;
2488+
2489+
if predecessor[sink] <> 0 then
2490+
v := predecessor[sink];
2491+
n := edgeindex[sink];
2492+
while v <> 0 do
2493+
capacity[v][n] := false;
2494+
n := edgeindex[v];
2495+
v := predecessor[v];
2496+
od;
2497+
flow := flow + 1;
2498+
else
2499+
return flow;
2500+
fi;
2501+
od;
2502+
end;
2503+
2504+
# Referring once again to Abdol-Hossein Esfahanian's paper (see newnetw, above)
2505+
# the following lines implement Algorithm Eleven of that paper.
2506+
mat := BooleanAdjacencyMatrix(digraph);
2507+
degs := ListWithIdenticalEntries(DigraphNrVertices(digraph), 0);
2508+
for i in DigraphVertices(digraph) do
2509+
for j in [i + 1 .. DigraphNrVertices(digraph)] do
2510+
if mat[i][j] or mat[j][i] then
2511+
degs[i] := degs[i] + 1;
2512+
degs[j] := degs[j] + 1;
2513+
fi;
2514+
od;
2515+
od;
2516+
2517+
mindegv := 0;
2518+
mindeg := DigraphNrVertices(digraph) + 1;
2519+
for i in DigraphVertices(digraph) do
2520+
if degs[i] < mindeg then
2521+
mindeg := degs[i];
2522+
mindegv := i;
2523+
fi;
2524+
od;
2525+
2526+
Nv := OutNeighboursOfVertex(digraph, mindegv);
2527+
outn := OutNeighbours(digraph);
2528+
2529+
for x in DigraphVertices(digraph) do
2530+
if x <> mindegv and not mat[x][mindegv] and not mat[mindegv][x] then
2531+
k := edmondskarp(newnetw(digraph, mindegv, x), mindegv, x);
2532+
if k = 0 then
2533+
return 0;
2534+
else
2535+
AddSet(kappas, k);
2536+
fi;
2537+
fi;
2538+
od;
2539+
2540+
for x in [1 .. Size(Nv) - 1] do
2541+
for y in [x + 1 .. Size(Nv)] do
2542+
if not mat[Nv[x]][Nv[y]] and not mat[Nv[y]][Nv[x]] then
2543+
k := edmondskarp(newnetw(digraph, Nv[x], Nv[y]), Nv[x], Nv[y]);
2544+
if k = 0 then
2545+
return 0;
2546+
else
2547+
AddSet(kappas, k);
2548+
fi;
2549+
fi;
2550+
od;
2551+
od;
2552+
return kappas[1];
2553+
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
@@ -2589,6 +2589,38 @@ true
25892589
gap> DigraphNrLoops(D) = 0;
25902590
true
25912591

2592+
# VertexConnectivity
2593+
gap> D := CompleteDigraph(10);
2594+
<immutable complete digraph with 10 vertices>
2595+
gap> VertexConnectivity(D);
2596+
9
2597+
gap> D := JohnsonDigraph(9, 2);
2598+
<immutable symmetric digraph with 36 vertices, 504 edges>
2599+
gap> VertexConnectivity(D);
2600+
14
2601+
gap> D := Digraph([]);
2602+
<immutable empty digraph with 0 vertices>
2603+
gap> VertexConnectivity(D);
2604+
0
2605+
gap> D := Digraph([[]]);
2606+
<immutable empty digraph with 1 vertex>
2607+
gap> VertexConnectivity(D);
2608+
0
2609+
gap> D := Digraph([[2, 4, 5], [1, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2610+
> [1, 4], [4, 7], [3, 4, 6]]);
2611+
<immutable digraph with 7 vertices, 20 edges>
2612+
gap> VertexConnectivity(D);
2613+
1
2614+
gap> D := Digraph([[2, 4, 5], [1, 3, 4], [4, 7], [1, 2, 3, 5, 6, 7],
2615+
> [1, 4], [4, 7], [3, 4, 6]]);
2616+
<immutable digraph with 7 vertices, 21 edges>
2617+
gap> VertexConnectivity(D);
2618+
2
2619+
gap> D := Digraph([[2, 3], [3, 5], [1, 2, 4], [2, 3], [3]]);
2620+
<immutable digraph with 5 vertices, 10 edges>
2621+
gap> VertexConnectivity(D);
2622+
2
2623+
25922624
# DIGRAPHS_UnbindVariables
25932625
gap> Unbind(adj);
25942626
gap> Unbind(adj1);

0 commit comments

Comments
 (0)