import math, time, itertools, json, random import numpy as np def random_regular(n, d, seed=0): if d < 0 or d >= n: raise ValueError("degree must satisfy 0 <= d < n") rng=np.random.default_rng(seed) if (n*d) % 2: raise ValueError("n*d must be even") # A randomly relabeled circulant is simple and exactly d-regular. # For odd d, add a perfect matching (requiring even n). if d % 2 and n % 2: raise ValueError("odd degree requires even n") adj=[set() for _ in range(n)] half=d//2 for i in range(n): for z in range(1,half+1): adj[i].add((i+z)%n); adj[i].add((i-z)%n) if d % 2: perm=rng.permutation(n) for a,b in perm.reshape(-1,2): adj[int(a)].add(int(b)); adj[int(b)].add(int(a)) perm=rng.permutation(n); inv=np.empty(n,dtype=int) for i,x in enumerate(perm): inv[x]=i out=[set() for _ in range(n)] for i in range(n): out[int(perm[i])]={int(perm[j]) for j in adj[i]} return [sorted(x) for x in out] def ring(n, d): adj=[set() for _ in range(n)] for i in range(n): for z in range(1,d//2+1): adj[i].update(((i-z)%n,(i+z)%n)) return [sorted(x) for x in adj] def boundary(adj, U): us=set(U); out=set() for i in U: out.update(j for j in adj[i] if j not in us) return len(out) def exact_stats(adj, k, eps): n=len(adj); rows=[] for s in range(k,n//2+1): vals=[] for U in itertools.combinations(range(n),s): b=boundary(adj,U); bound=eps*s/(math.log(3*s/k)**2) vals.append((b/s,b,bound)) a=np.array(vals) rows.append((s,float(a[:,0].min()),float(a[:,0].mean()),float(a[:,0].max()),float(a[:,2].max()))) return rows def sampled_stats(adj,k,eps,seed=1,samples=1000): rng=np.random.default_rng(seed); n=len(adj); rows=[] for s in [k, min(2*k,n//2), min(4*k,n//2), n//2]: vals=[] for _ in range(samples): U=rng.choice(n,s,replace=False); b=boundary(adj,U) vals.append((b/s, eps/(math.log(3*s/k)**2))) rows.append((s,float(np.min([x[0] for x in vals])),float(np.mean([x[0] for x in vals])),float(np.mean([x[1] for x in vals])))) return rows def bfs_depth(adj, seedset, target): seen=set(seedset); frontier=set(seedset); depth=0; history=[len(seen)] while len(seen)