Repository: sympy/sympy

Issue:
Missing parentheses pretty printing MatMul and KroneckerProduct
It seems this case wasn't fixed with https://github.com/sympy/sympy/issues/15439

```py
>>> i, j = symbols('i j', integer=True)
>>> X = MatrixSymbol('X', 1, j*k)
>>> A1 = MatrixSymbol("A1", j, 1)
>>> A2 = MatrixSymbol("A2", k, 1)
>>> pprint(X*KroneckerProduct(A1, A2))
X⋅A₁ ⨂ A₂
```

The other way is parenthesized

```py
>>> B = MatrixSymbol('B', i, j)
>>> pprint(KroneckerProduct(B*A1, A2))
(B⋅A₁) ⨂ A₂
```

But there is no implied precedence between a matrix product and Kronecker product, so both ways should be parenthesized.

Discussion:

Patch:
diff --git a/examples/beginner/print_pretty.py b/examples/beginner/print_pretty.py
index 8c61b3e2b1..a7daf9c2c3 100755
--- a/examples/beginner/print_pretty.py
+++ b/examples/beginner/print_pretty.py
@@ -5,13 +5,17 @@
 Demonstrates pretty printing.
 """
 
-from sympy import Symbol, pprint, sin, cos, exp, sqrt
+from sympy import Symbol, pprint, sin, cos, exp, sqrt, MatrixSymbol, KroneckerProduct
 
 
 def main():
     x = Symbol("x")
     y = Symbol("y")
 
+    a = MatrixSymbol("a", 1, 1)
+    b = MatrixSymbol("b", 1, 1)
+    c = MatrixSymbol("c", 1, 1)
+
     pprint( x**x )
     print('\n')  # separate with two blank likes
 
@@ -39,5 +43,8 @@ def main():
     pprint( (1/cos(x)).series(x, 0, 10) )
     print('\n')
 
+    pprint(a*(KroneckerProduct(b, c)))
+    print('\n')
+
 if __name__ == "__main__":
     main()
diff --git a/sympy/codegen/array_utils.py b/sympy/codegen/array_utils.py
index bb03e20e86..db34d3356c 100644
--- a/sympy/codegen/array_utils.py
+++ b/sympy/codegen/array_utils.py
@@ -432,9 +432,6 @@ def nest_permutation(self):
 
         >>> from sympy.codegen.array_utils import (CodegenArrayPermuteDims, CodegenArrayTensorProduct, nest_permutation)
         >>> from sympy import MatrixSymbol
-        >>> from sympy.combinatorics import Permutation
-        >>> Permutation.print_cyclic = True
-
         >>> M = MatrixSymbol("M", 3, 3)
         >>> N = MatrixSymbol("N", 3, 3)
         >>> cg = CodegenArrayPermuteDims(CodegenArrayTensorProduct(M, N), [1, 0, 3, 2])
@@ -771,9 +768,6 @@ def parse_indexed_expression(expr, first_indices=[]):
 
     >>> from sympy.codegen.array_utils import parse_indexed_expression
     >>> from sympy import MatrixSymbol, Sum, symbols
-    >>> from sympy.combinatorics import Permutation
-    >>> Permutation.print_cyclic = True
-
     >>> i, j, k, d = symbols("i j k d")
     >>> M = MatrixSymbol("M", d, d)
     >>> N = MatrixSymbol("N", d, d)
diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py
index 6c58307e0c..a696db1262 100644
--- a/sympy/printing/pretty/pretty.py
+++ b/sympy/printing/pretty/pretty.py
@@ -837,9 +837,9 @@ def _print_MatAdd(self, expr):
 
     def _print_MatMul(self, expr):
         args = list(expr.args)
-        from sympy import Add, MatAdd, HadamardProduct
+        from sympy import Add, MatAdd, HadamardProduct, KroneckerProduct
         for i, a in enumerate(args):
-            if (isinstance(a, (Add, MatAdd, HadamardProduct))
+            if (isinstance(a, (Add, MatAdd, HadamardProduct, KroneckerProduct))
                     and len(expr.args) > 1):
                 args[i] = prettyForm(*self._print(a).parens())
             else:


Test patch:
diff --git a/sympy/printing/pretty/tests/test_pretty.py b/sympy/printing/pretty/tests/test_pretty.py
index 638ad4c9ee..d413887f40 100644
--- a/sympy/printing/pretty/tests/test_pretty.py
+++ b/sympy/printing/pretty/tests/test_pretty.py
@@ -19,7 +19,7 @@
 from sympy.codegen.ast import (Assignment, AddAugmentedAssignment,
     SubAugmentedAssignment, MulAugmentedAssignment, DivAugmentedAssignment, ModAugmentedAssignment)
 
-from sympy.matrices import Adjoint, Inverse, MatrixSymbol, Transpose
+from sympy.matrices import Adjoint, Inverse, MatrixSymbol, Transpose, KroneckerProduct
 
 from sympy.printing.pretty import pretty as xpretty
 from sympy.printing.pretty import pprint
@@ -6476,3 +6476,10 @@ def test_pretty_print_tensor_partial_deriv():
     ucode_str = ascii_str
     assert pretty(expr) == ascii_str
     assert upretty(expr) == ucode_str
+
+
+def test_issue_15560():
+    a = MatrixSymbol('a', 1, 1)
+    e = pretty(a*(KroneckerProduct(a, a)))
+    result = 'a*(a x a)'
+    assert e == result