Repository: sympy/sympy

Issue:
pprint should align the middle of the matrix to the baseline?
Consider the current behaviour, where operators align with the top of the matrix:

```
>>> Z = Matrix(5,5, lambda i,j: i+j)
>>> pprint(MatMul(2,Z))
2⋅⎡0  1  2  3  4⎤
  ⎢             ⎥
  ⎢1  2  3  4  5⎥
  ⎢             ⎥
  ⎢2  3  4  5  6⎥
  ⎢             ⎥
  ⎢3  4  5  6  7⎥
  ⎢             ⎥
  ⎣4  5  6  7  8⎦
>>> pprint(MatAdd(Z,Z))
⎡0  1  2  3  4⎤ + ⎡0  1  2  3  4⎤
⎢             ⎥   ⎢             ⎥
⎢1  2  3  4  5⎥   ⎢1  2  3  4  5⎥
⎢             ⎥   ⎢             ⎥
⎢2  3  4  5  6⎥   ⎢2  3  4  5  6⎥
⎢             ⎥   ⎢             ⎥
⎢3  4  5  6  7⎥   ⎢3  4  5  6  7⎥
⎢             ⎥   ⎢             ⎥
⎣4  5  6  7  8⎦   ⎣4  5  6  7  8⎦
```

This looks poor, but I figured it might be the desired behaviour...

Here's the example that makes me think its wrong:

```
>>> pprint(sin((1+1/x)/(1+1/y)) + det(MatMul(2,Z)))
   ⎛    1⎞                       
   ⎜1 + ─⎟                       
   ⎜    x⎟                       
sin⎜─────⎟ + 32⋅│⎡0  1  2  3  4⎤│
   ⎜    1⎟      │⎢             ⎥│
   ⎜1 + ─⎟      │⎢1  2  3  4  5⎥│
   ⎝    y⎠      │⎢             ⎥│
                │⎢2  3  4  5  6⎥│
                │⎢             ⎥│
                │⎢3  4  5  6  7⎥│
                │⎢             ⎥│
                │⎣4  5  6  7  8⎦│
```

Here's how I think it should work, using the proposed #10423:

```
pprint(sin((1+1/x)/y) + Trace(Z))
               ⎛⎡0  1  2  3  4⎤⎞
   ⎛    1⎞     ⎜⎢             ⎥⎟
   ⎜1 + ─⎟     ⎜⎢1  2  3  4  5⎥⎟
   ⎜    x⎟     ⎜⎢             ⎥⎟
sin⎜─────⎟ + tr⎜⎢2  3  4  5  6⎥⎟
   ⎝  y  ⎠     ⎜⎢             ⎥⎟
               ⎜⎢3  4  5  6  7⎥⎟
               ⎜⎢             ⎥⎟
               ⎝⎣4  5  6  7  8⎦⎠
```

where note the `sin` alignment is by-design, and (relevant to this bug) the `+` and `tr` operator line up with `sin`.

At least, det, MatAdd, MatMul, MatPow would need fixed, maybe others I haven't thought of.


Discussion:
madan96: @cbm755 I will have to change some of the test cases as the results in those cases are tested for the older  print format.
cbm755: Can you add a test?  And fix the breaking test, if appropriate.

*ping* is usually when someone doesn't reply for like a week (most of us get email automatically for changes).  (No worries, its just FYI).

Patch:
diff --git a/doc/src/tutorial/matrices.rst b/doc/src/tutorial/matrices.rst
index 24fe4c87b6..bc3491784d 100644
--- a/doc/src/tutorial/matrices.rst
+++ b/doc/src/tutorial/matrices.rst
@@ -260,9 +260,9 @@ second is a list of indices of the pivot columns.
     ⎢              ⎥
     ⎣-1  -3  -3  -4⎦
     >>> M.rref()
-    ⎛⎡1  0   1    3 ⎤, [0, 1]⎞
+    ⎛⎡1  0   1    3 ⎤        ⎞
     ⎜⎢              ⎥        ⎟
-    ⎜⎢0  1  2/3  1/3⎥        ⎟
+    ⎜⎢0  1  2/3  1/3⎥, [0, 1]⎟
     ⎜⎢              ⎥        ⎟
     ⎝⎣0  0   0    0 ⎦        ⎠
 
