It seems that the tests could be marked as passing for both forms to see 
where tests fail because a routine is broken. Broken routines could be 
fixed (as necessary) so they are not assuming distribution. Would the 
decorator need to be taken off routines once everything was passing?

Except for a single Add from which only a Rational can be subtracted, I 
suspect that detecting a passing form for a given result would be more 
tricky than one might expect.

/c
On Thursday, February 22, 2024 at 7:57:05 PM UTC-6 Aaron Meurer wrote:

> I don't think we need to try to check the code for everywhere a
> multiplication happens. We can rely on the tests sufficiently covering
> the code.
>
> So what you would do is set the global distribute flag to False, run
> the tests, and see what fails. Then as you fix certain tests that are
> broken, add a @both_distribute decorator to the test to make sure it
> always passes with distribution both off and on.
>
> The downside of this incremental approach is that functions would need
> to work both with and without automatic distribution. In many cases,
> though, this is something that should happen anyway, as even currently
> automatic distribution is not guaranteed. For example, it doesn't
> happen with 2*x*(x + y). And it's not uncommon to have un-distributed
> expressions because functions like factor() create them.
>
> Aaron Meurer
>
> On Thu, Feb 22, 2024 at 2:15 PM Chris Smith <smi...@gmail.com> wrote:
> >
> > In order to solve the issue incrementally, it seems like we would need 
> to identify every line where multiplication is used (on arguments that 
> could possibly be Number and Add) and have them call `Mul` with a 
> `distribute=True` option.
> >
> > How to identify where the multiplication lines are located? Set a booby 
> trap in the `flatten` routine that requires the `distribute` flag to be 
> set. Repeatedly run the tests to identify locations and add the 
> `distribute=False`. At that point all tests are unchanged and passing.
> >
> > Now, one by one, change a distribute flag to True, run tests, fix tests 
> or code to handle the non-distribution since either could cause a failure: 
> the former because something previously distributed would no longer be so, 
> and the latter because expectations for the algorithm were not met and the 
> algorithm (and maybe the test) need modification.
> >
> > /c
> >
> > On Wednesday, February 21, 2024 at 6:07:35 PM UTC-6 Aaron Meurer wrote:
> >>
> >> On Wed, Feb 21, 2024 at 4:09 PM Chris Smith <smi...@gmail.com> wrote:
> >> >
> >> > > There is a distribute() context manager
> >> >
> >> > I had forgotten about that, thanks for the reminder!
> >>
> >> We probably shouldn't advertise it too widely. Like I said, it's not
> >> as bad as the evaluate() context manager, but it has some of the same
> >> fundamental issues.
> >>
> >> The main point of it is that there is a global flag in the core to
> >> turn the distribution off, which should make it easier to remove it if
> >> anyone ever wants to put in that work. For instance we could make a
> >> decorator for the tests that makes sure a specific test passes with
> >> automatic distribution turned off (similar to this one
> >> 
> https://github.com/sympy/sympy/blob/ae13ee38f54aa9c8944ef7d103dda778d2a39dbd/sympy/testing/pytest.py#L291
> ).
> >> That way we can start fixing the code incrementally, instead of taking
> >> an "all or nothing" approach, which has failed in the past.
> >>
> >> Aaron Meurer
> >>
> >> >
> >> > /c
> >> >
> >> > On Wednesday, February 21, 2024 at 4:39:22 PM UTC-6 Aaron Meurer 
> wrote:
> >> >>
> >> >> There is a distribute() context manager which lets you disable
> >> >> automatic distribution, though it's not pretty:
> >> >>
> >> >> >>> from sympy.core.parameters import distribute
> >> >> >>> with distribute(False):
> >> >> ... print(expr.diff(t))
> >> >> 3*a*(t - t0)**2 + 2*b*(t - t0)
> >> >>
> >> >> While this is less dangerous than the similar evaluate() context
> >> >> manager, it is possible this could break something if you put too 
> much
> >> >> under the context.
> >> >>
> >> >> As Chris said, we do want to eventually remove this automatic
> >> >> behavior, but it hasn't been easy to do as a lot of things depend on
> >> >> it currently. Rearranging things after the fact as Chris suggests is
> >> >> probably the better solution. There's really no guarantees about what
> >> >> the form of an expression from diff() will look like.
> >> >>
> >> >> Aaron Meurer
> >> >>
> >> >> On Sun, Feb 18, 2024 at 12:10 PM Chris Smith <smi...@gmail.com> 
> wrote:
> >> >> >
> >> >> > Autodistribution of Number into an Add is how SymPy works and 
> there is no flag for differentiation (or for many functions) that would 
> prevent it. Simply pass the expression to `factor_terms` to get it cleaned 
> up. (But that will extract a factor of `t-t0`, too, which you might not 
> want so you could use `Add(*[factor_terms(i) for i in expr.diff(t).args])` 
> in this case.)
> >> >> >
> >> >> > Some day autodistribution will go away and I expect that we will 
> then ask how to get constants to distribute into simple expressions.
> >> >> >
> >> >> > /c
> >> >> >
> >> >> > On Sunday, February 18, 2024 at 4:52:12 AM UTC-6 
> matthia...@gmail.com wrote:
> >> >> >>
> >> >> >> Hi all.
> >> >> >>
> >> >> >> I have a simple expression:
> >> >> >>
> >> >> >> >>> import sympy as sp
> >> >> >> >>> a, b, t, t0 = sp.symbols('a b t t0')
> >> >> >> >>> expr = a*(t - t0)**3 + b*(t - t0)**2
> >> >> >>
> >> >> >> And I would like to differentiate it with respect to t:
> >> >> >>
> >> >> >> >>> expr.diff(t)
> >> >> >> 3*a*(t - t0)**2 + b*(2*t - 2*t0)
> >> >> >>
> >> >> >> Why is the constant "2" distributed in the second term?
> >> >> >> It seems like an additional step that SymPy does, which doesn't 
> really
> >> >> >> "improve" the situation in this case.
> >> >> >> Maybe there is a more general advantage that's just not visible in
> >> >> >> this simple case?
> >> >> >> But if that is so, would it be possible to tell SymPy to skip the 
> distributing?
> >> >> >>
> >> >> >> To be clear, this is the result I was expecting:
> >> >> >>
> >> >> >> >>> expr.diff(t)
> >> >> >> 3*a*(t - t0)**2 + 2*b*(t - t0)
> >> >> >>
> >> >> >> For context, this question came up in a slightly more complicated
> >> >> >> situation: 
> https://github.com/AudioSceneDescriptionFormat/splines/issues/31
> >> >> >>
> >> >> >> cheers,
> >> >> >> Matthias
> >> >> >
> >> >> > --
> >> >> > 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+un...@googlegroups.com.
> >> >> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sympy/389f5dd9-1498-455a-b6cc-ffbbff89a9d7n%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+un...@googlegroups.com.
> >> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sympy/7a4673b7-4c4e-4101-a4e5-9056847d000en%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+un...@googlegroups.com.
> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sympy/cd7ba971-b424-4c23-b61a-a976aebd3020n%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/4ef9a536-10c9-42b4-84e0-9b20dd609334n%40googlegroups.com.

Reply via email to