| """ |
| ======================= |
| Distance-regular graphs |
| ======================= |
| """ |
|
|
| from collections import defaultdict |
| from itertools import combinations_with_replacement |
| from math import log |
|
|
| import networkx as nx |
| from networkx.utils import not_implemented_for |
|
|
| from .distance_measures import diameter |
|
|
| __all__ = [ |
| "is_distance_regular", |
| "is_strongly_regular", |
| "intersection_array", |
| "global_parameters", |
| ] |
|
|
|
|
| @nx._dispatchable |
| def is_distance_regular(G): |
| """Returns True if the graph is distance regular, False otherwise. |
| |
| A connected graph G is distance-regular if for any nodes x,y |
| and any integers i,j=0,1,...,d (where d is the graph |
| diameter), the number of vertices at distance i from x and |
| distance j from y depends only on i,j and the graph distance |
| between x and y, independently of the choice of x and y. |
| |
| Parameters |
| ---------- |
| G: Networkx graph (undirected) |
| |
| Returns |
| ------- |
| bool |
| True if the graph is Distance Regular, False otherwise |
| |
| Examples |
| -------- |
| >>> G = nx.hypercube_graph(6) |
| >>> nx.is_distance_regular(G) |
| True |
| |
| See Also |
| -------- |
| intersection_array, global_parameters |
| |
| Notes |
| ----- |
| For undirected and simple graphs only |
| |
| References |
| ---------- |
| .. [1] Brouwer, A. E.; Cohen, A. M.; and Neumaier, A. |
| Distance-Regular Graphs. New York: Springer-Verlag, 1989. |
| .. [2] Weisstein, Eric W. "Distance-Regular Graph." |
| http://mathworld.wolfram.com/Distance-RegularGraph.html |
| |
| """ |
| try: |
| intersection_array(G) |
| return True |
| except nx.NetworkXError: |
| return False |
|
|
|
|
| def global_parameters(b, c): |
| """Returns global parameters for a given intersection array. |
| |
| Given a distance-regular graph G with diameter d and integers b_i, |
| c_i,i = 0,....,d such that for any 2 vertices x,y in G at a distance |
| i=d(x,y), there are exactly c_i neighbors of y at a distance of i-1 from x |
| and b_i neighbors of y at a distance of i+1 from x. |
| |
| Thus, a distance regular graph has the global parameters, |
| [[c_0,a_0,b_0],[c_1,a_1,b_1],......,[c_d,a_d,b_d]] for the |
| intersection array [b_0,b_1,.....b_{d-1};c_1,c_2,.....c_d] |
| where a_i+b_i+c_i=k , k= degree of every vertex. |
| |
| Parameters |
| ---------- |
| b : list |
| |
| c : list |
| |
| Returns |
| ------- |
| iterable |
| An iterable over three tuples. |
| |
| Examples |
| -------- |
| >>> G = nx.dodecahedral_graph() |
| >>> b, c = nx.intersection_array(G) |
| >>> list(nx.global_parameters(b, c)) |
| [(0, 0, 3), (1, 0, 2), (1, 1, 1), (1, 1, 1), (2, 0, 1), (3, 0, 0)] |
| |
| References |
| ---------- |
| .. [1] Weisstein, Eric W. "Global Parameters." |
| From MathWorld--A Wolfram Web Resource. |
| http://mathworld.wolfram.com/GlobalParameters.html |
| |
| See Also |
| -------- |
| intersection_array |
| """ |
| return ((y, b[0] - x - y, x) for x, y in zip(b + [0], [0] + c)) |
|
|
|
|
| @not_implemented_for("directed") |
| @not_implemented_for("multigraph") |
| @nx._dispatchable |
| def intersection_array(G): |
| """Returns the intersection array of a distance-regular graph. |
| |
| Given a distance-regular graph G with integers b_i, c_i,i = 0,....,d |
| such that for any 2 vertices x,y in G at a distance i=d(x,y), there |
| are exactly c_i neighbors of y at a distance of i-1 from x and b_i |
| neighbors of y at a distance of i+1 from x. |
| |
| A distance regular graph's intersection array is given by, |
| [b_0,b_1,.....b_{d-1};c_1,c_2,.....c_d] |
| |
| Parameters |
| ---------- |
| G: Networkx graph (undirected) |
| |
| Returns |
| ------- |
| b,c: tuple of lists |
| |
| Examples |
| -------- |
| >>> G = nx.icosahedral_graph() |
| >>> nx.intersection_array(G) |
| ([5, 2, 1], [1, 2, 5]) |
| |
| References |
| ---------- |
| .. [1] Weisstein, Eric W. "Intersection Array." |
| From MathWorld--A Wolfram Web Resource. |
| http://mathworld.wolfram.com/IntersectionArray.html |
| |
| See Also |
| -------- |
| global_parameters |
| """ |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| if not nx.is_regular(G) or not nx.is_connected(G): |
| raise nx.NetworkXError("Graph is not distance regular.") |
|
|
| path_length = defaultdict(dict) |
| bint = {} |
| cint = {} |
|
|
| |
| |
| |
| diam = 0 |
| max_diameter_for_dr_graphs = (8 * log(len(G), 2)) / 3 |
| for u, v in combinations_with_replacement(G, 2): |
| |
| pl_u = path_length[u] |
| if v not in pl_u: |
| pl_u.update(nx.single_source_shortest_path_length(G, u)) |
| for x, distance in pl_u.items(): |
| path_length[x][u] = distance |
|
|
| i = path_length[u][v] |
| diam = max(diam, i) |
|
|
| |
| if diam > max_diameter_for_dr_graphs: |
| raise nx.NetworkXError("Graph is not distance regular.") |
|
|
| vnbrs = G[v] |
| |
| for n in vnbrs: |
| pl_n = path_length[n] |
| if u not in pl_n: |
| pl_n.update(nx.single_source_shortest_path_length(G, n)) |
| for x, distance in pl_n.items(): |
| path_length[x][n] = distance |
|
|
| |
| c = sum(1 for n in vnbrs if pl_u[n] == i - 1) |
| |
| b = sum(1 for n in vnbrs if pl_u[n] == i + 1) |
| |
| if cint.get(i, c) != c or bint.get(i, b) != b: |
| raise nx.NetworkXError("Graph is not distance regular") |
| bint[i] = b |
| cint[i] = c |
|
|
| return ( |
| [bint.get(j, 0) for j in range(diam)], |
| [cint.get(j + 1, 0) for j in range(diam)], |
| ) |
|
|
|
|
| |
| @not_implemented_for("directed") |
| @not_implemented_for("multigraph") |
| @nx._dispatchable |
| def is_strongly_regular(G): |
| """Returns True if and only if the given graph is strongly |
| regular. |
| |
| An undirected graph is *strongly regular* if |
| |
| * it is regular, |
| * each pair of adjacent vertices has the same number of neighbors in |
| common, |
| * each pair of nonadjacent vertices has the same number of neighbors |
| in common. |
| |
| Each strongly regular graph is a distance-regular graph. |
| Conversely, if a distance-regular graph has diameter two, then it is |
| a strongly regular graph. For more information on distance-regular |
| graphs, see :func:`is_distance_regular`. |
| |
| Parameters |
| ---------- |
| G : NetworkX graph |
| An undirected graph. |
| |
| Returns |
| ------- |
| bool |
| Whether `G` is strongly regular. |
| |
| Examples |
| -------- |
| |
| The cycle graph on five vertices is strongly regular. It is |
| two-regular, each pair of adjacent vertices has no shared neighbors, |
| and each pair of nonadjacent vertices has one shared neighbor:: |
| |
| >>> G = nx.cycle_graph(5) |
| >>> nx.is_strongly_regular(G) |
| True |
| |
| """ |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| return is_distance_regular(G) and diameter(G) == 2 |
|
|