probsys / sppl

Probabilistic programming system for fast and exact symbolic inference
Apache License 2.0
76 stars 10 forks source link

Gracefully handle EventFinite.solve with non-numeric values #14

Closed fsaad closed 4 years ago

fsaad commented 4 years ago

Example 1

>>> (X << {'a'}).solve()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/scratch/fsaad/sum-product-dsl/build/lib/spn/transforms.py", line 711, in solve
    return self.invert({1})
  File "/scratch/fsaad/sum-product-dsl/build/lib/spn/transforms.py", line 53, in invert
    return self.invert_finite(intersection)
  File "/scratch/fsaad/sum-product-dsl/build/lib/spn/transforms.py", line 764, in invert_finite
    return self.subexpr.invert(values_prime)
  File "/scratch/fsaad/sum-product-dsl/build/lib/spn/transforms.py", line 59, in invert
    assert False, 'Unknown intersection: %s' % (intersection,)
AssertionError: Unknown intersection: Intersection({a}, Union({-oo, oo}, Reals))

Example 2

>>> (~(X << {'a'})).solve()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/scratch/fsaad/sum-product-dsl/build/lib/spn/transforms.py", line 711, in solve
    return self.invert({1})
  File "/scratch/fsaad/sum-product-dsl/build/lib/spn/transforms.py", line 53, in invert
    return self.invert_finite(intersection)
  File "/scratch/fsaad/sum-product-dsl/build/lib/spn/transforms.py", line 764, in invert_finite
    return self.subexpr.invert(values_prime)
  File "/scratch/fsaad/sum-product-dsl/build/lib/spn/transforms.py", line 59, in invert
    assert False, 'Unknown intersection: %s' % (intersection,)
AssertionError: Unknown intersection: Reals \ {a}

The solution is to create two classes EventFiniteReal and EventFiniteNominal and handle the inversion appropriately under each case.

fsaad commented 4 years ago

These are now fine, but the major hurdle remains the unions and intersections of the symbolic events cases (from test_transforms_solve):

    # TODO: These test cases need to be fixed, so that
    #   Intersection(FiniteSet('a'), FiniteSet('b'))
    #   becomes EmptySet.
    # Solve a conjunction with intersection.
    event = (Y << {'a', 'b'}) & (Y << {'b', 'c'})
    assert event.solve() == sympy.Union(
        sympy.FiniteSet('b'),
        sympy.Intersection(sympy.FiniteSet('a'), sympy.FiniteSet('c')))
    # Solve a conjunction with no intersection.
    event = (Y << {'a', 'b'}) & (Y << {'c'})
    assert event.solve() == sympy.Intersection(
        sympy.FiniteSet('a', 'b'),
        sympy.FiniteSet('c'))