On Sun, Jun 7, 2020 at 4:08 PM Oscar Benjamin
<[email protected]> wrote:
>
> Hi Davide,
>
> I'll answer your questions one by one and then summarise the situation below.
>
> 1. Are the two modules interacting together now?
>
> The old and new assumptions interact in one direction: the new
> assumptions will query the old assumptions if it helps but the old
> assumptions are ignorant of the new. The rest of sympy does not really
> use the new assumptions though so any assumptions stated using e.g.
> "assuming" will be ignored by almost all of the code in sympy (e.g.
> integrate, solve etc).
>
> 2. Is the new module able to do everything the old module does?
>
> Since the new assumptions query the old they can make use of any
> information that is available in the old assumptions. In that sense a
> query using "ask" from the new assumptions API can answer all the same
> questions that the old assumptions API can. The new assumptions can
> also be used for a wider range of queries for example queries about
> matrices. The old assumptions are really just about numbers and can
> only answer questions like "is this a positive number".

The real benefit of the new assumptions is that assumptions can be
made on expressions, not just symbols. So it is now possible to say
something like Q.positive(x - y). You can also use arbitrary logical
predicates, like Or(Q.integer(x), Q.integer(y)).

>
> 3. What are the limitation of the new module? Where is it not implemented?
>
> The new assumptions were made a lot faster last Summer. Their slowness
> was one major limitation before. They are still slow in comparison to
> the old assumptions. The real limitation is the fact that the old
> assumptions are used all across the codebase in both elementary
> evaluations and in more complex routines. A huge amount of code would
> need to be changed in order to make it so that general routines like
> "integrate" use the new assumptions.

The biggest thing that is missing is the other direction, to make
expr.is_integer check ask(Q.integer(expr)). With the improved
performance, this may now be possible to do, although I suspect more
work is still required to make it so we don't slow down SymPy. For
instance, IMO we need a better model of assumptions evaluation so that
we can do fast checks vs. slow checks. The (new) assumptions do
various levels of checks starting from a simple "is this already
assumed" going all the way to a full SAT solve. But there's no way to
limit how far it tries to go to get an answer. It's either all or
nothing.

>
> I guess that the original plan was for the new assumptions to replace
> the old so that they could be a dropin replacement and then the old
> assumptions API would still be there but it would call into the new
> assumptions in order to resolve its queries. That's not possible
> though because the new assumptions actually depend on the old and
> there is a huge amount of work invested in making the old assumptions
> work the way that they do so replicating that in the new assumptions
> so that they can stand on their own without the old is not a small
> task.
>
> My main problem with the idea that the new assumptions can replace the
> old is about the internal organisation of the code base itself. The
> old assumptions are used as part of the internals of evaluating an
> expression such as "cos(n*pi)". To me that makes sense because
> evaluation creates Basic instances and the old assumptions sit on a
> "level below" symbolic evaluation and (mostly) do not create any Basic
> instances. The new assumptions API uses Basic instances even in order
> to express a query. That means that using the new assumptions as part
> of evaluation creates an inherent circularity and it also explains why
> the new assumptions are so slow (or at least limits how much faster
> they can get).

I don't think the new system should completely replace the old one.
The syntax for the old assumptions is very useful and shouldn't go
away. It is also useful in many cases to store assumptions logic on
the relevant object itself.

A benefit of the new assumptions, though, is that the handler logic is
often much simpler to write, especially the sathandlers style, because
you can write things down as logical statements. In the old
assumptions you have to carefully do the logic evaluation yourself,
and on top of it, you have to be careful everywhere to handle the
three-valued logic correctly. With a logical predicate, you don't have
to worry about three-valued logic. The top-level solver takes care of
the None case.

One goal is to remove assumptions based evaluation, or at least limit
it to only cases where the assumptions can be computed quickly. The
"n" in cos(n*pi) can be an arbitrarily complicated expression. With
the new assumptions, it may require a lot of computation to compute
whether or not n is an integer. This is due to the fact that the new
assumptions allow assuming more complicated logical predicates and
more complicated logical queries.

>
> There are other problems with the new assumptions such as the idea
> that we can have a global flag as the "with assuming(...)" API
> implies. The "assuming" context manager seems like a fundamentally bad
> idea to me because the intention is that it will bring in a global
> flag that will alter the behavour of every other part of the codebase.
> That means that it breaks thread-safety, that the cache would need to
> be cleared every time anything is assumed, that code is unpredictable
> because its behaviour can be manipulated from outside and many more
> problems. Basically the assuming API implies a massive and very
> complicated global variable and those are not usually good.
>
> If we want to use the new assumptions properly as part of lots of
> different functions around the codebase then the clean way is for most
> APIs to grow an assumptions keyword e.g.:
>
>     sol = solve(a*x - b, x, assumptions=Q.nonzero(a))

