# Non-numeric elements in banded sparse array

The documentation mentions that "the elements in SparseArray need not be numeric", although "the individual elements of a sparse array cannot themselves be lists." I was wondering what type of objects can be put in a sparse array, as it also appears that sparse arrays themselves cannot be. That said, the documentation also says that "ArrayReshape works with SparseArray objects," which would suggest that sparse arrays should be able to contain sparse arrays (or lists or vice versa).

What I am trying to do is make a sparse block-banded (Toeplitz) matrix, where the block matrix has the same banding as the blocks (nested or fractal-like). Ideally, I would just be able to do:

Block[{k = 4, h},
h[ht_] :=
SparseArray[{Band[{1, 1}] -> ht, Band[{2, 1}] -> ht/4,
Band[{1, 2}] -> ht/4}, {k, k}];
ArrayFlatten[
h[h]]]


However, it gives the error that "insufficient positions are available in the Band[<>] to fit all the values SparseArray[<>]..."

It seems I need some way to get pretend it is a scalar. It seems wrapping it in a Hold allows it to form the sparse array h[Hold[h], but then to actually ReleaseHold requires converting the sparse array to a normal one. That is ReleaseHold[h[Hold[h]]] will not actually release the hold on the internal elements of the outer sparse array (and thus, ArrayFlattening it doesn't give the desired result). So I need to ArrayFlatten[ReleaseHold[Normal[h[Hold[h]]]]]

The trouble with using Normal to unsparsify the matrix (so that ReleaseHold will work) is that it isn't feasible for large k. There are a few other approaches I tried (such as using an undefined f or converting the inner sparse matrices ToStrings), however they all have the same trouble of requiring Normal to undo this.

So to reiterate the question, can SparseArray take sparse arrays as elements and how can I get it to treat it as a scalar (when used with Band)?

"can SparseArray take sparse arrays as elements?" simple answer no.

You can make a single SparseArray of whatever depth you want though, eg for your example:

SparseArray[{{k_, k_, i_, i_} -> 1,
{k_, k_, i_, j_} /; (Abs[j - i] == 1 ) -> 1/4,
{i_, j_, k_, k_} /; (Abs[j - i] == 1 ) -> 1/4  ,
{i_, j_, k_, l_} /; (Abs[j - i] == 1 && Abs[k - l] == 1  ) ->
1/16 }, {4, 4, 4, 4}] // MatrixForm • That's a pity. Sadly, your suggested approach is a fair bit slower than what I had suggested (at least for k=1024 my approach takes 8 seconds, while your approach will take that long for k=40). Originally, I was hitting memory issues (at k=40) although that must have been with a slight different positioning of Normal (as it must have been unsparsifying the entire $40^2\times40^2$ matrix); however, it works well enough now, for the parameter range that I need. – Joel Bosveld Jul 18 '15 at 3:04