diff --git a/Makefile b/Makefile index 564aeff77..7c3017595 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,13 @@ -all: test +.PHONY: all install docs lint format test clean FORCE + +all: docs test install: pip install -e .[dev] +docs: FORCE + $(MAKE) -C docs html + lint: FORCE flake8 @@ -23,6 +28,6 @@ test: lint FORCE @echo PASS clean: FORCE - git clean -dfx -e pyro-egg.info + git clean -dfx -e funsor-egg.info FORCE: diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 000000000..45893adae --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = funsor +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 000000000..f6cee192e --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build +set SPHINXPROJ=funsor + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/source/adjoint.rst b/docs/source/adjoint.rst new file mode 100644 index 000000000..c4f0d61d5 --- /dev/null +++ b/docs/source/adjoint.rst @@ -0,0 +1,7 @@ +Adjoint Algorithms +------------------ +.. automodule:: funsor.adjoint + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 000000000..88aca10a8 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,190 @@ +import os +import sys + +import sphinx_rtd_theme + + +# import pkg_resources + +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +sys.path.insert(0, os.path.abspath('../..')) + +# -- Project information ----------------------------------------------------- + +project = u'Funsor' +copyright = u'2019, Uber Technologies, Inc' +author = u'Uber AI Labs' + +# The short X.Y version +version = u'0.0' +# The full version, including alpha/beta/rc tags +release = u'0.0' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.intersphinx', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', +] + +# Disable documentation inheritance so as to avoid inheriting +# docstrings in a different format, e.g. when the parent class +# is a PyTorch class. + +autodoc_inherit_docstrings = False + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# do not prepend module name to functions +add_module_names = False + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme" +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'funsordoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'Funsor.tex', u'Funsor Documentation', u'Uber AI Labs', 'manual'), +] + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'Funsor', u'Funsor Documentation', + [author], 1) +] + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'Funsor', u'Funsor Documentation', + author, 'Funsor', 'Functional analysis + tensors + symbolic algebra.', + 'Miscellaneous'), +] + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + 'python': ('https://docs.python.org/3/', None), + 'numpy': ('http://docs.scipy.org/doc/numpy/', None), + 'torch': ('http://pytorch.org/docs/master/', None), + 'pyro': ('http://docs.pyro.ai/en/stable/', None), + 'opt_einsum': ('https://optimized-einsum.readthedocs.io/en/stable/', None) +} + +# @jpchen's hack to get rtd builder to install latest pytorch +if 'READTHEDOCS' in os.environ: + os.system('pip install https://download.pytorch.org/whl/cpu/torch-1.0.0-cp27-cp27mu-linux_x86_64.whl') diff --git a/docs/source/distributions.rst b/docs/source/distributions.rst new file mode 100644 index 000000000..7e7ef1d8d --- /dev/null +++ b/docs/source/distributions.rst @@ -0,0 +1,7 @@ +Distributions +------------- +.. automodule:: funsor.distributions + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/docs/source/domains.rst b/docs/source/domains.rst new file mode 100644 index 000000000..580ca825d --- /dev/null +++ b/docs/source/domains.rst @@ -0,0 +1,7 @@ +Domains +------- +.. automodule:: funsor.domains + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/docs/source/einsum.rst b/docs/source/einsum.rst new file mode 100644 index 000000000..519fcf6e1 --- /dev/null +++ b/docs/source/einsum.rst @@ -0,0 +1,7 @@ +Einsum Interface +---------------- +.. automodule:: funsor.einsum + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/docs/source/funsors.rst b/docs/source/funsors.rst new file mode 100644 index 000000000..0e3e4480b --- /dev/null +++ b/docs/source/funsors.rst @@ -0,0 +1,58 @@ +Funsors +======= + +Basic Funsors +------------- +.. automodule:: funsor.terms + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource + +Delta +----- +.. automodule:: funsor.delta + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource + +PyTorch +------- +.. automodule:: funsor.torch + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource + +NumPy +----- +.. automodule:: funsor.numpy + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource + +Gaussian +-------- +.. automodule:: funsor.gaussian + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource + +Contract +-------- +.. automodule:: funsor.contract + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource + +Integrate +--------- +.. automodule:: funsor.integrate + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 000000000..1578c092d --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,36 @@ +.. funsor documentation master file, created by + sphinx-quickstart on Tue Apr 2 13:33:44 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Funsor's documentation! +================================== + +.. toctree:: + :glob: + :maxdepth: 2 + :caption: Funsor Core: + + funsors + domains + ops + interpretations + optimizer + adjoint + +.. toctree:: + :glob: + :maxdepth: 2 + :caption: Interfaces: + + distributions + minipyro + einsum + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/interpretations.rst b/docs/source/interpretations.rst new file mode 100644 index 000000000..e7331f376 --- /dev/null +++ b/docs/source/interpretations.rst @@ -0,0 +1,18 @@ +Interpretations +=============== + +Interpreter +----------- +.. automodule:: funsor.interpreter + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource + +Monte Carlo +----------- +.. automodule:: funsor.montecarlo + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/docs/source/minipyro.rst b/docs/source/minipyro.rst new file mode 100644 index 000000000..85ff184b4 --- /dev/null +++ b/docs/source/minipyro.rst @@ -0,0 +1,7 @@ +Mini-Pyro Interface +------------------- +.. automodule:: funsor.minipyro + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/docs/source/ops.rst b/docs/source/ops.rst new file mode 100644 index 000000000..6e4e2578b --- /dev/null +++ b/docs/source/ops.rst @@ -0,0 +1,6 @@ +Operations +---------- +.. automodule:: funsor.ops + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/optimizer.rst b/docs/source/optimizer.rst new file mode 100644 index 000000000..89a16b217 --- /dev/null +++ b/docs/source/optimizer.rst @@ -0,0 +1,7 @@ +Optimizer +--------- +.. automodule:: funsor.optimizer + :members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/funsor/gaussian.py b/funsor/gaussian.py index 82ca055fa..c09b63a1d 100644 --- a/funsor/gaussian.py +++ b/funsor/gaussian.py @@ -165,9 +165,9 @@ class Gaussian(Funsor): Funsor representing a batched joint Gaussian distribution as a log-density function. - Note that :class:`Gaussian`s are not normalized, rather they are + Note that :class:`Gaussian` s are not normalized, rather they are canonicalized to evaluate to zero at their maximum value (at ``loc``). This - canonical form is useful because it allows :class:`Gaussian`s with + canonical form is useful because it allows :class:`Gaussian` s with incomplete information, i.e. zero eigenvalues in the precision matrix. These incomplete distributions arise when making low-dimensional observations on higher dimensional hidden state. diff --git a/funsor/interpreter.py b/funsor/interpreter.py index 2cdba6834..c5f03e4e4 100644 --- a/funsor/interpreter.py +++ b/funsor/interpreter.py @@ -73,7 +73,7 @@ def reinterpret(x): ``ValueError`` in unhandled cases. :param x: An input, typically involving deferred - :class:`~funsor.terms.Funsor`s. + :class:`~funsor.terms.Funsor` s. :type x: A funsor or data structure holding funsors. :return: A reinterpreted version of the input. :raises: ValueError diff --git a/funsor/numpy.py b/funsor/numpy.py index 2856ed7f3..154bcdf95 100644 --- a/funsor/numpy.py +++ b/funsor/numpy.py @@ -16,9 +16,9 @@ def align_array(new_inputs, x): Permute and expand an array to match desired ``new_inputs``. :param OrderedDict new_inputs: A target set of inputs. - :param funsor.terms.Funsor x: A :class:`Array`s or - :class:`~funsor.terms.Number`. - :return: a number or :class:`np.ndarray` that can be broadcast to other + :param funsor.terms.Funsor x: A :class:`Array` s or + or :class:`~funsor.terms.Number` . + :return: a number or :class:`numpy.ndarray` that can be broadcast to other array with inputs ``new_inputs``. :rtype: tuple """ @@ -51,10 +51,10 @@ def align_arrays(*args): This is mainly useful for implementing eager funsor operations. - :param funsor.terms.Funsor \*args: Multiple :class:`Array`s and + :param funsor.terms.Funsor \*args: Multiple :class:`Array` s and :class:`~funsor.terms.Number`s. :return: a pair ``(inputs, arrays)`` where arrayss are all - :class:`np.ndarray`s that can be broadcast together to a single data + :class:`numpy.ndarray` s that can be broadcast together to a single data with given ``inputs``. :rtype: tuple """ @@ -259,7 +259,7 @@ def eager_binary_array_array(op, lhs, rhs): def arange(name, size): """ - Helper to create a named :func:`np.arange` funsor. + Helper to create a named :func:`numpy.arange` funsor. :param str name: A variable name. :param int size: A size. @@ -273,7 +273,7 @@ def arange(name, size): def materialize(x): """ Attempt to convert a Funsor to a :class:`~funsor.terms.Number` or - :class:`np.ndarray` by substituting :func:`arange`s into its free variables. + :class:`numpy.ndarray` by substituting :func:`arange` s into its free variables. """ assert isinstance(x, Funsor) if isinstance(x, (Number, Array)): diff --git a/funsor/terms.py b/funsor/terms.py index 487fd686f..0bc855fbc 100644 --- a/funsor/terms.py +++ b/funsor/terms.py @@ -233,7 +233,7 @@ def reduce(self, op, reduced_vars=None): def sample(self, sampled_vars, sample_inputs=None): """ Create a Monte Carlo approximation to this funsor by replacing - functions of ``sampled_vars`` with :class:`~funsor.delta.Delta`s. + functions of ``sampled_vars`` with :class:`~funsor.delta.Delta` s. The result is a :class:`Funsor` with the same ``.inputs`` and ``.output`` as the original funsor (plus ``sample_inputs`` if diff --git a/funsor/torch.py b/funsor/torch.py index 264364937..4b23274d7 100644 --- a/funsor/torch.py +++ b/funsor/torch.py @@ -23,8 +23,8 @@ def align_tensor(new_inputs, x): Permute and expand a tensor to match desired ``new_inputs``. :param OrderedDict new_inputs: A target set of inputs. - :param funsor.terms.Funsor x: A :class:`Tensor`s or - :class:`~funsor.terms.Number`. + :param funsor.terms.Funsor x: A :class:`Tensor` or + :class:`~funsor.terms.Number` . :return: a number or :class:`torch.Tensor` that can be broadcast to other tensors with inputs ``new_inputs``. :rtype: tuple @@ -58,10 +58,10 @@ def align_tensors(*args): This is mainly useful for implementing eager funsor operations. - :param funsor.terms.Funsor \*args: Multiple :class:`Tensor`s and + :param funsor.terms.Funsor \*args: Multiple :class:`Tensor` s and :class:`~funsor.terms.Number`s. :return: a pair ``(inputs, tensors)`` where tensors are all - :class:`torch.Tensor`s that can be broadcast together to a single data + :class:`torch.Tensor` s that can be broadcast together to a single data with given ``inputs``. :rtype: tuple """ @@ -471,7 +471,7 @@ def arange(name, size): def materialize(x): """ Attempt to convert a Funsor to a :class:`~funsor.terms.Number` or - :class:`Tensor` by substituting :func:`arange`s into its free variables. + :class:`Tensor` by substituting :func:`arange` s into its free variables. """ assert isinstance(x, Funsor) if isinstance(x, (Number, Tensor)): @@ -496,7 +496,7 @@ class Function(Funsor): Functions are assumed to support broadcasting and can be eagerly evaluated on funsors with free variables of int type (i.e. batch dimensions). - :class:`Function`s are usually created via the :func:`function` decorator. + :class:`Function` s are usually created via the :func:`function` decorator. :param callable fn: A PyTorch function to wrap. :param funsor.domains.Domain output: An output domain. @@ -610,7 +610,7 @@ def mvn_log_prob(loc, scale_tril, x): return d.log_prob(x) To support functions that output nested tuples of tensors, specify a nested - tuple of output types, for example: + tuple of output types, for example:: @funsor.torch.function(reals(8), (reals(), bint(8))) def max_and_argmax(x): diff --git a/setup.py b/setup.py index 8d0f8e5e3..3c1405fb1 100644 --- a/setup.py +++ b/setup.py @@ -13,6 +13,7 @@ install_requires=[ 'contextlib2', 'multipledispatch', + 'numpy>=1.7', 'opt_einsum>=2.3.2', 'pyro-ppl>=0.3', 'six>=1.10.0', @@ -21,7 +22,14 @@ ], extras_require={ 'test': ['flake8', 'pytest>=4.1', 'torchvision==0.2.1'], - 'dev': ['flake8', 'pytest>=4.1', 'isort'], + 'dev': [ + 'flake8', + 'isort', + 'pytest>=4.1', + 'sphinx', + 'sphinx_rtd_theme', + 'torchvision==0.2.1', + ], }, tests_require=['flake8', 'pytest>=4.1'], keywords='probabilistic machine learning bayesian statistics pytorch',