You're right. This might be useful. I'll keep it in mind as I continue to experiment with this.
I hope to issue a PR with this in the next couple days. People can also play with and improve it after then. While I like the separation of this code I think each of the pieces could be improved by someone with more time and attention to devote to it. On Tue, Oct 30, 2012 at 7:25 PM, Aaron Meurer <[email protected]> wrote: > As I noted on StackOverflow, if you allow the kbin to return empty > sets, those could represent identities (assuming your operation has > one). Then you would get the matches {a:0, b: 1 + 2 + 3} and {a: 1 + > 2 + 3, b: 0}. Depending on what you use this for, it may be desirable > to include those. > > Aaron Meurer > > On Tue, Oct 30, 2012 at 4:25 PM, Matthew Rocklin <[email protected]> > wrote: > > Chris' code now enables unification to produce all possible matches > > > > In [1]: run ../unify/unify_sympy.py > > In [2]: expr = Add(1, 2, 3, evaluate=False) > > In [3]: a, b = map(Wild, 'ab') > > In [4]: pattern = Add(a, b, evaluate=False) > > > > In [5]: for x in unify(expr, pattern, {}): print x > > {a_: 1, b_: 2 + 3} > > {a_: 2, b_: 1 + 3} > > {a_: 3, b_: 1 + 2} > > {a_: 1 + 2, b_: 3} > > {a_: 2 + 3, b_: 1} > > {a_: 1 + 3, b_: 2} > > > > Of course, this quickly leads to computational blowup. Fortunately you > can > > ask very efficiently for just the first, second, etc... > > > > Note that, as Aaron pointed out, this doesn't handle mathematical > matching. > > Here is an example which matches a very particular structure. > > > > In [8]: from sympy.abc import x > > In [9]: expr = Add(1, 2*x, 3, evaluate=False) > > In [10]: pattern = Add(a, 2*b, evaluate=False) > > In [11]: for x in unify(expr, pattern, {}): print x > > {a_: 1 + 3, b_: x} > > > > Of course, we don't need to match exact structure. Wilds can currently > match > > any node. > > > > In [6]: pattern = Add(a, b, evaluate=False) > > > > In [7]: for x in unify(expr, pattern, {}): print x > > {a_: 1, b_: 2*x + 3} > > {a_: 2*x, b_: 1 + 3} > > {a_: 3, b_: 2*x + 1} > > {a_: 2*x + 1, b_: 3} > > {a_: 2*x + 3, b_: 1} > > {a_: 1 + 3, b_: 2*x} > > > > On Tue, Oct 30, 2012 at 5:13 PM, Matthew Rocklin <[email protected]> > wrote: > >> > >> Yes, that works quite well. Thanks Chris! > >> > >> > >> On Tue, Oct 30, 2012 at 4:27 PM, Chris Smith <[email protected]> wrote: > >>> > >>> What is said works, I believe...see the docstring > >>> > >>> def kbin(l, k, ordered=True): > >>> """ > >>> Return sequence ``l`` partitioned into ``k`` bins. > >>> If ordered is True then the order of the items in the > >>> flattened partition will be the same as the order of the > >>> items in ``l``; if False, all permutations of the items will > >>> be given; if None, only unique permutations for a given > >>> partition will be given. > >>> > >>> Examples > >>> ======== > >>> > >>> >>> from sympy.utilities.iterables import kbin > >>> >>> for p in kbin(range(3), 2): > >>> ... print p > >>> ... > >>> [[0], [1, 2]] > >>> [[0, 1], [2]] > >>> >>> for p in kbin(range(3), 2, ordered=False): > >>> ... print p > >>> ... > >>> [(0,), (1, 2)] > >>> [(0,), (2, 1)] > >>> [(1,), (0, 2)] > >>> [(1,), (2, 0)] > >>> [(2,), (0, 1)] > >>> [(2,), (1, 0)] > >>> [(0, 1), (2,)] > >>> [(0, 2), (1,)] > >>> [(1, 0), (2,)] > >>> [(1, 2), (0,)] > >>> [(2, 0), (1,)] > >>> [(2, 1), (0,)] > >>> >>> for p in kbin(range(3), 2, ordered=None): > >>> ... print p > >>> ... > >>> [[0], [1, 2]] > >>> [[1], [2, 0]] > >>> [[2], [0, 1]] > >>> [[0, 1], [2]] > >>> [[1, 2], [0]] > >>> [[2, 0], [1]] > >>> > >>> """ > >>> from sympy.utilities.iterables import partitions, permutations > >>> def rotations(seq): > >>> for i in range(len(seq)): > >>> yield seq > >>> seq.append(seq.pop(0)) > >>> if ordered is None: > >>> func = rotations > >>> else: > >>> func = permutations > >>> for p in partitions(len(l), k): > >>> if sum(p.values()) != k: > >>> continue > >>> for pe in permutations(p.keys()): > >>> rv = [] > >>> i = 0 > >>> for part in pe: > >>> for do in range(p[part]): > >>> j = i + part > >>> rv.append(l[i: j]) > >>> i = j > >>> if ordered: > >>> yield rv > >>> else: > >>> template = [len(i) for i in rv] > >>> for pp in func(l): > >>> rvp = [] > >>> ii = 0 > >>> for t in template: > >>> jj = ii + t > >>> rvp.append(pp[ii: jj]) > >>> ii = jj > >>> yield rvp > >>> > >>> -- > >>> You received this message because you are subscribed to the Google > Groups > >>> "sympy" group. > >>> To post to this group, send email to [email protected]. > >>> To unsubscribe from this group, send email to > >>> [email protected]. > >>> 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 [email protected]. > > To unsubscribe from this group, send email to > > [email protected]. > > 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 [email protected]. > To unsubscribe from this group, send email to > [email protected]. > 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 [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
