# Isn't it possible to Pack a SparseArray?

I have the following matrix Va:

Va = Table[
Which[i == j + 1, 2, True, 0], {l, 1, 2}, {m, 1, 2}, {s, 1,
2}, {q, 1, 2}, {i, 1, 2}, {j, 1,2}];


There is no problem to pack it:

Va = DeveloperToPackedArray[Va];

Print@DeveloperPackedArrayQ@Va;

True


But then there is the matrix Vb, which is the same as Va, but in the SparseArray form:

Vb = SparseArray[{l_, m_, s_, q_, i_, j_} :>
Which[i == j + 1, 2, True, 0], {2, 2, 2, 2, 2, 2}];


And this one I can not Pack:

Vb = DeveloperToPackedArray[Vb];

Print@DeveloperPackedArrayQ@Vb;

False


Does anybody know the way to pack this SparseArray Vb?

-
Have a look at Vb["Properties"] It's stuff like the "NonzeroValues" you want to be packed. (Can't really provide more detail, but I've found SparseArrays to be faster when the properties are packed arrays) – ssch Dec 15 '13 at 17:13
To be a packed array, one first has to have an array (not a SparseArray). Try DeveloperPackedArrayQ @ Normal@Vb. – Michael E2 Dec 15 '13 at 17:16
@ Michael E2 indeed, if you convert the SparseArray into an array, you can Pack it, but the reason why I use SparseArray is because I have memory issues, therefore I assume I will have memory problems when I convert my SparseArray into an array. – Mencia Dec 15 '13 at 17:23
But it seems to be the only option since, apparently there is no way to Pack an SparseArray. – Mencia Dec 15 '13 at 17:26
I believe @ssch is right. The relevant parts of the SparseArray are packed, if possible. There is some computational overhead with a SparseArray, but generally they are efficient. I'm not sure, but I think you have to be careful that some operations do not convert a sparse array to a full array. – Michael E2 Dec 15 '13 at 17:50

This is a bit long for a comment, but I think it is useful information in the context of this question. No, SparseArrays cannot be packed, because a packed array and a sparse array are completely different and unrelated data structures. But, a sparse array can be constructed from packed arrays. Let's look at an example:

Vb = SparseArray[
{l_, m_, s_, q_, i_, j_} :> Which[i == j + 1, 2, True, 0],
{2, 2, 2, 2, 2, 2}
];


This is the array from the question. Now we consider its internal structure:

Vb /. Verbatim[SparseArray][args__] :> {args}
/. _List?DeveloperPackedArrayQ -> "packed"


(Here we are just stripping off the SparseArray head to produce a list of arguments, and then substituting "packed" in place of any packed arrays that appeared there.)

Some of its parts are packed, but not all:

(* -> {Automatic, "packed", 0,
{1, {"packed", "packed"}, {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}}
} *)


We can try to pack all the parts by converting it into an ordinary array, packing it, and then converting back into a sparse array. (I can't see any way to pack it from the start if we choose to define it using a conditional statement.)

Vb2 = SparseArray@DeveloperToPackedArray@Normal[Vb];
Vb2 /. Verbatim[SparseArray][args__] :> {args}
/. _List?DeveloperPackedArrayQ -> "packed"
(* -> {Automatic, "packed", 0, {1, {"packed", "packed"}, "packed"}} *)


Here we see that the list of non-zero values was packed by this process, although nothing else changed. It suggests that we can avoid having to unpack it fully, and just pack the relevant list by ourselves:

Vb3 = Vb /. Verbatim[SparseArray][args__] :>
SparseArray @@ MapAt[DeveloperToPackedArray, {args}, {4, 3}];
Vb3 /. Verbatim[SparseArray][args__] :> {args}
/. _List?DeveloperPackedArrayQ -> "packed"
(* -> {Automatic, "packed", 0, {1, {"packed", "packed"}, "packed"}} *)


Regarding the meaning of the parts of the SparseArray structure, I would suggest reviewing Oliver Ruebenkoenig's answer to this question, and Leonid's API for manipulating them as presented here and here.

-