def test_geigh_Lsym_bp(): Xs = [ np.random.uniform(size=(4, 5)), np.random.uniform(size=(5, 5)), np.random.uniform(size=(5, 1)) ] for X in Xs: Lsym = get_sym_laplacian_bp(X) true_evals, true_evecs = eigh_wrapper(Lsym, rank=None) for rank in range(1, sum(X.shape) + 1): gevals, gevecs = geigh_Lsym_bp(X, rank=rank, zero_tol=1e-10, end='largest') check_geigh_Lsym_internal_no_zeros(X, gevals, gevecs, rank) assert np.allclose(gevals[:rank], true_evals[:rank]) gevals, gevecs = geigh_Lsym_bp(X, rank=rank, zero_tol=1e-10, end='smallest') check_geigh_Lsym_internal_no_zeros(X, gevals, gevecs, rank) assert np.allclose(gevals[:rank], true_evals[-rank:]) rank = None gevals, gevecs = geigh_Lsym_bp(X, rank=rank, zero_tol=1e-10, end='largest') check_geigh_Lsym_internal_no_zeros(X, gevals, gevecs, rank) gevals, gevecs = geigh_Lsym_bp(X, rank=rank, zero_tol=1e-10, end='smallest') check_geigh_Lsym_internal_no_zeros(X, gevals, gevecs, rank) # test with zero rows/cols X = deepcopy(Xs)[0] X[0, :] = 0 X[:, 0] = 0 true_gevals, true_zero_mask = true_gevals_Lsym(X) for rank in range(1, 7 + 1): # make sure gen evals are correct gevals, gevecs = geigh_Lsym_bp(X, rank=rank, zero_tol=1e-10, end='largest') # check_geigh_Lsym_internal(X, gevals, gevecs, rank=rank) assert np.allclose(gevals, true_gevals[:rank]) # check gen evecs have correct zero rows assert np.allclose(abs(gevecs[true_zero_mask]).sum(), 0)
def check_vs_internal_smallest_eigh_Lsym_bp_from_Tsym_no_zeros(X, rank): """ Checks internal consistency """ evals, evecs = smallest_eigh_Lsym_bp_from_Tsym_no_zeros(X, rank=rank) if rank is None: rank = min(X.shape) Lsym = get_sym_laplacian_bp(X) assert len(evals) == rank assert evecs.shape[0] == sum(X.shape) assert evecs.shape[1] == rank for k in range(rank): v = evecs[:, k] q = Lsym @ v / v # check that v is an eigenvector # note 0 entries give infs so we ignore these for checking idx = np.where(abs(v) > 1e-10)[0][0] # for non nan for i in range(len(q)): assert np.allclose(v[i], 0) or np.allclose(q[i], q[idx]) # make sure the empirical eval is equal to the returned evals assert np.allclose(q[idx], evals[k]) assert np.allclose(evecs.T @ evecs, np.eye(rank))
def true_gevals_Lsym(X, zero_tol=1e-10): Lsym = get_sym_laplacian_bp(X) true_evals, true_evecs = eigh_wrapper(Lsym, rank=None) zero_row_mask = np.linalg.norm(X, axis=1) < zero_tol zero_col_mask = np.linalg.norm(X, axis=0) < zero_tol n_iso_verts = sum(zero_row_mask) + sum(zero_col_mask) meow = max(X.shape) - n_iso_verts true_gevals = np.concatenate([ true_evals[0:meow], [1] * (max(X.shape) - min(X.shape)), true_evals[-meow:] ]) true_gevals = np.sort(true_gevals)[::-1] true_zero_mask = np.concatenate([zero_row_mask, zero_col_mask]) return true_gevals, true_zero_mask
def check_eigh_Lsym_bp_from_Tsym(X, rank=None): """ Checks the output of get_sym_laplacian_bp """ Lsym = get_sym_laplacian_bp(X) true_evals, true_evecs = eigh_wrapper(Lsym) if rank is None: _rank = min(X.shape) else: _rank = rank # check largest eigenvectors evals, evecs = eigh_Lsym_bp_from_Tsym(X, end='largest', rank=rank) for k in range(len(evals)): # check the evals are correct assert np.allclose(evals[k], true_evals[k]) if not np.allclose(evals[k], 1): # non-unique subspace for 1 evals # check eigenvectors point in the same direction a = angle(true_evecs[:, k], evecs[:, k], subspace=True) assert a < 1e-4 # check normalization assert np.allclose(evecs.T @ evecs, np.eye(evecs.shape[1])) # check smallest eigenvectors evals, evecs = eigh_Lsym_bp_from_Tsym(X, end='smallest', rank=rank) base_idx = sum(X.shape) - min(X.shape) + (min(X.shape) - _rank) for k in range(len(evals)): # check the evals are correct assert np.allclose(evals[k], true_evals[base_idx + k]) if not np.allclose(evals[k], 1): # non-unique subspace for 1 evals # check eigenvectors point in the same direction a = angle(true_evecs[:, base_idx + k], evecs[:, k], subspace=True) assert a < 1e-4 # check normalization assert np.allclose(evecs.T @ evecs, np.eye(evecs.shape[1]))
def check_vs_truth_smallest_eigh_Lsym_bp_from_Tsym_no_zeros(X, rank): """ Check against ground truth """ evals, evecs = smallest_eigh_Lsym_bp_from_Tsym_no_zeros(X, rank=rank) if rank is None: rank = min(X.shape) Lsym = get_sym_laplacian_bp(X) evals_true, evecs_true = eigh_wrapper(A=Lsym) evals_true = evals_true[-rank:] evecs_true = evecs_true[:, -rank:] # check gevals match true gecals assert np.allclose(evals, evals_true) # check evecs span the correct space for k in range(rank): # ignore 1 evals since the evecs are non-unique if not np.allclose(evals[k], 1): assert angle(evecs[:, k], evecs_true[:, k], subspace=True) < 1e-4