.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/vietoris_rips/plot_laplacian.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_vietoris_rips_plot_laplacian.py: Laplacian ========== The Laplacian of a simplicial complex `K` with boundary matrix `D` is the matrix `L = D^T D + D D^T`. OAT provides a matrix oracle that computes the entries of `L` in a lazy fashion, without storing them permanently in memory. .. GENERATED FROM PYTHON SOURCE LINES 12-26 .. code-block:: Python import oat_python as oat from fractions import Fraction import numpy as np import pandas as pd import plotly import plotly.subplots import plotly.graph_objects as go import scipy.sparse as sparse from scipy.sparse import diags from scipy.sparse.linalg import LinearOperator, eigsh import tqdm .. GENERATED FROM PYTHON SOURCE LINES 27-29 Generate a Vietoris-Rips complex ------------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 31-32 Fix a random seed for reproducibility .. GENERATED FROM PYTHON SOURCE LINES 34-36 .. code-block:: Python np.random.seed(0) .. GENERATED FROM PYTHON SOURCE LINES 37-38 Generate a point cloud .. GENERATED FROM PYTHON SOURCE LINES 40-43 .. code-block:: Python points = oat.point_cloud.circle( n_points=30, radius=1.0 ) points = points + np.random.normal( scale=0.1, size=points.shape ) # Add some noise .. GENERATED FROM PYTHON SOURCE LINES 44-45 Initialize a Vietoris-Rips complex .. GENERATED FROM PYTHON SOURCE LINES 47-57 .. code-block:: Python dissimilarity_matrix = oat.dissimilarity.sparse_matrix_for_points( points = points, max_dissimilarity = 1.0 ) vietoris_rips_complex = oat.core.vietoris_rips.VietorisRipsComplex( dissimilarity_matrix=dissimilarity_matrix, ) .. GENERATED FROM PYTHON SOURCE LINES 58-59 Plot the 1-skeleton of the Vietoris-Rips complex .. GENERATED FROM PYTHON SOURCE LINES 61-95 .. code-block:: Python # initialize an empty list of traces traces = [] # add a trace for the points traces.append( go.Scatter( x=points[:,0], y=points[:,1], mode='markers', name='Points' ) ) # plot the edges edges = vietoris_rips_complex \ .simplices_for_dimensions([1]) \ .simplex # this pulls out the "simplex" clolumn of the dataframe for edge in edges: trace = oat.plot.trace_2d_for_edge( edge=edge, points = points ) trace.update( line = dict( width=1, color='blue' ) ) traces.append(trace) # plot the traces fig = go.Figure(data=traces) fig.update_layout( title='1-Skeleton of Vietoris-Rips Complex', xaxis=dict(title='X'), yaxis=dict(title='Y'), width=600, height=600, ) fig .. raw:: html


.. GENERATED FROM PYTHON SOURCE LINES 96-98 Access the Laplacian ------------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 100-101 Initialize a Laplacian matrix oracle .. GENERATED FROM PYTHON SOURCE LINES 103-105 .. code-block:: Python laplacian_matrix_oracle = vietoris_rips_complex.laplacian_matrix_oracle() .. GENERATED FROM PYTHON SOURCE LINES 106-107 Look up a row .. GENERATED FROM PYTHON SOURCE LINES 109-112 .. code-block:: Python vector_dataframe = laplacian_matrix_oracle.row_for_simplex((0,)) vector_dataframe .. raw:: html
simplex filtration coefficient
0 (0,) 0.0 7.0
1 (1,) 0.0 -1.0
2 (2,) 0.0 -1.0
3 (3,) 0.0 -1.0
4 (4,) 0.0 -1.0
5 (27,) 0.0 -1.0
6 (28,) 0.0 -1.0
7 (29,) 0.0 -1.0


.. GENERATED FROM PYTHON SOURCE LINES 113-114 Multiply the Laplacian with a vector .. GENERATED FROM PYTHON SOURCE LINES 116-120 .. code-block:: Python product = laplacian_matrix_oracle \ .product_with_vector( vector_dataframe ) product .. raw:: html
simplex filtration coefficient
0 (0,) 0.0 56.0
1 (1,) 0.0 -10.0
2 (2,) 0.0 -10.0
3 (3,) 0.0 -12.0
4 (4,) 0.0 -13.0
5 (5,) 0.0 4.0
6 (6,) 0.0 4.0
7 (7,) 0.0 2.0
8 (8,) 0.0 2.0
9 (9,) 0.0 1.0
10 (23,) 0.0 1.0
11 (24,) 0.0 2.0
12 (25,) 0.0 3.0
13 (26,) 0.0 3.0
14 (27,) 0.0 -12.0
15 (28,) 0.0 -11.0
16 (29,) 0.0 -10.0


