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".

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.

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).

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))

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' <sandona.dav...@gmail.com> 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 sympy+unsubscr...@googlegroups.com.
> 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 sympy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/CAHVvXxTsk9FJQ8okFuHHBeb_7tkMFzm-6kY7diff7QjnWLdakQ%40mail.gmail.com.

Reply via email to