@@ -281,11 +281,11 @@ To find the nullspace of a matrix, use ``nullspace``. ``nullspace`` returns a
     ⎢              ⎥
     ⎣4  10  0  0  1⎦
     >>> M.nullspace()
-    ⎡⎡-15⎤, ⎡0⎤, ⎡ 1  ⎤⎤
+    ⎡⎡-15⎤  ⎡0⎤  ⎡ 1  ⎤⎤
     ⎢⎢   ⎥  ⎢ ⎥  ⎢    ⎥⎥
     ⎢⎢ 6 ⎥  ⎢0⎥  ⎢-1/2⎥⎥
     ⎢⎢   ⎥  ⎢ ⎥  ⎢    ⎥⎥
-    ⎢⎢ 1 ⎥  ⎢0⎥  ⎢ 0  ⎥⎥
+    ⎢⎢ 1 ⎥, ⎢0⎥, ⎢ 0  ⎥⎥
     ⎢⎢   ⎥  ⎢ ⎥  ⎢    ⎥⎥
     ⎢⎢ 0 ⎥  ⎢1⎥  ⎢ 0  ⎥⎥
     ⎢⎢   ⎥  ⎢ ⎥  ⎢    ⎥⎥
@@ -305,9 +305,9 @@ To find the columnspace of a matrix, use ``columnspace``. ``columnspace`` return
     ⎢       ⎥
     ⎣3  1  4⎦
     >>> M.columnspace()
-    ⎡⎡1⎤, ⎡1⎤⎤
+    ⎡⎡1⎤  ⎡1⎤⎤
     ⎢⎢ ⎥  ⎢ ⎥⎥
-    ⎢⎢2⎥  ⎢1⎥⎥
+    ⎢⎢2⎥, ⎢1⎥⎥
     ⎢⎢ ⎥  ⎢ ⎥⎥
     ⎣⎣3⎦  ⎣1⎦⎦
 
@@ -339,10 +339,10 @@ returns a list of tuples of the form ``(eigenvalue:algebraic multiplicity,
 [eigenvectors])``.
 
     >>> M.eigenvects()
-    ⎡⎛-2, 1, ⎡⎡0⎤⎤⎞, ⎛3, 1, ⎡⎡1⎤⎤⎞, ⎛5, 2, ⎡⎡1⎤, ⎡0 ⎤⎤⎞⎤
+    ⎡⎛       ⎡⎡0⎤⎤⎞  ⎛      ⎡⎡1⎤⎤⎞  ⎛      ⎡⎡1⎤  ⎡0 ⎤⎤⎞⎤
     ⎢⎜       ⎢⎢ ⎥⎥⎟  ⎜      ⎢⎢ ⎥⎥⎟  ⎜      ⎢⎢ ⎥  ⎢  ⎥⎥⎟⎥
     ⎢⎜       ⎢⎢1⎥⎥⎟  ⎜      ⎢⎢1⎥⎥⎟  ⎜      ⎢⎢1⎥  ⎢-1⎥⎥⎟⎥
-    ⎢⎜       ⎢⎢ ⎥⎥⎟  ⎜      ⎢⎢ ⎥⎥⎟  ⎜      ⎢⎢ ⎥  ⎢  ⎥⎥⎟⎥
+    ⎢⎜-2, 1, ⎢⎢ ⎥⎥⎟, ⎜3, 1, ⎢⎢ ⎥⎥⎟, ⎜5, 2, ⎢⎢ ⎥, ⎢  ⎥⎥⎟⎥
     ⎢⎜       ⎢⎢1⎥⎥⎟  ⎜      ⎢⎢1⎥⎥⎟  ⎜      ⎢⎢1⎥  ⎢0 ⎥⎥⎟⎥
     ⎢⎜       ⎢⎢ ⎥⎥⎟  ⎜      ⎢⎢ ⎥⎥⎟  ⎜      ⎢⎢ ⎥  ⎢  ⎥⎥⎟⎥
     ⎣⎝       ⎣⎣1⎦⎦⎠  ⎝      ⎣⎣1⎦⎦⎠  ⎝      ⎣⎣0⎦  ⎣1 ⎦⎦⎠⎦
diff --git a/sympy/matrices/expressions/matadd.py b/sympy/matrices/expressions/matadd.py
index 92c75aeb47..216ddfaec0 100644
--- a/sympy/matrices/expressions/matadd.py
+++ b/sympy/matrices/expressions/matadd.py
@@ -89,12 +89,12 @@ def merge_explicit(matadd):
     >>> C = Matrix([[1, 2], [3, 4]])
     >>> X = MatAdd(A, B, C)
     >>> pprint(X)