But then any function that calls solve() must also have that keyword
argument, or you won't be able to make use of the assumptions. The end
result is that you have to extend the API of hundreds of functions,
and you can still easily have functions that don't support the API.
The context manager is simpler API wise although I can see how there
are technical issues with things like the cache.

I don't think the "globalness" of the new assumptions can be avoided.
With the old assumptions, you can only assume things about symbols, so
it's easy to make Symbol('x') and Symbol('x', positive=True) compare
unequal. But for something like, x > y (Q.positive(x - y)), it has to
be stored separately from the expressions that contain x and y.

Aaron Meurer

>
> Adding the assumptions keyword across all APIs and making use of it in
> the relevant functions is a lot of work but nowhere near as much as
> rewriting the old assumptions as the new. Then the new assumptions can
> be used judiciously at key places in key APIs so they won't cause a
> slowdown like they would if they were used as part of every elementary
> evaluation.
>
> The future I see for the old and new assumptions is that they will
> coexist. The old assumptions will be there for simple cases and will
> be used internally as part of evaluation. The new assumptions will be
> able to express more complex queries but will not be used
> automatically although some higher level APIs like integrate/solve
> could use the new assumptions for simplification or refinement. That
> gives us a clear path forward that can be implemented incrementally
>
> So to summarise the situation:
>
> 1. The new assumptions are basically not used anywhere in sympy.
> 2. You should not expect them to alter the behaviour of evaluation or
> of higher-level APIs like integrate.
> 3. You can try to refine the results from integrate yourself using
> "refine" but the "assuming" context manager basically has no effect
> because none of the code inside integrate uses "ask".
>
> Oscar
>
> On Sat, 6 Jun 2020 at 15:18, Davide Sandona' <[email protected]> wrote:
> >
> > Until a couple of days ago, I always used the old assumption module defined 
> > in sympy.core.assumptions, where we create symbols with assumptions and 
> > then the expression infer the values for its assumptions. For example, I 
> > know that with this old module it's not possible to create a symbol x 
> > assuming x > y.
> >
> > Now I'm exploring the new assumption module, defined in sympy.assumptions. 
> > Looking at the documentation, at questions over StackOverflow and into this 
> > mailing list, I understand that this module should be more powerful. I also 
> > read this interesting thread [1] from 2016, to understand how these two 
> > modules interact with each other. Back then, the two modules were separate 
> > entities. Also, by looking at questions over StackOverflow, people say the 
> > new module is not integrated that much with the rest of Sympy.
> >
> > What I understood so far is that the new module is great to ask queries 
> > about expressions and their assumption, it is good to refine certain kind 
> > of expression, but it is not really good to perform computations with given 
> > assumptions... Let me explain with an example:
> >
> > x = symbols("x")
> > a = symbols("a")
> > exp(a * x).integrate(x)
> >
> > This is going to return a piecewise result, with the condition being a=0 or 
> > different from 0. Suppose I use the old assumptions system:
> >
> > x = symbols("x")
> > a = symbols("a", nonzero=True)
> > exp(a * x).integrate(x)
> >
> > This is going to produce a single expression.
> >
> > Is there any way to produce the same single-expression result by using the 
> > new assumption module? I tried with this code:
> >
> > x = symbols("x")
> > a = symbols("a")
> > with assuming(Q.nonzero(a)):
> >     r = exp(a * x).integrate(x)
> > r
> >
> > However, it returns the piecewise result, so the assumption was not applied.
> >
> > In light of this, my questions are:
> >
> > Are the two modules interacting together now?
> > Is the new module able to do everything the old module does?
> > What are the limitation of the new module? Where is it not implemented?
> >
> > Thank you for your time,
> >
> > Davide.
> >
> > [1] 
> > https://groups.google.com/forum/#!searchin/sympy/assumptions|sort:date/sympy/AJVZdWnYQww/1VmnUmVEAAAJ
> >
> > --
> > You received this message because you are subscribed to the Google Groups 
> > "sympy" group.
> > To unsubscribe from this group and stop receiving emails from it, send an 
> > email to [email protected].
> > To view this discussion on the web visit 
> > https://groups.google.com/d/msgid/sympy/d3ba620e-1a3b-4248-b30f-e62989370d8eo%40googlegroups.com.
>
> --
> You received this message because you are subscribed to the Google Groups 
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sympy/CAHVvXxTsk9FJQ8okFuHHBeb_7tkMFzm-6kY7diff7QjnWLdakQ%40mail.gmail.com.

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/CAKgW%3D6JLv_Q%3D6ErqjTv0_bf_G6nGPXWho_6VMGiqEga7tddo6w%40mail.gmail.com.

Reply via email to