Implement Symbolic Assumptions System #1713
Replies: 3 comments 8 replies
-
        
 That's not a well defined operation unlike shape. If you evaluate the input of an Assumption Op you get an array, how do you extract assumptions at runtime? in other words what do you get from? 
 Shape is always well defined if you can only look at the input array at runtime. We can't add arbitrary attributes to runtimes arrays because we want to remain compatible with the other backends. Even if we could it would be expensive to compute this at runtime (whereas shape isn't, which is why a ShapeOp is fine). Also do you enforce the assumption at runtime (like specify_shape) or do you take it as a hint only? Your proposal should contrast to the  Also making make_node more complex for all Ops seems like a bad strategy. I would write the logic to propagate assumptions in rewrites only. This allows us not doing the work when we don't want to.  | 
  
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
| 
         I think it's important to temper ambitions on automatic inference of assumptions. Math is hard, Gödel, and blah blah, so it will never be as good as you might hope, and there isn't any "right way". Realistic expectations are basically that it will do well for whatever you hard-code, then it may randomly do a few clever things on top of that, and then it will rapidly taper off at some horizon (quite similarly to an LLM actually). 
 Variables are by default assumed to be complex, so x² is not non-negative unless you declare x to be real. Occasionally Mathematica can infer something useful, but only in some low ratio of cases, so in the end I would usually never bother.  | 
  
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Description
Proposal
I would like to see a symbolic logic system for the mathematical properties of tensors implemented in pytensor. The name "assumptions" comes from the sympy system that does what I'm asking for. I guess it's actually a "type" system, but that name is quite overloaded.
Under this proposal, variable constructors would allow for a range of assumptions / types to be passed in. For example:
By assumption, values of
xwill always be positive. Other tags includenon-negative,zero,non-zero,negative,non-positive. Under the sympy system, these values take one of three possible values:True,FalseorNone, whereNoneis interpreted as unknown or non-determinable.The assumptions of a variable should be stored in an
AssumptionsOp, the same way the shape of an Op is stored in aShapeOp. OtherOps can then implementinfer_assumptions, which tells us how they act on the various assumptions. Likewise,make_nodewill need to be expanded to include assumption logic.The objective here is to have a symbolic "assumptions graph" that can be evaluated the same way the shape graph is evaluated. Calling
x.assumptionsshould return a symbolic assumptions graph. Callingx.type.assumptionsshould return known static assumptions, orNonewhere assumptions are not statically known.Assumptions should have internal logic to maintain consistency. For example, a variable cannot be both
positiveandnegativeat the same time.Elementwise Examples
If no assumptions are provided, nothing is returned.
Some Ops can set assumptions even if assumptions of the inputs are unknown:
Ops with multiple inputs should reason over the assumptions of both inputs:
Some Ops will destroy knowledge
More Interesting Examples
The motivating examples for this feature relate to assumptions about matrices. For example, triangularity, positive-definite, negative-definite, positive semi-definite, banded, diagonal, topelitz, etc.
Users can define this manually
Or it can be the result of an op.
Multi-input Ops reason about the output assumptions
Other possible features
We could imagine using the assumptions to track the domain of a variable. This could help in rewrites involving conditions.
Open Questions
x = pt.tensor(shape=(None, None, None), positive=True, semidefinite=True). The first dim is always a batch dim? Or?COp(like shape)? Or just do it in python?realandimaginaryassumptions, or should assumptions also look at the dtype separately?True,nonnegativealso becomesTrue, andnegativebecomesFalse.Finally, the sympy team experimented with "new assumptions", presumably because there were flaws in the old assumptions. So copying their setup might not be the right way to go. I'm curious how this is handled in e.g. Maple and Mathmetica.
Beta Was this translation helpful? Give feedback.
All reactions