-    A + [1  0] + [1  2]
-        [    ]   [    ]
+        [1  0]   [1  2]
+    A + [    ] + [    ]
         [0  1]   [3  4]
     >>> pprint(merge_explicit(X))
-    A + [2  2]
-        [    ]
+        [2  2]
+    A + [    ]
         [3  5]
     """
     groups = sift(matadd.args, lambda arg: isinstance(arg, MatrixBase))
diff --git a/sympy/matrices/expressions/matmul.py b/sympy/matrices/expressions/matmul.py
index c79f5397e2..79f3035f92 100644
--- a/sympy/matrices/expressions/matmul.py
+++ b/sympy/matrices/expressions/matmul.py
@@ -160,22 +160,22 @@ def merge_explicit(matmul):
     >>> C = Matrix([[1, 2], [3, 4]])
     >>> X = MatMul(A, B, C)
     >>> pprint(X)
-    A*[1  1]*[1  2]
-      [    ] [    ]
+      [1  1] [1  2]
+    A*[    ]*[    ]
       [1  1] [3  4]
     >>> pprint(merge_explicit(X))
-    A*[4  6]
-      [    ]
+      [4  6]
+    A*[    ]
       [4  6]
 
     >>> X = MatMul(B, A, C)
     >>> pprint(X)
-    [1  1]*A*[1  2]
-    [    ]   [    ]
+    [1  1]   [1  2]
+    [    ]*A*[    ]
     [1  1]   [3  4]
     >>> pprint(merge_explicit(X))
-    [1  1]*A*[1  2]
-    [    ]   [    ]
+    [1  1]   [1  2]
+    [    ]*A*[    ]
     [1  1]   [3  4]
     """
     if not any(isinstance(arg, MatrixBase) for arg in matmul.args):
diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py
index ef64d8172c..59158e4f49 100644
--- a/sympy/printing/pretty/pretty.py
+++ b/sympy/printing/pretty/pretty.py
@@ -663,6 +663,7 @@ def _print_matrix_contents(self, e):
 
     def _print_MatrixBase(self, e):
         D = self._print_matrix_contents(e)
+        D.baseline = D.height()//2
         D = prettyForm(*D.parens('[', ']'))
         return D
     _print_ImmutableMatrix = _print_MatrixBase
@@ -699,7 +700,6 @@ def _print_MatrixElement(self, expr):
 
     def _print_MatrixSlice(self, m):
         # XXX works only for applied functions
-
         prettyFunc = self._print(m.parent)
         def ppslice(x):
             x = list(x)


Test patch:
diff --git a/sympy/printing/pretty/tests/test_pretty.py b/sympy/printing/pretty/tests/test_pretty.py
index 466e45cd40..c38e37b03e 100644
--- a/sympy/printing/pretty/tests/test_pretty.py
+++ b/sympy/printing/pretty/tests/test_pretty.py
@@ -2714,24 +2714,24 @@ def test_pretty_ndim_arrays():
 
         ascii_str = \
 """\
-[[1   y]  [ y    2 ]  [z      ]]\n\
-[[--  -]  [ -   y  ]  [-   y*z]]\n\
-[[ 2  x]  [ x      ]  [x      ]]\n\
-[[x    ]  [        ]  [       ]]\n\
-[[     ]  [y*z  w*y]  [ 2     ]]\n\
-[[z   w]              [z   w*z]]\n\
-[[-   -]                       ]\n\
+[[1   y]                       ]\n\
+[[--  -]              [z      ]]\n\
+[[ 2  x]  [ y    2 ]  [-   y*z]]\n\
+[[x    ]  [ -   y  ]  [x      ]]\n\
+[[     ]  [ x      ]  [       ]]\n\
+[[z   w]  [        ]  [ 2     ]]\n\
+[[-   -]  [y*z  w*y]  [z   w*z]]\n\
 [[x   x]                       ]\
 """
         ucode_str = \
 u("""\
-⎡⎡1   y⎤  ⎡ y    2 ⎤  ⎡z      ⎤⎤\n\
-⎢⎢──  ─⎥  ⎢ ─   y  ⎥  ⎢─   y⋅z⎥⎥\n\
-⎢⎢ 2  x⎥  ⎢ x      ⎥  ⎢x      ⎥⎥\n\
-⎢⎢x    ⎥  ⎢        ⎥  ⎢       ⎥⎥\n\
-⎢⎢     ⎥  ⎣y⋅z  w⋅y⎦  ⎢ 2     ⎥⎥\n\
-⎢⎢z   w⎥              ⎣z   w⋅z⎦⎥\n\
-⎢⎢─   ─⎥                       ⎥\n\
+⎡⎡1   y⎤                       ⎤\n\
+⎢⎢──  ─⎥              ⎡z      ⎤⎥\n\
+⎢⎢ 2  x⎥  ⎡ y    2 ⎤  ⎢─   y⋅z⎥⎥\n\
+⎢⎢x    ⎥  ⎢ ─   y  ⎥  ⎢x      ⎥⎥\n\
+⎢⎢     ⎥  ⎢ x      ⎥  ⎢       ⎥⎥\n\
+⎢⎢z   w⎥  ⎢        ⎥  ⎢ 2     ⎥⎥\n\
+⎢⎢─   ─⎥  ⎣y⋅z  w⋅y⎦  ⎣z   w⋅z⎦⎥\n\
 ⎣⎣x   x⎦                       ⎦\
 """)
         assert pretty(M2) == ascii_str
@@ -2739,13 +2739,13 @@ def test_pretty_ndim_arrays():
 
         ascii_str = \
 """\
-[ [1   y]   [ y    2 ]]\n\
-[ [--  -]   [ -   y  ]]\n\
-[ [ 2  x]   [ x      ]]\n\
-[ [x    ]   [        ]]\n\
-[ [     ]   [y*z  w*y]]\n\
-[ [z   w]             ]\n\
-[ [-   -]             ]\n\
+[ [1   y]             ]\n\
+[ [--  -]             ]\n\
+[ [ 2  x]   [ y    2 ]]\n\
+[ [x    ]   [ -   y  ]]\n\
+[ [     ]   [ x      ]]\n\
+[ [z   w]   [        ]]\n\
+[ [-   -]   [y*z  w*y]]\n\
 [ [x   x]             ]\n\
 [                     ]\n\
 [[z      ]  [ w      ]]\n\
@@ -2757,13 +2757,13 @@ def test_pretty_ndim_arrays():
 """
         ucode_str = \
 u("""\
-⎡ ⎡1   y⎤   ⎡ y    2 ⎤⎤\n\
-⎢ ⎢──  ─⎥   ⎢ ─   y  ⎥⎥\n\
-⎢ ⎢ 2  x⎥   ⎢ x      ⎥⎥\n\
-⎢ ⎢x    ⎥   ⎢        ⎥⎥\n\
-⎢ ⎢     ⎥   ⎣y⋅z  w⋅y⎦⎥\n\
-⎢ ⎢z   w⎥             ⎥\n\
-⎢ ⎢─   ─⎥             ⎥\n\
+⎡ ⎡1   y⎤             ⎤\n\
+⎢ ⎢──  ─⎥             ⎥\n\
+⎢ ⎢ 2  x⎥   ⎡ y    2 ⎤⎥\n\
+⎢ ⎢x    ⎥   ⎢ ─   y  ⎥⎥\n\
+⎢ ⎢     ⎥   ⎢ x      ⎥⎥\n\
+⎢ ⎢z   w⎥   ⎢        ⎥⎥\n\
+⎢ ⎢─   ─⎥   ⎣y⋅z  w⋅y⎦⎥\n\
 ⎢ ⎣x   x⎦             ⎥\n\
 ⎢                     ⎥\n\
 ⎢⎡z      ⎤  ⎡ w      ⎤⎥\n\
@@ -5788,3 +5788,15 @@ def test_pretty_UnevaluatedExpr():
   x\
 ''')
     assert upretty(x*he) == ucode_str
+
+
+def test_issue_10472():
+    M = (Matrix([[0, 0], [0, 0]]), Matrix([0, 0]))
+
+    ucode_str = \
+u("""\
+⎛⎡0  0⎤  ⎡0⎤⎞
+⎜⎢    ⎥, ⎢ ⎥⎟
+⎝⎣0  0⎦  ⎣0⎦⎠\
+""")
+    assert upretty(M) == ucode_str