<jupyter_start><jupyter_text>Null modelsIn this notebook we show several basic results concerning the behaviorof quadrangular structural coefficients in standard null models.  Global $q$-clustering in Erdős–Rényi (ER) random graphsIt is a well known fact that in ER random graphs expected global clusteringis equal to $p$, that is, to the edge exsitence probability.It can be deduced simply from the fact that for any $2$-path:```i -- j -- k```the probability that also `i` and `k` are connected is still equal to $p$as it is constant for all possible edges. Hence, each $2$-path is closedto make a triangle with probability of exactly $p$ resulting in the globalclustering equal to $p$.Similarly, for any $3$-path:```  i      l  |      |  j ---- k```probability that it is closed and form a strict quadrangle is equal tothe probability that `i` and `k` as well as `j` and `l` are not connectedwhich is $(1-p)^2$ times the probability that `i` and `l` are connectedwhich $p$. So this gives expected quadrangular clustering(global complementarity) equal to$p(1-p)^2$. Note that for graphs with low value of $p$ we have that$(1-p) \approx 1$, so both expected clustering and $q$-clusteringare comparable.  SimulationWe check the above assertion by simulating $100$ ER random graphs with$2000$ nodes and different values of $p = .01, .02, .05$.**NOTE.** This may take a while to execute.<jupyter_code>import random
import pandas as pd
import igraph as ig
from tqdm import tqdm
from pathcensus import PathCensus
random.seed(101)

P = (.001, .002, .005, .01)
N = 5000
R = 20

er_null = []

for p in P:
    for _ in tqdm(range(R)):
        graph = ig.Graph.Erdos_Renyi(N, p=p, directed=False)
        paths = PathCensus(graph) 
        index = dict(p=p, q=p*(1-p)**2)
        df = paths.coefs("global")
        for k, v in index.items():
            df[k] = v
        index["q"] = p
        er_null.append(df)

data = pd.concat(er_null, axis=0, ignore_index=True)
sim = data[["p", "sim_g", "sim", "tclust", "tclosure"]] \
    .reset_index() \
    .melt(id_vars=["index", "p"]) \
    .assign(relerr=lambda df: abs(df["value"] - df["p"]) / df["p"])
    
comp = data[[
    "q", "comp_g", "comp", "qclust", "qclosure"
]] \
    .reset_index() \
    .melt(id_vars=["index", "q"]) \
    .assign(relerr=lambda df: abs(df["value"] - df["q"]) / df["q"])<jupyter_output><empty_output><jupyter_text>Similarity coefficients vis-a-vis density in ER random graph ($p$)<jupyter_code>sim.groupby(["p", "variable"])["value"].describe()<jupyter_output><empty_output><jupyter_text>Complementarity coefficients vis-a-vis $p(1-p)^2$ in ER random graphs<jupyter_code>comp.groupby(["q", "variable"])["value"].describe().round(6)<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup