On Thu, Sep 6, 2012 at 12:07 AM, Juha Jeronen <juha.jero...@jyu.fi> wrote: > On 05.09.2012 17:48, Aaron Meurer wrote: >> >> On Wed, Sep 5, 2012 at 4:37 AM, Juha Jeronen <juha.jero...@jyu.fi> wrote: >>> >>> Hence, let's allow re-ordering. If we reorder the given syms list >>> independently in each subexpression, and collect by ["b","c"] (now in >>> automatically determined, appropriate order for each subexpression) we >>> obtain >>> >>> a*(b*(c*(d + 1) + 1) + 1) + d*(c*(b*(a + 1) + 1) + 1) >>> >>> which gets rid of the extra "c". The first parenthetical expression gets >>> collected by ["b","c"] and the second by ["c","b"]. >>> >>> >>> Now, it seems to me that this feature would be useful... so I extended my >>> recursive_collect() accordingly. The new one has a "reorder" flag which >>> affects the operation when the syms are given. When reordering is >>> enabled, >>> it basically runs the automatic syms generation, and filters the list to >>> include only those syms that were given by the user (while preserving the >>> ordering from the automatically generated list). >>> >>> What would be the sane default for this option? Intuitively, at least I >>> would expect the non-recursive version to do *exactly as it is told* >>> (i.e. >>> no reordering unless explicitly requested), whereas in the recursive >>> version, it would make more sense to have reordering enabled by default >>> in >>> order for collect() to "do what I mean" in cases like the above. >>> >>> Is this fine? >> >> It seems OK to me. > > > Ok. > > So, summarizing again: > > > collect(expr, syms=None, **kwargs) > > kwargs: > deep=True (default; API break!) or deep=False (top level only, like > old collect()) > > method="dfs" (old rcollect()) or method="bfs" (recursive_collect(); > suggesting this as default). > > reorder=bool; whether to allow reordering of given syms per-subexpression > to optimize collection. When deep=False, default is False, and when > deep=True, default is True (mnemonic: default has the same state as "deep"). > When syms=None (automatic syms), this flag has no effect. > > > > For syms, a list can be given as before. The default is the special > value None, which means "use automatic syms". > > rcollect(expr, *vars) just calls collect(expr, syms, deep=True, > method="dfs"). > > >>> Why I think this functionality should be included is, that by using this >>> it >>> is possible to produce efficient recursive collection w.r.t. the given >>> syms >>> only. Something like this is needed, if the user wants to (somewhat >>> optimally) collect e.g. only in variables, ignoring constants. >>> >>> >>> Moving on to the other topic, about the number atoms, is collect() >>> intended >>> to ignore numbers? To me it seems it does: >>> >>> import sympy as sy >>> sy.collect( sy.sympify("2*a + 2*b + 2*c"), sy.sympify("2") ) >>> => 2*a + 2*b + 2*c >> >> Probably. One issue with this is that numbers automatically >> distribute, so if you want to force them out, you have to use a hack >> (this is what factor() does). > > > Ah, I see. > > > >>> Also, this test >>> >>> assert collect(-x/8 + x*y, -x) == x*(y - S(1)/8) >>> >>> in simplify/tests/test_simplify.py, which produces the same result as >>> collecting w.r.t. just "x" - and indeed, according to the assert, is >>> expected to do so - seems to suggest that collect() is meant to ignore >>> numbers. >>> >>> NumberSymbols, OTOH, seem to be handled the same way as generic Symbols: >>> >>> sy.collect( sy.sympify("pi*a + pi*b + 2*pi*c"), sy.sympify("pi") ) >>> => pi*(a + b + 2*c) >>> >>> I'm asking because my automatic syms generator also currently ignores >>> numbers. It would be possible to handle numbers, too, but that would >>> require >>> complicating the ordering a bit (symbols first, numbers last). If it's >>> not >>> needed, I won't add the extra functionality (and the extra bugs to go >>> with >>> it). >> >> There are already good functions for pulling out numbers from an >> expression, like factor_terms, gcd_terms, as_content_primitive (I'm >> not sure what the best one to use is at the moment). So if anything >> collect() should just call one of those as a pre- or post-processor. > > > Ok. Thanks for the tip. I'll see what those can do. > > But I think this part can wait until later - it's probably better to first > just integrate the current version, which ignores numbers (consistently with > how collect() currently works), and then see about improving both. > > > >>> Finally, reading the latest source, I noticed some things about >>> collect(): >>> >>> - it descends into a top-level Mul even when not recursive. Is this >>> behaviour desired? (I think it's ok like this. It's just a bit surprising >>> - >>> maybe needs to be mentioned in the docstring.) >> >> This is probably an artifact of what I was talking about. Recursive >> should really be the default, because it's what most people. If >> collect() was truly non-recursive by default, it wouldn't do what most >> people wanted it to do. > > > Ok. > > > >>> - expr is sympified, but only after some processing (conditional on the >>> "if >>> evaluate:") is already run on it. This processing assumes that expr is >>> already an object tree; hence collect() errors out on string input if >>> evaluate=True. Doing the sympification a few lines earlier would fix this >>> and should have no negative side effects. If that's ok, I'll change this. >> >> It's OK, though note that in general, it's better to just pass SymPy >> objects rather than strings to functions. > > > Ok. > > In programs/scripts, I agree. I consider it mainly a convenience feature for > interactive use :)
For interactive use I would just use var() to create the variables, or even better, use isympy -a. SymPy does have features that are useful interactively but technically bad style, but they are always abused by those who don't know any better (or who don't care). Aaron Meurer > > > > -J > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To post to this group, send email to sympy@googlegroups.com. > To unsubscribe from this group, send email to > sympy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sympy?hl=en. > -- You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sympy@googlegroups.com. To unsubscribe from this group, send email to sympy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sympy?hl=en.