Skip to content

Commit 6e319d1

Browse files
Merge pull request #105 from brandonwillard/add-scan-meta-op
Add scan meta op
2 parents f0d4198 + 565d017 commit 6e319d1

29 files changed

+538
-444
lines changed

Makefile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,8 @@ coverage: test
6464
diff-cover coverage.xml --compare-branch=master --fail-under=100
6565

6666
docs:
67-
# latesttag=$(git describe --tags `git rev-list --tags --max-count=1`)
68-
# echo checking out ${latesttag}
69-
# git checkout ${latesttag}
7067
pushd docs && \
68+
sphinx-apidoc ../symbolic_pymc/ -o source --force && \
7169
make html && \
7270
ghp-import -n -p -r upstream -b gh-pages build/html && \
7371
popd

conftest.py

Lines changed: 0 additions & 16 deletions
This file was deleted.

docs/source/symbolic-pymc-tour.org

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,10 +1126,8 @@ like src_python[:eval never]{enable_lvar_defaults}, or by updates to the
11261126
defaults of meta object creation.
11271127

11281128
Likewise, there are tools available in Symbolic PyMC that make it easier to
1129-
determine why to objects won't unify
1130-
(i.e. src_python[:eval never]{symbolic_pymc.unify.debug_unify}) and exactly
1131-
which components are unequal between two meta objects
1132-
(i.e. src_python[:eval never]{symbolic_pymc.utils.meta_parts_unequal}).
1129+
determine which components are unequal between two meta objects
1130+
(e.g. src_python[:eval never]{symbolic_pymc.utils.meta_parts_unequal}).
11331131

11341132
Symbolic PyMC's library of relevant mathematical and statistical relations is
11351133
intended to evolve over time. These relations will reflect useful properties

docs/source/symbolic-pymc-tour.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,10 +1071,8 @@ like \ ``enable_lvar_defaults``\ , or by updates to the
10711071
defaults of meta object creation.
10721072

10731073
Likewise, there are tools available in Symbolic PyMC that make it easier to
1074-
determine why to objects won't unify
1075-
(i.e. \ ``symbolic_pymc.unify.debug_unify``\ ) and exactly
1076-
which components are unequal between two meta objects
1077-
(i.e. \ ``symbolic_pymc.utils.meta_parts_unequal``\ ).
1074+
determine which components are unequal between two meta objects
1075+
(e.g. \ ``symbolic_pymc.utils.meta_parts_unequal``\ ).
10781076

10791077
Symbolic PyMC's library of relevant mathematical and statistical relations is
10801078
intended to evolve over time. These relations will reflect useful properties

docs/source/symbolic_pymc.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@ Subpackages
1313
Submodules
1414
----------
1515

16-
symbolic\_pymc.meta module
17-
--------------------------
16+
symbolic\_pymc.dispatch module
17+
------------------------------
1818

19-
.. automodule:: symbolic_pymc.meta
19+
.. automodule:: symbolic_pymc.dispatch
2020
:members:
2121
:undoc-members:
2222
:show-inheritance:
2323

24-
symbolic\_pymc.unify module
25-
---------------------------
24+
symbolic\_pymc.meta module
25+
--------------------------
2626

27-
.. automodule:: symbolic_pymc.unify
27+
.. automodule:: symbolic_pymc.meta
2828
:members:
2929
:undoc-members:
3030
:show-inheritance:

docs/source/symbolic_pymc.tensorflow.rst

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ symbolic\_pymc.tensorflow package
44
Submodules
55
----------
66

7+
symbolic\_pymc.tensorflow.dispatch module
8+
-----------------------------------------
9+
10+
.. automodule:: symbolic_pymc.tensorflow.dispatch
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:
14+
15+
symbolic\_pymc.tensorflow.graph module
16+
--------------------------------------
17+
18+
.. automodule:: symbolic_pymc.tensorflow.graph
19+
:members:
20+
:undoc-members:
21+
:show-inheritance:
22+
723
symbolic\_pymc.tensorflow.meta module
824
-------------------------------------
925

@@ -20,14 +36,6 @@ symbolic\_pymc.tensorflow.printing module
2036
:undoc-members:
2137
:show-inheritance:
2238

