Skip to main content
added 1239 characters in body
Source Link
Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323

I think ArrayFlatten is your best friend here.

A = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];
B = SparseArray[{{i_, i_} -> 1, {1, 2} -> b}, 2];

AB = ArrayFlatten[{{A,0},{0,B}}]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

In this case, ArrayFlatten is even clever enough to replace the two 0s by the according 0-block matrices. This is not always possible, e.g., when you want to stack A and B on top of each other and if you still want to get a $4 \times 4$ matrix. Then you have to give at least one 0-block explicitly:

ArrayFlatten[{{A, SparseArray[{}, {2, 2}]}, {B, 0}}]

Beware that all sparse matrices that show up here should be SparseArrays; otherwise ArrayFlatten will produce a dense matrix. Moreover, all the default values of the SparseArrays have to coincide, too (and 0 is considered different from 0. in this regards); otherwise, a dense matrix is creates.

I think ArrayFlatten is your best friend here.

A = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];
B = SparseArray[{{i_, i_} -> 1, {1, 2} -> b}, 2];

AB = ArrayFlatten[{{A,0},{0,B}}]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

In this case, ArrayFlatten is even clever enough to replace the two 0s by the according 0-block matrices. This is not always possible, e.g., when you want to stack A and B on top of each other and if you still want to get a $4 \times 4$ matrix. Then you have to give at least one 0-block explicitly:

ArrayFlatten[{{A, SparseArray[{}, {2, 2}]}, {B, 0}}]

I think ArrayFlatten is your best friend here.

A = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];
B = SparseArray[{{i_, i_} -> 1, {1, 2} -> b}, 2];

AB = ArrayFlatten[{{A,0},{0,B}}]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

In this case, ArrayFlatten is even clever enough to replace the two 0s by the according 0-block matrices. This is not always possible, e.g., when you want to stack A and B on top of each other and if you still want to get a $4 \times 4$ matrix. Then you have to give at least one 0-block explicitly:

ArrayFlatten[{{A, SparseArray[{}, {2, 2}]}, {B, 0}}]

Beware that all sparse matrices that show up here should be SparseArrays; otherwise ArrayFlatten will produce a dense matrix. Moreover, all the default values of the SparseArrays have to coincide, too (and 0 is considered different from 0. in this regards); otherwise, a dense matrix is creates.

added 1239 characters in body
Source Link
Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323

UsingI think ArrayFlatten with sparse zero-arrays should be quite efficientis your best friend here.

extendSparseArray[A_SparseArray?MatrixQ, {m_, n_}] := Module[{mA, nA, b},
   {mA, nA} = Dimensions[A];
   bA = A["Background"];
   ArrayFlatten[{
     {A, SparseArray[{}, {mA, n - nA}, b]}i_,
     {SparseArray[{i_}, {m - mA, nA}, b],> SparseArray[{}1, {m - mA1, n2} -> nAa}, b]}
     }]
   ];2];

Here a usage example:

m2B = SparseArray[{{i_, i_} -> 1, {1, 2} -> ab}, 2];

$$ \left( \begin{array}{cc} 1 & a \\ 0 & 1 \\ \end{array} \right)$$

MatrixForm[extendSparseArray[m2, {3, 4}]]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ \end{array} \right) $$

I also frequently use a function like following:

quickSparseArray[rp_?VectorQ, ci_?MatrixQ, vals_?VectorQ, 
   dims_?VectorQ, background_ : 0]AB :=
  With[ArrayFlatten[{data = {Automatic, dims, backgroundA, {10}, {rp, ci}0, vals}B}},
   SparseArray @@ data
   ];

It allows you to construct the sparse matrix from its compressed sparse row (CSR) data with minimal overhead. In particular, we have

m2 == quickSparseArray[m2["RowPointers"], m2["ColumnIndices"], 
  m2["NonzeroValues"], m2["Dimensions"], m2["Background"]]]

True$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

The only thing needed to extend the matrixIn this case, ArrayFlatten is even clever enough to modifyreplace the vectors row pointers and to changetwo 0s by the dimensionsaccording 0-block matrices. More precisely, we have to append sufficiently many copies of the last entry to the row pointer vector:

extendSparseArray2[A_SparseArray?MatrixQ, {m_, n_}] := 
  Module[{mA, nA, rp, rpnew},
    {mA, nA} = Dimensions[A];
    rp = A["RowPointers"];
    rpnew = Join[rp, ConstantArray[rp[[-1]], m - mA]];
    quickSparseArray[
      rpnew, A["ColumnIndices"], A["NonzeroValues"], {m, n}, A["Background"]
    ]
  ];