.. GENERATED FROM PYTHON SOURCE LINES 121-127 Compute an eigenvector ------------------------------------------ To do this we will use the power method built into Scipy. First define a function which takes a 1d numpy.ndarray as input and returns the Laplacian operator applied to it. .. GENERATED FROM PYTHON SOURCE LINES 129-142 .. code-block:: Python def laplacian_operator( v ): """ Evaluate the Laplacian operator on a 0-chain `v` represented as a 1-dimensional numpy.ndarray """ vector_dataframe = vietoris_rips_complex.simplices_for_dimensions(dimensions=[0]) vector_dataframe["coefficient"] = v product = laplacian_matrix_oracle.product_with_vector(vector_dataframe) return product.coefficient.to_numpy() .. GENERATED FROM PYTHON SOURCE LINES 143-144 Obtain eigenvalues and eigenvectors of the Laplacian operator using scipy's eigsh function. .. GENERATED FROM PYTHON SOURCE LINES 146-163 .. code-block:: Python import scipy.sparse as sparse import scipy.sparse.linalg from scipy.sparse.linalg import LinearOperator, eigsh node_dataframe = vietoris_rips_complex.simplices_for_dimensions( [0] ) n_nodes = node_dataframe.shape[0] scipy_operator = LinearOperator( shape = (n_nodes, n_nodes), matvec = laplacian_operator, ) eigvals, eigvecs = eigsh( scipy_operator, # the linear operator k=6, # first k eigenvalues which='SM', # 'SM' = smallest magnitude ) .. GENERATED FROM PYTHON SOURCE LINES 164-165 Plot the eigenvector. .. GENERATED FROM PYTHON SOURCE LINES 167-192 .. code-block:: Python node_list = [ simplex[0] for simplex in node_dataframe.simplex ] trace = go.Scatter( x = points[ node_list, [0] ], y = points[ node_list, [1] ], mode = 'markers', marker = dict( size = 10, color = eigvecs[:, 1], colorscale = 'Jet', colorbar = dict(title='Eigenvector Coefficient') ), name = 'Eigenvector Coefficient' ) fig = go.Figure(data=[trace]) fig.update_layout( title='Second Eigenvector of the Laplacian Operator', xaxis=dict(title='X'), yaxis=dict(title='Y'), width=700, height=600, ) fig .. raw:: html


.. GENERATED FROM PYTHON SOURCE LINES 193-195 Validate the oracle ------------------------------------------ .. GENERATED FROM PYTHON SOURCE LINES 197-198 We can also compute the Laplacian in a non-lazy fashion. First compute the dimension-1 boundary matrix. .. GENERATED FROM PYTHON SOURCE LINES 200-213 .. code-block:: Python d1 = vietoris_rips_complex \ .boundary_matrix_oracle() \ .write_submatrix_to_csr( vietoris_rips_complex.submatrix_index_tool( row_dimensions = [0], column_dimensions = [1] ) ) d1 .. rst-class:: sphx-glr-script-out .. code-block:: none <30x133 sparse matrix of type '' with 266 stored elements in Compressed Sparse Row format> .. GENERATED FROM PYTHON SOURCE LINES 214-215 Compute the Laplacian matrix for 0-chains: .. GENERATED FROM PYTHON SOURCE LINES 217-219 .. code-block:: Python scipy_zero_laplacian = d1 @ d1.T .. GENERATED FROM PYTHON SOURCE LINES 220-221 Verify that each row of the Laplacian oracle matches the corresponding row of the Scipy sparse matrix .. GENERATED FROM PYTHON SOURCE LINES 223-242 .. code-block:: Python vector_index_tool = vietoris_rips_complex.vector_index_tool(dimensions=[0]) for node_number in range(n_nodes): simplex = vector_index_tool \ .simplex_for_index_number(node_number) \ .simplex() row_dataframe = laplacian_matrix_oracle \ .row_for_simplex(simplex) row_dataframe["coefficient"] = row_dataframe["coefficient"].apply(lambda x: Fraction(x)) oracle_row = vector_index_tool \ .dense_array_for_dataframe(row_dataframe) \ .astype(float) scipy_row = scipy_zero_laplacian[node_number].todense() assert np.allclose(oracle_row, scipy_row, rtol=1e-5, atol=1e-8), \ f"Mismatch in row {node_number}: {oracle_row} vs {scipy_row}" .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.151 seconds) .. _sphx_glr_download_auto_examples_vietoris_rips_plot_laplacian.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_laplacian.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_laplacian.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_laplacian.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_