def relaxation_vectors(A, R, k, alpha): """Generate test vectors by relaxing on Ax=0 for some random vectors x. Parameters ---------- A : {csr_matrix} Sparse NxN matrix alpha : scalar Weight for Jacobi R : integer Number of random vectors k : integer Number of relaxation passes Returns ------- x : {array} Dense array N x k array of relaxation vectors """ # random n x R block in column ordering n = A.shape[0] x = np.random.rand(n * R) - 0.5 x = np.reshape(x, (n, R), order='F') # for i in range(R): # x[:,i] = x[:,i] - np.mean(x[:,i]) b = np.zeros((n, 1)) for r in range(0, R): jacobi(A, x[:, r], b, iterations=k, omega=alpha) # x[:,r] = x[:,r]/norm(x[:,r]) return x
def algebraic_distance(A, alpha=0.5, R=5, k=20, theta=0.1, p=2): """Construct an AMG strength of connection matrix using an algebraic distance measure. Parameters ---------- A : {csr_matrix} Sparse NxN matrix alpha : scalar Weight for Jacobi R : integer Number of random vectors k : integer Number of relaxation passes theta : scalar Drop values larger than theta p : scalar or inf p-norm of the measure Returns ------- C : {csr_matrix} Sparse matrix of strength values References ---------- .. [1] "Advanced Coarsening Schemes for Graph Partitioning" by Ilya Safro, Peter Sanders, and Christian Schulz Notes ----- No unit testing yet. Does not handle BSR matrices yet. """ print(A.format) if not sparse.isspmatrix_csr(A): warn("Implicit conversion of A to csr", sparse.SparseEfficiencyWarning) A = sparse.csr_matrix(A) if alpha < 0: raise ValueError('expected alpha>0') if R <= 0 or not isinstance(R, int): raise ValueError('expected integer R>0') if k <= 0 or not isinstance(k, int): raise ValueError('expected integer k>0') if theta < 0: raise ValueError('expected theta>0.0') if p < 1: raise ValueError('expected p>1 or equal to numpy.inf') # random n x R block in column ordering n = A.shape[0] x = np.random.rand(n * R) - 0.5 x = np.reshape(x, (n, R), order='F') b = np.zeros((n, 1)) # relax k times for r in range(0, R): jacobi(A, x[:, r], b, iterations=k, omega=alpha) # get distance measure d C = A.tocoo() I = C.row J = C.col # TODO : this is not right vvvvvvv if p != np.inf: d = np.sum((x[I] - x[J])**p, axis=1)**(1.0/p) else: d = np.abs(x[I] - x[J]).max(axis=1) del d # drop weak connections larger than theta weak = np.where(C.data > theta)[0] C.data[weak] = 0 C = C.tocsr() C.eliminate_zeros() # Strength represents "distance", so take the magnitude C.data = np.abs(C.data) # Standardized strength values require small values be weak and large # values be strong. So, we invert the distances. C.data = 1.0/C.data # Put an identity on the diagonal C = C + sparse.eye(C.shape[0], C.shape[1], format='csr') # Scale C by the largest magnitude entry in each row C = scale_rows_by_largest_entry(C) return C