Repository: sympy/sympy

Issue:
sqrt and other root functions should inherit from Function
The functions sqrt, cbrt, root, and real_root, defined in `miscellaneous.py`, are plain Python functions, defined with `def sqrt(arg): ...` This is in contrast to all other mathematical SymPy functions, which inherit from class Function. As a result, one cannot use `sqrt(5.5, evaluate=False)` to create un-evaluated sqrt(5.5), the way it works with exp, log, and all others. 

Those functions should be rewritten, following the model used for other functions (see sympy.functions.elementary for many examples).

Discussion:

Patch:
diff --git a/sympy/core/operations.py b/sympy/core/operations.py
index 1ec708a4c9..362fdb067c 100644
--- a/sympy/core/operations.py
+++ b/sympy/core/operations.py
@@ -31,7 +31,10 @@ def __new__(cls, *args, **options):
         args = list(map(_sympify, args))
         args = [a for a in args if a is not cls.identity]
 
-        if not options.pop('evaluate', global_evaluate[0]):
+        evaluate = options.get('evaluate')
+        if evaluate is None:
+            evaluate = global_evaluate[0]
+        if not evaluate:
             return cls._from_args(args)
 
         if len(args) == 0:
diff --git a/sympy/functions/elementary/miscellaneous.py b/sympy/functions/elementary/miscellaneous.py
index dd922e4b5c..e46dfe8a4f 100644
--- a/sympy/functions/elementary/miscellaneous.py
+++ b/sympy/functions/elementary/miscellaneous.py
@@ -61,11 +61,14 @@ def __new__(cls):
 ###############################################################################
 
 
-def sqrt(arg):
+def sqrt(arg, evaluate=None):
     """The square root function
 
     sqrt(x) -> Returns the principal square root of x.
 
+    The parameter evaluate determines if the expression should be evaluated.
+    If None, its value is taken from global_evaluate
+
     Examples
     ========
 
@@ -126,13 +129,16 @@ def sqrt(arg):
     .. [2] http://en.wikipedia.org/wiki/Principal_value
     """
     # arg = sympify(arg) is handled by Pow
-    return Pow(arg, S.Half)
+    return Pow(arg, S.Half, evaluate=evaluate)
 
 
-def cbrt(arg):
+def cbrt(arg, evaluate=None):
     """This function computes the principal cube root of `arg`, so
     it's just a shortcut for `arg**Rational(1, 3)`.
 
+    The parameter evaluate determines if the expression should be evaluated.
+    If None, its value is taken from global_evaluate.
+
     Examples
     ========
 
@@ -176,13 +182,15 @@ def cbrt(arg):
     * http://en.wikipedia.org/wiki/Principal_value
 
     """
-    return Pow(arg, Rational(1, 3))
+    return Pow(arg, Rational(1, 3), evaluate=evaluate)
 
 
-def root(arg, n, k=0):
+def root(arg, n, k=0, evaluate=None):
     """root(x, n, k) -> Returns the k-th n-th root of x, defaulting to the
     principal root (k=0).
 
+    The parameter evaluate determines if the expression should be evaluated.
+    If None, its value is taken from global_evaluate.
 
     Examples
     ========
@@ -265,16 +273,19 @@ def root(arg, n, k=0):
     """
     n = sympify(n)
     if k:
-        return Pow(arg, S.One/n)*S.NegativeOne**(2*k/n)
-    return Pow(arg, 1/n)
+        return Mul(Pow(arg, S.One/n, evaluate=evaluate), S.NegativeOne**(2*k/n), evaluate=evaluate)
+    return Pow(arg, 1/n, evaluate=evaluate)
 
 
-def real_root(arg, n=None):
+def real_root(arg, n=None, evaluate=None):
     """Return the real nth-root of arg if possible. If n is omitted then
     all instances of (-n)**(1/odd) will be changed to -n**(1/odd); this
     will only create a real root of a principal root -- the presence of
     other factors may cause the result to not be real.
 
+    The parameter evaluate determines if the expression should be evaluated.
+    If None, its value is taken from global_evaluate.
+
     Examples
     ========
 
@@ -308,10 +319,10 @@ def real_root(arg, n=None):
     from sympy.functions.elementary.piecewise import Piecewise
     if n is not None:
         return Piecewise(
-            (root(arg, n), Or(Eq(n, S.One), Eq(n, S.NegativeOne))),
-            (sign(arg)*root(Abs(arg), n), And(Eq(im(arg), S.Zero),
-                Eq(Mod(n, 2), S.One))),
-            (root(arg, n), True))
+            (root(arg, n, evaluate=evaluate), Or(Eq(n, S.One), Eq(n, S.NegativeOne))),
+            (Mul(sign(arg), root(Abs(arg), n, evaluate=evaluate), evaluate=evaluate),
+            And(Eq(im(arg), S.Zero), Eq(Mod(n, 2), S.One))),
+            (root(arg, n, evaluate=evaluate), True))
     rv = sympify(arg)
     n1pow = Transform(lambda x: -(-x.base)**x.exp,
                       lambda x:


Test patch:
diff --git a/sympy/functions/elementary/tests/test_miscellaneous.py b/sympy/functions/elementary/tests/test_miscellaneous.py
index bdfbb02c60..fdf30427f3 100644
--- a/sympy/functions/elementary/tests/test_miscellaneous.py
+++ b/sympy/functions/elementary/tests/test_miscellaneous.py
@@ -3,6 +3,7 @@
 
 from sympy.core.function import Function
 from sympy.core.numbers import I, oo, Rational
+from sympy.core.power import Pow
 from sympy.core.singleton import S
 from sympy.core.symbol import Symbol
 from sympy.functions.elementary.miscellaneous import (sqrt, cbrt, root, Min,
@@ -312,7 +313,7 @@ def test_root():
     assert root(x, n) == x**(1/n)
     assert root(x, -n) == x**(-1/n)
 
-    assert root(x, n, k) == x**(1/n)*(-1)**(2*k/n)
+    assert root(x, n, k) == (-1)**(2*k/n)*x**(1/n)
 
 
 def test_real_root():
@@ -427,3 +428,15 @@ def test(e):
     test(Max(x, y))
     test(Min(x, y, z))
     test(Min(Max(w, x), Max(y, z)))
+
+def test_issue_14000():
+    assert isinstance(sqrt(4, evaluate=False), Pow) == True
+    assert isinstance(cbrt(3.5, evaluate=False), Pow) == True
+    assert isinstance(root(16, 4, evaluate=False), Pow) == True
+
+    assert sqrt(4, evaluate=False) == Pow(4, S.Half, evaluate=False)
+    assert cbrt(3.5, evaluate=False) == Pow(3.5, Rational(1, 3), evaluate=False)
+    assert root(4, 2, evaluate=False) == Pow(4, Rational(1, 2), evaluate=False)
+
+    assert root(16, 4, 2, evaluate=False).has(Pow) == True
+    assert real_root(-8, 3, evaluate=False).has(Pow) == True