Neighboring nodes in the network
I will choose a bit better GraphLayout
for a tree:
net = Graph[graph, VertexLabels -> "Name", GraphLayout -> "RadialEmbedding"];
I suggest don't just count directly - get an object - a subgraph - of your query, so you can then run various computations on it and don't need count all over again based on different criteria w/ a different code.
nei[v_, d_] := NeighborhoodGraph[net, v, d]
Take distance 1:
nei[19, 1]
and see it is right:
HighlightGraph[net, nei[19, 1]]
Now you can compute whatever you need:
VertexList[nei[19, 1]]
Length[%] - 1
{19, 15, 22, 23, 39, 80, 83}
6
For the distance 2:
VertexList[nei[19, 1]]
VertexList[nei[19, 2]]
Complement[%, %%]
Length[%]
{19, 15, 22, 23, 39, 80, 83}
{19, 13, 15, 22, 23, 39, 49, 51, 59, 80, 82, 83, 96, 98}
{13, 49, 51, 59, 82, 96, 98}
7
Timings for large graphs
net = RandomGraph[BarabasiAlbertGraphDistribution[20000, 1]];
nei[v_, d_] := NeighborhoodGraph[net, v, d]
dist15:=Length[Complement[VertexList[nei[#,15]],VertexList[nei[#,14]]]&@RandomInteger[1000]]
Table[AbsoluteTiming[dist15;][[1]], 5]
{0.097359, 0.094737, 0.092589, 0.08872, 0.087478}
You could build it using BreadthFirstScan:
net = RandomGraph[BarabasiAlbertGraphDistribution[200000, 1]];
distance =
GroupBy[Reap[
BreadthFirstScan[net,
19, {"DiscoverVertex" -> (Sow[#3 -> #1] &)}]][[2, 1]],
First -> Last, Association[{"length" -> Length[#], "set" -> #}] &];
Get length:
distance[3, "length"]
1194
distance[[All, "length"]]
<|0 -> 1, 1 -> 214, 2 -> 1194, 3 -> 3058, 4 -> 5826, 5 -> 10069, 6 -> 15110, 7 -> 19992, 8 -> 23821, 9 -> 24910, 10 -> 24767, 11 -> 21459, 12 -> 17869, 13 -> 13525, 14 -> 9119, 15 -> 5146, 16 -> 2406, 17 -> 1025, 18 -> 337, 19 -> 106, 20 -> 34, 21 -> 11, 22 -> 1|>
and set distance[21, "set"]
{182224, 145742, 171910, 124658, 125540, 128520, 196392, 166986, 159530, 196846, 144772}
For weighted graphs:
SeedRandom[123];net2 = Graph[net, EdgeWeight -> RandomInteger[{1, 20}, EdgeCount[net]]];
edgeWeight[g_, x_, y_] :=
With[{weight = PropertyValue[{g, UndirectedEdge[x, y]},EdgeWeight]},
If[NumericQ[weight], weight, 0]]
Clear[dist]; dist[_] := 0;
weights =
Reap[BreadthFirstScan[net2,
9, {"DiscoverVertex" -> ((dist[#1] =
dist[#2] + edgeWeight[net2, #1, #2];
Sow[#1 -> dist[#1]]) &)}]][[2, 1]];
set = Select[weights, #[[2]] <= 5 &];
set[[;; 10]]
{9 -> 0, 66 -> 4, 126 -> 5, 160 -> 5, 190 -> 3, 274 -> 3, 283 -> 4,
312 -> 4, 519 -> 5, 537 -> 4}
set // Length
105
Note that BreadthFirstScan approach might not work in general (non tree graphs).
To count how many nodes there are at every distance (unsorted Association
): use this if you want to Lookup
a particular distance:
Counts@GraphDistance[net, g]
<|4 -> 4, 5 -> 12, 3 -> 7, 6 -> 26, 7 -> 20, 2 -> 7, 8 -> 15, 1 -> 6, 0 -> 1, 9 -> 2|>
Look them all up in order:
BinCounts[GraphDistance[net, g], {0, d, 1}]
{1, 6, 7, 7, 4, 12, 26, 20, 15, 2, 0, 0}