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:
sympy-bot: :white_check_mark:

Hi, I am the [SymPy bot](https://github.com/sympy/sympy-bot) (v161). I'm here to help you write a release notes entry. Please read the [guide on how to write release notes](https://github.com/sympy/sympy/wiki/Writing-Release-Notes).



Your release notes are in good order.

Here is what the release notes will look like:
* solvers
  * use of `match` was removed to make solving more reliable ([#22079](https://github.com/sympy/sympy/pull/22079) by [@smichr](https://github.com/smichr))

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.9.

<details><summary>Click here to see the pull request description that was parsed.</summary>

    <!-- Your title above should be a short description of what
    was changed. Do not include the issue number in the title. -->

    #### References to other Issues or PRs
    <!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
    format, e.g. "Fixes #1234" (see
    https://tinyurl.com/auto-closing for more information). Also, please
    write a comment on that issue linking back to this pull request once it is
    open. -->

    fixes #21942
    #### Brief description of what is fixed or changed


    #### Other comments


    #### Release Notes

    <!-- Write the release notes for this release below between the BEGIN and END
    statements. The basic format is a bulleted list with the name of the subpackage
    and the release note for this PR. For example:

    * solvers
      * Added a new solver for logarithmic equations.

    * functions
      * Fixed a bug with log of integers.

    or if no release note(s) should be included use:

    NO ENTRY

    See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
    information on how to write release notes. The bot will check your release
    notes automatically to see if they are formatted correctly. -->

    <!-- BEGIN RELEASE NOTES -->
    * solvers
      * use of `match` was removed to make solving more reliable
    <!-- END RELEASE NOTES -->


</details><p>


Patch:
diff --git a/.github/workflows/ci-sage.yml b/.github/workflows/ci-sage.yml
index 2367dae5e8..3cf01ba235 100644
--- a/.github/workflows/ci-sage.yml
+++ b/.github/workflows/ci-sage.yml
@@ -39,9 +39,6 @@ on:
     # Allow to run manually
     branches:
       - master
-      # run on release branches
-      # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#patterns-to-match-branches-and-tags
-      - "[1-9].[0-9]+*"
 
 env:
   # Ubuntu packages to install so that the project's "make dist" can succeed
diff --git a/sympy/core/add.py b/sympy/core/add.py
index 8c478bc09a..411f71c3d2 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 9933eb601a..e7f720a0c7 100644
--- a/sympy/core/mul.py
+++ b/sympy/core/mul.py
@@ -1228,7 +1228,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 bc1baaf742..b8f83e7f32 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,
@@ -1445,17 +1445,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:
diff --git a/sympy/solvers/solveset.py b/sympy/solvers/solveset.py
index c49c994cdb..769d5e2957 100644
--- a/sympy/solvers/solveset.py
+++ b/sympy/solvers/solveset.py
@@ -862,7 +862,7 @@ def _solve_radical(f, unradf, symbol, solveset_solver):
         result = Union(*[imageset(Lambda(y, g_y), f_y_sols)
                          for g_y in g_y_s])
 
-    if not isinstance(result, FiniteSet):
+    if isinstance(result, Complement) or isinstance(result,ConditionSet):
         solution_set = result
     else:
         f_set = []  # solutions for FiniteSet
@@ -1065,7 +1065,7 @@ def _solveset(f, symbol, domain, _check=False):
         elif isinstance(rhs_s, FiniteSet):
             for equation in [lhs - rhs for rhs in rhs_s]:
                 if equation == f:
-                    u = unrad(f, symbol)
+                    u = unrad(f)
                     if u:
                         result += _solve_radical(equation, u,
                                                  symbol,
@@ -2936,6 +2936,7 @@ def substitution(system, symbols, result=[{}], known_symbols=[],
 
     """
 
+    from sympy import Complement
     from sympy.core.compatibility import is_sequence
 
     if not system:
@@ -3447,7 +3448,7 @@ def _separate_poly_nonpoly(system, symbols):
         # Store denom expression if it contains symbol
         denominators.update(_simple_dens(eq, symbols))
         # try to remove sqrt and rational power
-        without_radicals = unrad(simplify(eq), *symbols)
+        without_radicals = unrad(simplify(eq))
         if without_radicals:
             eq_unrad, cov = without_radicals
             if not cov:


Test patch:
diff --git a/sympy/core/tests/test_match.py b/sympy/core/tests/test_match.py
index 6d08f763b9..f03ab811c9 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])
@@ -709,6 +709,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 7dbc09582b..3cef1ac997 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):
@@ -2385,3 +2385,9 @@ def test_issue_6819():
 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))]
diff --git a/sympy/solvers/tests/test_solveset.py b/sympy/solvers/tests/test_solveset.py
index 7563ea4e6f..079d233a52 100644
--- a/sympy/solvers/tests/test_solveset.py
+++ b/sympy/solvers/tests/test_solveset.py
@@ -2895,9 +2895,3 @@ def test_issue_21236():
 def test_issue_21908():
     assert nonlinsolve([(x**2 + 2*x - y**2)*exp(x), -2*y*exp(x)], x, y
                       ) == {(-2, 0), (0, 0)}
-
-
-def test_issue_22058():
-    sol = solveset(-sqrt(t)*x**2 + 2*x + sqrt(t), x, S.Reals)
-    # doesn't fail (and following numerical check)
-    assert sol.xreplace({t: 1}) == {1 - sqrt(2), 1 + sqrt(2)}, sol.xreplace({t: 1})