Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Open In Colab Binder

Structure of each exercise: problem + hint (with a solution dropdown) → Python numerical verification (with execution output)

The verification code must be run in order: some helper functions are defined in earlier code cells and reused by later exercises.

Helper functions loaded

§5.1 Definition and Basic Operations of Block Matrices

============================================================
  Exercise 1 | Ways to Partition a 3×3 Matrix
============================================================

▶ Step 1: 2×2 partitions
----------------------------------------
horizontal cut r=[1], vertical cut c=[1]: ['1×1', '1×2', '2×1', '2×2']
  [sub-blocks agree with the solution] ✓
  [np.block reassembles A] ✓
horizontal cut r=[1], vertical cut c=[2]: ['1×2', '1×1', '2×2', '2×1']
  [sub-blocks agree with the solution] ✓
  [np.block reassembles A] ✓
horizontal cut r=[2], vertical cut c=[1]: ['2×1', '2×2', '1×1', '1×2']
  [sub-blocks agree with the solution] ✓
  [np.block reassembles A] ✓
horizontal cut r=[2], vertical cut c=[2]: ['2×2', '2×1', '1×2', '1×1']
  [sub-blocks agree with the solution] ✓
  [np.block reassembles A] ✓
  [2×2 partition count = C(2,1)·C(2,1)] ✓

▶ Step 2: 1×2 partitions
----------------------------------------
horizontal cut r=[], vertical cut c=[1]: ['3×1', '3×2']
  [sub-blocks agree with the solution] ✓
  [np.block reassembles A] ✓
horizontal cut r=[], vertical cut c=[2]: ['3×2', '3×1']
  [sub-blocks agree with the solution] ✓
  [np.block reassembles A] ✓
  [1×2 partition count = C(2,0)·C(2,1)] ✓

▶ Step 3: 2×1 partitions
----------------------------------------
horizontal cut r=[1], vertical cut c=[]: ['1×3', '2×3']
  [sub-blocks agree with the solution] ✓
  [np.block reassembles A] ✓
horizontal cut r=[2], vertical cut c=[]: ['2×3', '1×3']
  [sub-blocks agree with the solution] ✓
  [np.block reassembles A] ✓
  [2×1 partition count = C(2,1)·C(2,0)] ✓

▶ Step 4: Special sub-blocks: whole columns and whole rows
----------------------------------------
  [1×2 partition c=1: A_00 = col_0(A)] ✓
  [1×2 partition c=2: A_01 = col_2(A)] ✓
  [2×1 partition r=1: A_00 = row_0(A)] ✓
  [2×1 partition r=2: A_10 = row_2(A)] ✓
True
============================================================
  Exercise 2 | Compatibility for Block Addition
============================================================

▶ Step 1: Decide whether the block structures are the same
----------------------------------------
  [(a) same block structure] ✓
  [(b) different block structures] ✓
  (b) size of P_00 (1, 1) , size of Q_00 (2, 2)

▶ Step 2: (a) Add block by block
----------------------------------------
  [P_00 + Q_00 = 0] ✓
  [P_01 + Q_01 = [0 3]] ✓
  [P_10 + Q_10 = [1;3]] ✓
  [P_11 + Q_11 = [[0,4],[6,5]]] ✓
[[0 0 3]
 [1 0 4]
 [3 6 5]]
  [reassembled = P + Q] ✓
  [P + Q = [[0,0,3],[1,0,4],[3,6,5]]] ✓
True
============================================================
  Exercise 3 | Sub-blocks of a Block Transpose
============================================================

▶ Step 1: Partition of A: row partition {0,1}|{2}, column partition {0}|{1,2}
----------------------------------------
  A_00 (2×1) = [[1], [4]]
  A_01 (2×2) = [[2, 3], [5, 6]]
  A_10 (1×1) = [[7]]
  A_11 (1×2) = [[8, 9]]

▶ Step 2: Partition of A^T: row partition {0}|{1,2}, column partition {0,1}|{2}
----------------------------------------
  [B_00 = (A_00)^T = [1 4]] ✓
  [B_00 values] ✓
  [B_01 = (A_10)^T = [7]] ✓
  [B_01 values] ✓
  [B_10 = (A_01)^T] ✓
  [B_10 values] ✓
  [B_11 = (A_11)^T] ✓
  [B_11 values] ✓

▶ Step 3: Reassemble A^T
----------------------------------------
  [np.block(B) = A^T = [[1,4,7],[2,5,8],[3,6,9]]] ✓
  [B_01 ≠ (A_01)^T (different sizes)] ✓
True
============================================================
  Exercise 4 | 4D Tensor Indices of Block Matrices
============================================================

▶ Step 1: (a) 𝒜[0,1,1,0] and the index of 19 in 𝒜
----------------------------------------
  [shape of 𝒜 = (2, 2, 2, 2)] ✓
  [𝒜[i,j,k,l] = A[2i+k, 2j+l]] ✓
  A_01 = [[2, 3], [11, 13]]
  [𝒜[0,1,1,0] = 11] ✓

[Entry 19: 4D index]
  Computed value: (1, 0, 0, 1)
  Expected value: (1, 0, 0, 1)
  [19 = 𝒜[1, 0, 0, 1]] ✓

▶ Step 2: (b) 𝒜[0,1,1,0] and the index of 4 in 𝒜
----------------------------------------
  [shape of 𝒜 = (1, 3, 2, 2)] ✓
  [𝒜[i,j,k,l] = A[2i+k, 2j+l]] ✓
  A_01 = [[1, 2], [6, 7]]
  [𝒜[0,1,1,0] = 6] ✓

[Entry 4: 4D index]
  Computed value: (0, 2, 0, 1)
  Expected value: (0, 2, 0, 1)
  [4 = 𝒜[0, 2, 0, 1]] ✓

▶ Step 3: (c) 𝒜[0,1,1,0] and the index of 26 in 𝒜
----------------------------------------
  [shape of 𝒜 = (3, 3, 2, 2)] ✓
  [𝒜[i,j,k,l] = A[2i+k, 2j+l]] ✓
  A_01 = [[6, 7], [8, 14]]
  [𝒜[0,1,1,0] = 8] ✓

[Entry 26: 4D index]
  Computed value: (1, 2, 0, 0)
  Expected value: (1, 2, 0, 0)
  [26 = 𝒜[1, 2, 0, 0]] ✓

§5.2 Multiplication of Block Matrices

============================================================
  Exercise 5 | Partition Compatibility for Block Multiplication
============================================================

▶ Step 1: Compatibility: do the vertical cuts of X (column partition) equal the horizontal cuts of Y (row partition)?
----------------------------------------
  (a) X column-partition cut points [1], Y row-partition cut points [1]
  [(a) verdict = Yes (rule)] ✓
  [(a) can actually be multiplied block by block] ✓
  (b) X column-partition cut points [1], Y row-partition cut points [2]
  [(b) verdict = No (rule)] ✓
  [(b) can actually be multiplied block by block] ✓
  (c) X column-partition cut points [1], Y row-partition cut points [1]
  [(c) verdict = Yes (rule)] ✓
  [(c) can actually be multiplied block by block] ✓
  (d) X column-partition cut points [], Y row-partition cut points []
  [(d) verdict = Yes (rule)] ✓
  [(d) can actually be multiplied block by block] ✓
  (e) X column-partition cut points [1], Y row-partition cut points [1]
  [(e) verdict = Yes (rule)] ✓
  [(e) can actually be multiplied block by block] ✓
  (f) X column-partition cut points [2], Y row-partition cut points []
  [(f) verdict = No (rule)] ✓
  [(f) can actually be multiplied block by block] ✓

▶ Step 2: (a) sub-blocks and intermediate terms
----------------------------------------
  [X_00 Y_00 = -1] ✓
  [X_01 Y_10 = 3] ✓
  [X_01 Y_11 = [3 -3]] ✓
  [X_10 Y_00 = [0;-2]] ✓
  [X_11 Y_10 = [5;11]] ✓
  [X_11 Y_11 = [[3,-4],[1,-6]]] ✓
  [(XY)_00 = 2] ✓
  [(XY)_01 = [3 -3]] ✓
  [(XY)_10 = [5;9]] ✓
  [(XY)_11] ✓

▶ Step 3: (c) sub-blocks and intermediate terms
----------------------------------------
  [X_00 Y_00] ✓
  [X_01 Y_10] ✓
  [X_01 Y_11 = [-3;-4;-6]] ✓
  [(XY)_00 = [[2,3],[5,3],[9,1]]] ✓
  [(XY)_01 = [-3;-4;-6]] ✓

▶ Step 4: (d) sub-blocks
----------------------------------------
  [(XY)_00 = [2;5]] ✓
  [(XY)_01] ✓
  [(XY)_10 = 9] ✓
  [(XY)_11 = [1 -6]] ✓

▶ Step 5: (e) outer product + block-product contribution
----------------------------------------
  [x w^T = [[-1,0,0],[0,0,0],[-2,0,0]]] ✓
  [rank of the outer product = 1] ✓
  [X_01 Y_10 = [[3,3,-3],[5,3,-4],[11,1,-6]]] ✓
  [(e) single-block result = sum of the two terms] ✓

▶ Step 6: All four feasible expressions reassemble to the same XY
----------------------------------------
[[ 2  3 -3]
 [ 5  3 -4]
 [ 9  1 -6]]
  [XY = [[2,3,-3],[5,3,-4],[9,1,-6]]] ✓
  [(a) np.block = XY] ✓
  [(c) np.block = XY] ✓
  [(d) np.block = XY] ✓
  [(e) np.block = XY] ✓
============================================================
  Exercise 6 | Outer-Product Representation of Rank-One Matrices
============================================================

▶ Step 1: Randomly generate rank-1 matrices (including cases with zero columns, and constructions not written as outer products)
----------------------------------------

▶ Step 2: Verify each conclusion of the proof in turn
----------------------------------------

  Instance 0: shape (6, 2)
  [rank(A) = 1] ✓
  [every column col_j(A) = v_j u] ✓
  [v_{j0} = v_1 = 1] ✓
  [u ≠ 0 and v ≠ 0] ✓
  [A = u v^T = |u⟩⟨v|] ✓
  [a_ij = u_i v_j] ✓
  [not unique: (2u)(v/2)^T = A] ✓

  Instance 1: shape (5, 6)
  [rank(A) = 1] ✓
  [every column col_j(A) = v_j u] ✓
  [v_{j0} = v_1 = 1] ✓
  [u ≠ 0 and v ≠ 0] ✓
  [A = u v^T = |u⟩⟨v|] ✓
  [a_ij = u_i v_j] ✓
  [not unique: (2u)(v/2)^T = A] ✓

  Instance 2: shape (5, 3)
  [rank(A) = 1] ✓
  [every column col_j(A) = v_j u] ✓
  [v_{j0} = v_0 = 1] ✓
  [u ≠ 0 and v ≠ 0] ✓
  [A = u v^T = |u⟩⟨v|] ✓
  [a_ij = u_i v_j] ✓
  [not unique: (2u)(v/2)^T = A] ✓

  Instance 3: shape (2, 5)
  [rank(A) = 1] ✓
  [every column col_j(A) = v_j u] ✓
  [v_{j0} = v_0 = 1] ✓
  [u ≠ 0 and v ≠ 0] ✓
  [A = u v^T = |u⟩⟨v|] ✓
  [a_ij = u_i v_j] ✓
  [not unique: (2u)(v/2)^T = A] ✓

  Instance 4: shape (5, 4)
  [rank(A) = 1] ✓
  [every column col_j(A) = v_j u] ✓
  [v_{j0} = v_0 = 1] ✓
  [u ≠ 0 and v ≠ 0] ✓
  [A = u v^T = |u⟩⟨v|] ✓
  [a_ij = u_i v_j] ✓
  [not unique: (2u)(v/2)^T = A] ✓

  Instance 5: shape (5, 5)
  [rank(A) = 1] ✓
  [every column col_j(A) = v_j u] ✓
  [v_{j0} = v_0 = 1] ✓
  [u ≠ 0 and v ≠ 0] ✓
  [A = u v^T = |u⟩⟨v|] ✓
  [a_ij = u_i v_j] ✓
  [not unique: (2u)(v/2)^T = A] ✓

§5.3 Inverses of Matrices in Block Form

============================================================
  Exercise 7 | Computations with Block Diagonal Matrices
============================================================

▶ Step 1: (a) M^2 = diag(M_0^2, M_1^2)
----------------------------------------
  [M_0^2 = [[11,4],[2,3]]] ✓
  [M_1^2 = I] ✓
[[11  4  0  0]
 [ 2  3  0  0]
 [ 0  0  1  0]
 [ 0  0  0  1]]
  [M^2 = diag(M_0^2, M_1^2)] ✓
  [M^2 values] ✓

▶ Step 2: (b) Multiply the diagonal blocks block by block (block sizes 1,2,1)
----------------------------------------
  [X_1 Y_1 = [[-4,-8],[4,0]]] ✓
  [corners: 2·4 = 8, (-2)·7 = -14] ✓
[[  8   0   0   0]
 [  0  -4  -8   0]
 [  0   4   0   0]
 [  0   0   0 -14]]
  [XY values] ✓

▶ Step 3: (c) Invert block by block (sympy for exact fractions)
----------------------------------------
  [det N_0 = -1] ✓
  [N_0^{-1} = [[-3,2],[5,-3]]] ✓
  [N_1^{-1} = [[0,1/2],[1/2,0]]] ✓
Matrix([[-3, 2, 0, 0], [5, -3, 0, 0], [0, 0, 0, 1/2], [0, 0, 1/2, 0]])
  [N^{-1} = diag(N_0^{-1}, N_1^{-1}) (exact)] ✓
  [N N^{-1} = I_4] ✓
True
============================================================
  Exercise 8 | Inverse of a Block Upper Triangular Matrix
============================================================

▶ Step 1: Random instance: A is 2×2, D is 2×2, B is 2×2
----------------------------------------
  [M N = I] ✓
  [N M = I] ✓
  [N equals np.linalg.inv(M)] ✓
  [when C = 0, S = D - C A^{-1} B = D] ✓
  [agrees with the block inversion formula] ✓

▶ Step 2: Random instance: A is 2×2, D is 3×3, B is 2×3
----------------------------------------
  [M N = I] ✓
  [N M = I] ✓
  [N equals np.linalg.inv(M)] ✓
  [when C = 0, S = D - C A^{-1} B = D] ✓
  [agrees with the block inversion formula] ✓

▶ Step 3: Random instance: A is 3×3, D is 1×1, B is 3×1
----------------------------------------
  [M N = I] ✓
  [N M = I] ✓
  [N equals np.linalg.inv(M)] ✓
  [when C = 0, S = D - C A^{-1} B = D] ✓
  [agrees with the block inversion formula] ✓

▶ Step 4: Random instance: A is 1×1, D is 4×4, B is 1×4
----------------------------------------
  [M N = I] ✓
  [N M = I] ✓
  [N equals np.linalg.inv(M)] ✓
  [when C = 0, S = D - C A^{-1} B = D] ✓
  [agrees with the block inversion formula] ✓
============================================================
  Exercise 9 | Inverse of a Block Lower Triangular Matrix
============================================================

▶ Step 1: Random instance: A is 2×2, D is 2×2, C is 2×2
----------------------------------------
  [N equals np.linalg.inv(M)] ✓
  [the transpose route ((M^T)^{-1})^T gives the same result] ✓
  [agrees with the block inversion formula (B = 0)] ✓

▶ Step 2: Random instance: A is 3×3, D is 2×2, C is 2×3
----------------------------------------
  [N equals np.linalg.inv(M)] ✓
  [the transpose route ((M^T)^{-1})^T gives the same result] ✓
  [agrees with the block inversion formula (B = 0)] ✓

▶ Step 3: Random instance: A is 1×1, D is 3×3, C is 3×1
----------------------------------------
  [N equals np.linalg.inv(M)] ✓
  [the transpose route ((M^T)^{-1})^T gives the same result] ✓
  [agrees with the block inversion formula (B = 0)] ✓
============================================================
  Exercise 10 | Numerical Block Inversion
============================================================

▶ Step 1: 3×3 matrix: A = (2), B = (1 5), D = [[1,2],[2,3]]
----------------------------------------
  [lower-left block is zero] ✓ (exact)
  [A^{-1} = (1/2)] ✓ (exact)
  [D^{-1} = [[-3,2],[2,-1]]] ✓ (exact)
  [upper-right block -A^{-1} B D^{-1} = (-7/2, 3/2)] ✓ (exact)
M1^{-1} =
  [  1/2  -7/2   3/2 ]
  [    0    -3     2 ]
  [    0     2    -1 ]
  [agrees with the solution] ✓ (exact)
  [M1 M1^{-1} = I] ✓ (exact)
  [M1^{-1} M1 = I] ✓ (exact)

▶ Step 2: 4×4 matrix: 2+2 partition and the Schur complement
----------------------------------------
  [A^{-1} = [[-3,2],[5,-3]]] ✓ (exact)
  [C A^{-1}] ✓ (exact)
  [C A^{-1} B] ✓ (exact)
  [S = [[3,3],[6,1]]] ✓ (exact)
  [S^{-1}] ✓ (exact)

▶ Step 3: Substitute block by block into the block inversion formula
----------------------------------------
  [A^{-1} B] ✓ (exact)
  [upper-right block -A^{-1} B S^{-1}] ✓ (exact)
  [lower-left block -S^{-1} C A^{-1}] ✓ (exact)
  [A^{-1} B S^{-1} C A^{-1}] ✓ (exact)
  [upper-left block] ✓ (exact)
M2^{-1} =
  [  -4/15     2/5   -4/15    -1/5 ]
  [    6/5    -4/5     1/5     2/5 ]
  [ -16/15     3/5   -1/15     1/5 ]
  [   -3/5     2/5     2/5    -1/5 ]
  [agrees with the exact Gauss–Jordan inverse] ✓ (exact)
  [M2 M2^{-1} = I] ✓ (exact)
  [M2^{-1} M2 = I] ✓ (exact)
  [agrees with np.linalg.inv (floating point)] ✓
True
============================================================
  Exercise 11 | Deriving the Block Inversion Formula by Block Gaussian Elimination
============================================================

▶ Step 1: Random instance: A is 2×2, D is 2×2
----------------------------------------
  [(a) E M = U] ✓
  [E^{-1} = [[I, 0], [C A^{-1}, I]]] ✓
  [U^{-1} (formula of Exercise 8)] ✓
  [M^{-1} = U^{-1} E] ✓
  [U^{-1} E equals the block inversion formula] ✓

▶ Step 2: Random instance: A is 3×3, D is 2×2
----------------------------------------
  [(a) E M = U] ✓
  [E^{-1} = [[I, 0], [C A^{-1}, I]]] ✓
  [U^{-1} (formula of Exercise 8)] ✓
  [M^{-1} = U^{-1} E] ✓
  [U^{-1} E equals the block inversion formula] ✓

▶ Step 3: Random instance: A is 2×2, D is 4×4
----------------------------------------
  [(a) E M = U] ✓
  [E^{-1} = [[I, 0], [C A^{-1}, I]]] ✓
  [U^{-1} (formula of Exercise 8)] ✓
  [M^{-1} = U^{-1} E] ✓
  [U^{-1} E equals the block inversion formula] ✓
============================================================
  Exercise 12 | Inverting a 4×4 Matrix with the Block Inversion Formula
============================================================

▶ Step 1: Partition: B = C = P, D = 0
----------------------------------------
  [B = P] ✓ (exact)
  [C = P] ✓ (exact)
  [D = 0] ✓ (exact)

▶ Step 2: A^{-1} and the Schur complement
----------------------------------------
  [A^{-1} = [[2,-1],[-1,1]]] ✓ (exact)
  [C A^{-1} (swap the two rows)] ✓ (exact)
  [C A^{-1} B (then swap the two columns)] ✓ (exact)
  [S = [[-1,1],[1,-2]]] ✓ (exact)
  [S^{-1} = [[-2,-1],[-1,-1]]] ✓ (exact)

▶ Step 3: Substitute block by block into the formula
----------------------------------------
  [A^{-1} B] ✓ (exact)
  [A^{-1} B S^{-1}] ✓ (exact)
  [S^{-1} C A^{-1}] ✓ (exact)
  [A^{-1} B S^{-1} C A^{-1}] ✓ (exact)
  [upper-left block = 0] ✓ (exact)
  [upper-right block = P] ✓ (exact)
  [lower-left block = P] ✓ (exact)

▶ Step 4: Assemble and verify
----------------------------------------
M^{-1} =
  [  0   0   0   1 ]
  [  0   0   1   0 ]
  [  0   1  -2  -1 ]
  [  1   0  -1  -1 ]
  [agrees with the solution] ✓ (exact)
  [upper-right block check A P + P S^{-1} = 0] ✓ (exact)
  [M M^{-1} = I_4] ✓ (exact)
  [M^{-1} M = I_4] ✓ (exact)
True
============================================================
  Exercise 13 | The Block Inversion Formula with D as Pivot
============================================================

▶ Step 1: A is a non-invertible 2×2 matrix, D is 2×2
----------------------------------------
  rank(A) = 1 < 2, so A is not invertible
  [A is not invertible (rank(A) = p-1)] ✓
  [formula = np.linalg.inv(M)] ✓
  [Π M Π^T = [[D, C], [B, A]]] ✓
  [M^{-1} = Π^T (M')^{-1} Π, with (M')^{-1} from the block inversion formula] ✓

▶ Step 2: A is a non-invertible 3×3 matrix, D is 2×2
----------------------------------------
  rank(A) = 2 < 3, so A is not invertible
  [A is not invertible (rank(A) = p-1)] ✓
  [formula = np.linalg.inv(M)] ✓
  [Π M Π^T = [[D, C], [B, A]]] ✓
  [M^{-1} = Π^T (M')^{-1} Π, with (M')^{-1} from the block inversion formula] ✓

▶ Step 3: A is a non-invertible 2×2 matrix, D is 4×4
----------------------------------------
  rank(A) = 1 < 2, so A is not invertible
  [A is not invertible (rank(A) = p-1)] ✓
  [formula = np.linalg.inv(M)] ✓
  [Π M Π^T = [[D, C], [B, A]]] ✓
  [M^{-1} = Π^T (M')^{-1} Π, with (M')^{-1} from the block inversion formula] ✓

▶ Step 4: A is a non-invertible 4×4 matrix, D is 3×3
----------------------------------------
  rank(A) = 3 < 4, so A is not invertible
  [A is not invertible (rank(A) = p-1)] ✓
  [formula = np.linalg.inv(M)] ✓
  [Π M Π^T = [[D, C], [B, A]]] ✓
  [M^{-1} = Π^T (M')^{-1} Π, with (M')^{-1} from the block inversion formula] ✓

▶ Step 5: Example: A = 0, B = C = D = I_n (n = 3)
----------------------------------------
  [M^{-1} = [[-I, I], [I, 0]]] ✓
  [M M^{-1} = I] ✓

▶ Step 6: Note: when A, D, S, T are all invertible the two formulas agree (Woodbury form)
----------------------------------------
  [(A - B D^{-1} C)^{-1} = A^{-1} + A^{-1} B S^{-1} C A^{-1}] ✓
  [the two block formulas give the same M^{-1}] ✓
True
============================================================
  Exercise 14 | Must M Be Non-invertible When Neither Diagonal Block Is Invertible?
============================================================

▶ Step 1: Smallest counterexample: A = D = (0), B = C = (1)
----------------------------------------
  [A = (0) is not invertible (rank 0)] ✓
  [M M = I_2, so M^{-1} = M] ✓
  [n = 2: [[0, I], [I, 0]]^2 = I] ✓
  [n = 3: [[0, I], [I, 0]]^2 = I] ✓

▶ Step 2: Counterexample with nonzero diagonal blocks: M = [[J_2, I_2], [I_2, J_2]] = J_4 - P
----------------------------------------
M =
 [[1. 1. 1. 0.]
 [1. 1. 0. 1.]
 [1. 0. 1. 1.]
 [0. 1. 1. 1.]]
  [M = J_4 - P] ✓
  [rank(J_2) = 1, so the diagonal blocks are not invertible] ✓
  [J_4^2 = 4 J_4] ✓
  [J_4 P = P J_4 = J_4] ✓
  [P^2 = I_4] ✓
  [M^{-1} = J_4/3 - P] ✓
  [agrees with the solution matrix (1/3)[[1,1,1,-2],...]] ✓
  [M M^{-1} = I_4] ✓

▶ Step 3: Comparison: block upper triangular with A not invertible forces M to be non-invertible; A, D invertible does not make M invertible
----------------------------------------
  [A v = 0] ✓
  [M [v; 0] = 0, so M is not invertible] ✓
  [[[1,1],[1,1]]: A = D = (1) invertible but rank(M) = 1] ✓
True
============================================================
  Exercise 15 | Choosing the Pivot to Invert a 4×4 Matrix
============================================================

▶ Step 1: M1: A is not invertible, D is invertible
----------------------------------------
  [rank(A) = 1, so A is not invertible] ✓
  [D^{-1} = [[2,-1],[-1,1]]] ✓ (exact)

▶ Step 2: M1: Schur complement T = A - B D^{-1} C
----------------------------------------
  [B D^{-1}] ✓ (exact)
  [B D^{-1} C] ✓ (exact)
  [T = [[1,2],[1,1]]] ✓ (exact)
  [T^{-1} = [[-1,2],[1,-1]]] ✓ (exact)

▶ Step 3: M1: substitute block by block into the formula of Exercise 13
----------------------------------------
  [upper-right block -T^{-1} B D^{-1}] ✓ (exact)
  [D^{-1} C] ✓ (exact)
  [lower-left block -D^{-1} C T^{-1}] ✓ (exact)
  [D^{-1} C T^{-1} B D^{-1}] ✓ (exact)
  [lower-right block = [[0,1],[0,0]]] ✓ (exact)
M1^{-1} =
  [ -1   2  -1   1 ]
  [  1  -1   1  -1 ]
  [ -2   2   0   1 ]
  [  1  -1   0   0 ]
  [agrees with the solution] ✓ (exact)
  inner products of row 0 with columns 0 and 1: 1 0
  [M1 M1^{-1} = I_4] ✓ (exact)
  [M1^{-1} M1 = I_4] ✓ (exact)

▶ Step 4: M2: A^{-1} and the Schur complement S
----------------------------------------
  [A^{-1} = diag(1, 1/2)] ✓ (exact)
  [C A^{-1}] ✓ (exact)
  [C A^{-1} B] ✓ (exact)
  [S = diag(1/2, 1)] ✓ (exact)
  [S^{-1} = diag(2, 1)] ✓ (exact)

▶ Step 5: M2: substitute block by block into the block inversion formula
----------------------------------------
  [A^{-1} B] ✓ (exact)
  [A^{-1} B S^{-1} = P] ✓ (exact)
  [S^{-1} C A^{-1} = P] ✓ (exact)
  [A^{-1} B S^{-1} C A^{-1} = diag(1, 1/2)] ✓ (exact)
  [upper-left block = diag(2, 1)] ✓ (exact)
M2^{-1} =
  [  2   0   0  -1 ]
  [  0   1  -1   0 ]
  [  0  -1   2   0 ]
  [ -1   0   0   1 ]
  [agrees with the solution] ✓ (exact)
  [M2 M2^{-1} = I_4] ✓ (exact)
  [M2^{-1} M2 = I_4] ✓ (exact)

▶ Step 6: M2: indices {0,3} and {1,2} are not coupled (block diagonal after reordering)
----------------------------------------
  [entries of M2 in {0,3}×{1,2} are all 0] ✓ (exact)
  [[[1,1],[1,2]]^{-1} sits at the {0,3} positions of M2^{-1}] ✓ (exact)
  [[[2,1],[1,1]]^{-1} sits at the {1,2} positions of M2^{-1}] ✓ (exact)
True
============================================================
  Exercise 16 | Inverse of the Block Matrix [[I, X], [Y, 0]]
============================================================

▶ Step 1: n = 2: (a) formula, (b) two-sided check, (c) simplification
----------------------------------------
  [(a) formula = np.linalg.inv(M)] ✓
  [(a) formula = block inversion formula (A = I, D = 0)] ✓
  [(b) M M^{-1} = I_{2n}] ✓
  [(b) M^{-1} M = I_{2n}] ✓
  [(c) M^{-1} = [[0, Y^{-1}], [X^{-1}, -X^{-1} Y^{-1}]]] ✓
  [(c) upper-left block I - X (YX)^{-1} Y = 0] ✓

▶ Step 2: n = 3: (a) formula, (b) two-sided check, (c) simplification
----------------------------------------
  [(a) formula = np.linalg.inv(M)] ✓
  [(a) formula = block inversion formula (A = I, D = 0)] ✓
  [(b) M M^{-1} = I_{2n}] ✓
  [(b) M^{-1} M = I_{2n}] ✓
  [(c) M^{-1} = [[0, Y^{-1}], [X^{-1}, -X^{-1} Y^{-1}]]] ✓
  [(c) upper-left block I - X (YX)^{-1} Y = 0] ✓

▶ Step 3: n = 4: (a) formula, (b) two-sided check, (c) simplification
----------------------------------------
  [(a) formula = np.linalg.inv(M)] ✓
  [(a) formula = block inversion formula (A = I, D = 0)] ✓
  [(b) M M^{-1} = I_{2n}] ✓
  [(b) M^{-1} M = I_{2n}] ✓
  [(c) M^{-1} = [[0, Y^{-1}], [X^{-1}, -X^{-1} Y^{-1}]]] ✓
  [(c) upper-left block I - X (YX)^{-1} Y = 0] ✓

▶ Step 4: Note: in the square case, YX invertible ⟹ X, Y invertible (checked via rank)
----------------------------------------
  [when rank(YX) = n, rank(X) = rank(Y) = n] ✓

▶ Step 5: Note: the rectangular case, X is n×k and Y is k×n (k < n)
----------------------------------------
  [n = 4, k = 2: M M^{-1} = I_{n+k}] ✓
  [n = 4, k = 2: M^{-1} M = I_{n+k}] ✓
  [n = 4, k = 2: X (YX)^{-1} Y is a projection (P^2 = P)] ✓
  [n = 5, k = 3: M M^{-1} = I_{n+k}] ✓
  [n = 5, k = 3: M^{-1} M = I_{n+k}] ✓
  [n = 5, k = 3: X (YX)^{-1} Y is a projection (P^2 = P)] ✓
============================================================
  Exercise 17 | Inverse of the Block Matrix [[A, B], [-B, A]]
============================================================

▶ Step 1: (a) n = 2: general (noncommuting) A, B
----------------------------------------
  ||AB - BA|| = 2.5247 (noncommuting)
  [S = A (I + K^2)] ✓
  [G K = K G] ✓
  [X = (A + B A^{-1} B)^{-1}] ✓
  [M^{-1} = [[X, Y], [-Y, X]]] ✓
  [M^{-1} upper-left block = lower-right block] ✓
  [M^{-1} lower-left block = -upper-right block] ✓
  [Note: M J = J M and M^{-1} J = J M^{-1}] ✓

▶ Step 2: (a) n = 3: general (noncommuting) A, B
----------------------------------------
  ||AB - BA|| = 5.6205 (noncommuting)
  [S = A (I + K^2)] ✓
  [G K = K G] ✓
  [X = (A + B A^{-1} B)^{-1}] ✓
  [M^{-1} = [[X, Y], [-Y, X]]] ✓
  [M^{-1} upper-left block = lower-right block] ✓
  [M^{-1} lower-left block = -upper-right block] ✓
  [Note: M J = J M and M^{-1} J = J M^{-1}] ✓

▶ Step 3: (a) n = 4: general (noncommuting) A, B
----------------------------------------
  ||AB - BA|| = 13.2893 (noncommuting)
  [S = A (I + K^2)] ✓
  [G K = K G] ✓
  [X = (A + B A^{-1} B)^{-1}] ✓
  [M^{-1} = [[X, Y], [-Y, X]]] ✓
  [M^{-1} upper-left block = lower-right block] ✓
  [M^{-1} lower-left block = -upper-right block] ✓
  [Note: M J = J M and M^{-1} J = J M^{-1}] ✓

▶ Step 4: (b) commuting A, B: take B to be a polynomial in A
----------------------------------------
  [n = 2: AB = BA] ✓
  [n = 2: M^{-1} = [[A R, -B R], [B R, A R]]] ✓
  [n = 2: R A = A R] ✓
  [n = 3: AB = BA] ✓
  [n = 3: M^{-1} = [[A R, -B R], [B R, A R]]] ✓
  [n = 3: R A = A R] ✓
  [n = 4: AB = BA] ✓
  [n = 4: M^{-1} = [[A R, -B R], [B R, A R]]] ✓
  [n = 4: R A = A R] ✓

▶ Step 5: The formula of (b) does not need A to be invertible: A = diag(0, 1), B = diag(1, 0)
----------------------------------------
  [A^2 + B^2 = I] ✓
  [M^{-1} = [[A R, -B R], [B R, A R]]] ✓

▶ Step 6: Note: n = 1 corresponds to the complex number a + bi (a = 3, b = 4)
----------------------------------------
  [[[a,b],[-b,a]]^{-1} = (1/(a^2+b^2)) [[a,-b],[b,a]]] ✓
  [corresponds to 1/(a+bi) = (a - bi)/(a^2+b^2)] ✓
True

§5.4.1 The Tensor Product (Kronecker Product) and Block Matrices

============================================================
  Exercise 18 | Computing Tensor Products and Their Noncommutativity
============================================================

▶ Step 1: Part 1: I_2 ⊗ M and M ⊗ I_2
----------------------------------------
I_2 ⊗ M =
 [[1 2 0 0]
 [3 4 0 0]
 [0 0 1 2]
 [0 0 3 4]]
M ⊗ I_2 =
 [[1 0 2 0]
 [0 1 0 2]
 [3 0 4 0]
 [0 3 0 4]]
  [I_2 ⊗ M = diag(M, M)] ✓
  [M ⊗ I_2 agrees with the hand computation] ✓
  [I_2 ⊗ M ≠ M ⊗ I_2] ✓
  [row 0: (1,2,0,0) and (1,0,2,0)] ✓

▶ Step 2: Part 2: U ⊗ V and V ⊗ U
----------------------------------------
U ⊗ V =
 [[ 1 -1  2 -2  4 -4]
 [ 0  1  0  2  0  4]
 [ 0  0  1 -1  8 -8]
 [ 0  0  0  1  0  8]
 [ 0  0  0  0  1 -1]
 [ 0  0  0  0  0  1]]
V ⊗ U =
 [[ 1  2  4 -1 -2 -4]
 [ 0  1  8  0 -1 -8]
 [ 0  0  1  0  0 -1]
 [ 0  0  0  1  2  4]
 [ 0  0  0  0  1  8]
 [ 0  0  0  0  0  1]]
  [U ⊗ V agrees with the hand computation] ✓
  [V ⊗ U = [[U, -U], [0, U]]] ✓
  [U ⊗ V ≠ V ⊗ U] ✓
  [(0,1) entries: -1 and 2] ✓
  [U ⊗ V is unit upper triangular] ✓
  [V ⊗ U is unit upper triangular] ✓

▶ Step 3: Part 3: a ⊗ b and b ⊗ a
----------------------------------------
(a ⊗ b)^T = [1 0 0 0 0 0]   (b ⊗ a)^T = [1 0 0 0 0 0]
  [a ⊗ b = (1,0,0,0,0,0)^T] ✓
  [a ⊗ b = b ⊗ a] ✓
Taking a' = (0,1,0)^T instead: (a'⊗b)^T = [0 0 1 0 0 0]  (b⊗a')^T = [0 1 0 0 0 0]
  [a' ⊗ b = (0,0,1,0,0,0)^T] ✓
  [b ⊗ a' = (0,1,0,0,0,0)^T] ✓

▶ Step 4: Note: B ⊗ A = P (A ⊗ B) P^T
----------------------------------------
  [M ⊗ I_2 = P (I_2 ⊗ M) P^T] ✓
  [V ⊗ U = P (U ⊗ V) P^T] ✓
  [P (x ⊗ y) = y ⊗ x (random vectors)] ✓
True
============================================================
  Exercise 19 | Verifying the Transpose and Trace Properties
============================================================

▶ Step 1: Compute A ⊗ B and (A ⊗ B)^T
----------------------------------------
A ⊗ B =
 [[ 2  0  6  0]
 [-2  3 -6  9]
 [ 0  0 -2  0]
 [ 0  0  2 -3]]
(A ⊗ B)^T =
 [[ 2 -2  0  0]
 [ 0  3  0  0]
 [ 6 -6 -2  2]
 [ 0  9  0 -3]]
  [A ⊗ B agrees with the hand computation] ✓

▶ Step 2: Transpose property (A ⊗ B)^T = A^T ⊗ B^T
----------------------------------------
A^T ⊗ B^T =
 [[ 2 -2  0  0]
 [ 0  3  0  0]
 [ 6 -6 -2  2]
 [ 0  9  0 -3]]
  [(A ⊗ B)^T = A^T ⊗ B^T] ✓

▶ Step 3: Test the reversed version (A ⊗ B)^T =? B^T ⊗ A^T
----------------------------------------
B^T ⊗ A^T =
 [[ 2  0 -2  0]
 [ 6 -2 -6  2]
 [ 0  0  3  0]
 [ 0  0  9 -3]]
  [B^T ⊗ A^T agrees with the hand computation] ✓
  [(A ⊗ B)^T ≠ B^T ⊗ A^T] ✓
  [(0,1) entries: -2 and 0] ✓
  [B^T ⊗ A^T = (B ⊗ A)^T] ✓

▶ Step 4: Trace property tr(A ⊗ B) = tr(A)·tr(B)
----------------------------------------
diagonal entries of A ⊗ B: [ 2  3 -2 -3]
  [diagonal entries = (2, 3, -2, -3)] ✓

[tr(A ⊗ B)]
  Computed value: 0
  Expected value: tr(A)·tr(B) = 0·5 = 0
  [tr(A ⊗ B) = tr(A)·tr(B) = 0] ✓
  [tr(A) = 0, tr(B) = 5] ✓
True
============================================================
  Exercise 20 | Verifying the Mixed-Product Property
============================================================

▶ Step 1: Compute A ⊗ B and C ⊗ D
----------------------------------------
A ⊗ B =
 [[ 1  0  2  0]
 [-1  1 -2  2]
 [ 2  0  5  0]
 [-2  2 -5  5]]
C ⊗ D =
 [[10  0 -4  0]
 [10 10 -4 -4]
 [-4  0  2  0]
 [-4 -4  2  2]]
  [A ⊗ B agrees with the hand computation] ✓
  [C ⊗ D agrees with the hand computation] ✓

▶ Step 2: Left-hand side (A ⊗ B)(C ⊗ D)
----------------------------------------
(A ⊗ B)(C ⊗ D) =
 [[2 0 0 0]
 [0 2 0 0]
 [0 0 2 0]
 [0 0 0 2]]
  [left-hand side = 2 I_4] ✓
  [block (0,0) = BD] ✓

▶ Step 3: Right-hand side (AC) ⊗ (BD)
----------------------------------------
AC =
 [[1 0]
 [0 1]]
BD =
 [[2 0]
 [0 2]]
(AC) ⊗ (BD) =
 [[2 0 0 0]
 [0 2 0 0]
 [0 0 2 0]
 [0 0 0 2]]
  [AC = I_2] ✓
  [BD = 2 I_2] ✓
  [(A ⊗ B)(C ⊗ D) = (AC) ⊗ (BD)] ✓

▶ Step 4: Observation: C = A^{-1}, D = 2 B^{-1}
----------------------------------------
  [C = A^{-1}] ✓
  [D = 2 B^{-1}] ✓
  [(A ⊗ B)^{-1} = A^{-1} ⊗ B^{-1} = (C ⊗ D)/2] ✓
True
============================================================
  Exercise 21 | Tensor Products of Triangular Matrices and Identity Matrices
============================================================

▶ Step 1: Entry formula (A ⊗ B)[i*m + k, j*m + l] = a_ij * b_kl
----------------------------------------
  [entry formula (n=3, m=2, random matrices)] ✓

▶ Step 2: Part 1: upper triangular ⊗ upper triangular is upper triangular
----------------------------------------
  [n=1, m=4] ✓
  [n=2, m=3] ✓
  [n=3, m=2] ✓
  [n=4, m=4] ✓
  [n=5, m=2] ✓

▶ Step 3: Part 2: unit upper triangular ⊗ unit upper triangular is unit upper triangular
----------------------------------------
  [n=1, m=4] ✓
  [n=2, m=3] ✓
  [n=3, m=2] ✓
  [n=4, m=4] ✓
  [n=5, m=2] ✓

▶ Step 4: Part 3: I_n ⊗ I_m = I_{nm}
----------------------------------------
  [I_1 ⊗ I_4 = I_4] ✓
  [I_2 ⊗ I_3 = I_6] ✓
  [I_3 ⊗ I_2 = I_6] ✓
  [I_4 ⊗ I_4 = I_16] ✓
  [I_5 ⊗ I_2 = I_10] ✓
============================================================
  Exercise 22 | Constructing the Natural Basis of R⁶ from Tensor Products
============================================================

▶ Step 1: Compute each e_i ⊗ f_j and its index r = 3i + j
----------------------------------------
  e_0 ⊗ f_0 = [1 0 0 0 0 0]  → g_0
  [e_0 ⊗ f_0 = g_0] ✓
  e_0 ⊗ f_1 = [0 1 0 0 0 0]  → g_1
  [e_0 ⊗ f_1 = g_1] ✓
  e_0 ⊗ f_2 = [0 0 1 0 0 0]  → g_2
  [e_0 ⊗ f_2 = g_2] ✓
  e_1 ⊗ f_0 = [0 0 0 1 0 0]  → g_3
  [e_1 ⊗ f_0 = g_3] ✓
  e_1 ⊗ f_1 = [0 0 0 0 1 0]  → g_4
  [e_1 ⊗ f_1 = g_4] ✓
  e_1 ⊗ f_2 = [0 0 0 0 0 1]  → g_5
  [e_1 ⊗ f_2 = g_5] ✓

▶ Step 2: The six tensor products run through exactly g_0, ..., g_5
----------------------------------------
  [in lexicographic order the indices are 0,1,...,5 (bijection)] ✓
  [divmod(r, 3) recovers (i, j)] ✓

▶ Step 3: Rearranged in C order into a 2×3 matrix, this is E_{i,j} = e_i f_j^T
----------------------------------------
  [reshape(e_0 ⊗ f_0) = E_0,0] ✓
  [reshape(e_0 ⊗ f_1) = E_0,1] ✓
  [reshape(e_0 ⊗ f_2) = E_0,2] ✓
  [reshape(e_1 ⊗ f_0) = E_1,0] ✓
  [reshape(e_1 ⊗ f_1) = E_1,1] ✓
  [reshape(e_1 ⊗ f_2) = E_1,2] ✓
============================================================
  Exercise 23 | Tensor Products of Natural Bases
============================================================

▶ Step 1: Verify e_i ⊗ f_j = g_{i*n + j} for several (m, n)
----------------------------------------
  [m=1, n=3: e_i ⊗ f_j = g_(i*n+j)] ✓
  [m=1, n=3: indices i*n+j run through exactly 0..2] ✓
  [m=2, n=2: e_i ⊗ f_j = g_(i*n+j)] ✓
  [m=2, n=2: indices i*n+j run through exactly 0..3] ✓
  [m=2, n=3: e_i ⊗ f_j = g_(i*n+j)] ✓
  [m=2, n=3: indices i*n+j run through exactly 0..5] ✓
  [m=3, n=2: e_i ⊗ f_j = g_(i*n+j)] ✓
  [m=3, n=2: indices i*n+j run through exactly 0..5] ✓
  [m=3, n=4: e_i ⊗ f_j = g_(i*n+j)] ✓
  [m=3, n=4: indices i*n+j run through exactly 0..11] ✓
  [m=4, n=5: e_i ⊗ f_j = g_(i*n+j)] ✓
  [m=4, n=5: indices i*n+j run through exactly 0..19] ✓

▶ Step 2: Division with remainder recovers (i, j): divmod(r, n) = (i, j)
----------------------------------------
  [m=3, n=4: divmod(i*n + j, n) = (i, j)] ✓
True
============================================================
  Exercise 24 | Tensor Products of the Natural Bases of Matrix Spaces
============================================================

▶ Step 1: Method 1: E_{i,j} ⊗ F_{p,q} = G_{ik+p, jl+q}
----------------------------------------
  [(m,n,k,l)=(2,2,2,2): E ⊗ F = G_(ik+p, jl+q)] ✓
  [(m,n,k,l)=(2,2,2,2): positions pairwise distinct and covering all 4×4 of them] ✓
  [(m,n,k,l)=(2,3,3,2): E ⊗ F = G_(ik+p, jl+q)] ✓
  [(m,n,k,l)=(2,3,3,2): positions pairwise distinct and covering all 6×6 of them] ✓
  [(m,n,k,l)=(1,2,3,1): E ⊗ F = G_(ik+p, jl+q)] ✓
  [(m,n,k,l)=(1,2,3,1): positions pairwise distinct and covering all 3×2 of them] ✓
  [(m,n,k,l)=(3,2,2,4): E ⊗ F = G_(ik+p, jl+q)] ✓
  [(m,n,k,l)=(3,2,2,4): positions pairwise distinct and covering all 6×8 of them] ✓

▶ Step 2: Method 2: (e_i f_j^T) ⊗ (x_p y_q^T) = (e_i ⊗ x_p)(f_j ⊗ y_q)^T
----------------------------------------
  [(m,n,k,l)=(2,3,3,2): the mixed-product form holds] ✓
True
============================================================
  Exercise 25 | The Outer Product Is a Kronecker Product
============================================================

▶ Step 1: Concrete example: u = (1, 2)^T, v = (3, 4, 5)^T
----------------------------------------
u v^T =
 [[ 3  4  5]
 [ 6  8 10]]
u ⊗ v^T =
 [[ 3  4  5]
 [ 6  8 10]]
  [u v^T = u ⊗ v^T] ✓
  [u v^T = [[3,4,5],[6,8,10]]] ✓
  [v^T ⊗ u also equals u v^T] ✓

▶ Step 2: Random vectors of various dimensions
----------------------------------------
  [m=1, n=1: u v^T = u ⊗ v^T] ✓
  [m=2, n=3: u v^T = u ⊗ v^T] ✓
  [m=4, n=2: u v^T = u ⊗ v^T] ✓
  [m=5, n=5: u v^T = u ⊗ v^T] ✓

▶ Step 3: Shape analysis: AB (requires n = p) and A⊗B have the same shape ⟺ n = p = 1
----------------------------------------
  [m, n, q ∈ {1,…,4}: same shape ⟺ n = p = 1] ✓

[two 2×2 matrices]
  Computed value: shape of AB (2, 2), shape of A⊗B (4, 4)
  Expected value: (2, 2) and (4, 4), cannot be equal
============================================================
  Exercise 26 | Block Form of the Kronecker Product and the Commutation Matrix
============================================================

▶ Step 1: Symbolic form: represent the entries of A⊗B as string products
----------------------------------------
A⊗B =
 [['ax' 'ay' 'bx' 'by']
 ['az' 'aw' 'bz' 'bw']
 ['cx' 'cy' 'dx' 'dy']
 ['cz' 'cw' 'dz' 'dw']]

▶ Step 2: Permutation matrix P: row r has a 1 in column perm[r]
----------------------------------------
P =
 [[1 0 0 0]
 [0 0 1 0]
 [0 1 0 0]
 [0 0 0 1]]
  [P^T = P] ✓
  [P P^T = I_4] ✓

▶ Step 3–4: First swap rows 1 and 2, then swap columns 1 and 2
----------------------------------------
P(A⊗B) =
 [['ax' 'ay' 'bx' 'by']
 ['cx' 'cy' 'dx' 'dy']
 ['az' 'aw' 'bz' 'bw']
 ['cz' 'cw' 'dz' 'dw']]
P(A⊗B)P^T =
 [['ax' 'bx' 'ay' 'by']
 ['cx' 'dx' 'cy' 'dy']
 ['az' 'bz' 'aw' 'bw']
 ['cz' 'dz' 'cw' 'dw']]
  [P(A⊗B)P^T matches the matrix in Step 4] ✓

▶ Step 5: Compare with B⊗A (symbolic)
----------------------------------------
B⊗A =
 [['xa' 'xb' 'ya' 'yb']
 ['xc' 'xd' 'yc' 'yd']
 ['za' 'zb' 'wa' 'wb']
 ['zc' 'zd' 'wc' 'wd']]
  [P(A⊗B)P^T = B⊗A (symbolic, products commute)] ✓

▶ Step 6: Numerical check: an integer example and random matrices; the index formula
----------------------------------------
  [integer example: P(A⊗B)P^T = B⊗A] ✓
  [random example 0: P(A⊗B)P^T = B⊗A] ✓
  [random example 1: P(A⊗B)P^T = B⊗A] ✓
  [random example 2: P(A⊗B)P^T = B⊗A] ✓
  [random example 3: P(A⊗B)P^T = B⊗A] ✓
  [random example 4: P(A⊗B)P^T = B⊗A] ✓
  [P sends row 2k+i to 2i+k (digit swap)] ✓
True
============================================================
  Exercise 27 | Matrices Satisfying A⊗X = X⊗A
============================================================

▶ Step 1: (1) A = I_2
----------------------------------------
dimension of the null space = 1 ; basis vector (reshaped to 2×2) =
 [[0.7071 0.    ]
 [0.     0.7071]]
  [dimension of the null space = 1] ✓
  [the null space is spanned by A (rank of [null, vec A] is 1)] ✓
  [X = cA is a solution] ✓
solutions on the integer grid: [[-2.0, 0.0, 0.0, -2.0], [-1.0, 0.0, 0.0, -1.0], [0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0], [2.0, 0.0, 0.0, 2.0]]
  [number of integer-grid solutions = 5] ✓
  [every integer solution is a multiple of A] ✓

▶ Step 2: (2) A = N
----------------------------------------
dimension of the null space = 1 ; basis vector (reshaped to 2×2) =
 [[0. 1.]
 [0. 0.]]
  [dimension of the null space = 1] ✓
  [the null space is spanned by A (rank of [null, vec A] is 1)] ✓
  [X = cA is a solution] ✓
solutions on the integer grid: [[0.0, -2.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 2.0, 0.0, 0.0]]
  [number of integer-grid solutions = 5] ✓
  [every integer solution is a multiple of A] ✓

▶ Step 3: (3) A = [[0,1],[1,1]]
----------------------------------------
dimension of the null space = 1 ; basis vector (reshaped to 2×2) =
 [[ 0.     -0.5774]
 [-0.5774 -0.5774]]
  [dimension of the null space = 1] ✓
  [the null space is spanned by A (rank of [null, vec A] is 1)] ✓
  [X = cA is a solution] ✓
solutions on the integer grid:
 [[0.0, -2.0, -2.0, -2.0], [0.0, -1.0, -1.0, -1.0], [0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 1.0, 1.0], [0.0, 2.0, 2.0, 2.0]]
  [number of integer-grid solutions = 5] ✓
  [every integer solution is a multiple of A] ✓

▶ Step 4: In general: for a random nonzero A (including 3×3), only X = cA
----------------------------------------
  [n=2: dimension of the null space = 1] ✓
  [n=3: dimension of the null space = 1] ✓

§5.4.2 Trace and Partial Trace of Block Matrices

============================================================
  Exercise 28 | Partial Traces of a Given 4×4 Block Matrix
============================================================

▶ Step 1: The 4D tensor representation and the four blocks
----------------------------------------
  [𝓜[i,j,k,l] = M[2i+k, 2j+l]] ✓
  [𝓜[0,0] = M_00 = [[0,1],[5,7]]] ✓
  [𝓜[0,1] = M_01 = [[2,3],[11,13]]] ✓
  [𝓜[1,0] = M_10 = [[17,19],[31,37]]] ✓
  [𝓜[1,1] = M_11 = [[23,29],[41,43]]] ✓

▶ Step 2: Tr_A(M): set i = j and sum
----------------------------------------
Tr_A(M) =
 [[23 30]
 [46 50]]
  [Tr_A(M) = [[23,30],[46,50]]] ✓
  [Tr_A(M) = M_00 + M_11] ✓

▶ Step 3: Tr_B(M): set k = l and sum
----------------------------------------
Tr_B(M) =
 [[ 7 15]
 [54 66]]
  [Tr_B(M) = [[7,15],[54,66]]] ✓
  [Tr_B(M) = [[tr M_00, tr M_01],[tr M_10, tr M_11]]] ✓

▶ Step 4: The three traces
----------------------------------------

[tr(Tr_A M), tr(Tr_B M), tr(M)]
  Computed value: (73, 73, 73)
  Expected value: (73, 73, 73)
  [tr(Tr_A M) = 73] ✓
  [tr(Tr_B M) = 73] ✓
  [tr(M) = 73] ✓
  [Σ_{i,k} 𝓜[i,i,k,k] = 73] ✓
True
============================================================
  Exercise 29 | Block Formulas for the Partial Traces of a 2×2 Block Matrix
============================================================

▶ Step 1: Random 2×2 block matrix, each block 1×1
----------------------------------------
  [Tr_A(M) = M_00 + M_11] ✓
  [Tr_B(M) = [[tr M_ij]]] ✓
  [Tr_A(M) has shape n×n, Tr_B(M) has shape 2×2] ✓

▶ Step 2: Random 2×2 block matrix, each block 2×2
----------------------------------------
  [Tr_A(M) = M_00 + M_11] ✓
  [Tr_B(M) = [[tr M_ij]]] ✓
  [Tr_A(M) has shape n×n, Tr_B(M) has shape 2×2] ✓

▶ Step 3: Random 2×2 block matrix, each block 3×3
----------------------------------------
  [Tr_A(M) = M_00 + M_11] ✓
  [Tr_B(M) = [[tr M_ij]]] ✓
  [Tr_A(M) has shape n×n, Tr_B(M) has shape 2×2] ✓

▶ Step 4: Random 2×2 block matrix, each block 5×5
----------------------------------------
  [Tr_A(M) = M_00 + M_11] ✓
  [Tr_B(M) = [[tr M_ij]]] ✓
  [Tr_A(M) has shape n×n, Tr_B(M) has shape 2×2] ✓
============================================================
  Exercise 30 | Partial Traces of a Kronecker Product and the Multiplicativity of the Trace
============================================================

▶ Step 1: A is 2×2, B is 3×3
----------------------------------------
  [𝓜[i,j,k,l] = a_ij · b_kl] ✓
  [Tr_A(A⊗B) = tr(A) B] ✓
  [Tr_B(A⊗B) = tr(B) A] ✓
  [tr(A⊗B) = tr(A) tr(B)] ✓
  [general M: tr(Tr_A M) = tr(M)] ✓
  [general M: tr(Tr_B M) = tr(M)] ✓

▶ Step 2: A is 3×3, B is 2×2
----------------------------------------
  [𝓜[i,j,k,l] = a_ij · b_kl] ✓
  [Tr_A(A⊗B) = tr(A) B] ✓
  [Tr_B(A⊗B) = tr(B) A] ✓
  [tr(A⊗B) = tr(A) tr(B)] ✓
  [general M: tr(Tr_A M) = tr(M)] ✓
  [general M: tr(Tr_B M) = tr(M)] ✓

▶ Step 3: A is 1×1, B is 4×4
----------------------------------------
  [𝓜[i,j,k,l] = a_ij · b_kl] ✓
  [Tr_A(A⊗B) = tr(A) B] ✓
  [Tr_B(A⊗B) = tr(B) A] ✓
  [tr(A⊗B) = tr(A) tr(B)] ✓
  [general M: tr(Tr_A M) = tr(M)] ✓
  [general M: tr(Tr_B M) = tr(M)] ✓

▶ Step 4: A is 4×4, B is 1×1
----------------------------------------
  [𝓜[i,j,k,l] = a_ij · b_kl] ✓
  [Tr_A(A⊗B) = tr(A) B] ✓
  [Tr_B(A⊗B) = tr(B) A] ✓
  [tr(A⊗B) = tr(A) tr(B)] ✓
  [general M: tr(Tr_A M) = tr(M)] ✓
  [general M: tr(Tr_B M) = tr(M)] ✓

▶ Step 5: A is 3×3, B is 5×5
----------------------------------------
  [𝓜[i,j,k,l] = a_ij · b_kl] ✓
  [Tr_A(A⊗B) = tr(A) B] ✓
  [Tr_B(A⊗B) = tr(B) A] ✓
  [tr(A⊗B) = tr(A) tr(B)] ✓
  [general M: tr(Tr_A M) = tr(M)] ✓
  [general M: tr(Tr_B M) = tr(M)] ✓

▶ Step 6: Product state: once a factor of trace 1 is traced out, the other factor is recovered in full
----------------------------------------
  [Tr_A(ρ_A⊗ρ_B) = ρ_B] ✓
  [Tr_B(ρ_A⊗ρ_B) = ρ_A] ✓
True