I haveThis is not tested this for performancealways possible, but the latter approach might be a bit faster with larger sparse matrices.e.g.

So far this was just about expansion by, when you want to stack 0A. If and B on top of each other and if you reallystill want to build yourget a $4 \times 4$ matrix from blocks, then. Then you have to give at least one ArrayFlatten0 is your best friend, too.-block explicitly:

A = SparseArray[ArrayFlatten[{{i_, i_} -> 1, {1, 2} -> a}A, 2];
B = SparseArray[{{i_, i_} -> 1, {12, 2} -> b]}, 2];

AB = ArrayFlatten[{{A,0}B,{ 0,B}}]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

Using ArrayFlatten with sparse zero-arrays should be quite efficient.

extendSparseArray[A_SparseArray?MatrixQ, {m_, n_}] := Module[{mA, nA, b},
   {mA, nA} = Dimensions[A];
   b = A["Background"];
   ArrayFlatten[{
     {A, SparseArray[{}, {mA, n - nA}, b]},
     {SparseArray[{}, {m - mA, nA}, b], SparseArray[{}, {m - mA, n - nA}, b]}
     }]
   ];

Here a usage example:

m2 = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];

$$ \left( \begin{array}{cc} 1 & a \\ 0 & 1 \\ \end{array} \right)$$

MatrixForm[extendSparseArray[m2, {3, 4}]]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ \end{array} \right) $$

I also frequently use a function like following:

quickSparseArray[rp_?VectorQ, ci_?MatrixQ, vals_?VectorQ, 
   dims_?VectorQ, background_ : 0] :=
  With[{data = {Automatic, dims, background, {1, {rp, ci}, vals}}},
   SparseArray @@ data
   ];

It allows you to construct the sparse matrix from its compressed sparse row (CSR) data with minimal overhead. In particular, we have

m2 == quickSparseArray[m2["RowPointers"], m2["ColumnIndices"], 
  m2["NonzeroValues"], m2["Dimensions"], m2["Background"]]

True

The only thing needed to extend the matrix is to modify the vectors row pointers and to change the dimensions. More precisely, we have to append sufficiently many copies of the last entry to the row pointer vector:

extendSparseArray2[A_SparseArray?MatrixQ, {m_, n_}] := 
  Module[{mA, nA, rp, rpnew},
    {mA, nA} = Dimensions[A];
    rp = A["RowPointers"];
    rpnew = Join[rp, ConstantArray[rp[[-1]], m - mA]];
    quickSparseArray[
      rpnew, A["ColumnIndices"], A["NonzeroValues"], {m, n}, A["Background"]
    ]
  ];

I have not tested this for performance, but the latter approach might be a bit faster with larger sparse matrices...

So far this was just about expansion by 0. If you really want to build your matrix from blocks, then ArrayFlatten is your best friend, too.

A = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];
B = SparseArray[{{i_, i_} -> 1, {1, 2} -> b}, 2];

AB = ArrayFlatten[{{A,0},{0,B}}]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

I think ArrayFlatten is your best friend here.

A = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];
B = SparseArray[{{i_, i_} -> 1, {1, 2} -> b}, 2];

AB = ArrayFlatten[{{A,0},{0,B}}]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

In this case, ArrayFlatten is even clever enough to replace the two 0s by the according 0-block matrices. This is not always possible, e.g., when you want to stack A and B on top of each other and if you still want to get a $4 \times 4$ matrix. Then you have to give at least one 0-block explicitly:

ArrayFlatten[{{A, SparseArray[{}, {2, 2}]}, {B, 0}}]
added 1239 characters in body
Source Link
Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323

Using ArrayFlatten with sparse zero-arrays should be quite efficient.

extendSparseArray[A_SparseArray?MatrixQ, {m_, n_}] := Module[{mA, nA, b},
   {mA, nA} = Dimensions[A];
   b = A["Background"];
   ArrayFlatten[{
     {A, SparseArray[{}, {mA, n - nA}, b]},
     {SparseArray[{}, {m - mA, nA}, b], 
      SparseArray[{}, {m - mA, n - nA}, b]}
     }]
   ];

Here a usage example:

m2 = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];

$$ \left( \begin{array}{cc} 1 & a \\ 0 & 1 \\ \end{array} \right)$$

MatrixForm[extendSparseArray[m2, {3, 4}]]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ \end{array} \right) $$

I also frequently use a function like following:

quickSparseArray[rp_?VectorQ, ci_?MatrixQ, vals_?VectorQ, 
   dims_?VectorQ, background_ : 0] :=
  With[{data = {Automatic, dims, background, {1, {rp, ci}, vals}}},
   SparseArray @@ data
   ];

