Repository: sympy/sympy

Issue:
invert_real should use free_symbols, not has
This should raise an error since the `x` in the function is only a dummy symbol:
```
>>> invert_real(CRootOf(x**4 + x - 1, 2), 0, x, S.Reals)
```
This should not raise an error since the `y` (2nd arg) doesn't really contain `x` -- again, it's a dummy symbol:
```
>>> invert_rea(x**2, CRootOf(x**4 + x - 1, 2), x, S.Reals)
```

This mod in `_invert` will take care of that:

```diff
-    if not f_x.has(x):
+    if x not in f_x.free_symbols:
         raise ValueError("Inverse of constant function doesn't exist")
     y = sympify(y)
-    if y.has(x):
+    if x in y.free_symbols:
```

Discussion:

Patch:
diff --git a/sympy/solvers/solveset.py b/sympy/solvers/solveset.py
index 1b16d6ba65..dc74aa4773 100644
--- a/sympy/solvers/solveset.py
+++ b/sympy/solvers/solveset.py
@@ -137,10 +137,10 @@ def _invert(f_x, y, x, domain=S.Complexes):
     if not x.is_Symbol:
         raise ValueError("x must be a symbol")
     f_x = sympify(f_x)
-    if not f_x.has(x):
+    if x not in f_x.free_symbols:
         raise ValueError("Inverse of constant function doesn't exist")
     y = sympify(y)
-    if y.has(x):
+    if x in y.free_symbols:
         raise ValueError("y should be independent of x ")
 
     if domain.is_subset(S.Reals):


Test patch:
diff --git a/sympy/solvers/tests/test_solveset.py b/sympy/solvers/tests/test_solveset.py
index 0c288518c3..80cb8ddc49 100644
--- a/sympy/solvers/tests/test_solveset.py
+++ b/sympy/solvers/tests/test_solveset.py
@@ -1737,3 +1737,12 @@ def test_issue_14300():
     assert solveset(f, x) == \
         ImageSet(Lambda(n, -I*(2*n*pi + arg(-y + 1))/18000000 -
             log(Abs(y - 1))/18000000), S.Integers)
+
+
+def test_issue_14454():
+    x = Symbol('x')
+    raises(ValueError, lambda: invert_real(CRootOf(x**4 + x - 1, 2), 0, x, S.Reals))
+
+    y = invert_real(x**2, CRootOf(x**4 + x - 1, 2), x, S.Reals)
+    assert y[1].has(Intersection) == True
+    assert y[1].has(CRootOf) == True