On Sat, Jun 13, 2020 at 5:50 AM Oscar Benjamin <oscar.j.benja...@gmail.com> wrote: > > On Sat, 13 Jun 2020 at 00:22, Aaron Meurer <asmeu...@gmail.com> wrote: > > > > On Sun, Jun 7, 2020 at 4:08 PM Oscar Benjamin > > <oscar.j.benja...@gmail.com> wrote: > > > > > > 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. > > We can't have `expr.is_integer` call `ask(Q.integer(expr))` without > first making the new assumptions free standing. At the moment the new > assumptions are propped up by the old and depend heavily on them for > their queries. > > The old assumptions for something like `expr.is_integer` are *already* > too slow. This is the main cause of slowness when working with large > expressions as you can see if you profile e.g. a slow call to expand: > https://github.com/sympy/sympy/pull/19485#issuecomment-639416355
I didn't realize that. Do we know which parts are slow? Is it the logic in the core, or are the _eval handlers slow? I have a hard time reading the graph on that comment. > > If the new assumptions are any slower then I don't think that we > should use them by default in evaluation. Instead I would much rather > remove the slower parts of the old assumptions and implement the more > complicated ways of evaluating queries in the new assumptions and then > have those used judiciously so core evaluation can use the old > assumptions and be fast while key algorithms or APIs can choose at the > appropriate place to use the new assumptions to answer a critical > query or to simplify something important like a Piecewise. That's why I think we need a clear stepping stone of assumptions evaluations from faster <====> more powerful which makes it possible to avoid using the more powerful evaluation unless it is in a place where the user will likely want to wait for it to happen. We currently have a hodgepodge of different methods but it isn't easy to only do the fastest evaluation. It also isn't clear which methods are completely redundant and are either too slow or insufficiently powerful relative to other methods. For example, the ask() quick fact check is likely completely unnecessary if it were to be combined with the old assumptions which does the same thing (or visa versa, whichever is slower). > > > 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. > > It would be very difficult to remove assumptions based evaluation but > it would be potentially worthwhile. The goal as I would put it is to > limit evaluation itself. We should also remove the slower parts of the > old assumptions when the new assumptions can pick up the slack. Yes, definitely. Assumptions based evaluation is among the more egregious evaluations because it can be non-constant time (c.f. https://github.com/sympy/sympy/wiki/Automatic-Simplification). > > > > 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. > > That's correct. It will be a lot of work. Changing the API is the > easier part compared to identifying and implementing support for the > new assumptions in the right places. > > > 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. > > The assumptions should be stored in the call stack as an explicit > local variable. They should be provided as an explicit parameter to > API that needs them. That API should document what it will potentially > use the assumptions for. > > The other problem with "with assuming" is that it's very confusing for > users to know when it should have any effect. The "new" assumptions > have been new for years and throughout that time people have been > trying to use "with assuming" because it claims to be able to affect > everything when even now it still affects nothing. An explicit > parameter can clearly document when and how the new assumptions are > being used as support for using them is added (which will still take > years from now). That's fair. I agree the new assumptions haven't been sufficiently documented as being experimental. The problem is that no one anticipated how slowly they would be to fully integrate into the core. Aaron Meurer > > -- > Oscar > > -- > 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/CAHVvXxQZ7S8%3DdZZ2DcpcpS_2cHbufwsp%2BYz0iCGtjN_ExC9Gyw%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 sympy+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAKgW%3D6KULbcw-_ddgoZ29Dqw%3DqmSEMgKPAJuawajfEF0BkCZ3g%40mail.gmail.com.