Repository: sympy/sympy

Issue:
PolynomialError when I try to call classify_ode
```python
from sympy import Function, Symbol, classify_ode, Eq, E
x = Symbol('x')
y = Function('y')
eq = Eq(-E**x*y(x).diff().diff() + y(x).diff(), 0)
classify_ode(eq)

THERE IS ERROR

eq = Eq(-E**x*y(x).diff().diff() + y(x).diff(), 0)
eq
Eq(-exp(x)*Derivative(y(x), (x, 2)) + Derivative(y(x), x), 0)

```

The error:

```
Traceback (most recent call last):
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 211, in _parallel_dict_from_expr_if_gens
    monom[indices[base]] = exp
KeyError: exp(x)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/lib/python3.9/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/solvers/ode/ode.py", line 1033, in classify_ode
    if solver.matches():
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/solvers/ode/single.py", line 289, in matches
    self._matched = self._matches()
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/solvers/ode/single.py", line 2092, in _matches
    d = equivalence_hypergeometric(A, B, func)
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/solvers/ode/hypergeometric.py", line 116, in equivalence_hypergeometric
    sing_point.append(list(roots(arg, x).keys())[0])
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/polys/polyroots.py", line 886, in roots
    F = Poly(f, *gens, **flags)
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/polys/polytools.py", line 181, in __new__
    return cls._from_expr(rep, opt)
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/polys/polytools.py", line 310, in _from_expr
    rep, opt = _dict_from_expr(rep, opt)
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 368, in _dict_from_expr
    rep, gens = _dict_from_expr_if_gens(expr, opt)
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 307, in _dict_from_expr_if_gens
    (poly,), gens = _parallel_dict_from_expr_if_gens((expr,), opt)
  File "/home/satels/workenv/krcore/lib/python3.9/site-packages/sympy/polys/polyutils.py", line 216, in _parallel_dict_from_expr_if_gens
    raise PolynomialError("%s contains an element of "
sympy.polys.polyerrors.PolynomialError: exp(2*x) contains an element of the set of generators.
```

Discussion:
sympy-bot: :white_check_mark:

Hi, I am the [SymPy bot](https://github.com/sympy/sympy-bot) (v167). 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
  * fixes bug in `hypergeometric.py` and `classify_ode()` does not raise `PolynomialError`. ([#23478](https://github.com/sympy/sympy/pull/23478) by [@praneethratna](https://github.com/praneethratna))

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

<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. -->


    #### Brief description of what is fixed or changed
    Fixes #23425 and now `classify_ode(Eq(-E**x*y(x).diff().diff() + y(x).diff(), 0))` gives `('Liouville', 'nth_order_reducible', '2nd_power_series_ordinary', 'Liouville_Integral')` instead of `PolynomialError`.

    #### 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
      * fixes bug in `hypergeometric.py` and `classify_ode()` does not raise `PolynomialError`.
    <!-- END RELEASE NOTES -->


</details><p>

praneethratna: @oscarbenjamin is the `circleci: Build Error` specific to this PR? I'm not sure why it is failing.

Patch:
diff --git a/sympy/solvers/ode/hypergeometric.py b/sympy/solvers/ode/hypergeometric.py
index b159053048..51a40b1cba 100644
--- a/sympy/solvers/ode/hypergeometric.py
+++ b/sympy/solvers/ode/hypergeometric.py
@@ -97,6 +97,14 @@ def _power_counting(num):
     # computing I0 of the given equation
     I0 = powdenest(simplify(factor(((J1/k**2) - S(1)/4)/((x**k)**2))), force=True)
     I0 = factor(cancel(powdenest(I0.subs(x, x**(S(1)/k)), force=True)))
+
+    # Before this point I0, J1 might be functions of e.g. sqrt(x) but replacing
+    # x with x**(1/k) should result in I0 being a rational function of x or
+    # otherwise the hypergeometric solver cannot be used. Note that k can be a
+    # non-integer rational such as 2/7.
+    if not I0.is_rational_function(x):
+        return None
+
     num, dem = I0.as_numer_denom()
 
     max_num_pow = max(_power_counting((num, )))


Test patch:
diff --git a/sympy/solvers/ode/tests/test_ode.py b/sympy/solvers/ode/tests/test_ode.py
index fe3faf1c0d..eb0b0c77e1 100644
--- a/sympy/solvers/ode/tests/test_ode.py
+++ b/sympy/solvers/ode/tests/test_ode.py
@@ -1,5 +1,5 @@
 from sympy.core.function import (Derivative, Function, Subs, diff)
-from sympy.core.numbers import (I, Rational, pi)
+from sympy.core.numbers import (E, I, Rational, pi)
 from sympy.core.relational import Eq
 from sympy.core.singleton import S
 from sympy.core.symbol import (Symbol, symbols)
@@ -1069,3 +1069,12 @@ def test_issue_22462():
             Eq(f(x).diff(x), -20*f(x)**2 - 500*f(x)/7200),
             Eq(f(x).diff(x), -2*f(x)**2 - 5*f(x)/7)]:
         assert 'Bernoulli' in classify_ode(de, f(x))
+
+
+def test_issue_23425():
+    x = symbols('x')
+    y = Function('y')
+    eq = Eq(-E**x*y(x).diff().diff() + y(x).diff(), 0)
+    assert classify_ode(eq) == \
+        ('Liouville', 'nth_order_reducible', \
+        '2nd_power_series_ordinary', 'Liouville_Integral')