Repository: sympy/sympy

Issue:
Algebraic re-arrangement of exponential equations
Sympy version: 1.7.1
Environment: Google Colab
Python version: 3.7

I am trying to use Sympy 1.7.1 in a google Colab environment running python 3.7 to automate some tedious algebra in macroeconomic models, and I'm running into an issue when trying to re-arrange equations of the form:
```
mc = (a * r ** (1 - p) + (1 - a) * w ** (1 - p)) ** (1 / (1 - p))
```
With parameters 0 < a < 1, and p > 0, p != 1 given, and w, r > 0. I would like to be able to re-arrange this expression to obtain functions r(mc, w) or w(mc, r). In the case of r, my expected output is:
 ```
r = ((1 / a) * (mc ** (1 - p) - (1 - a) * w ** (1 - p))) ** (1 / (1 - p))
```

To solve this equation I am trying the following code:

```
import sympy as sp

a, p, mc, r, w = sp.symbols(['a', 'p', 'mc', 'r', 'w'], real=True, nonnegative=True)
eq = mc - (a * r ** (1 - p) + (1 - a) * w ** (1 - p)) ** (1 / (1 - p))
sp.solve(eq, r)
```

Which results in the following error and trace-back: 

```
TypeError                                 Traceback (most recent call last)
<ipython-input-15-a95f68afce93> in <module>()
----> 1 sp.solve(eq, r)

/usr/local/lib/python3.7/dist-packages/sympy/solvers/solvers.py in _solve(f, *symbols, **flags)
   1458                 d = dgen.pop()
   1459                 w = Wild('g')
-> 1460                 gen = f_num.match(D.xreplace({d: w}))[w]
   1461                 spart = gen.as_independent(symbol)[1].as_base_exp()[0]
   1462                 if spart == symbol:

TypeError: 'NoneType' object is not subscriptable
```

When i define a new parameter q = (1 - p), however, so that:
```
mc = (a * r ** q + (1 - a) * w ** q) ** (1 / q)
```

Sympy.solve finds expressions for r or w without any problem. Indeed, it seems only the outside exponent, (1 / (1 - p)) is important to change: the system is able to solve `mc = (a * r ** (1 - p) + (1 - a) * w ** (1 - p)) ** (1 / p)` without any problem. Evidently, that (1 - p) in the denominator of the exponent is causing the problem, but I don't know enough about how the solve function works to understand why that would be the case.

Are there best practices for writing functions of exponents, such as the one I have presented here, in order to facilitate the solve function? 

Thanks for any help in advance! This is my first time posting an issue on github, so I apologize if I did it wrong. 


Discussion:

Patch:
diff --git a/sympy/core/add.py b/sympy/core/add.py
index 6b30806987..697589271e 100644
--- a/sympy/core/add.py
+++ b/sympy/core/add.py
@@ -527,14 +527,16 @@ def _combine_inverse(lhs, rhs):
                 S.Infinity: oo,
                 S.NegativeInfinity: -oo}
             ireps = {v: k for k, v in reps.items()}
-            eq = signsimp(lhs.xreplace(reps) - rhs.xreplace(reps))
+            eq = lhs.xreplace(reps) - rhs.xreplace(reps)
             if eq.has(oo):
                 eq = eq.replace(
                     lambda x: x.is_Pow and x.base is oo,
                     lambda x: x.base)
-            return eq.xreplace(ireps)
+            rv = eq.xreplace(ireps)
         else:
-            return signsimp(lhs - rhs)
+            rv = lhs - rhs
+        srv = signsimp(rv)
+        return srv if srv.is_Number else rv
 
     @cacheit
     def as_two_terms(self):
diff --git a/sympy/core/mul.py b/sympy/core/mul.py
index 1b3fc566cc..57a2175412 100644
--- a/sympy/core/mul.py
+++ b/sympy/core/mul.py
@@ -1224,7 +1224,9 @@ def check(l, r):
             if len(b) != blen:
                 lhs = Mul(*[k**v for k, v in a.items()]).xreplace(i_)
                 rhs = Mul(*[k**v for k, v in b.items()]).xreplace(i_)
-        return signsimp(lhs/rhs)
+        rv = lhs/rhs
+        srv = signsimp(rv)
+        return srv if srv.is_Number else rv
 
     def as_powers_dict(self):
         d = defaultdict(int)
diff --git a/sympy/functions/special/error_functions.py b/sympy/functions/special/error_functions.py
index 8b6a190fca..051f2ea1cf 100644
--- a/sympy/functions/special/error_functions.py
+++ b/sympy/functions/special/error_functions.py
@@ -2146,7 +2146,7 @@ def _eval_as_leading_term(self, x, logx=None, cdir=0):
         elif not arg0.is_infinite:
             return self.func(arg0)
         elif arg0.is_infinite:
-            return -pi*S.ImaginaryUnit/2
+            return -pi*S.ImaginiryUnit/2
         else:
             return self
 
