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

Indexed should work with subs on a container #7985

Closed
asmeurer opened this Issue Sep 5, 2014 · 7 comments

Comments

Projects
None yet
3 participants
@asmeurer
Copy link
Member

asmeurer commented Sep 5, 2014

See http://stackoverflow.com/questions/25669581/lambdas-operating-on-containers-in-sympy/25693303#25693303. Ideally one could just do

d = IndexedBase('d')
l = Lambda(d, d[1] + d[2])
l(Dict({1: x, 2: y}))

A hand-grown solution like I have in my answer there requires a lot of tricks which have already been figured out with Indexed (and I probably missed some as well).

@asmeurer

This comment has been minimized.

Copy link
Member

asmeurer commented Sep 5, 2014

Another idea would be to ditch IndexedBase and just define __getitem__ on Symbol, but that would require everything to very carefully use iterable() to avoid infinite looping on a Symbol.

@asmeurer

This comment has been minimized.

Copy link
Member

asmeurer commented Sep 6, 2014

I think what is basically needed here is to make this work

In [23]: d = IndexedBase('d')

In [24]: d[1].subs(d, {1: 2})
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-24-09ed4c40789c> in <module>()
----> 1 d[1].subs(d, {1: 2})

/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/basic.py in subs(self, *args, **kwargs)
    903             rv = self
    904             for old, new in sequence:
--> 905                 rv = rv._subs(old, new, **kwargs)
    906                 if not isinstance(rv, Basic):
    907                     break

/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/basic.py in _subs(self, old, new, **hints)
   1017         rv = self._eval_subs(old, new)
   1018         if rv is None:
-> 1019             rv = fallback(self, old, new)
   1020         return rv
   1021

/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/core/basic.py in fallback(self, old, new)
    994                     args[i] = arg
    995             if hit:
--> 996                 rv = self.func(*args)
    997                 hack2 = hints.get('hack2', False)
    998                 if hack2 and self.is_Mul and not rv.is_Mul:  # 2-arg hack

/Users/aaronmeurer/Documents/Python/sympy/sympy/sympy/tensor/indexed.py in __new__(cls, base, *args, **kw_args)
    144         elif not isinstance(base, IndexedBase):
    145             raise TypeError(filldedent("""
--> 146                 Indexed expects string, Symbol or IndexedBase as base."""))
    147         args = list(map(sympify, args))
    148         return Expr.__new__(cls, base, *args, **kw_args)

TypeError:
Indexed expects string, Symbol or IndexedBase as base.

@asmeurer asmeurer added the Easy to Fix label Sep 6, 2014

@asmeurer

This comment has been minimized.

Copy link
Member

asmeurer commented Sep 6, 2014

It should be easy to fix. You just need to extend the type check to look for objects with __getitem__.

MridulS added a commit to MridulS/sympy that referenced this issue Sep 19, 2014

MridulS added a commit to MridulS/sympy that referenced this issue Sep 19, 2014

MridulS added a commit to MridulS/sympy that referenced this issue Sep 19, 2014

MridulS added a commit to MridulS/sympy that referenced this issue Sep 22, 2014

@moorepants

This comment has been minimized.

Copy link
Member

moorepants commented Mar 25, 2015

No, it does not seem the issue is fixed. There is work in this PR to address it: #8065

asmeurer added a commit that referenced this issue Aug 12, 2015

Merge pull request #8065 from MridulS/issue_7985
added type check to look for objects with _getitem_ Fixes #7985
@zanzibar7

This comment has been minimized.

Copy link
Contributor

zanzibar7 commented Sep 15, 2015

I'm working on an issue with subs, and have encountered the following code in test_indexed.py which I do not understand.

def test_IndexedBase_subs():
    i, j, k = symbols('i j k', integer=True)
    a, b, c = symbols('a b c')
    A = IndexedBase(a)
    B = IndexedBase(b)
    C = IndexedBase(c)
    assert A[i] == B[i].subs(b, a)
    assert isinstance(C[1].subs(C, {1: 2}), type(A[1]))

The test passes, but C[1].subs(C, {1: 2}) seems to evaluate to {1: 2}[1]. What's that supposed to mean? My best interpretation is that we really want C[2] out of this evaluation, but that's not what we're getting.

@asmeurer

This comment has been minimized.

Copy link
Member

asmeurer commented Oct 28, 2015

You can look at the discussion on the PR. The idea is that subs should not necessarily evaluate expressions automatically (doit() on that should give the final answer 2).

skirpichev added a commit to skirpichev/diofant that referenced this issue Jun 19, 2016

skirpichev added a commit to skirpichev/diofant that referenced this issue Jun 26, 2016

skirpichev added a commit to skirpichev/diofant that referenced this issue Jul 16, 2016

Added type check to look for objects with _getitem_
Fixes sympy/sympy#7985

// edited by skirpichev: dict (unhashable) -> Dict in tests

Signed-off-by: Sergey B Kirpichev <skirpichev@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment