def test_line_graph(self): adjacency = [ [0, 1, 1, 3], [1, 0, 1, 0], [1, 1, 0, 1], [3, 0, 1, 0], ] coords = [ [0, 0], [4, 0], [4, 2], [0, 2], ] graph = graphs.Graph(adjacency, coords=coords) graph = graphs.LineGraph(graph) adjacency = [ [0, 1, 1, 1, 0], [1, 0, 1, 1, 1], [1, 1, 0, 0, 1], [1, 1, 0, 0, 1], [0, 1, 1, 1, 0], ] coords = [ [2, 0], [2, 1], [0, 1], [4, 1], [2, 2], ] np.testing.assert_equal(graph.W.toarray(), adjacency) np.testing.assert_equal(graph.coords, coords) if sys.version_info > (3, 4): # no assertLogs in python 2.7 with self.assertLogs(level='WARNING'): graphs.LineGraph(graphs.Graph([[0, 2], [2, 0]]))
def test_differential_operator(self, n_vertices=98): r"""The Laplacian must always be the divergence of the gradient, whether the Laplacian is combinatorial or normalized, and whether the graph is directed or weighted.""" def test_incidence_nx(graph): r"""Test that the incidence matrix corresponds to NetworkX.""" incidence_pg = np.sign(graph.D.toarray()) G = nx.OrderedDiGraph if graph.is_directed() else nx.OrderedGraph graph_nx = nx.from_scipy_sparse_matrix(graph.W, create_using=G) incidence_nx = nx.incidence_matrix(graph_nx, oriented=True) np.testing.assert_equal(incidence_pg, incidence_nx.toarray()) for graph in [ graphs.Graph(np.zeros((n_vertices, n_vertices))), graphs.Graph(np.identity(n_vertices)), graphs.Graph([[0, 0.8], [0.8, 0]]), graphs.Graph([[1.3, 0], [0.4, 0.5]]), graphs.ErdosRenyi(n_vertices, directed=False, seed=42), graphs.ErdosRenyi(n_vertices, directed=True, seed=42) ]: for lap_type in ['combinatorial', 'normalized']: graph.compute_laplacian(lap_type) graph.compute_differential_operator() L = graph.D.dot(graph.D.T) np.testing.assert_allclose(L.toarray(), graph.L.toarray()) test_incidence_nx(graph)
def test_is_connected(self): graph = graphs.Graph([ [0, 1, 0], [1, 0, 2], [0, 2, 0], ]) self.assertEqual(graph.is_directed(), False) self.assertEqual(graph.is_connected(), True) graph = graphs.Graph([ [0, 1, 0], [1, 0, 0], [0, 2, 0], ]) self.assertEqual(graph.is_directed(), True) self.assertEqual(graph.is_connected(), False) graph = graphs.Graph([ [0, 1, 0], [1, 0, 0], [0, 0, 0], ]) self.assertEqual(graph.is_directed(), False) self.assertEqual(graph.is_connected(), False) graph = graphs.Graph([ [0, 1, 0], [0, 0, 2], [3, 0, 0], ]) self.assertEqual(graph.is_directed(), True) self.assertEqual(graph.is_connected(), True)
def test_laplacian(self): adjacency = np.array([ [0, 3, 0, 1], [3, 0, 1, 0], [0, 1, 0, 3], [1, 0, 3, 0], ]) laplacian = np.array([ [+4, -3, +0, -1], [-3, +4, -1, +0], [+0, -1, +4, -3], [-1, +0, -3, +4], ]) G = graphs.Graph(adjacency) self.assertFalse(G.is_directed()) G.compute_laplacian('combinatorial') np.testing.assert_allclose(G.L.toarray(), laplacian) G.compute_laplacian('normalized') np.testing.assert_allclose(G.L.toarray(), laplacian / 4) adjacency = np.array([ [0, 6, 0, 1], [0, 0, 0, 0], [0, 2, 0, 3], [1, 0, 3, 0], ]) G = graphs.Graph(adjacency) self.assertTrue(G.is_directed()) G.compute_laplacian('combinatorial') np.testing.assert_allclose(G.L.toarray(), laplacian) G.compute_laplacian('normalized') np.testing.assert_allclose(G.L.toarray(), laplacian / 4) def test_combinatorial(G): np.testing.assert_equal(G.L.toarray(), G.L.T.toarray()) np.testing.assert_equal(G.L.sum(axis=0), 0) np.testing.assert_equal(G.L.sum(axis=1), 0) np.testing.assert_equal(G.L.diagonal(), G.dw) def test_normalized(G): np.testing.assert_equal(G.L.toarray(), G.L.T.toarray()) np.testing.assert_equal(G.L.diagonal(), 1) G = graphs.ErdosRenyi(100, directed=False) self.assertFalse(G.is_directed()) G.compute_laplacian(lap_type='combinatorial') test_combinatorial(G) G.compute_laplacian(lap_type='normalized') test_normalized(G) G = graphs.ErdosRenyi(100, directed=True) self.assertTrue(G.is_directed()) G.compute_laplacian(lap_type='combinatorial') test_combinatorial(G) G.compute_laplacian(lap_type='normalized') test_normalized(G)
def test_degree(self): W = 0.3 * (np.ones((4, 4)) - np.diag(4 * [1])) G = graphs.Graph(W) A = np.ones(W.shape) - np.diag(np.ones(4)) np.testing.assert_allclose(G.A.toarray(), A) np.testing.assert_allclose(G.d, 3 * np.ones([4])) np.testing.assert_allclose(G.dw, 3 * 0.3)
def test_empty_graph(self, n_vertices=11): """Empty graphs have either no edge, or self-loops only. The Laplacian doesn't see self-loops, as the gradient on those edges is always zero. """ adjacencies = [ np.zeros((n_vertices, n_vertices)), np.identity(n_vertices), ] for adjacency, n_edges in zip(adjacencies, [0, n_vertices]): graph = graphs.Graph(adjacency) self.assertEqual(graph.n_vertices, n_vertices) self.assertEqual(graph.n_edges, n_edges) self.assertEqual(graph.W.nnz, n_edges) for laplacian in ['combinatorial', 'normalized']: graph.compute_laplacian(laplacian) self.assertEqual(graph.L.nnz, 0) sources, targets, weights = graph.get_edge_list() self.assertEqual(len(sources), n_edges) self.assertEqual(len(targets), n_edges) self.assertEqual(len(weights), n_edges) graph.compute_differential_operator() self.assertEqual(graph.D.nnz, 0) graph.compute_fourier_basis() np.testing.assert_allclose(graph.U, np.identity(n_vertices)) np.testing.assert_allclose(graph.e, np.zeros(n_vertices)) # NetworkX uses the same conventions. G = nx.from_scipy_sparse_matrix(graph.W) self.assertEqual(nx.laplacian_matrix(G).nnz, 0) self.assertEqual(nx.normalized_laplacian_matrix(G).nnz, 0) self.assertEqual(nx.incidence_matrix(G).nnz, 0)
def models(N, graph_name, connected=True, default_params=False, k=12, sigma=0.5): tries = 0 while True: tries = tries + 1 if graph_name == "regular": if default_params: k = 10 offsets = [] for i in range(1, int(k / 2) + 1): offsets.append(i) offsets.append(-(N - i)) offsets = np.array(offsets) vals = np.ones_like(offsets) W = sp.sparse.diags( vals, offsets, shape=(N, N), format="csc", dtype=np.float ) W = (W + W.T) / 2 G = graphs.Graph(W=W) else: print("ERROR: uknown model") return if connected == False or G.is_connected(): break if tries > 1: print("WARNING: disconnected graph.. trying to use the giant component") G = graph_utils.get_giant_component(G) break return G
def test(adjacency): G = graphs.Graph(adjacency) G.compute_laplacian('combinatorial') G.compute_laplacian('normalized') G.estimate_lmax() G.compute_fourier_basis() G.compute_differential_operator()
def _tree_depths(A, root): if not graphs.Graph(A=A).is_connected(): raise ValueError('Graph is not connected') N = np.shape(A)[0] assigned = root - 1 depths = np.zeros((N)) parents = np.zeros((N)) next_to_expand = np.array([root]) current_depth = 1 while len(assigned) < N: new_entries_whole_round = [] for i in range(len(next_to_expand)): neighbors = np.where(A[next_to_expand[i]])[0] new_entries = np.setdiff1d(neighbors, assigned) parents[new_entries] = next_to_expand[i] depths[new_entries] = current_depth assigned = np.concatenate((assigned, new_entries)) new_entries_whole_round = np.concatenate((new_entries_whole_round, new_entries)) current_depth = current_depth + 1 next_to_expand = new_entries_whole_round return depths, parents
def test_default_graph(): W = np.arange(16).reshape(4, 4) G = graphs.Graph(W) ki, kj = np.nonzero(G.A) self.assertEqual(ki.shape[0], G.Ne) self.assertEqual(kj.shape[0], G.Ne) needed_attributes_testing(G)
def healpix_graph(nside=16, nest=True, lap_type='normalized', indexes=None, use_4=False, dtype=np.float32): """Build a healpix graph using the pygsp from NSIDE.""" from pygsp import graphs if indexes is None: indexes = range(nside**2 * 12) # 1) get the coordinates npix = hp.nside2npix(nside) # number of pixels: 12 * nside**2 pix = range(npix) x, y, z = hp.pix2vec(nside, pix, nest=nest) coords = np.vstack([x, y, z]).transpose()[indexes] # 2) computing the weight matrix if use_4: raise NotImplementedError() W = build_matrix_4_neighboors(nside, indexes, nest=nest, dtype=dtype) else: W = healpix_weightmatrix(nside=nside, nest=nest, indexes=indexes, dtype=dtype) # 3) building the graph G = graphs.Graph(W, lap_type=lap_type, coords=coords) return G
def test_degree(self): graph = graphs.Graph([ [0, 1, 0], [1, 0, 2], [0, 2, 0], ]) self.assertEqual(graph.is_directed(), False) np.testing.assert_allclose(graph.d, [1, 2, 1]) np.testing.assert_allclose(graph.dw, [1, 3, 2]) graph = graphs.Graph([ [0, 1, 0], [0, 0, 2], [0, 2, 0], ]) self.assertEqual(graph.is_directed(), True) np.testing.assert_allclose(graph.d, [0.5, 1.5, 1]) np.testing.assert_allclose(graph.dw, [0.5, 2.5, 2])
def test_graph(self): adjacency = [ [0., 3., 0., 2.], [3., 0., 4., 0.], [0., 4., 0., 5.], [2., 0., 5., 0.], ] # Input types. G = graphs.Graph(adjacency) self.assertIs(type(G.W), sparse.csr_matrix) adjacency = np.array(adjacency) G = graphs.Graph(adjacency) self.assertIs(type(G.W), sparse.csr_matrix) adjacency = sparse.coo_matrix(adjacency) G = graphs.Graph(adjacency) self.assertIs(type(G.W), sparse.csr_matrix) adjacency = sparse.csr_matrix(adjacency) # G = graphs.Graph(adjacency) # self.assertIs(G.W, adjacency) # Not copied if already CSR. # Attributes. np.testing.assert_allclose(G.W.toarray(), adjacency.toarray()) np.testing.assert_allclose(G.A.toarray(), G.W.toarray() > 0) np.testing.assert_allclose(G.d, np.array([2, 2, 2, 2])) np.testing.assert_allclose(G.dw, np.array([5, 7, 9, 7])) self.assertEqual(G.n_vertices, 4) self.assertIs(G.N, G.n_vertices) self.assertEqual(G.n_edges, 4) self.assertIs(G.Ne, G.n_edges) # Errors and warnings. self.assertRaises(ValueError, graphs.Graph, np.ones((3, 4))) self.assertRaises(ValueError, graphs.Graph, np.ones((3, 3, 4))) self.assertRaises(ValueError, graphs.Graph, [[0, np.nan], [0, 0]]) self.assertRaises(ValueError, graphs.Graph, [[0, np.inf], [0, 0]]) if sys.version_info > (3, 4): # no assertLogs in python 2.7 with self.assertLogs(level='WARNING'): graphs.Graph([[0, -1], [-1, 0]]) with self.assertLogs(level='WARNING'): graphs.Graph([[1, 1], [1, 0]]) for attr in ['A', 'd', 'dw', 'lmax', 'U', 'e', 'coherence', 'D']: # FIXME: The Laplacian L should be there as well. self.assertRaises(AttributeError, setattr, G, attr, None) self.assertRaises(AttributeError, delattr, G, attr)
def coarsening(args, adj): G = graphs.Graph(adj) C, Gc, Call, Gall = coarsen(G, K=args.K, r=args.ratio, method=args.method) adj_coarse = Gc.W n_nodes = adj_coarse.shape[0] D = sp.sparse.diags(np.array(1/(np.sum(C,0)+1))[0]) Pinv = C.dot(D) adj_temp = Pinv.dot(G.W) return adj_temp, adj_coarse, n_nodes
def test_default_graph(): W = np.arange(16).reshape(4, 4) G = graphs.Graph(W) self.assertEqual(G.W, sparse.lil_matrix(W)) self.assertEqual(G.A, G.W > 0) self.assertEqual(G.N, 4) self.assertEqual(G.d, [3, 4, 4, 4]) self.assertEqual(G.Ne, 15) self.assertTrue(G.directed)
def coarsening(args, adj): G = graphs.Graph(adj) C, Gc, Call, Gall = coarsen(G, K=args.K, r=args.ratio, method=args.method) adj_coarse = Gc.W n_nodes = adj_coarse.shape[0] D = sp.sparse.diags(np.array(1/np.sum(C,0))[0]) Pinv = C.dot(D) adj_temp = Pinv.dot(G.W) return torch.FloatTensor(np.array(adj_temp.todense())), torch.FloatTensor(adj_coarse.toarray()), n_nodes
def learn_graph(self, samples): adjency_matrix = sparse.lil_matrix((self.num_states, self.num_states)) for sample in samples: if sample.state[0] != sample.next_state[0]: adjency_matrix[sample.state[0], sample.next_state[0]] = 1. adjency_matrix[sample.next_state[0], sample.state[0]] = 1. return graphs.Graph(adjency_matrix)
def test_is_directed(self): graph = graphs.Graph([ [0, 3, 0, 0], [3, 0, 4, 0], [0, 4, 0, 2], [0, 0, 2, 0], ]) assert graph.W.nnz == 6 self.assertEqual(graph.is_directed(), False)
def _handle_directed(G): # FIXME: plot edge direction. For now we just symmetrize the weight matrix. if not G.is_directed(): return G else: from pygsp import graphs G2 = graphs.Graph(utils.symmetrize(G.W)) G2.coords = G.coords G2.plotting = G.plotting return G2
def coarsen_gso(gso, coarsening_ratio, method = 'variation_neighborhood', r= 0.5, k=10): S = (gso > 0).astype(int) np.fill_diagonal(S, 0) S = np.triu(S)+np.triu(S).T np.fill_diagonal(S, 0) S= coo_matrix(S) G = graphs.Graph(W = S) G.compute_fourier_basis() C, Gc, Call, Gall = coarsen(G, K=k, r=r, method=method) return C, Gc, Call, Gall
def tikhonov_diffusion(x_train, x_test, loss_fn, params): n_shot, n_val = int(x_train.shape[0]), int(x_test.shape[0]) x_latent = torch.cat([x_train, x_test], dim=0) weights = weights_from_loss_fn(x_latent, loss_fn, params.num_neighbors, regular=True, undirected=True, normalize_weights=False) graph = graphs.Graph(adjacency=weights.numpy()) mask = np.array([True]*n_shot + [False]*n_val) z_latent = learning.regression_tikhonov(graph, np.copy(x_latent.numpy()), mask, tau=1.) return torch.FloatTensor(z_latent)
def create_data_eeg_graph(montage, X, threshold=0.7): montage = mne.channels.read_montage(kind="standard_1005", ch_names=montage, unit="m") C = np.matmul(X, X.T) / X.shape[1] C = C - np.eye(C.shape[0]) C[C < threshold] = 0 G = graphs.Graph(C, lap_type="normalized", coords=montage.get_pos2d()) print("- Nodes:", G.N) print("- Edges:", G.Ne) return G
def test_graph(self): W = np.arange(16).reshape(4, 4) G = graphs.Graph(W) np.testing.assert_allclose(G.W.A, W) np.testing.assert_allclose(G.A.A, G.W.A > 0) self.assertEqual(G.N, 4) np.testing.assert_allclose(G.d, np.array([3, 4, 4, 4])) self.assertEqual(G.Ne, 15) self.assertTrue(G.is_directed()) ki, kj = np.nonzero(G.A) self.assertEqual(ki.shape[0], G.Ne) self.assertEqual(kj.shape[0], G.Ne)
def knn_graph(cloud, k=30, r=1, dist3D=True, mode='connectivity', neightype='number', lap_type='combinatorial', norm=False, sigma=None, plot_dist_ditrib=False, V=None): """ Construct graph using PyGSP toolbox from the adjacency matrix. Return: If the graph is normalized by the largest eigenvalue: - G : Graph constructed by PyGSP package - l : The largest eignevalue of the normalized graph, which is 1. Else, only return G """ W, _ = knn_w(cloud, k=k, r=r, dist3D=dist3D, mode=mode, neightype=neightype, sigma=sigma, plot_dist_ditrib=plot_dist_ditrib, V=V) G = graphs.Graph(W, lap_type=lap_type) G.estimate_lmax() if norm == True: l = G.lmax W = W / l G = graphs.Graph(W, lap_type=lap_type) G.estimate_lmax() return G, l else: return G
def test_regression_tikhonov_1(self): """Solve a trivial regression problem.""" G = graphs.Ring(N=8) signal = np.array([0, np.nan, 4, np.nan, 4, np.nan, np.nan, np.nan]) mask = np.array([True, False, True, False, True, False, False, False]) truth = np.array([0, 2, 4, 4, 4, 3, 2, 1]) recovery = learning.regression_tikhonov(G, signal, mask, tau=0) np.testing.assert_allclose(recovery, truth) # Test the numpy solution. G = graphs.Graph(G.W.toarray()) recovery = learning.regression_tikhonov(G, signal, mask, tau=0) np.testing.assert_allclose(recovery, truth)
def create_spatial_eeg_graph(montage, q=0.05, k=0.1): montage = mne.channels.read_montage(kind="standard_1005", ch_names=montage, unit="m") d = spdist.pdist(montage.pos) W = np.exp(-(d**2) / (2 * q**2)) W[d > k] = 0 W = spdist.squareform(W) G = graphs.Graph(W, lap_type="normalized", coords=montage.get_pos2d()) print("Created EEG-graph with q=%.2f and k=%.2f" % (q, k)) print("- Nodes:", G.N) print("- Edges:", G.Ne) return G
def test_estimate_lmax(self): graph = graphs.Sensor() self.assertRaises(ValueError, graph.estimate_lmax, method='unk') def check_lmax(graph, lmax): graph.estimate_lmax(method='bounds') np.testing.assert_allclose(graph.lmax, lmax) graph.estimate_lmax(method='lanczos') np.testing.assert_allclose(graph.lmax, lmax * 1.01) graph.compute_fourier_basis() np.testing.assert_allclose(graph.lmax, lmax) # Full graph (bound is tight). n_nodes, value = 10, 2 adjacency = np.full((n_nodes, n_nodes), value) graph = graphs.Graph(adjacency, lap_type='combinatorial') check_lmax(graph, lmax=value * n_nodes) # Regular bipartite graph (bound is tight). adjacency = [ [0, 0, 1, 1], [0, 0, 1, 1], [1, 1, 0, 0], [1, 1, 0, 0], ] graph = graphs.Graph(adjacency, lap_type='combinatorial') check_lmax(graph, lmax=4) # Bipartite graph (bound is tight). adjacency = [ [0, 0, 1, 1], [0, 0, 1, 0], [1, 1, 0, 0], [1, 0, 0, 0], ] graph = graphs.Graph(adjacency, lap_type='normalized') check_lmax(graph, lmax=2)
def learn_signal_TV(signal, adj, theta): gamma=1/theta d=pyunlocbox.functions.dummy() r=pyunlocbox.functions.norm_l1() f=pyunlocbox.functions.norm_l2(w=1, y=signal, lambda_=gamma) G = graphs.Graph(W=adj) G.compute_differential_operator() L=G.D.toarray() step=0.999/(1+np.linalg.norm(L)) solver=pyunlocbox.solvers.mlfbf(L=L, step=step) x0=signal.copy() prob=pyunlocbox.solvers.solve([d,r,f], solver=solver, x0=x0, rtol=0, maxit=1000) solution=prob['sol'] return solution
def learn_node_features_TV(signal, adj, theta, node_num, dimension, item_features): theta=3 d=pyunlocbox.functions.dummy() r=pyunlocbox.functions.norm_l1() f=pyunlocbox.functions.norm_l2(w=1, y=signal.T, lambda_=theta) G = graphs.Graph(W=adj) G.compute_differential_operator() L=G.D.toarray() step=0.999/(1+np.linalg.norm(L)) solver=pyunlocbox.solvers.mlfbf(L=L, step=step) x0=signal.copy().T prob=pyunlocbox.solvers.solve([d,r,f], solver=solver, x0=x0, rtol=0, maxit=10000) solution=prob['sol'] return solution
def learn_graph(self, sample_length, num_samples, sampling_policy): samples = [] for i in range(num_samples): sample = self.generate_samples(sample_length, sampling_policy) samples.extend(sample) adjency_matrix = sparse.lil_matrix((self.num_states, self.num_states)) for sample in samples: if sample.state[0] != sample.next_state[0]: adjency_matrix[sample.state[0], sample.next_state[0]] = 1. adjency_matrix[sample.next_state[0], sample.state[0]] = 1. return graphs.Graph(adjency_matrix)