23-
symbolic\_pymc.tensorflow.unify module
24-
--------------------------------------
25-
26-
.. automodule:: symbolic_pymc.tensorflow.unify
27-
:members:
28-
:undoc-members:
29-
:show-inheritance:
30-
3139

3240
Module contents
3341
---------------

docs/source/symbolic_pymc.theano.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ symbolic\_pymc.theano package
44
Submodules
55
----------
66

7+
symbolic\_pymc.theano.dispatch module
8+
-------------------------------------
9+
10+
.. automodule:: symbolic_pymc.theano.dispatch
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:
14+
715
symbolic\_pymc.theano.meta module
816
---------------------------------
917

@@ -52,14 +60,6 @@ symbolic\_pymc.theano.random\_variables module
5260
:undoc-members:
5361
:show-inheritance:
5462

55-
symbolic\_pymc.theano.unify module
56-
----------------------------------
57-
58-
.. automodule:: symbolic_pymc.theano.unify
59-
:members:
60-
:undoc-members:
61-
:show-inheritance:
62-
6363
symbolic\_pymc.theano.utils module
6464
----------------------------------
6565

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
setuptools>=45.2.0
2+
six>=1.14.0
13
-e ./
24
sympy>=1.3
35
coveralls

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def get_long_description():
3232
author_email=AUTHOR_EMAIL,
3333
url=URL,
3434
install_requires=[
35+
"numpy>=1.18.1",
3536
"scipy>=1.4.0",
3637
"Theano>=1.0.4",
3738
"tf-estimator-nightly==2.1.0.dev2020012309",

symbolic_pymc/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# We need this so that `multipledispatch` initialization occurs
2-
from .unify import *
2+
from .dispatch import *
33

44
from ._version import get_versions
55

symbolic_pymc/unify.py renamed to symbolic_pymc/dispatch.py

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from functools import wraps
21
from collections.abc import Mapping
32

43
from cons.core import _car, _cdr, ConsError
@@ -13,36 +12,6 @@
1312
from .meta import MetaSymbol, MetaVariable
1413

1514

16-
class UnificationFailure(Exception):
17-
pass
18-
19-
20-
def debug_unify(enable=True): # pragma: no cover
21-
"""Wrap unify functions so that they raise a `UnificationFailure` exception when unification fails."""
22-
if enable:
23-
24-
def set_debug(f):
25-
@wraps(f)
26-
def wrapper(*args, **kwargs):
27-
s = f(*args, **kwargs)
28-
if s is False:
29-
import pdb
30-
31-
pdb.set_trace()
32-
raise UnificationFailure()
33-
return s
34-
35-
return wrapper
36-
37-
_unify.funcs = {
38-
sig: set_debug(getattr(f, "__wrapped__", f)) for sig, f in _unify.funcs.items()
39-
}
40-
_unify._cache.clear()
41-
else:
42-
_unify.funcs = {sig: getattr(f, "__wrapped__", f) for sig, f in _unify.funcs.items()}
43-
_unify._cache.clear()
44-
45-
4615
def unify_MetaSymbol(u, v, s):
4716
if type(u) != type(v):
4817
return False
@@ -157,6 +126,3 @@ def cdr_MetaVariable(x):
157126

158127
# arguments.add((MetaSymbol,), cdr_MetaSymbol)
159128
arguments.add((MetaVariable,), cdr_MetaVariable)
160-
161-
162-
__all__ = ["debug_unify"]

symbolic_pymc/meta.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,12 @@ def __ne__(self, other):
335335
return not self.__eq__(other)
336336

337337
def __hash__(self):
338-
return hash((self.base, self.rands))
338+
try:
339+
rands = self.rands
340+
except NotImplementedError: # pragma: no cover
341+
return NotImplemented
342+
343+
return hash((self.base, rands))
339344

340345
def __str__(self):
341346
return self.__repr__(show_obj=False, _repr=str)

symbolic_pymc/relations/theano/__init__.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,56 @@
1+
import numpy as np
2+
import theano.tensor as tt
3+
14
from unification import var
5+
from unification.utils import transitive_get as walk
26

37
from kanren import eq
48
from kanren.core import lall, Zzz
59
from kanren.facts import fact
610
from kanren.graph import applyo, walko
711
from kanren.assoccomm import commutative, associative
12+
from kanren.constraints import neq
813

914
from etuples import etuple
1015

11-
from ...theano.meta import mt
12-
16+
from ...utils import HashableNDArray
17+
from ...theano.meta import TheanoMetaConstant, mt
1318

19+
# Establish some Theano `Op`s as commutative and/or associative
1420
fact(commutative, mt.add)
1521
fact(commutative, mt.mul)
1622
fact(associative, mt.add)
1723
fact(associative, mt.mul)
1824

1925

26+
def constant_neq(lvar, val):
27+
"""Assert that a constant graph variable is not equal to a specific value.
28+
29+
Scalar values are broadcast across arrays.
30+
31+
XXX: This goal is non-relational.
32+
TODO: Rewrite this as an actual constraint.
33+
"""
34+
35+
if isinstance(val, np.ndarray):
36+
val = val.view(HashableNDArray)
37+
38+
def constant_neq_goal(S):
39+
lvar_rf = walk(lvar, S)
40+
if isinstance(lvar_rf, (tt.Constant, TheanoMetaConstant)):
41+
# Although `neq` is an actual constraint, the preceding type check
42+
# and alternative success--when not a constant type--make the
43+
# entire goal non-relational/not a true constraint, since the
44+
# aforementioned check will only occur once per goal-stream/state
45+
# and never again.
46+
yield from neq(lvar_rf.data, val)(S)
47+
else:
48+
# When the value isn't a Theano constant, consider it satisfied
49+
yield S
50+
51+
return constant_neq_goal
52+
53+
2054
def non_obs_walko(relation, a, b):
2155
"""Construct a goal that applies a relation to all nodes above an observed random variable.
2256

symbolic_pymc/relations/theano/distributions.py

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
"""Relations pertaining to probability distributions."""
2-
import numpy as np
3-
import theano.tensor as tt
4-
52
from unification import var
6-
from unification.utils import transitive_get as walk
73

84
from etuples import etuple
95

106
from kanren import conde, eq
117
from kanren.facts import fact, Relation
12-
from kanren.constraints import neq
138

9+
from . import constant_neq
1410
from .. import concat
15-
from ...utils import HashableNDArray
16-
from ...theano.meta import TheanoMetaConstant, mt
11+
from ...theano.meta import mt
1712

1813

1914
derived_dist = Relation("derived_dist")
@@ -57,28 +52,6 @@
5752
# None)
5853

5954

60-
def constant_neq(lvar, val):
61-
"""Assert that a constant graph variable is not equal to a specific value.
62-
63-
Scalar values are broadcast across arrays.
64-
65-
XXX: This goal is non-relational
66-
"""
67-
68-
if isinstance(val, np.ndarray):
69-
val = val.view(HashableNDArray)
70-
71-
def constant_neq_goal(S):
72-
lvar_rf = walk(lvar, S)
73-
if isinstance(lvar_rf, (tt.Constant, TheanoMetaConstant)):
74-
# TODO: Can we get away with `neq(lvar_rf, val)` alone?
75-
yield from neq(lvar_rf.data, val)(S)
76-
else:
77-
yield S
78-
79-
return constant_neq_goal
80-
81-
8255
def scale_loc_transform(in_expr, out_expr):
8356
"""Create relations for lifting and sinking scale and location parameters of distributions.
8457

symbolic_pymc/tensorflow/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# Needed to register generic functions
2-
from .unify import *
2+
from .dispatch import *

symbolic_pymc/tensorflow/unify.py renamed to symbolic_pymc/tensorflow/dispatch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from .meta import TFlowMetaSymbol
1414
from ..meta import metatize
15-
from ..unify import unify_MetaSymbol
15+
from ..dispatch import unify_MetaSymbol
1616

1717
tf_class_abstractions = tuple(c.base for c in TFlowMetaSymbol.base_subclasses())
1818

symbolic_pymc/theano/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# Needed to register generic functions
2-
from .unify import *
2+
from .dispatch import *

symbolic_pymc/theano/unify.py renamed to symbolic_pymc/theano/dispatch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from .meta import TheanoMetaSymbol
1515
from ..meta import metatize
16-
from ..unify import unify_MetaSymbol
16+
from ..dispatch import unify_MetaSymbol
1717

1818

1919
tt_class_abstractions = tuple(c.base for c in TheanoMetaSymbol.base_subclasses())

0 commit comments

Comments
 (0)