diff --git a/sympy/solvers/solvers.py b/sympy/solvers/solvers.py
index e2f6927111..4459d1417f 100644
--- a/sympy/solvers/solvers.py
+++ b/sympy/solvers/solvers.py
@@ -18,7 +18,7 @@
     default_sort_key)
 from sympy.core.sympify import sympify
 from sympy.core import (S, Add, Symbol, Equality, Dummy, Expr, Mul,
-    Pow, Unequality, Wild)
+    Pow, Unequality)
 from sympy.core.exprtools import factor_terms
 from sympy.core.function import (expand_mul, expand_log,
                           Derivative, AppliedUndef, UndefinedFunction, nfloat,
@@ -1447,17 +1447,12 @@ def _solve(f, *symbols, **flags):
             return [sol]
 
         poly = None
-        # check for a single non-symbol generator
-        dums = f_num.atoms(Dummy)
-        D = f_num.replace(
-            lambda i: isinstance(i, Add) and symbol in i.free_symbols,
-            lambda i: Dummy())
-        if not D.is_Dummy:
-            dgen = D.atoms(Dummy) - dums
-            if len(dgen) == 1:
-                d = dgen.pop()
-                w = Wild('g')
-                gen = f_num.match(D.xreplace({d: w}))[w]
+        # check for a single Add generator
+        if not f_num.is_Add:
+            add_args = [i for i in f_num.atoms(Add)
+                if symbol in i.free_symbols]
+            if len(add_args) == 1:
+                gen = add_args[0]
                 spart = gen.as_independent(symbol)[1].as_base_exp()[0]
                 if spart == symbol:
                     try:


Test patch:
diff --git a/sympy/core/tests/test_match.py b/sympy/core/tests/test_match.py
index 62c06c9f96..513eceda39 100644
--- a/sympy/core/tests/test_match.py
+++ b/sympy/core/tests/test_match.py
@@ -1,5 +1,5 @@
 from sympy import (abc, Add, cos, collect, Derivative, diff, exp, Float, Function,
-    I, Integer, log, Mul, oo, Poly, Rational, S, sin, sqrt, Symbol, symbols,
+    I, Integer, log, Mul, oo, Poly, Rational, S, signsimp, sin, sqrt, Symbol, symbols,
     Wild, pi, meijerg, Sum
 )
 
@@ -509,7 +509,7 @@ def test_issue_3883():
     a, b, c = symbols('a b c', cls=Wild, exclude=(gamma,))
 
     assert f.match(a * log(gamma) + b * gamma + c) == \
-        {a: Rational(-1, 2), b: -(mu - x)**2/2, c: log(2*pi)/2}
+        {a: Rational(-1, 2), b: -(-mu + x)**2/2, c: log(2*pi)/2}
     assert f.expand().collect(gamma).match(a * log(gamma) + b * gamma + c) == \
         {a: Rational(-1, 2), b: (-(x - mu)**2/2).expand(), c: (log(2*pi)/2).expand()}
     g1 = Wild('g1', exclude=[gamma])
@@ -717,6 +717,18 @@ def test_match_issue_17397():
     assert r == {a3: x - 4 + 4/x, b3: 1 - 2/x, c3: x - 4}
 
 
+def test_match_issue_21942():
+    a, r, w = symbols('a, r, w', nonnegative=True)
+    p = symbols('p', positive=True)
+    g_ = Wild('g')
+    pattern = g_ ** (1 / (1 - p))
+    eq = (a * r ** (1 - p) + w ** (1 - p) * (1 - a)) ** (1 / (1 - p))
+    m = {g_: a * r ** (1 - p) + w ** (1 - p) * (1 - a)}
+    assert pattern.matches(eq) == m
+    assert (-pattern).matches(-eq) == m
+    assert pattern.matches(signsimp(eq)) is None
+
+
 def test_match_terms():
     X, Y = map(Wild, "XY")
     x, y, z = symbols('x y z')
diff --git a/sympy/functions/special/tests/test_error_functions.py b/sympy/functions/special/tests/test_error_functions.py
index b580ab6c00..9c7f26048a 100644
--- a/sympy/functions/special/tests/test_error_functions.py
+++ b/sympy/functions/special/tests/test_error_functions.py
@@ -615,8 +615,6 @@ def test_si():
     t = Symbol('t', Dummy=True)
     assert Si(x).rewrite(sinc) == Integral(sinc(t), (t, 0, x))
 
-    assert limit(Shi(x), x, S.NegativeInfinity) == -I*pi/2
-
 
 def test_ci():
     m1 = exp_polar(I*pi)
diff --git a/sympy/solvers/tests/test_solvers.py b/sympy/solvers/tests/test_solvers.py
index c2100197c6..21ffe5d655 100644
--- a/sympy/solvers/tests/test_solvers.py
+++ b/sympy/solvers/tests/test_solvers.py
@@ -20,7 +20,7 @@
 from sympy.testing.pytest import slow, XFAIL, SKIP, raises
 from sympy.testing.randtest import verify_numerically as tn
 
-from sympy.abc import a, b, c, d, k, h, p, x, y, z, t, q, m, R
+from sympy.abc import a, b, c, d, e, k, h, p, x, y, z, t, q, m, R
 
 
 def NS(e, n=15, **options):
@@ -2390,3 +2390,9 @@ def test_issue_17454():
 def test_issue_21852():
     solution = [21 - 21*sqrt(2)/2]
     assert solve(2*x + sqrt(2*x**2) - 21) == solution
+
+
+def test_issue_21942():
+    eq = -d + (a*c**(1 - e) + b**(1 - e)*(1 - a))**(1/(1 - e))
+    sol = solve(eq, c, simplify=False, check=False)
+    assert sol == [(b/b**e - b/(a*b**e) + d**(1 - e)/a)**(1/(1 - e))]