def euclidean_gen(A, D, m, eta, model_var): mseed = np.size(np.where(A.flat)) // 2 if type(model_var) == tuple: mv1, mv2 = model_var else: mv1, mv2 = model_var, model_var if mv1 != mv2: raise BCTParamError('Too many hyperparameters specified') if mv1 in ('powerlaw', 'power_law'): Fd = D**eta elif mv1 in ('exponential', ): Fd = np.exp(eta**D) u, v = np.where(np.triu(np.ones((n, n)), 1)) P = Fd * np.logical_not(A) b = np.zeros((m, ), dtype=int) b[:mseed] = np.squeeze(np.where(A[u, v])) for i in range(mseed, m): C = np.append(0, np.cumsum(P[u, v])) r = np.sum(rng.random_sample() * C[-1] >= C) b[i] = r P = Fd P[u[b[:i]], v[b[:i]]] = P[v[b[:i]], u[b[:i]]] = 0 A[u[r], v[r]] = A[v[r], u[r]] = 1 return A
def get_components(A, no_depend=False): ''' Returns the components of an undirected graph specified by the binary and undirected adjacency matrix adj. Components and their constitutent nodes are assigned the same index and stored in the vector, comps. The vector, comp_sizes, contains the number of nodes beloning to each component. Parameters ---------- A : NxN np.ndarray binary undirected adjacency matrix no_depend : Any Does nothing, included for backwards compatibility Returns ------- comps : Nx1 np.ndarray vector of component assignments for each node comp_sizes : Mx1 np.ndarray vector of component sizes Notes ----- Note: disconnected nodes will appear as components with a component size of 1 Note: The identity of each component (i.e. its numerical value in the result) is not guaranteed to be identical the value returned in BCT, matlab code, although the component topology is. Many thanks to Nick Cullen for providing this implementation ''' if not np.all(A == A.T): # ensure matrix is undirected raise BCTParamError('get_components can only be computed for undirected' ' matrices. If your matrix is noisy, correct it with np.around') A = binarize(A, copy=True) n = len(A) np.fill_diagonal(A, 1) edge_map = [{u,v} for u in range(n) for v in range(n) if A[u,v] == 1] union_sets = [] for item in edge_map: temp = [] for s in union_sets: if not s.isdisjoint(item): item = s.union(item) else: temp.append(s) temp.append(item) union_sets = temp comps = np.array([i+1 for v in range(n) for i in range(len(union_sets)) if v in union_sets[i]]) comp_sizes = np.array([len(s) for s in union_sets]) return comps, comp_sizes
def corr_flat_dir(a1, a2): ''' Returns the correlation coefficient between two flattened adjacency matrices. Similarity metric for weighted matrices. Parameters ---------- A1 : NxN np.ndarray directed matrix 1 A2 : NxN np.ndarray directed matrix 2 Returns ------- r : float Correlation coefficient describing edgewise similarity of a1 and a2 ''' n = len(a1) if len(a2) != n: raise BCTParamError("Cannot calculate flattened correlation on " "matrices of different size") ix = np.logical_not(np.eye(n)) return np.corrcoef(a1[ix].flat, a2[ix].flat)[0][1]
def corr_flat_und(a1, a2): ''' Returns the correlation coefficient between two flattened adjacency matrices. Only the upper triangular part is used to avoid double counting undirected matrices. Similarity metric for weighted matrices. Parameters ---------- A1 : NxN np.ndarray undirected matrix 1 A2 : NxN np.ndarray undirected matrix 2 Returns ------- r : float Correlation coefficient describing edgewise similarity of a1 and a2 ''' n = len(a1) if len(a2) != n: raise BCTParamError("Cannot calculate flattened correlation on " "matrices of different size") triu_ix = np.where(np.triu(np.ones((n, n)), 1)) return np.corrcoef(a1[triu_ix].flat, a2[triu_ix].flat)[0][1]
def get_components_old(A, no_depend=False): ''' Returns the components of an undirected graph specified by the binary and undirected adjacency matrix adj. Components and their constitutent nodes are assigned the same index and stored in the vector, comps. The vector, comp_sizes, contains the number of nodes beloning to each component. Parameters ---------- adj : NxN np.ndarray binary undirected adjacency matrix no_depend : bool If true, doesn't import networkx to do the calculation. Default value is false. Returns ------- comps : Nx1 np.ndarray vector of component assignments for each node comp_sizes : Mx1 np.ndarray vector of component sizes Notes ----- Note: disconnected nodes will appear as components with a component size of 1 Note: The identity of each component (i.e. its numerical value in the result) is not guaranteed to be identical the value returned in BCT, although the component topology is. Note: networkx is used to do the computation efficiently. If networkx is not available a breadth-first search that does not depend on networkx is used instead, but this is less efficient. The corresponding BCT function does the computation by computing the Dulmage-Mendelsohn decomposition. I don't know what a Dulmage-Mendelsohn decomposition is and there doesn't appear to be a python equivalent. If you think of a way to implement this better, let me know. ''' # nonsquare matrices cannot be symmetric; no need to check if not np.all(A == A.T): # ensure matrix is undirected raise BCTParamError('get_components can only be computed for undirected' ' matrices. If your matrix is noisy, correct it with np.around') A = binarize(A, copy=True) n = len(A) np.fill_diagonal(A, 1) try: if no_depend: raise ImportError() else: import networkx as nx net = nx.from_numpy_matrix(A) cpts = list(nx.connected_components(net)) cptvec = np.zeros((n,)) cptsizes = np.zeros(len(cpts)) for i, cpt in enumerate(cpts): cptsizes[i] = len(cpt) for node in cpt: cptvec[node] = i + 1 except ImportError: # if networkx is not available use less efficient breadth first search cptvec = np.zeros((n,)) r, _ = breadthdist(A) for node, reach in enumerate(r): if cptvec[node] > 0: continue else: cptvec[np.where(reach)] = np.max(cptvec) + 1 cptsizes = np.zeros(np.max(cptvec)) for i in np.arange(np.max(cptvec)): cptsizes[i] = np.size(np.where(cptvec == i + 1)) return cptvec, cptsizes
def find_motif34(m, n=None): ''' This function returns all motif isomorphs for a given motif id and class (3 or 4). The function also returns the motif id for a given motif matrix 1. Input: Motif_id, e.g. 1 to 13, if class is 3 Motif_class, number of nodes, 3 or 4. Output: Motif_matrices, all isomorphs for the given motif 2. Input: Motif_matrix e.g. [0 1 0; 0 0 1; 1 0 0] Output Motif_id e.g. 1 to 13, if class is 3 Parameters ---------- m : int | matrix In use case 1, a motif_id which is an integer. In use case 2, the entire matrix of the motif (e.g. [0 1 0; 0 0 1; 1 0 0]) n : int | None In use case 1, the motif class, which is the number of nodes. This is either 3 or 4. In use case 2, None. Returns ------- M : np.ndarray | int In use case 1, returns all isomorphs for the given motif In use case 2, returns the motif_id for the specified motif matrix ''' from scipy import io import os fname = os.path.join(os.path.dirname(__file__), motiflib) z = (0,) if n == 3: mot = io.loadmat(fname) m3 = mot['m3'] id3 = mot['id3'].squeeze() ix, = np.where(id3 == m) M = np.zeros((3, 3, len(ix))) for i, ind in enumerate(ix): M[:, :, i] = np.reshape(np.concatenate( (z, m3[ind, 0:3], z, m3[ind, 3:6], z)), (3, 3)) elif n == 4: mot = io.loadmat(fname) m4 = mot['m4'] id4 = mot['id4'].squeeze() ix, = np.where(id4 == m) M = np.zeros((4, 4, len(ix))) for i, ind in enumerate(ix): M[:, :, i] = np.reshape(np.concatenate( (z, m4[ind, 0:4], z, m4[ind, 4:8], z, m4[ind, 8:12], z)), (4, 4)) elif n is None: try: m = np.array(m) except TypeError: raise BCTParamError('motif matrix must be an array-like') if m.shape[0] == 3: M, = np.where(motif3struct_bin(m)) elif m.shape[0] == 4: M, = np.where(motif4struct_bin(m)) else: raise BCTParamError('motif matrix must be 3x3 or 4x4') else: raise BCTParamError('Invalid motif class, must be 3, 4, or None') return M
def generative_model(A, D, m, eta, gamma=None, model_type='matching', model_var='powerlaw', epsilon=1e-6, copy=True, seed=None): ''' Generates synthetic networks using the models described in Betzel et al. (2016) Neuroimage. See this paper for more details. Succinctly, the probability of forming a connection between nodes u and v is P(u,v) = E(u,v)**eta * K(u,v)**gamma where eta and gamma are hyperparameters, E(u,v) is the euclidean or similar distance measure, and K(u,v) is the algorithm that defines the model. This describes the power law formulation, an alternative formulation uses the exponential function P(u,v) = exp(E(u,v)*eta) * exp(K(u,v)*gamma) Parameters ---------- A : np.ndarray Binary network of seed connections D : np.ndarray Matrix of euclidean distances or other distances between nodes m : int Number of connections that should be present in the final synthetic network eta : np.ndarray A vector describing a range of values to estimate for eta, the hyperparameter describing exponential weighting of the euclidean distance. gamma : np.ndarray A vector describing a range of values to estimate for theta, the hyperparameter describing exponential weighting of the basis algorithm. If model_type='euclidean' or another distance metric, this can be None. model_type : Enum(str) euclidean : Uses only euclidean distances to generate connection probabilities neighbors : count of common neighbors matching : matching index, the normalized overlap in neighborhoods clu-avg : Average clustering coefficient clu-min : Minimum clustering coefficient clu-max : Maximum clustering coefficient clu-diff : Difference in clustering coefficient clu-prod : Product of clustering coefficient deg-avg : Average degree deg-min : Minimum degree deg-max : Maximum degree deg-diff : Difference in degree deg-prod : Product of degrees model_var : Enum(str) Default value is powerlaw. If so, uses formulation of P(u,v) as described above. Alternate value is exponential. If so, uses P(u,v) = exp(E(u,v)*eta) * exp(K(u,v)*gamma) epsilon : float A small positive value added to all P(u,v). The default value is 1e-6 copy : bool Some algorithms add edges directly to the input matrix. Set this flag to make a copy of the input matrix instead. Defaults to True. seed : hashable, optional If None (default), use the np.random's global random state to generate random numbers. Otherwise, use a new np.random.RandomState instance seeded with the given value. ''' rng = get_rng(seed) if copy: A = A.copy() n = len(D) #These parameters don't do any of the voronoi narrowing. #Its a list of eta values paired with gamma values. #To try 3 eta and 3 gamma pairs, should use 9 list values. if len(eta) != len(gamma): raise BCTParamError('Eta and gamma hyperparameters must be lists of ' 'the same size') nparams = len(eta) B = np.zeros((n, n, nparams)) def k_avg(K): return ((np.tile(K, (n, 1)) + np.transpose(np.tile(K, (n, 1)))) / 2 + epsilon) def k_diff(K): return np.abs(np.tile(K, (n, 1)) - np.transpose(np.tile(K, (n, 1)))) + epsilon def k_max(K): return np.max(np.dstack( (np.tile(K, (n, 1)), np.transpose(np.tile(K, (n, 1))))), axis=2) + epsilon def k_min(K): return np.min(np.dstack( (np.tile(K, (n, 1)), np.transpose(np.tile(K, (n, 1))))), axis=2) + epsilon def k_prod(K): return np.outer(K, np.transpose(K)) + epsilon def s_avg(K, sc): return (K + sc) / 2 + epsilon def s_diff(K, sc): return np.abs(K - sc) + epsilon def s_min(K, sc): return np.where(K < sc, K + epsilon, sc + epsilon) def s_max(K, sc): #return np.max((K, sc.T), axis=0) return np.where(K > sc, K + epsilon, sc + epsilon) def s_prod(K, sc): return K * sc + epsilon def x_avg(K, ixes): nr_ixes = np.size(np.where(ixes)) Ksc = np.tile(K, (nr_ixes, 1)) Kix = np.transpose(np.tile(K[ixes], (n, 1))) return s_avg(Ksc, Kix) def x_diff(K, ixes): nr_ixes = np.size(np.where(ixes)) Ksc = np.tile(K, (nr_ixes, 1)) Kix = np.transpose(np.tile(K[ixes], (n, 1))) return s_diff(Ksc, Kix) def x_max(K, ixes): nr_ixes = np.size(np.where(ixes)) Ksc = np.tile(K, (nr_ixes, 1)) Kix = np.transpose(np.tile(K[ixes], (n, 1))) return s_max(Ksc, Kix) def x_min(K, ixes): nr_ixes = np.size(np.where(ixes)) Ksc = np.tile(K, (nr_ixes, 1)) Kix = np.transpose(np.tile(K[ixes], (n, 1))) return s_min(Ksc, Kix) def x_prod(K, ixes): nr_ixes = np.size(np.where(ixes)) Ka = np.reshape(K[ixes], (nr_ixes, 1)) Kb = np.reshape(np.transpose(K), (1, n)) return np.outer(Ka, Kb) + epsilon def clu_gen(A, K, D, m, eta, gamma, model_var, x_fun): mseed = np.size(np.where(A.flat)) // 2 A = A > 0 if type(model_var) == tuple: mv1, mv2 = model_var else: mv1, mv2 = model_var, model_var if mv1 in ('powerlaw', 'power_law'): Fd = D**eta elif mv1 in ('exponential', ): Fd = np.exp(eta * D) if mv2 in ('powerlaw', 'power_law'): Fk = K**gamma elif mv2 in ('exponential', ): Fk = np.exp(gamma * K) c = clustering_coef_bu(A) k = np.sum(A, axis=1) Ff = Fd * Fk * np.logical_not(A) u, v = np.where(np.triu(np.ones((n, n)), 1)) #print(mseed, m) for i in range(mseed + 1, m): C = np.append(0, np.cumsum(Ff[u, v])) r = np.sum(rng.random_sample() * C[-1] >= C) uu = u[r] vv = v[r] A[uu, vv] = A[vv, uu] = 1 k[uu] += 1 k[vv] += 1 bu = A[uu, :].astype(bool) bv = A[vv, :].astype(bool) su = A[np.ix_(bu, bu)] sv = A[np.ix_(bu, bu)] bth = np.logical_and(bu, bv) c[bth] += 2 / (k[bth]**2 - k[bth]) c[uu] = np.size(np.where(su.flat)) / (k[uu] * (k[uu] - 1)) c[vv] = np.size(np.where(sv.flat)) / (k[vv] * (k[vv] - 1)) c[k <= 1] = 0 bth[uu] = 1 bth[vv] = 1 k_result = x_fun(c, bth) #print(np.shape(k_result)) #print(np.shape(K)) #print(K) #print(np.shape(K[bth,:])) K[bth, :] = k_result K[:, bth] = k_result.T if mv2 in ('powerlaw', 'power_law'): Ff[bth, :] = Fd[bth, :] * K[bth, :]**gamma Ff[:, bth] = Fd[:, bth] * K[:, bth]**gamma elif mv2 in ('exponential', ): Ff[bth, :] = Fd[bth, :] * np.exp(K[bth, :]) * gamma Ff[:, bth] = Fd[:, bth] * np.exp(K[:, bth]) * gamma Ff = Ff * np.logical_not(A) return A def deg_gen(A, K, D, m, eta, gamma, model_var, s_fun): mseed = np.size(np.where(A.flat)) // 2 k = np.sum(A, axis=1) if type(model_var) == tuple: mv1, mv2 = model_var else: mv1, mv2 = model_var, model_var if mv1 in ('powerlaw', 'power_law'): Fd = D**eta elif mv1 in ('exponential', ): Fd = np.exp(eta * D) if mv2 in ('powerlaw', 'power_law'): Fk = K**gamma elif mv2 in ('exponential', ): Fk = np.exp(gamma * K) P = Fd * Fk * np.logical_not(A) u, v = np.where(np.triu(np.ones((n, n)), 1)) b = np.zeros((m, ), dtype=int) # print(mseed) # print(np.shape(u),np.shape(v)) # print(np.shape(b)) # print(np.shape(A[u,v])) # print(np.shape(np.where(A[u,v])), 'sqishy') # print(np.shape(P), 'squnnaq') #b[:mseed] = np.where(A[np.ix_(u,v)]) b[:mseed] = np.squeeze(np.where(A[u, v])) #print(mseed, m) for i in range(mseed, m): C = np.append(0, np.cumsum(P[u, v])) r = np.sum(rng.random_sample() * C[-1] >= C) uu = u[r] vv = v[r] k[uu] += 1 k[vv] += 1 if mv2 in ('powerlaw', 'power_law'): Fk[:, uu] = Fk[uu, :] = s_fun(k, k[uu])**gamma Fk[:, vv] = Fk[vv, :] = s_fun(k, k[vv])**gamma elif mv2 in ('exponential', ): Fk[:, uu] = Fk[uu, :] = np.exp(s_fun(k, k[uu]) * gamma) Fk[:, vv] = Fk[vv, :] = np.exp(s_fun(k, k[vv]) * gamma) P = Fd * Fk b[i] = r P[u[b[:i]], v[b[:i]]] = P[v[b[:i]], u[b[:i]]] = 0 A[u[r], v[r]] = A[v[r], u[r]] = 1 #P[b[u[:i]], b[v[:i]]] = P[b[v[:i]], b[u[:i]]] = 0 #A[uu,vv] = A[vv,uu] = 1 # indx = v*n + u # indx[b] # # nH = np.zeros((n,n)) # nH.ravel()[indx[b]]=1 # # nG = np.zeros((n,n)) # nG[ u[b], v[b] ]=1 # nG = nG + nG.T # # print(np.shape(np.where(A != nG))) # # import pdb # pdb.set_trace() return A def matching_gen(A, K, D, m, eta, gamma, model_var): K += epsilon mseed = np.size(np.where(A.flat)) // 2 if type(model_var) == tuple: mv1, mv2 = model_var else: mv1, mv2 = model_var, model_var if mv1 in ('powerlaw', 'power_law'): Fd = D**eta elif mv1 in ('exponential', ): Fd = np.exp(eta * D) if mv2 in ('powerlaw', 'power_law'): Fk = K**gamma elif mv2 in ('exponential', ): Fk = np.exp(gamma * K) Ff = Fd * Fk * np.logical_not(A) u, v = np.where(np.triu(np.ones((n, n)), 1)) for ii in range(mseed, m): C = np.append(0, np.cumsum(Ff[u, v])) r = np.sum(rng.random_sample() * C[-1] >= C) uu = u[r] vv = v[r] A[uu, vv] = A[vv, uu] = 1 updateuu, = np.where(np.inner(A, A[:, uu])) np.delete(updateuu, np.where(updateuu == uu)) np.delete(updateuu, np.where(updateuu == vv)) c1 = np.append(A[:, uu], A[uu, :]) for i in range(len(updateuu)): j = updateuu[i] c2 = np.append(A[:, j], A[j, :]) use = np.logical_or(c1, c2) use[uu] = use[uu + n] = use[j] = use[j + n] = 0 ncon = np.sum(c1[use]) + np.sum(c2[use]) if ncon == 0: K[uu, j] = K[j, uu] = epsilon else: K[uu, j] = K[j, uu] = ( 2 / ncon * np.sum(np.logical_and(c1[use], c2[use])) + epsilon) updatevv, = np.where(np.inner(A, A[:, vv])) np.delete(updatevv, np.where(updatevv == uu)) np.delete(updatevv, np.where(updatevv == vv)) c1 = np.append(A[:, vv], A[vv, :]) for i in range(len(updatevv)): j = updatevv[i] c2 = np.append(A[:, j], A[j, :]) use = np.logical_or(c1, c2) use[vv] = use[vv + n] = use[j] = use[j + n] = 0 ncon = np.sum(c1[use]) + np.sum(c2[use]) if ncon == 0: K[vv, j] = K[j, vv] = epsilon else: K[vv, j] = K[j, vv] = ( 2 / ncon * np.sum(np.logical_and(c1[use], c2[use])) + epsilon) Ff = Fd * Fk * np.logical_not(A) return A def neighbors_gen(A, K, D, m, eta, gamma, model_var): K += epsilon mseed = np.size(np.where(A.flat)) // 2 if type(model_var) == tuple: mv1, mv2 = model_var else: mv1, mv2 = model_var, model_var if mv1 in ('powerlaw', 'power_law'): Fd = D**eta elif mv1 in ('exponential', ): Fd = np.exp(eta * D) if mv2 in ('powerlaw', 'power_law'): Fk = K**gamma elif mv2 in ('exponential', ): Fk = np.exp(gamma * K) Ff = Fd * Fk * np.logical_not(A) u, v = np.where(np.triu(np.ones((n, n)), 1)) for ii in range(mseed, m): C = np.append(0, np.cumsum(Ff[u, v])) r = np.sum(rng.random_sample() * C[-1] >= C) uu = u[r] vv = v[r] A[uu, vv] = A[vv, uu] = 1 x = A[uu, :].astype(int) y = A[:, vv].astype(int) K[uu, y] += 1 K[y, uu] += 1 K[vv, x] += 1 K[x, vv] += 1 if mv2 in ('powerlaw', 'power_law'): Fk = K**gamma elif mv2 in ('exponential', ): Fk = np.exp(gamma * K) if mv2 in ('powerlaw', 'power_law'): Ff[uu, y] = Ff[y, uu] = Fd[uu, y] * (K[uu, y]**gamma) Ff[vv, x] = Ff[x, vv] = Fd[vv, x] * (K[vv, x]**gamma) elif mv2 in ('exponential', ): Ff[uu, y] = Ff[y, uu] = Fd[uu, y] * np.exp(gamma * K[uu, y]) Ff[vv, x] = Ff[x, vv] = Fd[vv, x] * np.exp(gamma * K[vv, x]) Ff[np.where(A)] = 0 return A def euclidean_gen(A, D, m, eta, model_var): mseed = np.size(np.where(A.flat)) // 2 if type(model_var) == tuple: mv1, mv2 = model_var else: mv1, mv2 = model_var, model_var if mv1 != mv2: raise BCTParamError('Too many hyperparameters specified') if mv1 in ('powerlaw', 'power_law'): Fd = D**eta elif mv1 in ('exponential', ): Fd = np.exp(eta**D) u, v = np.where(np.triu(np.ones((n, n)), 1)) P = Fd * np.logical_not(A) b = np.zeros((m, ), dtype=int) b[:mseed] = np.squeeze(np.where(A[u, v])) for i in range(mseed, m): C = np.append(0, np.cumsum(P[u, v])) r = np.sum(rng.random_sample() * C[-1] >= C) b[i] = r P = Fd P[u[b[:i]], v[b[:i]]] = P[v[b[:i]], u[b[:i]]] = 0 A[u[r], v[r]] = A[v[r], u[r]] = 1 return A if model_type in ('clu-avg', 'clu_avg'): Kseed = k_avg(clustering_coef_bu(A)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = clu_gen(A, Kseed, D, m, ep, gp, model_var, x_avg) elif model_type in ('clu-diff', 'clu_diff'): Kseed = k_diff(clustering_coef_bu(A)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = clu_gen(A, Kseed, D, m, ep, gp, model_var, x_diff) elif model_type in ('clu-max', 'clu_max'): Kseed = k_max(clustering_coef_bu(A)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = clu_gen(A, Kseed, D, m, ep, gp, model_var, x_max) elif model_type in ('clu-min', 'clu_min'): Kseed = k_min(clustering_coef_bu(A)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = clu_gen(A, Kseed, D, m, ep, gp, model_var, x_min) elif model_type in ('clu-prod', 'clu_prod'): Kseed = k_prod(clustering_coef_bu(A)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = clu_gen(A, Kseed, D, m, ep, gp, model_var, x_prod) elif model_type in ('deg-avg', 'deg_avg'): Kseed = k_avg(np.sum(A, axis=1)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = deg_gen(A, Kseed, D, m, ep, gp, model_var, s_avg) elif model_type in ('deg-diff', 'deg_diff'): Kseed = k_diff(np.sum(A, axis=1)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = deg_gen(A, Kseed, D, m, ep, gp, model_var, s_diff) elif model_type in ('deg-max', 'deg_max'): Kseed = k_max(np.sum(A, axis=1)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = deg_gen(A, Kseed, D, m, ep, gp, model_var, s_max) elif model_type in ('deg-min', 'deg_min'): Kseed = k_min(np.sum(A, axis=1)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = deg_gen(A, Kseed, D, m, ep, gp, model_var, s_min) elif model_type in ('deg-prod', 'deg_prod'): Kseed = k_prod(np.sum(A, axis=1)) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = deg_gen(A, Kseed, D, m, ep, gp, model_var, s_prod) elif model_type in ('neighbors', ): Kseed = np.inner(A, A) np.fill_diagonal(Kseed, 0) for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = neighbors_gen(A, Kseed, D, m, ep, gp, model_var) elif model_type in ('matching', 'matching-ind', 'matching_ind'): mi, _, _ = matching_ind(A) Kseed = mi + mi.T for j, (ep, gp) in enumerate(zip(eta, gamma)): B[:, :, j] = matching_gen(A, Kseed, D, m, ep, gp, model_var) elif model_type in ('spatial', 'geometric', 'euclidean'): for j, ep in enumerate(eta): B[:, :, j] = euclidean_gen(A, D, m, ep, model_var) return np.squeeze(B)