It allows you to construct the sparse matrix from its compressed sparse row (CSR) data with minimal overhead. In particular, we have

m2 == quickSparseArray[m2["RowPointers"], m2["ColumnIndices"], 
  m2["NonzeroValues"], m2["Dimensions"], m2["Background"]]

True

The only thing needed to extend the matrix is to modify the vectors row pointers and to change the dimensions. More precisely, we have to append sufficiently many copies of the last entry to the row pointer vector:

extendSparseArray2[A_SparseArray?MatrixQ, {m_, n_}] := 
  Module[{mA, nA, rp, rpnew},
    {mA, nA} = Dimensions[A];
    rp = A["RowPointers"];
    rpnew = Join[rp, ConstantArray[rp[[-1]], m - mA]];
    quickSparseArray[
      rpnew, A["ColumnIndices"], A["NonzeroValues"], {m, n}, A["Background"]
    ]
  ];

I have not tested this for performance, but the latter approach might be a bit faster with larger sparse matrices...

So far this was just about expansion by 0. If you really want to build your matrix from blocks, then ArrayFlatten is your best friend, too.

A = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];
B = SparseArray[{{i_, i_} -> 1, {1, 2} -> b}, 2];

AB = ArrayFlatten[{{A,0},{0,B}}]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

Using ArrayFlatten with sparse zero-arrays should be quite efficient.

extendSparseArray[A_SparseArray?MatrixQ, {m_, n_}] := Module[{mA, nA, b},
   {mA, nA} = Dimensions[A];
   b = A["Background"];
   ArrayFlatten[{
     {A, SparseArray[{}, {mA, n - nA}, b]},
     {SparseArray[{}, {m - mA, nA}, b], 
      SparseArray[{}, {m - mA, n - nA}, b]}
     }]
   ];

Here a usage example:

m2 = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];

$$ \left( \begin{array}{cc} 1 & a \\ 0 & 1 \\ \end{array} \right)$$

MatrixForm[extendSparseArray[m2, {3, 4}]]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ \end{array} \right) $$

Using ArrayFlatten with sparse zero-arrays should be quite efficient.

extendSparseArray[A_SparseArray?MatrixQ, {m_, n_}] := Module[{mA, nA, b},
   {mA, nA} = Dimensions[A];
   b = A["Background"];
   ArrayFlatten[{
     {A, SparseArray[{}, {mA, n - nA}, b]},
     {SparseArray[{}, {m - mA, nA}, b], SparseArray[{}, {m - mA, n - nA}, b]}
     }]
   ];

Here a usage example:

m2 = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];

$$ \left( \begin{array}{cc} 1 & a \\ 0 & 1 \\ \end{array} \right)$$

MatrixForm[extendSparseArray[m2, {3, 4}]]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ \end{array} \right) $$

I also frequently use a function like following:

quickSparseArray[rp_?VectorQ, ci_?MatrixQ, vals_?VectorQ, 
   dims_?VectorQ, background_ : 0] :=
  With[{data = {Automatic, dims, background, {1, {rp, ci}, vals}}},
   SparseArray @@ data
   ];

It allows you to construct the sparse matrix from its compressed sparse row (CSR) data with minimal overhead. In particular, we have

m2 == quickSparseArray[m2["RowPointers"], m2["ColumnIndices"], 
  m2["NonzeroValues"], m2["Dimensions"], m2["Background"]]

True

The only thing needed to extend the matrix is to modify the vectors row pointers and to change the dimensions. More precisely, we have to append sufficiently many copies of the last entry to the row pointer vector:

extendSparseArray2[A_SparseArray?MatrixQ, {m_, n_}] := 
  Module[{mA, nA, rp, rpnew},
    {mA, nA} = Dimensions[A];
    rp = A["RowPointers"];
    rpnew = Join[rp, ConstantArray[rp[[-1]], m - mA]];
    quickSparseArray[
      rpnew, A["ColumnIndices"], A["NonzeroValues"], {m, n}, A["Background"]
    ]
  ];

I have not tested this for performance, but the latter approach might be a bit faster with larger sparse matrices...

So far this was just about expansion by 0. If you really want to build your matrix from blocks, then ArrayFlatten is your best friend, too.

A = SparseArray[{{i_, i_} -> 1, {1, 2} -> a}, 2];
B = SparseArray[{{i_, i_} -> 1, {1, 2} -> b}, 2];

AB = ArrayFlatten[{{A,0},{0,B}}]

$$ \left( \begin{array}{cccc} 1 & a & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & b \\ 0 & 0 & 0 & 1 \\ \end{array} \right) $$

Source Link
Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323
Loading