Repository: sympy/sympy

Issue:
Complex exponentials are not recognized by domains
```python3
>>> from sympy import *

>>> x = Symbol('x')
>>> w = exp(I*2*pi/3)
>>> Poly([w**2, w, 1], x, extension=True)
Poly(exp(-2*I*pi/3)*x**2 + exp(2*I*pi/3)*x + 1, x, domain='ZZ(exp(I*pi/3))')
>>> w = w.expand(complex=True)
>>> Poly([w**2, w, 1], x, extension=True)
Poly((-1/2 - sqrt(3)*I/2)*x**2 + (-1/2 + sqrt(3)*I/2)*x + 1, x, domain='QQ<sqrt(3) + I>')
```

Only the second one gets recognized as algebraic extension

Discussion:

Patch:
diff --git a/sympy/combinatorics/permutations.py b/sympy/combinatorics/permutations.py
index 24a89834a4..e56aec9682 100644
--- a/sympy/combinatorics/permutations.py
+++ b/sympy/combinatorics/permutations.py
@@ -790,56 +790,6 @@ class Permutation(Atom):
     >>> Permutation.from_sequence('SymPy')
     Permutation([1, 3, 2, 0, 4])
 
-    Checking if a Permutation is contained in a Group
-    =================================================
-
-    Generally if you have a group of permutations G on n symbols, and
-    you're checking if a permutation on less than n symbols is part
-    of that group, the check will fail.
-
-    Here is an example for n=5 and we check if the cycle
-    (1,2,3) is in G:
-
-    >>> from sympy import init_printing
-    >>> init_printing(perm_cyclic=True, pretty_print=False)
-    >>> from sympy.combinatorics import Cycle, Permutation
-    >>> from sympy.combinatorics.perm_groups import PermutationGroup
-    >>> G = PermutationGroup(Cycle(2, 3)(4, 5), Cycle(1, 2, 3, 4, 5))
-    >>> p1 = Permutation(Cycle(2, 5, 3))
-    >>> p2 = Permutation(Cycle(1, 2, 3))
-    >>> a1 = Permutation(Cycle(1, 2, 3).list(6))
-    >>> a2 = Permutation(Cycle(1, 2, 3)(5))
-    >>> a3 = Permutation(Cycle(1, 2, 3),size=6)
-    >>> for p in [p1,p2,a1,a2,a3]: p, G.contains(p)
-    ((2 5 3), True)
-    ((1 2 3), False)
-    ((5)(1 2 3), True)
-    ((5)(1 2 3), True)
-    ((5)(1 2 3), True)
-
-    The check for p2 above will fail.
-
-    Checking if p1 is in G works because SymPy knows
-    G is a group on 5 symbols, and p1 is also on 5 symbols
-    (its largest element is 5).
-
-    For ``a1``, the ``.list(6)`` call will extend the permutation to 5
-    symbols, so the test will work as well. In the case of ``a2`` the
-    permutation is being extended to 5 symbols by using a singleton,
-    and in the case of ``a3`` it's extended through the constructor
-    argument ``size=6``.
-
-    There is another way to do this, which is to tell the ``contains``
-    method that the number of symbols the group is on doesn't need to
-    match perfectly the number of symbols for the permutation:
-
-    >>> G.contains(p2,strict=False)
-    True
-
-    This can be via the ``strict`` argument to the ``contains`` method,
-    and SymPy will try to extend the permutation on its own and then
-    perform the containment check.
-
     See Also
     ========
 
diff --git a/sympy/functions/elementary/exponential.py b/sympy/functions/elementary/exponential.py
index fd360934c6..c4b0231395 100644
--- a/sympy/functions/elementary/exponential.py
+++ b/sympy/functions/elementary/exponential.py
@@ -445,15 +445,13 @@ def complex_extended_negative(arg):
         return fuzzy_or(complex_extended_negative(self.args[0]))
 
     def _eval_is_algebraic(self):
-        s = self.func(*self.args)
-        if s.func == self.func:
-            if fuzzy_not(self.exp.is_zero):
-                if self.exp.is_algebraic:
-                    return False
-                elif (self.exp/S.Pi).is_rational:
-                    return False
-        else:
-            return s.is_algebraic
+        if (self.exp / S.Pi / S.ImaginaryUnit).is_rational:
+            return True
+        if fuzzy_not(self.exp.is_zero):
+            if self.exp.is_algebraic:
+                return False
+            elif (self.exp / S.Pi).is_rational:
+                return False
 
     def _eval_is_extended_positive(self):
         if self.args[0].is_extended_real:


Test patch:
diff --git a/sympy/functions/elementary/tests/test_exponential.py b/sympy/functions/elementary/tests/test_exponential.py
index bad76c2b16..d2718c70fd 100644
--- a/sympy/functions/elementary/tests/test_exponential.py
+++ b/sympy/functions/elementary/tests/test_exponential.py
@@ -382,6 +382,10 @@ def test_exp_assumptions():
     assert exp(pi*r).is_algebraic is None
     assert exp(pi*rn).is_algebraic is False
 
+    assert exp(0, evaluate=False).is_algebraic is True
+    assert exp(I*pi/3, evaluate=False).is_algebraic is True
+    assert exp(I*pi*r, evaluate=False).is_algebraic is True
+
 
 def test_exp_AccumBounds():
     assert exp(AccumBounds(1, 2)) == AccumBounds(E, E**2)
diff --git a/sympy/polys/tests/test_constructor.py b/sympy/polys/tests/test_constructor.py
index 33e2ede9dc..0f2c747202 100644
--- a/sympy/polys/tests/test_constructor.py
+++ b/sympy/polys/tests/test_constructor.py
@@ -5,7 +5,8 @@
 from sympy.polys.domains.realfield import RealField
 from sympy.polys.domains.complexfield import ComplexField
 
-from sympy import S, sqrt, sin, Float, E, I, GoldenRatio, pi, Catalan, Rational
+from sympy import (
+    S, sqrt, sin, exp, Float, E, I, GoldenRatio, pi, Catalan, Rational)
 from sympy.abc import x, y
 
 
@@ -149,6 +150,17 @@ def test_construct_domain():
     assert construct_domain({}) == (ZZ, {})
 
 
+def test_complex_exponential():
+    w = exp(-I*2*pi/3, evaluate=False)
+    alg = QQ.algebraic_field(w)
+    assert construct_domain([w**2, w, 1], extension=True) == (
+        alg,
+        [alg.convert(w**2),
+         alg.convert(w),
+         alg.convert(1)]
+    )
+
+
 def test_composite_option():
     assert construct_domain({(1,): sin(y)}, composite=False) == \
         (EX, {(1,): EX(sin(y))})