Hi again. On Sep 16, 2010, at 9:51 PM, Nicholas Kinar wrote:
> >>> I think you want the collect() function and the .as_independent method. >>> The easiest way to manipulate Equalities is to first convert them into >>> regular expressions. Then, you would call collect on the expression using >>> x**2. collect collects all powers of the argument by default, but you can >>> use the exact=False flag to turn this off (see the docstring of collect). >>> Actually, collect is optional, and is only if you want (A + D)*x**2 instead >>> of A*x**2 + D*x**2. >>> >>> Then, you can gather the independent and dependent parts using >>> as_independent. Here is an example of how you would do it with your >>> expression: >>> >>> In [1]: var('A B C D E F') >>> Out[1]: (A, B, C, D, E, F) >>> >>> In [2]: expr = Eq(A*x**2 + B*y**2 + C*x*y + D*x**2, E*z**2 + F) >>> >>> In [3]: expr >>> Out[3]: >>> 2 2 2 2 >>> C⋅x⋅y + A⋅x + B⋅y + D⋅x = F + E⋅z >>> >>> In [4]: expr = expr.lhs - expr.rhs >>> >>> In [5]: expr >>> Out[5]: >>> 2 2 2 2 >>> -F + C⋅x⋅y + A⋅x + B⋅y + D⋅x - E⋅z >>> >>> In [6]: expr = collect(expr, x**2, exact=True) >>> >>> In [7]: expr >>> Out[7]: >>> 2 2 2 >>> -F + x ⋅(A + D) + C⋅x⋅y + B⋅y - E⋅z >>> >>> In [8]: expr.as_independent(x**2, y**2) >>> Out[8]: >>> ⎛ 2 2 2⎞ >>> ⎝-F + C⋅x⋅y - E⋅z , x ⋅(A + D) + B⋅y ⎠ >>> >>> In [9]: expr = Eq(*reversed(expr.as_independent(x**2, y**2))) >>> >>> In [10]: expr >>> Out[10]: >>> 2 2 2 >>> x ⋅(A + D) + B⋅y = -F + C⋅x⋅y - E⋅z >>> >>> It shouldn't be too hard to write a simple function that is passed an >>> Equality and some variables and returns the result like in [10]. >>> >>> Aaron Meurer >>> >> >> Thanks, Aaron; that's exactly what I wanted and it is very exciting to >> realize that this can be done. I've just started playing with sympy and >> exploring its possibilities, so thank you very much for helping to guide me >> and for your response! >> > > I've been playing around with the algebraic rearrangement being discussed in > this post, and I am wondering if it is possible to do the same operation with > variables that are indexed. Let me perhaps demonstrate what I would like to > achieve. > > In [1]: from sympy import * > In [2]: from sympy.tensor import Indexed, Idx > In [3]: var('A B C D') > In [4]: i, j, n, m = symbols('i j n m', integer=True) > In [5]: M = Indexed('M') > In [6]: expr = Eq(A*M(i,j)**(n+1) + B*M(i+1,j)**(n+1), C*M(i+1,j)**(n+1) + > D*M(i,j)**n) > > In [7]: expr > Out[7]: A*M(i, j)**(1 + n) + B*M(1 + i, j)**(1 + n) == D*M(i, j)**n + C*M(1 + > i, j)**(1 + n) + D*M(i, j)**(1 + n) I'm not sure if exponentiation is the correct way to do superscripts. I guess you could use it, as an abstraction, but remember that SymPy is going to want to treat M(i, j)**(1 + n) as M(i, j)*M(i, j)**n. Probably a better idea would be to just put the "superscript" as another element of the index, such as M(i, j, 1 + n). The only disadvantage is that It won't print the same. Maybe we should implement special handling for super/subscripts in Indexed with printing support (feel free to send in a patch to do this). Also, the things I say below will work much better if you make n an index of M. > > So essentially what I've done is created an equation with a variable M. The > variable M has superscripts (either 1+n or n), and subscripts (i,j). I would > now like to do the following: > > (1) Set i = 1 and j = 1. These are just example integers, but i and j could > be set to other numbers. So then the expr should become: Use .subs(). > > A*M(1, 1)**(1 + n) + B*M(1 + 1, 1)**(1 + n) == D*M(1, 1)**n + C*M(1 + 1, > 1)**(1 + n) + D*M(1, 1)**(1 + n) > A*M(1, 1)**(1 + n) + B*M(2, 1)**(1 + n) == D*M(1, 1)**n + C*M(2, 1)**(1 + n) > + D*M(1, 1)**(1 + n) > > (2) Group all terms with similar subscripts and move all terms with (1 + n) > superscripts to the LHS of the equation: So the same thing I said before would work, except collect() and .as_independent aren't so smart to handle more complex things like this. One idea I had was to use .atoms(), but it seems that it doesn't work as expected for Indexed: In [98]: expr = Eq(A*M(i,j)**(n+1) + B*M(i+1,j)**(n+1), C*M(i+1,j)**(n+1) + D*M(i,j)**n) In [100]: expr.atoms() Out[100]: set(1, A, B, C, D, M, i, j, n) In [101]: expr.atoms(Indexed) Out[101]: set(M) If the second one had given set([M(i, j) ,M(1 + i, j)]), then you could have had something to work with (Chris or Oyvind, do you know why it does this?). Of course, the way I gave again above will still work, if you know what the M's are in the expression: In [104]: expr = expr.lhs - expr.rhs In [105]: expr.subs({i:1}).as_independent(M) Out[105]: ⎛ n 1 + n 1 + n 1 + n⎞ ⎝0, - D⋅M(1, j) + A⋅M(1, j) + B⋅M(2, j) - C⋅M(2, j) ⎠ In [106]: expr.subs({i:1}).as_independent(M(1, j)) Out[106]: ⎛ 1 + n 1 + n n 1 + n⎞ ⎝B⋅M(2, j) - C⋅M(2, j) , - D⋅M(1, j) + A⋅M(1, j) ⎠ The problem is knowing that M(1, j) and M(2, j) are the indexed objects in the expression (that is where I would have liked to use atoms). > > (A - D)*M(1, 1)**(1 + n) + (B - C)*M(2, 1)**(1 + n) == D*M(1, 1)**n > > (3) Print this new expression out in a "nice" format suitable for reading. You can use the same collect() idea that I gave above, but again, you have to give each full indexed object at this point in time. > > If anyone could point me in the right direction, I would be extremely > grateful. Could these operations be done using sympy? > > Nicholas Indexed() is kind of new, so most functions don't know about it. But I think if we fix the atoms bug above, what you want to do should be possible. Aaron Meurer -- You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sy...@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.