├── .gitignore
├── MANIFEST.in
├── README.md
├── docs
├── Makefile
├── make.bat
└── source
│ ├── conf.py
│ ├── dynamics.rst
│ ├── examples.rst
│ ├── imgs
│ ├── heuns_tf.png
│ ├── kpm_dos.png
│ ├── stdog.png
│ ├── stdog_logo_100.png
│ ├── stdog_logo_200.png
│ ├── stdog_logo_36.ico
│ ├── stdog_logo_36.png
│ └── stdog_logo_50.png
│ ├── index.rst
│ ├── install.rst
│ ├── spectra.rst
│ └── utils.rst
├── readthedocs.yml
├── requirements.txt
├── requirements_docs.txt
├── setup.py
├── stdog.svg
├── stdog
├── __init__.py
├── dynamics
│ ├── __init__.py
│ └── kuramoto
│ │ ├── __init__.py
│ │ ├── cuheuns.py
│ │ ├── heuns.py
│ │ └── tfops
│ │ ├── __init__.py
│ │ ├── heuns.py
│ │ └── misc.py
├── spectra
│ ├── __init__.py
│ ├── dos.py
│ └── trace_function.py
└── utils
│ ├── __init__.py
│ ├── misc.py
│ └── tfops
│ ├── __init__.py
│ └── misc.py
├── stdog_logo.png
└── stdog_logo.svg
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | # Byte-compiled / optimized / DLL files
3 | __pycache__/
4 | *.py[cod]
5 | *$py.class
6 |
7 | # C extensions
8 | *.so
9 |
10 | # Distribution / packaging
11 | .Python
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .coverage
43 | .coverage.*
44 | .cache
45 | nosetests.xml
46 | coverage.xml
47 | *.cover
48 | .hypothesis/
49 | .pytest_cache/
50 |
51 | # Translations
52 | *.mo
53 | *.pot
54 |
55 | # Django stuff:
56 | *.log
57 | local_settings.py
58 | db.sqlite3
59 |
60 | # Flask stuff:
61 | instance/
62 | .webassets-cache
63 |
64 | # Scrapy stuff:
65 | .scrapy
66 |
67 | # Sphinx documentation
68 | docs/_build/
69 |
70 | # PyBuilder
71 | target/
72 |
73 | # Jupyter Notebook
74 | .ipynb_checkpoints
75 |
76 | # pyenv
77 | .python-version
78 |
79 | # celery beat schedule file
80 | celerybeat-schedule
81 |
82 | # SageMath parsed files
83 | *.sage.py
84 |
85 | # Environments
86 | .env
87 | .venv
88 | env/
89 | venv/
90 | ENV/
91 | env.bak/
92 | venv.bak/
93 |
94 | # Spyder project settings
95 | .spyderproject
96 | .spyproject
97 |
98 | # Rope project settings
99 | .ropeproject
100 |
101 | # mkdocs documentation
102 | /site
103 |
104 | # mypy
105 | .mypy_cache/
106 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README.md
2 | include docs/source/imgs/kpm_dos.png
3 | include docs/source/imgs/stdog.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 
2 | # Structure and Dynamics on Graphs (Beta)
3 |
4 | The main goal of StDoG is to provide a package which can be used to study
5 | dynamical and structural properties (like spectra) on graphs with a large
6 | number of vertices. The modules of StDoG are being built by
7 | combining codes written in *Tensorflow* + *CUDA* and *C++*.
8 |
9 | ## 1 - Install
10 |
11 | ```
12 | pip install stdog
13 | ```
14 |
15 | ## 2 - Examples
16 |
17 | ### 2.1 - Dynamics
18 |
19 | #### 2.1.1 - Kuramoto
20 |
21 | ##### Tensorflow
22 | ```python
23 | import numpy as np
24 | import igraph as ig
25 | from stdog.utils.misc import ig2sparse #Function to convert igraph format to sparse matrix
26 |
27 |
28 | num_couplings = 40
29 | N = 20480
30 |
31 | G = ig.Graph.Erdos_Renyi(N, 3/N)
32 | adj = ig2sparse(G)
33 |
34 | omegas = np.random.normal(size= N).astype("float32")
35 | couplings = np.linspace(0.0,4.,num_couplings)
36 | phases = np.array([
37 | np.random.uniform(-np.pi,np.pi,N)
38 | for i_l in range(num_couplings)
39 |
40 | ],dtype=np.float32)
41 |
42 |
43 | precision =32
44 |
45 | dt = 0.01
46 | num_temps = 50000
47 | total_time = dt*num_temps
48 | total_time_transient = total_time
49 | transient = False
50 | ```
51 |
52 | ```python
53 | from stdog.dynamics.kuramoto import Heuns
54 |
55 | heuns_0 = Heuns(adj, phases, omegas, couplings, total_time, dt,
56 | device="/gpu:0", # or /cpu:
57 | precision=precision, transient=transient)
58 |
59 | heuns_0.run()
60 | heuns_0.transient = True
61 | heuns_0.total_time = total_time_transient
62 | heuns_0.run()
63 | order_parameter_list = heuns_0.order_parameter_list # (num_couplings, total_time//dt)
64 | ```
65 | ```python
66 | import matplotlib.pyplot as plt
67 |
68 | r = np.mean(order_parameter_list, axis=1)
69 | stdr = np.std(order_parameter_list, axis=1)
70 |
71 | plt.ion()
72 | fig, ax1 = plt.subplots()
73 | ax1.plot(couplings,r,'.-')
74 | ax2 = ax1.twinx()
75 | ax2.plot(couplings,stdr,'r.-')
76 | plt.show()
77 | ```
78 | 
79 |
80 | #### CUDA - Faster than Tensorflow implementation
81 |
82 | If CUDA is available. You can install our another package,
83 | [stdogpkg/cukuramoto](https://github.com/stdogpkg/cukuramoto) (C)
84 | ```
85 | pip install cukuramoto
86 | ```
87 |
88 | ```python
89 | from stdog.dynamics.kuramoto.cuheuns import CUHeuns as cuHeuns
90 |
91 | heuns_0 = cuHeuns(adj, phases, omegas, couplings,
92 | total_time, dt, block_size = 1024, transient = False)
93 |
94 | heuns_0.run()
95 |
96 | heuns_0.transient = True
97 | heuns_0.total_time = total_time_transient
98 | heuns_0.run()
99 | order_parameter_list = heuns_0.order_parameter_list #
100 | ```
101 | ### 2.2 Spectral
102 |
103 | #### Spectral Density
104 |
105 | The Kernel Polynomial Method [1] can estimate the spectral density of large sparse Hermitan matrices with a computational cost almost linear. This method combines three key ingredients: the Chebyshev expansion + the stochastic trace estimator [2] + kernel smoothing.
106 |
107 | ```python
108 | import igraph as ig
109 | import numpy as np
110 |
111 | N = 3000
112 | G = ig.Graph.Erdos_Renyi(N, 3/N)
113 |
114 | W = np.array(G.get_adjacency().data, dtype=np.float64)
115 | vals = np.linalg.eigvalsh(W).real
116 | ```
117 |
118 | ```python
119 | import stdog.spectra as spectra
120 | from stdog.utils.misc import ig2sparse
121 |
122 | W = ig2sparse(G)
123 | num_moments = 300
124 | num_vecs = 200
125 | extra_points = 10
126 | ek, rho = spectra.dos.kpm(W, num_moments, num_vecs, extra_points, device="/gpu:0")
127 | ```
128 |
129 | ```python
130 | import matplotlib.pyplot as plt
131 | plt.hist(vals, density=True, bins=100, alpha=.9, color="steelblue")
132 | plt.scatter(ek, rho, c="tomato", zorder=999, alpha=0.9, marker="d")
133 | plt.ylim(0, 1)
134 | plt.show()
135 | ```
136 | 
137 | #### Trace Functions through Stochastic Lanczos Quadrature (SLQ)[3]
138 |
139 |
140 | ##### Computing custom trace functions
141 |
142 | ```python
143 | from stdog.spectra.trace_function import slq
144 | import tensorflow as tf
145 |
146 | def trace_function(eig_vals):
147 | return tf.exp(eig_vals)
148 |
149 | num_vecs = 100
150 | num_steps = 50
151 | approximated_estrada_index, _ = slq(L_sparse, num_vecs, num_steps, trace_function, device="/gpu:0")
152 | exact_estrada_index = np.sum(np.exp(vals_laplacian))
153 | approximated_estrada_index, exact_estrada_index
154 | ```
155 | The above code returns
156 |
157 | ```
158 | (3058.012, 3063.16457163222)
159 | ```
160 | ##### Entropy
161 | ```python
162 | import scipy
163 | import scipy.sparse
164 | from stdog.spectra.trace_function import entropy as slq_entropy
165 |
166 | def entropy(eig_vals):
167 | s = 0.
168 | for val in eig_vals:
169 | if val > 0:
170 | s += -val*np.log(val)
171 | return s
172 |
173 | L = np.array(G.laplacian(normalized=True), dtype=np.float64)
174 | vals_laplacian = np.linalg.eigvalsh(L).real
175 |
176 | exact_entropy = entropy(vals_laplacian)
177 |
178 | L_sparse = scipy.sparse.coo_matrix(L)
179 |
180 | num_vecs = 100
181 | num_steps = 50
182 | approximated_entropy = slq_entropy(
183 | L_sparse, num_vecs, num_steps, device="/cpu:0")
184 |
185 | approximated_entropy, exact_entropy
186 | ```
187 | ```
188 | (-509.46283, -512.5283224633046)
189 | ```
190 |
191 | ## References
192 |
193 | 1 - Wang, L.W., 1994. Calculating the density of states and
194 | optical-absorption spectra of large quantum systems by the plane-wave moments
195 | method. Physical Review B, 49(15), p.10154.
196 |
197 | 2 - Hutchinson, M.F., 1990. A stochastic estimator of the trace of the
198 | influence matrix for laplacian smoothing splines. Communications in
199 | Statistics-Simulation and Computation, 19(2), pp.433-450.
200 |
201 | 3 - Ubaru, S., Chen, J., & Saad, Y. (2017). Fast Estimation of tr(f(A)) via Stochastic Lanczos Quadrature.
202 | SIAM Journal on Matrix Analysis and Applications, 38(4), 1075-1099.
203 |
204 |
205 | ## 3 - How to cite
206 |
207 | [Thomas Peron](https://tkdmperon.github.io/), [Bruno Messias](http://brunomessias.com/), Angélica S. Mata, [Francisco A. Rodrigues](http://conteudo.icmc.usp.br/pessoas/francisco/), and [Yamir Moreno](http://cosnet.bifi.es/people/yamir-moreno/). On the onset of synchronization of Kuramoto oscillators in scale-free networks. [arXiv:1905.02256](https://arxiv.org/abs/1905.02256) (2019).
208 |
209 | ## 4 - Acknowledgements
210 |
211 | This work has been supported also by FAPESP grants 11/50761-2 and 2015/22308-2. Research carriedout using the computational resources of the Center forMathematical Sciences Applied to Industry (CeMEAI)funded by FAPESP (grant 2013/07375-0).
212 |
213 | ### Responsible authors
214 |
215 | [@devmessias](https://github.com/devmessias), [@tkdmperon](https://github.com/tkdmperon)
216 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SOURCEDIR = source
8 | BUILDDIR = build
9 |
10 | # Put it first so that "make" without argument is like "make help".
11 | help:
12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13 |
14 | .PHONY: help Makefile
15 |
16 | # Catch-all target: route all unknown targets to Sphinx using the new
17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
18 | %: Makefile
19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Configuration file for the Sphinx documentation builder.
4 | #
5 | # This file does only contain a selection of the most common options. For a
6 | # full list see the documentation:
7 | # http://www.sphinx-doc.org/en/master/config
8 |
9 | # -- Path setup --------------------------------------------------------------
10 |
11 | # If extensions (or modules to document with autodoc) are in another directory,
12 | # add these directories to sys.path here. If the directory is relative to the
13 | # documentation root, use os.path.abspath to make it absolute, like shown here.
14 | #
15 | import os
16 | import sys
17 | sys.path.insert(0, os.path.abspath('../..'))
18 | sys.path.insert(0, os.path.abspath('..'))
19 | sys.setrecursionlimit(1500)
20 |
21 | # -- Project information -----------------------------------------------------
22 |
23 | project = 'StDoG'
24 | copyright = '2019, Bruno Messias; Thomas Peron'
25 | author = 'Bruno Messias; Thomas Peron'
26 |
27 | # The short X.Y version
28 | version = ''
29 | # The full version, including alpha/beta/rc tags
30 | release = '1.0.3'
31 |
32 |
33 | # -- General configuration ---------------------------------------------------
34 |
35 | # If your documentation needs a minimal Sphinx version, state it here.
36 | #
37 | # needs_sphinx = '1.0'
38 |
39 | # Add any Sphinx extension module names here, as strings. They can be
40 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
41 | # ones.
42 | extensions = [
43 | 'sphinx.ext.autodoc',
44 | # 'sphinx.ext.intersphinx',
45 | 'sphinx.ext.todo',
46 | 'sphinx.ext.mathjax',
47 | 'sphinx.ext.ifconfig',
48 | 'sphinx.ext.viewcode',
49 | 'sphinx.ext.githubpages',
50 | 'sphinxcontrib.napoleon',
51 | # 'sphinx.ext.napoleon',
52 | ]
53 | napoleon_google_docstring = False
54 |
55 | napoleon_numpy_docstring = True
56 | napoleon_include_init_with_doc = True
57 | napoleon_include_private_with_doc = False
58 | napoleon_include_special_with_doc = True
59 | napoleon_use_admonition_for_examples = True
60 | napoleon_use_admonition_for_notes = True
61 | napoleon_use_admonition_for_references = True
62 | napoleon_use_ivar = True
63 | napoleon_use_param = True
64 | napoleon_use_rtype = True
65 |
66 | # Add any paths that contain templates here, relative to this directory.
67 | templates_path = ['_templates']
68 |
69 | # The suffix(es) of source filenames.
70 | # You can specify multiple suffix as a list of string:
71 | #
72 | # source_suffix = ['.rst', '.md']
73 | source_suffix = '.rst'
74 |
75 | # The master toctree document.
76 | master_doc = 'index'
77 | html_logo = "imgs/stdog_logo_100.png"
78 | html_favicon = "imgs/stdog_logo_36.ico"
79 | # The language for content autogenerated by Sphinx. Refer to documentation
80 | # for a list of supported languages.
81 | #
82 | # This is also used if you do content translation via gettext catalogs.
83 | # Usually you set "language" from the command line for these cases.
84 | language = None
85 |
86 | # List of patterns, relative to source directory, that match files and
87 | # directories to ignore when looking for source files.
88 | # This pattern also affects html_static_path and html_extra_path.
89 | exclude_patterns = []
90 |
91 | # The name of the Pygments (syntax highlighting) style to use.
92 | pygments_style = None
93 |
94 |
95 | # -- Options for HTML output -------------------------------------------------
96 |
97 | # The theme to use for HTML and HTML Help pages. See the documentation for
98 | # a list of builtin themes.
99 | #
100 |
101 | html_theme = 'sphinx_rtd_theme'
102 |
103 |
104 | # Theme options are theme-specific and customize the look and feel of a theme
105 | # further. For a list of options available for each theme, see the
106 | # documentation.
107 | #
108 | # html_theme_options = {}
109 |
110 | # Add any paths that contain custom static files (such as style sheets) here,
111 | # relative to this directory. They are copied after the builtin static files,
112 | # so a file named "default.css" will overwrite the builtin "default.css".
113 | html_static_path = ['_static']
114 |
115 | # Custom sidebar templates, must be a dictionary that maps document names
116 | # to template names.
117 | #
118 | # The default sidebars (for documents that don't match any pattern) are
119 | # defined by theme itself. Builtin themes are using these templates by
120 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
121 | # 'searchbox.html']``.
122 | #
123 | # html_sidebars = {}
124 |
125 |
126 | # -- Options for HTMLHelp output ---------------------------------------------
127 |
128 | # Output file base name for HTML help builder.
129 | htmlhelp_basename = 'StDoGdoc'
130 |
131 |
132 | # -- Options for LaTeX output ------------------------------------------------
133 |
134 | latex_elements = {
135 | # The paper size ('letterpaper' or 'a4paper').
136 | #
137 | # 'papersize': 'letterpaper',
138 |
139 | # The font size ('10pt', '11pt' or '12pt').
140 | #
141 | # 'pointsize': '10pt',
142 |
143 | # Additional stuff for the LaTeX preamble.
144 | #
145 | # 'preamble': '',
146 |
147 | # Latex figure (float) alignment
148 | #
149 | # 'figure_align': 'htbp',
150 | }
151 |
152 | # Grouping the document tree into LaTeX files. List of tuples
153 | # (source start file, target name, title,
154 | # author, documentclass [howto, manual, or own class]).
155 | latex_documents = [
156 | (master_doc, 'StDoG.tex', 'StDoG Documentation',
157 | 'Bruno Messias; Thomas Peron', 'manual'),
158 | ]
159 |
160 |
161 | # -- Options for manual page output ------------------------------------------
162 |
163 | # One entry per manual page. List of tuples
164 | # (source start file, name, description, authors, manual section).
165 | man_pages = [
166 | (master_doc, 'stdog', 'StDoG Documentation',
167 | [author], 1)
168 | ]
169 |
170 |
171 | # -- Options for Texinfo output ----------------------------------------------
172 |
173 | # Grouping the document tree into Texinfo files. List of tuples
174 | # (source start file, target name, title, author,
175 | # dir menu entry, description, category)
176 | texinfo_documents = [
177 | (master_doc, 'StDoG', 'StDoG Documentation',
178 | author, 'StDoG', 'One line description of project.',
179 | 'Miscellaneous'),
180 | ]
181 |
182 |
183 | # -- Options for Epub output -------------------------------------------------
184 |
185 | # Bibliographic Dublin Core info.
186 | epub_title = project
187 |
188 | # The unique identifier of the text. This can be a ISBN number
189 | # or the project homepage.
190 | #
191 | # epub_identifier = ''
192 |
193 | # A unique identification for the text.
194 | #
195 | # epub_uid = ''
196 |
197 | # A list of files that should not be packed into the epub file.
198 | epub_exclude_files = ['search.html']
199 |
200 |
201 | # -- Extension configuration -------------------------------------------------
202 |
203 | # -- Options for intersphinx extension ---------------------------------------
204 |
205 | # Example configuration for intersphinx: refer to the Python standard library.
206 | #intersphinx_mapping = {'https://docs.python.org/': None}
207 |
208 | # -- Options for todo extension ----------------------------------------------
209 |
210 | # If true, `todo` and `todoList` produce output, else they produce nothing.
211 | todo_include_todos = True
212 |
--------------------------------------------------------------------------------
/docs/source/dynamics.rst:
--------------------------------------------------------------------------------
1 | ==========
2 | Dynamics
3 | ==========
4 |
5 | .. automodule:: stdog.dynamics.kuramoto.heuns
6 | :members:
7 |
8 | .. automodule:: stdog.dynamics.kuramoto.cuheuns
9 | :members:
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/source/examples.rst:
--------------------------------------------------------------------------------
1 | ========
2 | Examples
3 | ========
4 |
5 | Dynamics
6 | ========
7 |
8 |
9 |
10 | Kuramoto
11 | --------
12 |
13 | StDoG provides two implementations of Heun’s method. The
14 | first uses the TensorFlow. Therefore, it can be used with both
15 | CPU’s or GPU’s. The second implementation is a python wrapper to a
16 | CUDA code. The second (CUDA) is faster than TensorFlow implementation.
17 | However, a CUDA-compatible GPU is required
18 |
19 |
20 |
21 | Creating the data and setting the variables
22 |
23 | .. code-block:: python
24 |
25 | import numpy as np
26 | import igraph as ig
27 | from stdog.utils.misc import ig2sparse
28 | num_couplings = 40
29 | N = 20480
30 |
31 | G = ig.Graph.Erdos_Renyi(N, 3/N)
32 | adj = ig2sparse(G)
33 |
34 | omegas = np.random.normal(size= N).astype("float32")
35 | couplings = np.linspace(0.0,4.,num_couplings)
36 | phases = np.array([
37 | np.random.uniform(-np.pi,np.pi,N)
38 | for i_l in range(num_couplings)
39 |
40 | ],dtype=np.float32)
41 |
42 | precision =32
43 |
44 | dt = 0.01
45 | num_temps = 50000
46 | total_time = dt*num_temps
47 | total_time_transient = total_time
48 | transient = False
49 |
50 | Tensorflow implementation
51 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52 |
53 | .. code-block:: python
54 |
55 | from stdog.dynamics.kuramoto import Heuns
56 |
57 | heuns_0 = Heuns(adj, phases, omegas, couplings, total_time, dt,
58 | device="/gpu:0", # or /cpu:
59 | precision=precision, transient=transient)
60 |
61 | heuns_0.run()
62 | heuns_0.transient = True
63 | heuns_0.total_time = total_time_transient
64 | heuns_0.run()
65 | order_parameter_list = heuns_0.order_parameter_list
66 |
67 | Plotting the result
68 |
69 | .. code-block:: python
70 |
71 | import matplotlib.pyplot as plt
72 |
73 | r = np.mean(order_parameter_list, axis=1)
74 | stdr = np.std(order_parameter_list, axis=1)
75 |
76 | plt.ion()
77 | fig, ax1 = plt.subplots()
78 | ax1.plot(couplings,r,'.-')
79 | ax2 = ax1.twinx()
80 | ax2.plot(couplings,stdr,'r.-')
81 | plt.show()
82 |
83 | .. image:: imgs/heuns_tf.png
84 |
85 |
86 | CUDA implementation (faster)
87 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88 |
89 | For that, you need to install our another package,
90 | `cukuramoto http://github.com/stdogpkg/cukuramoto`
91 |
92 | .. code-block:: bash
93 |
94 | $ pip install cukuramoto
95 |
96 | .. code-block:: python
97 |
98 | from stdog.dynamics.kuramoto.cuheuns import CUHeuns as cuHeuns
99 |
100 | heuns_0 = cuHeuns(adj, phases, omegas, couplings,
101 | total_time, dt, block_size = 1024, transient = False)
102 |
103 | heuns_0.run()
104 |
105 | heuns_0.transient = True
106 | heuns_0.total_time = total_time_transient
107 | heuns_0.run()
108 | order_parameter_list = heuns_0.order_parameter_list
109 |
110 | References
111 | ----------
112 |
113 | [1] - Thomas Peron, Bruno Messias, Angélica S. Mata, Francisco A. Rodrigues,
114 | and Yamir Moreno. On the onset of synchronization of Kuramoto oscillators in
115 | scale-free networks. arXiv:1905.02256 (2019).
116 |
117 |
118 |
119 | Spectra
120 | =======
121 |
122 |
123 | Spectral Density
124 | ----------------
125 |
126 |
127 | The Kernel Polynomial Method can estimate the spectral density of large
128 | sparse Hermitan matrices with a computational cost almost linear. This method
129 | combines three key ingredients: the Chebyshev expansion + the stochastic
130 | trace estimator + kernel smoothing.
131 |
132 |
133 | .. code-block:: python
134 |
135 | import igraph as ig
136 | import numpy as np
137 |
138 | N = 3000
139 | G = ig.Graph.Erdos_Renyi(N, 3/N)
140 |
141 | W = np.array(G.get_adjacency().data, dtype=np.float64)
142 | vals = np.linalg.eigvalsh(W).real
143 |
144 | .. code-block:: python
145 |
146 | import stdog.spectra as spectra
147 | from stdog.utils.misc import ig2sparse
148 |
149 | W = ig2sparse(G)
150 | num_moments = 300
151 | num_vecs = 200
152 | extra_points = 10
153 | ek, rho = spectra.dos.kpm(W, num_moments, num_vecs, extra_points, device="/gpu:0")
154 |
155 |
156 | .. code-block:: python
157 |
158 | import matplotlib.pyplot as plt
159 | plt.hist(vals, density=True, bins=100, alpha=.9, color="steelblue")
160 | plt.scatter(ek, rho, c="tomato", zorder=999, alpha=0.9, marker="d")
161 | plt.ylim(0, 1)
162 | plt.show()
163 |
164 |
165 | .. image:: imgs/kpm_dos.png
166 |
167 | References
168 | ----------
169 |
170 | [1] Wang, L.W., 1994. Calculating the density of states and
171 | optical-absorption spectra of large quantum systems by the plane-wave moments
172 | method. Physical Review B, 49(15), p.10154.
173 |
174 | [2] Hutchinson, M.F., 1990. A stochastic estimator of the trace of the
175 | influence matrix for laplacian smoothing splines. Communications in
176 | Statistics-Simulation and Computation, 19(2), pp.433-450.
177 |
178 | Trace Functions
179 | ---------------
180 | Given a semi-positive definite matrix :math:`A \in \mathbb R^{|V|\times|V|}`,
181 | which has the set of eigenvalues given by :math:`\{\lambda_i\}` a trace of
182 | a matrix function is given by
183 |
184 | .. math::
185 |
186 | \mathrm{tr}(f(A)) = \sum\limits_{i=0}^{|V|} f(\lambda_i)
187 |
188 | The methods for calculating such traces functions have a
189 | cubic computational complexity lower bound, :math:`O(|V|^3)`.
190 | Therefore, it is not feasible for large networks. One way
191 | to overcome such computational complexity it is use stochastic approximations
192 | combined with a mryiad of another methods
193 | to get the results with enough accuracy and with a small computational cost.
194 | The methods available in this module uses the Sthocastic Lanczos Quadrature,
195 | a procedure proposed in the work made by Ubaru, S. et.al. [1] (you need to cite them).
196 |
197 |
198 | Spectral Entropy
199 | ^^^^^^^^^^^^^^^^^
200 |
201 | .. code-block:: python
202 |
203 | import scipy
204 | import scipy.sparse
205 | import igraph as ig
206 | import numpy as np
207 |
208 | N = 3000
209 | G = ig.Graph.Erdos_Renyi(N, 3/N)
210 |
211 | .. code-block:: python
212 |
213 | from stdog.spectra.trace_function import entropy as slq_entropy
214 |
215 | def entropy(eig_vals):
216 | s = 0.
217 | for val in eig_vals:
218 | if val > 0:
219 | s += -val*np.log(val)
220 | return s
221 |
222 | L = np.array(G.laplacian(normalized=True), dtype=np.float64)
223 | vals_laplacian = np.linalg.eigvalsh(L).real
224 |
225 | exact_entropy = entropy(vals_laplacian)
226 |
227 | L_sparse = scipy.sparse.coo_matrix(L)
228 |
229 | num_vecs = 100
230 | num_steps = 50
231 | approximated_entropy = slq_entropy(
232 | L_sparse, num_vecs, num_steps, device="/cpu:0")
233 |
234 | approximated_entropy, exact_entropy
235 |
236 |
237 | The above code returns
238 |
239 | .. code-block:: bash
240 |
241 | (-509.46283, -512.5283224633046)
242 |
243 |
244 | Custom Trace Function
245 | ^^^^^^^^^^^^^^^^^^^^^^
246 |
247 | .. code-block:: python
248 |
249 | import tensorflow as tf
250 |
251 | from stdog.spectra.trace_function import slq
252 | def trace_function(eig_vals):
253 | return tf.exp(eig_vals)
254 |
255 |
256 | num_vecs = 100
257 | num_steps = 50
258 | approximated_trace_function, _ = slq(L_sparse, num_vecs, num_steps, trace_function)
259 |
260 |
261 | References
262 | -------------
263 |
264 | 1 - Ubaru, S., Chen, J., & Saad, Y. (2017). Fast Estimation of tr(f(A)) via Stochastic Lanczos Quadrature.
265 | SIAM Journal on Matrix Analysis and Applications, 38(4), 1075-1099.
266 |
267 | 2 - Hutchinson, M. F. (1990). A stochastic estimator of the trace of the
268 | influence matrix for laplacian smoothing splines. Communications in
269 | Statistics-Simulation and Computation, 19(2), 433-450.
270 |
--------------------------------------------------------------------------------
/docs/source/imgs/heuns_tf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/docs/source/imgs/heuns_tf.png
--------------------------------------------------------------------------------
/docs/source/imgs/kpm_dos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/docs/source/imgs/kpm_dos.png
--------------------------------------------------------------------------------
/docs/source/imgs/stdog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/docs/source/imgs/stdog.png
--------------------------------------------------------------------------------
/docs/source/imgs/stdog_logo_100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/docs/source/imgs/stdog_logo_100.png
--------------------------------------------------------------------------------
/docs/source/imgs/stdog_logo_200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/docs/source/imgs/stdog_logo_200.png
--------------------------------------------------------------------------------
/docs/source/imgs/stdog_logo_36.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/docs/source/imgs/stdog_logo_36.ico
--------------------------------------------------------------------------------
/docs/source/imgs/stdog_logo_36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/docs/source/imgs/stdog_logo_36.png
--------------------------------------------------------------------------------
/docs/source/imgs/stdog_logo_50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/docs/source/imgs/stdog_logo_50.png
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. meta::
2 | :description lang=en:
3 | StDoG is a package which can be used to study
4 | dynamical and structural properties (like spectra)
5 | on/off graphs with a large number of vertices.
6 |
7 | Home
8 | =====================================
9 |
10 | Strucutre and Dyanmics on Graphs
11 | ----------------------------------------
12 | .. image:: imgs/stdog.png
13 | :align: center
14 |
15 | The main goal of StDoG is to provide a package which can be used to study
16 | dynamical and structural properties (like spectra) on graphs with a large
17 | number of vertices. The modules of StDoG are being built by
18 | combining codes written in *Tensorflow* + *CUDA* and *C++*.
19 |
20 |
21 | The package is available as a pypi repository
22 |
23 | .. code-block:: bash
24 |
25 | $ pip install stdog
26 |
27 | The source code is available at http://github.com/stdogpkg.
28 |
29 | .. toctree::
30 | :hidden:
31 |
32 | self
33 |
34 | .. toctree::
35 | :maxdepth: 2
36 |
37 | install
38 | examples
39 |
40 | .. toctree::
41 | :maxdepth: 2
42 | :caption: Modules:
43 |
44 | dynamics
45 | spectra
46 | utils
47 |
48 |
49 |
--------------------------------------------------------------------------------
/docs/source/install.rst:
--------------------------------------------------------------------------------
1 | Install
2 | ========
3 |
4 | The package is available as as pypi repository
5 |
6 | .. code-block:: bash
7 |
8 | $ pip install stdog
9 |
10 | The source code is available at http://github.com/stdogpkg.
11 |
12 |
--------------------------------------------------------------------------------
/docs/source/spectra.rst:
--------------------------------------------------------------------------------
1 | ==========
2 | Spectra
3 | ==========
4 |
5 |
6 | The methods in this Spectra module uses our another package
7 | *eMaTe*, which is available at https://github.com/stdogpkg/emate .
8 |
9 |
10 | eMaTe is a python package implemented in tensorflow which the main goal is
11 | provide useful methods capable of estimate spectral densities and trace
12 | functions of large sparse matrices.
13 |
14 | .. automodule:: stdog.spectra.trace_function
15 | :members:
16 |
17 | .. automodule:: stdog.spectra.dos
18 | :members:
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/docs/source/utils.rst:
--------------------------------------------------------------------------------
1 | Utils
2 | ==========
3 |
4 | .. automodule:: stdog.utils.misc
5 | :members:
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/readthedocs.yml:
--------------------------------------------------------------------------------
1 |
2 | build:
3 | image: latest
4 |
5 | python:
6 | version: 3.6
7 | requirements_file: requirements_docs.txt
8 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | scipy
2 | numpy
3 | tensorflow
4 |
--------------------------------------------------------------------------------
/requirements_docs.txt:
--------------------------------------------------------------------------------
1 | sphinx-gallery
2 | sphinxcontrib-napoleon
3 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 |
4 | with open("README.md", "r") as f:
5 | README_TEXT = f.read()
6 |
7 | setup(
8 | name="stdog",
9 | version="v1.0.4",
10 | packages=find_packages(exclude=["build", ]),
11 | long_description=README_TEXT,
12 | long_description_content_type="text/markdown",
13 | install_requires=["tensorflow", "scipy", "numpy", "emate"],
14 | include_package_data=True,
15 | license="MIT",
16 | description="Structure and Dynamics on Graphs",
17 | author_email="messias.physics@gmail.com",
18 | author="Bruno Messias; Thomas K. Peron",
19 | download_url="https://github.com/stdogpkg/stdog/archive/v1.0.4.tar.gz",
20 | keywords=[
21 | "gpu", "science", "complex-networks", "graphs", "dynamics",
22 | "tensorflow", "kuramoto"
23 | ],
24 | classifiers=[
25 | "Development Status :: 4 - Beta",
26 | "License :: OSI Approved :: MIT License",
27 | "Intended Audience :: Science/Research",
28 | "Programming Language :: Python :: 3",
29 | "Topic :: Scientific/Engineering :: Physics",
30 | "Topic :: Scientific/Engineering :: Mathematics",
31 | "Topic :: Scientific/Engineering :: Information Analysis"
32 | ],
33 | url="https://github.com/stdogpkg/stdog"
34 | )
35 |
--------------------------------------------------------------------------------
/stdog.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/stdog/__init__.py:
--------------------------------------------------------------------------------
1 | from stdog import dynamics
2 | from stdog import spectra
3 | from stdog import utils
4 |
5 |
6 | __version__ = "1.0.4"
7 | __license__ = "MIT"
8 | __author__ = "Bruno Messias, Thomas K. Peron"
9 | __author_email__ = "messias.physics@gmail.com"
10 | __all__ = ["dynamics", "spectra", "utils"]
11 |
--------------------------------------------------------------------------------
/stdog/dynamics/__init__.py:
--------------------------------------------------------------------------------
1 | from stdog.dynamics import kuramoto
2 |
3 | __all__ = ["kuramoto"]
4 |
--------------------------------------------------------------------------------
/stdog/dynamics/kuramoto/__init__.py:
--------------------------------------------------------------------------------
1 | from stdog.dynamics.kuramoto import tfops
2 | from stdog.dynamics.kuramoto.heuns import Heuns
3 | from stdog.dynamics.kuramoto.cuheuns import CUHeuns
4 |
5 | __all__ = ["Heuns", "tfops", "CUHeuns"]
6 |
--------------------------------------------------------------------------------
/stdog/dynamics/kuramoto/cuheuns.py:
--------------------------------------------------------------------------------
1 | """
2 | ================================
3 | Kuramoto: Heun's method in CUDA
4 | ================================
5 |
6 | allow efficiently simulating phase oscillators
7 | (the Kuramoto model) on large heterogeneous networks using the
8 | Heun's method with a "pure" CUDA implementation. Should be
9 | faster than tensorflow implementation.
10 | References
11 | ----------
12 |
13 | [1] - Thomas Peron, Bruno Messias, Angélica S. Mata, Francisco A. Rodrigues,
14 | and Yamir Moreno. On the onset of synchronization of Kuramoto oscillators in
15 | scale-free networks. arXiv:1905.02256 (2019).
16 |
17 |
18 | """
19 | import numpy as np
20 | try:
21 | import cukuramoto
22 | except ImportError:
23 | pass
24 |
25 |
26 | class CUHeuns:
27 | """Allow efficiently simulating phase oscillators (the Kuramoto model) on
28 | large heterogeneous networks using the Heun’s method. This class uses a
29 | pure CUDA implementation of Heun’s method. Therefore, should be faster
30 | than TensorFlow implementation also provided by StDoG
31 |
32 | Attributes
33 | ----------
34 | adjacency : coo matrix
35 | phases : np.ndarray
36 | omegas : np.ndarray
37 | couplings : np.ndarray
38 | total_time : float
39 | dt : float
40 | transient : bool
41 | order_parameter_list : np.ndarray
42 |
43 | """
44 |
45 | def __init__(
46 | self,
47 | adjacency,
48 | phases,
49 | omegas,
50 | couplings,
51 | total_time,
52 | dt,
53 | transient=False,
54 | block_size=1024,
55 | ):
56 |
57 | self._adjacency = adjacency
58 | self._phases = phases.astype("float32")
59 | self._omegas = omegas.astype("float32")
60 | self._couplings = couplings.astype("float32")
61 | self.transient = transient
62 | self.total_time = total_time
63 | self.dt = dt
64 |
65 | self.block_size = block_size
66 |
67 | self.order_parameter_list = np.array([])
68 | self.create_simulation()
69 |
70 | @property
71 | def num_couplings(self):
72 | return len(self.couplings)
73 |
74 | @property
75 | def num_oscilators(self):
76 | return self.adjacency.shape[0]
77 |
78 | @property
79 | def num_temps(self):
80 | return int(self.total_time/self.dt)
81 |
82 | @property
83 | def phases(self):
84 | phases = self.simulation.get_phases().reshape(
85 | (self.num_couplings, self.num_oscilators)
86 | )
87 | self._phases = phases
88 | return phases
89 |
90 | @property
91 | def omegas(self):
92 | return self._omegas
93 |
94 | @omegas.setter
95 | def omegas(self, omegas):
96 | self._omegas = omegas.astype("float32")
97 | self.create_simulation()
98 |
99 | @property
100 | def couplings(self):
101 | return self._couplings
102 |
103 | @couplings.setter
104 | def couplings(self, couplings):
105 | self._couplings = couplings.astype("float32")
106 | self.create_simulation()
107 |
108 | @property
109 | def adjacency(self):
110 | return self._adjacency
111 |
112 | @adjacency.setter
113 | def adjacency(self, adjacency):
114 | self._adjacency = adjacency
115 | self.create_simulation()
116 |
117 | def create_simulation(self):
118 | """This method method crates the simulation.
119 | """
120 | adj = self.adjacency.tocsr()
121 | ptr, indices = adj.indptr.astype("int32"), adj.indices.astype("int32")
122 |
123 | simulation = cukuramoto.Heuns(
124 | self.num_oscilators, self.block_size, self.omegas,
125 | self._phases.flatten(), self.couplings, indices, ptr)
126 |
127 | self.simulation = simulation
128 |
129 | def run(self):
130 | """This runs the algorithm and updates the phases.
131 |
132 | If transiet is set to True, then the order parameters is
133 | calculated and the array order_parameter_list is updated.
134 | """
135 |
136 | if self.transient:
137 | order_parameter_list = self.simulation.get_order_parameter(
138 | self.num_temps, self.dt)
139 | self.order_parameter_list = order_parameter_list.reshape(
140 | (self.num_couplings, self.num_temps)
141 | )
142 | else:
143 | self.simulation.heuns(
144 | self.num_temps, self.dt)
145 |
146 | __all__ = ["CUHeuns"]
147 |
--------------------------------------------------------------------------------
/stdog/dynamics/kuramoto/heuns.py:
--------------------------------------------------------------------------------
1 | """
2 | =======================================
3 | Kuramoto: Heun's method in Tensorflow
4 | =======================================
5 |
6 | References
7 | ----------
8 |
9 | [1] - Thomas Peron, Bruno Messias, Angélica S. Mata, Francisco A. Rodrigues,
10 | and Yamir Moreno. On the onset of synchronization of Kuramoto oscillators in
11 | scale-free networks. arXiv:1905.02256 (2019).
12 |
13 |
14 | """
15 |
16 | import numpy as np
17 | import tensorflow as tf
18 |
19 | from .tfops.heuns import heuns_while, heuns_step
20 | from .tfops.misc import get_order_parameter
21 |
22 |
23 | class Heuns:
24 | """This class allow efficiently simulating phase oscillators
25 | (the Kuramoto model) on large heterogeneous networks using the
26 | Heun's method implemented in TensorFlow.
27 |
28 | Attributes
29 | ----------
30 | adjacency : coo matrix
31 | phases : np.ndarray
32 | omegas : np.ndarray
33 | couplings : np.ndarray
34 | total_time : float
35 | dt : float
36 | transient : bool
37 | frustation : bool
38 | device : str
39 | log : bool
40 | use_while : bool
41 | order_parameter_list : np.ndarray
42 |
43 | """
44 | def __init__(
45 | self,
46 | adjacency,
47 | phases,
48 | omegas,
49 | couplings,
50 | total_time,
51 | dt,
52 | transient=False,
53 | frustration=None,
54 | precision=32,
55 | device="/gpu:0",
56 | log=None,
57 | use_while=False,
58 | ):
59 |
60 | self.device = device
61 | self.log = log
62 | self.use_while = use_while
63 |
64 | self.adjacency = adjacency
65 | self.phases = phases
66 | self.omegas = omegas
67 | self.couplings = couplings
68 | self.frustration = frustration
69 | self.transient = transient
70 | self.total_time = total_time
71 | self.dt = dt
72 |
73 | self.num_couplings = len(self.couplings)
74 | self.num_oscilators = adjacency.shape[0]
75 |
76 | if precision == 64:
77 | self.complex_np_type = np.complex128
78 | self.complex_tf_type = tf.complex128
79 |
80 | self.real_np_type = np.float64
81 | self.real_tf_type = tf.float64
82 |
83 | self.int_tf_type = tf.int64
84 |
85 | elif precision == 32:
86 | self.complex_np_type = np.complex64
87 | self.complex_tf_type = tf.complex64
88 |
89 | self.real_np_type = np.float32
90 | self.real_tf_type = tf.float32
91 |
92 | self.int_tf_type = tf.int64
93 |
94 | else:
95 | raise Exception("Valid options for precision are: 32 or 64")
96 |
97 | self.omegas = np.array(
98 | self.omegas,
99 | dtype=self.real_np_type
100 | )
101 | self.order_parameter_list = np.array([])
102 | self.create_tf_graph()
103 |
104 | @property
105 | def num_temps(self):
106 | return int(self.total_time/self.dt)
107 |
108 | @property
109 | def frustration(self):
110 | return self.__frustration
111 |
112 | @frustration.setter
113 | def frustration(self, frustration):
114 |
115 | not_first_call = hasattr(self, "frustration")
116 | if not_first_call:
117 | old = self.__frustration is None
118 | new = frustration is None
119 | self.__frustration = frustration
120 |
121 | if not_first_call and (old ^ new):
122 | self.create_tf_graph()
123 | else:
124 | self.__frustration = frustration
125 |
126 | @property
127 | def transient(self):
128 | return self.__transient
129 |
130 | @transient.setter
131 | def transient(self, transient):
132 |
133 | not_first_call = hasattr(self, "transient")
134 | if not_first_call:
135 | old = self.__transient
136 | self.__transient = transient
137 |
138 | if not_first_call and (old ^ transient):
139 | self.create_tf_graph()
140 | else:
141 | self.__transient = transient
142 |
143 | def create_tf_graph(self):
144 | """
145 | This method creates the tensorflow graph
146 |
147 | """
148 | with tf.device(self.device):
149 | self.graph = tf.Graph()
150 |
151 | with self.graph.as_default():
152 |
153 | if self.frustration is not None:
154 | frustration = tf.placeholder(
155 | dtype=self.real_tf_type,
156 | shape=[self.num_couplings, self.num_oscilators],
157 | name="frustration"
158 | )
159 |
160 | else:
161 | frustration = None
162 |
163 | initial_phases = tf.placeholder(
164 | dtype=self.real_tf_type,
165 | shape=[self.num_couplings, self.num_oscilators],
166 | name="initial_phases"
167 | )
168 | omegas = tf.placeholder(
169 | shape=self.omegas.shape,
170 | dtype=self.real_tf_type,
171 | name="omegas"
172 | )
173 | couplings = tf.placeholder(
174 | shape=self.couplings.shape,
175 | dtype=self.real_tf_type,
176 | name="couplings"
177 | )
178 | dt = tf.placeholder(self.real_tf_type, shape=[], name="dt")
179 | sp_indices = tf.placeholder(dtype=tf.int64, name="sp_indices")
180 | sp_values = tf.placeholder(
181 | dtype=self.real_tf_type,
182 | name="sp_values"
183 | )
184 | adjacency = tf.SparseTensor(
185 | sp_indices,
186 | sp_values,
187 | dense_shape=np.array(self.adjacency.shape, dtype=np.int32)
188 | )
189 |
190 | pi2 = tf.constant(
191 | 2*np.pi,
192 | dtype=self.real_tf_type
193 | )
194 | dtDiv2 = tf.divide(
195 | dt, 2.
196 | )
197 |
198 | omegas = omegas[tf.newaxis:, ]
199 | omegasDouble = tf.multiply(
200 | 2., omegas
201 | )
202 | couplings = couplings[:, tf.newaxis]
203 |
204 | if self.use_while:
205 | num_temps = tf.placeholder(tf.int64, name="num_temps")
206 | self.tf_phases, self.tf_order_parameters = heuns_while(
207 | initial_phases,
208 | frustration,
209 | adjacency,
210 | couplings,
211 | omegas,
212 | dt,
213 | omegasDouble,
214 | dtDiv2,
215 | pi2,
216 | self.num_couplings,
217 | num_temps,
218 | transient=self.transient,
219 | tf_float=self.real_tf_type,
220 | tf_complex=self.complex_tf_type
221 | )
222 | else:
223 | phases = tf.Variable(
224 | np.zeros_like(self.phases),
225 | dtype=self.real_tf_type,
226 | name="phases"
227 | )
228 | assign_initial_phases = tf.assign(
229 | phases, initial_phases, name="assign_initial_phases")
230 |
231 | new_phases = heuns_step(
232 | phases, frustration, adjacency, couplings,
233 | omegas, dt, omegasDouble, dtDiv2, pi2)
234 |
235 | assign_new_phases = tf.assign(
236 | phases, new_phases, name="assign_new_phases")
237 |
238 | if self.transient:
239 | with tf.control_dependencies([assign_new_phases]):
240 | new_order_parameter = get_order_parameter(
241 | phases,
242 | tf_complex=self.complex_tf_type
243 | )
244 | new_order_parameter = tf.reshape(
245 | new_order_parameter, (
246 | self.num_couplings, 1),
247 | name="new_order_parameter"
248 | )
249 |
250 | def run(self):
251 | """This runs the algorithm and updates the phases.
252 |
253 | If transiet is set to True, then the order parameters is
254 | calculated and the array order_parameter_list is updated.
255 | """
256 | coo = self.adjacency.tocoo()
257 |
258 | sp_values = np.array(coo.data, dtype=self.real_np_type)
259 | sp_indices = np.mat([coo.row, coo.col], dtype=np.int64).transpose()
260 |
261 | with tf.Session(graph=self.graph) as sess:
262 | sess.run(tf.global_variables_initializer())
263 |
264 | if self.log is not None:
265 | tf.summary.FileWriter(self.log, sess.graph)
266 |
267 | if self.use_while:
268 | feed_dict = {
269 | "sp_values:0": sp_values,
270 | "sp_indices:0": sp_indices,
271 | "initial_phases:0": self.phases,
272 | "omegas:0": self.omegas,
273 | "couplings:0": self.couplings,
274 | "dt:0": self.dt,
275 | "num_temps:0": self.num_temps,
276 | }
277 |
278 | if self.frustration is not None:
279 | feed_dict["frustration:0"] = self.frustration
280 |
281 | phases, order_parameters = sess.run(
282 | [self.tf_phases, self.tf_order_parameters],
283 | feed_dict
284 | )
285 | self.phases = phases
286 | if self.transient:
287 | order_parameters = np.delete(
288 | order_parameters, (0), axis=1)
289 | self.order_parameter_list = order_parameters
290 | else:
291 | sess.run(
292 | "assign_initial_phases:0",
293 | feed_dict={"initial_phases:0": self.phases})
294 |
295 | feed_dict = {
296 | "sp_values:0": sp_values,
297 | "sp_indices:0": sp_indices,
298 | "omegas:0": self.omegas,
299 | "couplings:0": self.couplings,
300 | "dt:0": self.dt,
301 | }
302 | if self.frustration is not None:
303 | feed_dict["frustration:0"] = self.frustration
304 |
305 | for i_temp in range(self.num_temps):
306 | if self.transient:
307 | order_parameter = sess.run(
308 | "new_order_parameter:0", feed_dict)
309 | if self.order_parameter_list.shape[0] > 0:
310 | self.order_parameter_list = np.concatenate([
311 | self.order_parameter_list, order_parameter
312 | ], axis=1)
313 | else:
314 | self.order_parameter_list = order_parameter
315 |
316 | else:
317 | sess.run("assign_new_phases:0", feed_dict)
318 |
319 | self.phases = sess.run("phases:0")
320 |
321 |
322 | __all__ = ["Heuns"]
323 |
--------------------------------------------------------------------------------
/stdog/dynamics/kuramoto/tfops/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/stdog/dynamics/kuramoto/tfops/__init__.py
--------------------------------------------------------------------------------
/stdog/dynamics/kuramoto/tfops/heuns.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import tensorflow as tf
3 |
4 | from stdog.utils.tfops.misc import tfmod
5 | from .misc import get_order_parameter
6 |
7 |
8 | def heuns_evolve_vec(a, b, adjacency):
9 | with tf.name_scope("heuns_evolve_vec"):
10 | c = tf.sparse_tensor_dense_matmul(
11 | adjacency,
12 | tf.transpose(a),
13 | )
14 | c = tf.multiply(
15 | b,
16 | tf.transpose(c)
17 | )
18 |
19 | return c
20 |
21 |
22 | def heuns_evolve_m(phases, frustration, adjacency, couplings):
23 | with tf.name_scope("heuns_evolve_m"):
24 | if frustration is not None:
25 | phases = tf.add(phases, frustration)
26 |
27 | vs = tf.sin(phases)
28 | vc = tf.cos(phases)
29 |
30 | Ms = heuns_evolve_vec(vs, vc, adjacency)
31 | Mc = heuns_evolve_vec(vc, vs, adjacency)
32 |
33 | M = tf.multiply(
34 | tf.subtract(Ms, Mc),
35 | couplings
36 | )
37 |
38 | return M
39 |
40 |
41 | def update_phases(phases, dt, M, omegas):
42 | return tf.add(
43 | phases,
44 | tf.multiply(
45 | dt,
46 | tf.add(omegas, M)
47 | )
48 | )
49 |
50 |
51 | def heuns_step(
52 | phases, frustration, adjacency, couplings, omegas, dt, omegasDouble,
53 | dtDiv2, pi2):
54 |
55 | with tf.name_scope("heuns_step"):
56 | M = heuns_evolve_m(phases, frustration, adjacency, couplings)
57 |
58 | temporary_phases = update_phases(phases, dt, M, omegas)
59 |
60 | M2 = heuns_evolve_m(
61 | temporary_phases, frustration, adjacency, couplings)
62 |
63 | M = tf.add(M2, M)
64 |
65 | new_phases = update_phases(phases, dtDiv2, M, omegasDouble)
66 |
67 | return new_phases
68 |
69 |
70 | def heuns_while(
71 | phases, frustration, adjacency, couplings, omegas, dt,
72 | omegasDouble, dtDiv2, pi2,
73 | num_couplings, num_temps, transient=False, tf_float=tf.float32,
74 | tf_complex=tf.complex64):
75 | with tf.name_scope("heuns"):
76 | with tf.name_scope("init"):
77 | i_dt = tf.constant(0, dtype=tf.int64)
78 |
79 | order_parameters = tf.zeros(
80 | (num_couplings, 1),
81 | dtype=tf_float
82 | )
83 |
84 | def cond(phases, order_parameters, dt, i_dt, num_temps):
85 | return tf.less(i_dt, num_temps)
86 |
87 | def body(phases, order_parameters, dt, i_dt, num_temps):
88 | new_phases = heuns_step(
89 | phases, frustration, adjacency, couplings,
90 | omegas, dt, omegasDouble, dtDiv2, pi2)
91 |
92 | if transient:
93 | new_order_parameter = get_order_parameter(
94 | phases,
95 | tf_complex=tf_complex
96 | )
97 | new_order_parameter = tf.reshape(
98 | new_order_parameter, (num_couplings, 1)
99 | )
100 |
101 | order_parameters = tf.concat(
102 | [
103 | order_parameters, new_order_parameter
104 | ],
105 | axis=1
106 | )
107 | return [
108 | new_phases,
109 | order_parameters,
110 | dt,
111 | tf.add(i_dt, 1),
112 | num_temps
113 | ]
114 |
115 | phases, order_parameters, dt, i_dt, num_temps = tf.while_loop(
116 | cond,
117 | body,
118 | [
119 | phases,
120 | order_parameters,
121 | dt,
122 | i_dt,
123 | num_temps
124 | ],
125 | shape_invariants=[
126 | phases.get_shape(),
127 | tf.TensorShape([num_couplings, None]),
128 | dt.get_shape(),
129 | i_dt.get_shape(),
130 | num_temps.get_shape()
131 | ]
132 | )
133 |
134 | return phases, order_parameters
135 |
136 |
137 | __all__ = [
138 | "heuns_evolve_vec", "heuns_evolve_m", "heuns_step", "heuns_while"]
139 |
--------------------------------------------------------------------------------
/stdog/dynamics/kuramoto/tfops/misc.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 |
4 | def get_order_parameter(phases, tf_complex=tf.complex64):
5 | with tf.name_scope("get_order_parameter"):
6 | order_parameter = tf.exp(1j*tf.cast(
7 | phases,
8 | tf_complex
9 | )
10 | )
11 | order_parameter = tf.reduce_mean(
12 | order_parameter,
13 | axis=1
14 | )
15 |
16 | order_parameter = tf.abs(
17 | order_parameter,
18 | )
19 |
20 | return order_parameter
21 |
22 |
23 | __all__ = ["get_order_parameter"]
24 |
--------------------------------------------------------------------------------
/stdog/spectra/__init__.py:
--------------------------------------------------------------------------------
1 | from stdog.spectra import dos
2 | from stdog.spectra import trace_function
3 |
4 | __all__ = ["dos", "trace_function"]
5 |
6 |
--------------------------------------------------------------------------------
/stdog/spectra/dos.py:
--------------------------------------------------------------------------------
1 | """
2 | Spectral Density
3 | ================
4 |
5 | The Kernel Polynomial Method can estimate the spectral density of large
6 | sparse Hermitan matrices with a computational cost almost linear. This method
7 | combines three key ingredients: the Chebyshev expansion + the stochastic
8 | trace estimator + kernel smoothing.
9 |
10 | """
11 | from emate.hermitian.kpm import pykpm as kpm
12 |
13 | __all__ = ["kpm"]
--------------------------------------------------------------------------------
/stdog/spectra/trace_function.py:
--------------------------------------------------------------------------------
1 | """
2 | Trace Functions
3 | ==============================
4 |
5 | The core module responsible to calc trace functions.
6 |
7 |
8 | Given a semi-positive definite matrix :math:`A \in \mathbb R^{|V|\\times|V|}`,
9 | which has the set of eigenvalues given by :math:`\{\lambda_i\}` a trace of
10 | a matrix function is given by
11 |
12 | .. math::
13 |
14 | \mathrm{tr}(f(A)) = \sum\limits_{i=0}^{|V|} f(\lambda_i)
15 |
16 | The methods for calculating such traces functions have a
17 | cubic computational complexity lower bound, :math:`O(|V|^3)`.
18 | Therefore, it is not feasible for large networks. One way
19 | to overcome such computational complexity it is use stochastic approximations
20 | combined with a mryiad of another methods
21 | to get the results with enough accuracy and with a small computational cost.
22 | The methods available in this module uses the Sthocastic Lanczos Quadrature,
23 | a procedure proposed in the work made by Ubaru, S. et.al. [1] (you need to cite them).
24 |
25 | References
26 | -----------
27 |
28 | [1] Ubaru, S., Chen, J., & Saad, Y. (2017). Fast Estimation of tr(f(A)) via
29 | Stochastic Lanczos Quadrature. SIAM Journal on Matrix Analysis and
30 | Applications, 38(4), 1075-1099.
31 |
32 | [2] Hutchinson, M. F. (1990). A stochastic estimator of the trace of the
33 | influence matrix for laplacian smoothing splines. Communications in
34 | Statistics-Simulation and Computation, 19(2), 433-450.
35 | """
36 | import tensorflow as tf
37 | import numpy as np
38 |
39 | from emate.symmetric.slq import pyslq as slq
40 |
41 |
42 | def estrada_index(L, num_vecs=100, num_steps=50, device="/gpu:0"):
43 | """ Given the Laplacian matrix :math:`L \in \mathbb R^{|V|\\times |V|}` s.t. for all :math:`v \in \mathbb R^{|V|}` we have :math:`v^T L v > 0` the Estrada Index
44 | is given by
45 |
46 | .. math::
47 |
48 | \mathrm{tr}\exp(L) = \sum\limits_{i=0}^{|V|} e^{\lambda_i}
49 |
50 |
51 | Parameters
52 | ----------
53 | L: sparse matrix
54 | num_vecs: int
55 | Number of random vectors used to approximate the trace
56 | using the Hutchison's trick [1]
57 | num_steps: int
58 | Number of Lanczos steps or Chebyschev's moments
59 | device: str
60 | "/cpu:int" our "/gpu:int"
61 |
62 | Returns
63 | -------
64 | approximated_estrada_index: float
65 |
66 | References
67 | ----------
68 |
69 | 1 - Ubaru, S., Chen, J., & Saad, Y. (2017). Fast Estimation of tr(f(A)) via
70 | Stochastic Lanczos Quadrature. SIAM Journal on Matrix Analysis and Applications,
71 | 38(4), 1075-1099.
72 |
73 | 2 - Hutchinson, M. F. (1990). A stochastic estimator of the trace of the
74 | influence matrix for laplacian smoothing splines. Communications in
75 | Statistics-Simulation and Computation, 19(2), 433-450.
76 | """
77 | def trace_function(eig_vals):
78 | return tf.exp(eig_vals)
79 |
80 | approximated_estrada_index, _ = slq(
81 | L, num_vecs, num_steps, trace_function, device=device)
82 |
83 | return approximated_estrada_index
84 |
85 |
86 | def entropy(L_sparse, num_vecs=100, num_steps=50, device="/gpu:0"):
87 | """Compute the spectral entropy
88 |
89 | .. math::
90 |
91 | \sum\limits_{i=0}^{|V|} f(\lambda_i)
92 |
93 | f(\lambda) = \\begin{cases}
94 | -\lambda \log_2\lambda \ \ if \ \lambda > 0; \\newline
95 | 0,\ \ otherwise
96 | \end{cases}
97 |
98 | Parameters
99 | ----------
100 | L: sparse matrix
101 | num_vecs: int
102 | Number of random vectors used to approximate the trace
103 | using the Hutchison's trick [1]
104 | num_steps: int
105 | Number of Lanczos steps or Chebyschev's moments
106 | device: str
107 | "/cpu:int" our "/gpu:int"
108 |
109 | Returns
110 | -------
111 | approximated_spectral_entropy: float
112 |
113 | References
114 | ----------
115 |
116 | 1 - Ubaru, S., Chen, J., & Saad, Y. (2017). Fast Estimation of tr(f(A)) via
117 | Stochastic Lanczos Quadrature. SIAM Journal on Matrix Analysis and Applications,
118 | 38(4), 1075-1099.
119 |
120 | 2 - Hutchinson, M. F. (1990). A stochastic estimator of the trace of the
121 | influence matrix for laplacian smoothing splines. Communications in
122 | Statistics-Simulation and Computation, 19(2), 433-450.
123 | """
124 |
125 | def trace_function(eig_vals):
126 | return tf.map_fn(
127 | lambda val: tf.cond(
128 | val > 0,
129 | lambda: -val*tf.log(val),
130 | lambda: 0.),
131 | eig_vals)
132 |
133 | approximated_entropy, _ = slq(
134 | L_sparse, num_vecs, num_steps, trace_function, device=device)
135 |
136 | return approximated_entropy
137 |
138 |
139 | __all__ = ["slq", "entropy", "estrada_index"]
140 |
--------------------------------------------------------------------------------
/stdog/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/stdog/utils/__init__.py
--------------------------------------------------------------------------------
/stdog/utils/misc.py:
--------------------------------------------------------------------------------
1 | """
2 | Misc
3 | ======
4 |
5 | Contains tools to help some boring tasks
6 | """
7 | import numpy as np
8 | from scipy.sparse import coo_matrix
9 |
10 |
11 | def ig2sparse(G, transpose=False, attr=None, precision=32):
12 | """Given an igraph instance returns the sparse adjacency matrix
13 | in COO format.
14 |
15 | Parameters
16 | ----------
17 | G: igraph instance
18 | transpose : bool
19 | If the adjacency matrix should be transposed or not
20 | attr : str
21 | The name of weight attribute
22 | precision : int
23 | The precision used to store the weight attributes
24 |
25 | Returns
26 | --------
27 | L : COO Sparse matrix
28 |
29 |
30 | """
31 |
32 | if attr:
33 | source, target, data = zip(*[
34 | (e.source, e.target, e[attr])
35 | for e in G.es if not np.isnan(e[attr])
36 | ])
37 | else:
38 | source, target = zip(*[
39 | (e.source, e.target)
40 | for e in G.es
41 | ])
42 | data = np.ones(len(source)).astype('int').tolist()
43 |
44 | if not G.is_directed():
45 | source, target = source + target, target + source
46 | data = data + data
47 |
48 | if precision == 64:
49 | np_type = np.float64
50 | elif precision == 32:
51 | np_type = np.float32
52 |
53 | data = np.array(data, dtype=np_type)
54 | if transpose:
55 | L = coo_matrix(
56 | (data, (target, source)),
57 | shape=[G.vcount(), G.vcount()]
58 | )
59 | else:
60 | L = coo_matrix(
61 | (data, (source, target)),
62 | shape=[G.vcount(), G.vcount()]
63 | )
64 |
65 | return L
66 |
67 |
68 | __all__ = ["ig2sparse"]
69 |
--------------------------------------------------------------------------------
/stdog/utils/tfops/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/stdog/utils/tfops/misc.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 |
3 |
4 | def tfmod(vals, mod_int):
5 | with tf.name_scope("tfmod"):
6 | mod_vals = tf.subtract(
7 | vals, tf.multiply(tf.floordiv(vals, mod_int), mod_int)
8 | )
9 | return mod_vals
10 |
11 |
12 | __all__ = ["tfmod"]
13 |
--------------------------------------------------------------------------------
/stdog_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stdogpkg/stdog/775153945442c3941948ba07d3e791b92a8a904a/stdog_logo.png
--------------------------------------------------------------------------------
/stdog_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------