Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Substitution of Indexed into Sum #11829

Open
skyreflectedinmirrors opened this issue Nov 9, 2016 · 1 comment
Open

Substitution of Indexed into Sum #11829

skyreflectedinmirrors opened this issue Nov 9, 2016 · 1 comment
Labels

Comments

@skyreflectedinmirrors
Copy link
Contributor

skyreflectedinmirrors commented Nov 9, 2016

Consider the following example:

from sympy import *

i, j, l = symbols('i j', cls=Idx)
a, b, c = symbols(a b c', cls=IndexedBase)

print Sum(a[i] * b[i], (i, 1, 10)).subs(a[i] * b[i], c[i])

Currently, this substitution is ignored, resulting in Sum(a[i]*b[i], (i, 1, 10)) due to the intersection of the old value's free symbols set([i, b, a]) with the summation variable i, however I think this is a legitimate substitution pattern.

I have found one way to fix this problem, by simply uncommenting Indexed.free_symbols

    @property
    def free_symbols(self):
        return {self}

However, doing so results in several test failures, and I am not sure that it is the best way to accomplish the above given that the ExprWithLimit's _eval_subs seems to be designed to not allow substitutions of variables that depend on the Summation index.

With that in mind:

  1. Is this a change that would be supported for implementation? My use of Sympy relies quite a bit on it, but I could always derive my own Sum class and use that.

  2. If so, what would be the best way of implementing this change? One thought I had (as opposed to the above) would be to modify the _eval_subs such that sub_into_function is allowed if the ExprWithLimit's function contains the old parameter exactly, e.g. on line 314 in r9ce7495:

if len(xab[0].free_symbols.intersection(old.free_symbols)) != 0:
    if not func.has(old):
        sub_into_func = False
        break

However, this again breaks many tests and the underlying architecture of the ExprWithLimit's _eval_subs. Perhaps in conjunction with a flag passed into the original subs call? Or with the stipulation that the summation variable must not be "directly" in old (e.g. c[i]) and the new must also indirectly contain the same summation variable?

Looking for feedback here,

Thanks,

arghdos

@oscarbenjamin
Copy link
Contributor

You can use xreplace for this:

In [97]: Sum(a[i] * b[i], (i, 1, 10)).xreplace({a[i] * b[i]: c[i]})                                                                                           
Out[97]: 
  10      
 ___      
 ╲        
  ╲   c[i]
  ╱       
 ╱        
 ‾‾‾      
i = 1 

.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants