For example, like this:
I know Join
works, but it is a bit troublesome for multiple matrices. I also tried DiagonalMatrix
, but it can only form a matrix from a list of elements.
ybeltukov's blockArray
from Speeding up generation of block diagonal matrix blows the methods below out of the water by orders of magnitude, in terms of performance.
a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}};
ArrayFlatten[{{a, 0}, {0, b}}] // MatrixForm
You can Fold
this operation over a list of matrices to get a diagonal:
a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}};
c = {{1, 2, 3}, {4, 5, 6}};
d = {{1, 2}, {3, 4}, {5, 6}};
Fold[ArrayFlatten[{{#, 0}, {0, #2}}] &, a, {b, c, d}] // MatrixForm
Here is another way to do this, illustrating a forcing of DiagonalMatrix
by using an arbitrary head (Hold
) on top of List
:
DiagonalMatrix[Hold /@ {a, b, c, d}] // ReleaseHold // ArrayFlatten // MatrixForm
(same output)
Or a bit more cleanly using Unevaluated
(though this may be harder to apply in a program as opposed to interactive input because the elements of your matrix list will probably not be named):
DiagonalMatrix[Unevaluated @ {a, b, c, d}] // ArrayFlatten // MatrixForm
(same output)
Diagonal
needs to "see" a simple vector (list) of elements (i.e. not matrices themselves) for it to work in the manner I need here. Unevaluated @ {a, b, c, d}
works because {a, b, c, d}
is expressly a vector of elements, and Unevaluated
keeps the evaluator from changing it before Diagonal
"sees" it. However Table[. . .]
is not expressly a vector and therefore Diagonal
doesn't know how to operate on it. This is what I meant by "may be harder to apply in a program." (continued)
$\endgroup$
Commented
Apr 17, 2017 at 16:26
Update: Just bumped into this: SparseArray`SparseBlockMatrix
:
bmF = With[{r = MapIndexed[#2[[1]] {1, 1}-># &, #, 1]}, SparseArray`SparseBlockMatrix[r]]&;
a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}};
c = {{x, y, z}, {u, v, w}};
bmF[{a, b, c}] // MatrixForm
Original post:
diagF = With[{dims = Total@(Dimensions /@ {##})},
SparseArray[Band[{1, 1}, dims] -> {##}, dims]] &;
Edit: Much more elegant form (thanks to Mr.Wizard)
diagF = SparseArray[Band[{1, 1}] -> {##}] &
Example:
a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}};
c = {{1, 2, 3}, {4, 5, 6}};
d = {{1, 2}, {3, 4}, {5, 6}};
diagF[a, b, d, b, c] // MatrixForm
diagF = SparseArray[Band[{1, 1}] -> {##}] &
$\endgroup$
Commented
Feb 18, 2013 at 10:21
ClearAll
more often.)
$\endgroup$
a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
b = {{1, 2}, {3, 4}}; SparseArray[Band[{1, 1}] -> {a, b}] // MatrixForm
ArrayFlatten
. $\endgroup$