Repository: sympy/sympy

Issue:
Circularity in assumptions of products
Running ``(2*z).is_complex`` with SYMPY_USE_CACHE=no leads to
```
RuntimeError: maximum recursion depth exceeded
```
This also happens with other assumptions (except ``is_commutative``).

Discussion:

Patch:
diff --git a/sympy/core/facts.py b/sympy/core/facts.py
index 0ef1e92e94..4cc36ac997 100644
--- a/sympy/core/facts.py
+++ b/sympy/core/facts.py
@@ -79,7 +79,7 @@ def transitive_closure(implications):
     Computes the transitive closure of a list of implications
 
     Uses Warshall's algorithm, as described at
-    http://www.cs.hope.edu/~cusack/Notes/Notes/DiscreteMath/Warshall.pdf.
+    http://chuck.ferzle.com/Notes/Notes/DiscreteMath/Warshall.pdf.
     """
     full_implications = set(implications)
     literals = set().union(*map(set, full_implications))
diff --git a/sympy/core/mul.py b/sympy/core/mul.py
index 982d8db475..e877c5ac71 100644
--- a/sympy/core/mul.py
+++ b/sympy/core/mul.py
@@ -1025,7 +1025,9 @@ def _eval_is_polar(self):
             all(arg.is_polar or arg.is_positive for arg in self.args)
 
     def _eval_is_real(self):
-        real = True
+        return self._eval_real_imag(True)
+
+    def _eval_real_imag(self, real):
         zero = one_neither = False
 
         for t in self.args:
@@ -1062,10 +1064,12 @@ def _eval_is_imaginary(self):
         if z:
             return False
         elif z is False:
-            return (S.ImaginaryUnit*self).is_real
+            return self._eval_real_imag(False)
 
     def _eval_is_hermitian(self):
-        real = True
+        return self._eval_herm_antiherm(True)
+
+    def _eval_herm_antiherm(self, real):
         one_nc = zero = one_neither = False
 
         for t in self.args:
@@ -1077,10 +1081,14 @@ def _eval_is_hermitian(self):
             if t.is_antihermitian:
                 real = not real
             elif t.is_hermitian:
-                if zero is False:
-                    zero = fuzzy_not(t.is_nonzero)
-                    if zero:
-                        return True
+                if not zero:
+                    z = t.is_zero
+                    if not z and zero is False:
+                        zero = z
+                    elif z:
+                        if all(a.is_finite for a in self.args):
+                            return True
+                        return
             elif t.is_hermitian is False:
                 if one_neither:
                     return
@@ -1099,7 +1107,7 @@ def _eval_is_antihermitian(self):
         if z:
             return False
         elif z is False:
-            return (S.ImaginaryUnit*self).is_hermitian
+            return self._eval_herm_antiherm(False)
 
     def _eval_is_irrational(self):
         for t in self.args:
@@ -1127,8 +1135,9 @@ def _eval_is_positive(self):
             pos * neg * nonpositive -> pos or zero -> None is returned
             pos * neg * nonnegative -> neg or zero -> False is returned
         """
+        return self._eval_pos_neg(1)
 
-        sign = 1
+    def _eval_pos_neg(self, sign):
         saw_NON = False
         for t in self.args:
             if t.is_positive:
@@ -1136,7 +1145,9 @@ def _eval_is_positive(self):
             elif t.is_negative:
                 sign = -sign
             elif t.is_zero:
-                return False
+                if all(a.is_finite for a in self.args):
+                    return False
+                return
             elif t.is_nonpositive:
                 sign = -sign
                 saw_NON = True
@@ -1150,7 +1161,9 @@ def _eval_is_positive(self):
             return False
 
     def _eval_is_negative(self):
-        return (-self).is_positive
+        if self.args[0] == -1:
+            return (-self).is_positive  # remove -1
+        return self._eval_pos_neg(-1)
 
     def _eval_is_odd(self):
         is_integer = self.is_integer


Test patch:
diff --git a/sympy/core/tests/test_arit.py b/sympy/core/tests/test_arit.py
index d79df338d8..8ec0bb33d0 100644
--- a/sympy/core/tests/test_arit.py
+++ b/sympy/core/tests/test_arit.py
@@ -1812,6 +1812,17 @@ def test(z, b, e):
         e = Mul(b, z, evaluate=False)
         test(z, b, e)
 
+def test_Mul_with_zero_infinite():
+    zer = Dummy(zero=True)
+    inf = Dummy(finite=False)
+
+    e = Mul(zer, inf, evaluate=False)
+    assert e.is_positive is None
+    assert e.is_hermitian is None
+
+    e = Mul(inf, zer, evaluate=False)
+    assert e.is_positive is None
+    assert e.is_hermitian is None
 
 def test_issue_8247_8354():
     from sympy import tan