Metadata-Version: 2.2
Name: effectful
Version: 0.0.1
Summary: Metaprogramming infrastructure
Home-page: https://www.basis.ai/
Author: Basis
License: Apache 2.0
Project-URL: Source, https://github.com/BasisResearch/effectful
Keywords: machine learning statistics probabilistic programming bayesian modeling pytorch
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.10
License-File: LICENSE.md
Requires-Dist: typing_extensions
Requires-Dist: dm-tree
Provides-Extra: torch
Requires-Dist: torch; extra == "torch"
Provides-Extra: pyro
Requires-Dist: torch; extra == "pyro"
Requires-Dist: pyro-ppl; extra == "pyro"
Provides-Extra: dev
Requires-Dist: torch; extra == "dev"
Requires-Dist: pyro-ppl; extra == "dev"
Requires-Dist: torch; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: pytest-xdist; extra == "dev"
Requires-Dist: pytest-benchmark; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: isort; extra == "dev"
Requires-Dist: sphinx; extra == "dev"
Requires-Dist: sphinxcontrib-bibtex; extra == "dev"
Requires-Dist: sphinx_rtd_theme; extra == "dev"
Requires-Dist: myst-parser; extra == "dev"
Requires-Dist: nbsphinx; extra == "dev"
Requires-Dist: nbval; extra == "dev"
Requires-Dist: nbqa; extra == "dev"
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: project-url
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

.. index-inclusion-marker

Effectful 
=========

Effectful is an algebraic effect system for Python, intended for use in the
implementation of probabilistic programming languages. It is a core component of
the `ChiRho <https://basisresearch.github.io/chirho/getting_started.html>`_
causal modeling language.

Installation
------------

Install From Source
^^^^^^^^^^^^^^^^^^^^
.. code:: sh

   git clone git@github.com:BasisResearch/effectful.git
   cd effectful
   git checkout master
   pip install -e .[test]

Install With Optional PyTorch/Pyro Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

``effectful`` has optional support for `PyTorch <https://pytorch.org/>`_ (tensors
with named dimensions) and `Pyro <https://pyro.ai/>`_ (wrappers for Pyro
effects).

To enable PyTorch support:

.. code:: sh

   pip install effectful[torch]

Pyro support (which includes PyTorch support):

.. code:: sh

   pip install effectful[pyro]

Getting Started
---------------

Here's an example demonstrating how ``effectful`` can be used to implement a simple DSL that performs arithmetic on terms with free variables.

.. code:: python

   import operator
   import functools

   from effectful.handlers.operator import OPERATORS
   from effectful.ops.types import Term
   from effectful.ops.syntax import defop
   from effectful.ops.semantics import handler, evaluate, coproduct, fwd
   import effectful.handlers.operator

   add = OPERATORS[operator.add]

   def beta_add(x: int, y: int) -> int:        
       match x, y:
           case int(), int():
               return x + y
           case _:
               return fwd()

   def commute_add(x: int, y: int) -> int:
       match x, y:
           case Term(), int():
               return y + x  
           case _:
               return fwd()

   def assoc_add(x: int, y: int) -> int:
       match x, y:
           case _, Term(op, (a, b)) if op == add:
               return (x + a) + b 
           case _:
               return fwd()

   beta_rules = {add: beta_add}
   commute_rules = {add: commute_add}
   assoc_rules = {add: assoc_add}

   eager_mixed = functools.reduce(coproduct, (beta_rules, commute_rules, assoc_rules))

We can represent free variables as operations with no arguments, generated using ``defop``:

.. code:: python

   >>> x = defop(int, name="x")
   >>> y = defop(int, name="y")

If we evaluate an expression containing free variables, we get a term:

.. code:: python

   >>> e = 1 + 1 + (x() + 1) + (5 + y())
   >>> print(e)
   add(2, add(add(x(), 1), add(5, y())))

We can make the evaluation strategy smarter by taking advantage of the commutativity and associativity of addition, as expressed by the ``commute_add`` and ``assoc_add`` handlers.

.. code:: python

   >>> with handler(eager_mixed):
   >>>     print(evaluate(e))
   add(8, add(x(), y()))
   
Learn More
----------

More examples and API documentation can be found in the `docs <https://basisresearch.github.io/effectful/index.html>`_.
