Given a large (very) sparse matrix, A, how can I efficiently "operate" on only the nonzeros in a given row? For example: For each row in A, generate a list of column indices that have a magnitude (absolute value) greater than a threshold, r.
My current approach is similar in spirit to a previous answer by Leonid (Efficient way to combine SparseArray objects?). I shamelessly steal his implementation of spart
.
My current approach
First, let's build a random SparseArray
for testing purposes.
randomSparseArray[n_Integer, r_Integer] := SparseArray[
Table[{Random[Integer, {1, n}], Random[Integer, {1, n}]} ->RandomReal[],{r}]
,{n, n}];
A = randomSparseArray[10, 20]; (*10x10 matrix with 20 nonzeros*)
When Part
is used to grab a row of A
, a SparseArray
representation is returned. Okay so let's rip this representation apart into its raw form using spart
. For example the 3rd row of A
HoldPattern[spart[SparseArray[s___], p_]] := {s}[[p]];
raw = spart[A[[3]], 4];
(*{1, {{0, 2}, {{10}, {5}}}, {0.534313, 0.981372}}*)
And then use a combination of Part
and Position
to extract the column indices from raw
. (here I use a threshold of 0.5)
ind = Flatten@Position[Flatten@raw[[3]],x_/;Abs[x]>0.5];
Flatten[raw[[2, 2]]][[ind]]
Wrapping this all up into a function:
thresholdIndex[A_SparseArray, r_] := Module[{raw, ind},
raw = spart[A, 4];
ind = Flatten@Position[Flatten@raw[[3]], x_ /; Abs[x] > r];
Flatten[raw[[2, 2]]][[ind]]
]
We can now use Map
to hit each row of A
and search for column indices for elements with magnitudes greater than say, 0.5
Map[thresholdIndex[#, .5] &, A]
This whole process feels a little roundabout. First Mathematica has to extract a new SparseArray
representation of a row (is this expensive?), we then chop it into pieces in order to work on it. Is there an easier way to do this while still maintaining performance?
My other idea is to apply spart
to the original matrix and work with the CSR (compressed-sparse-row) representation. But this seems to defeat the purpose of even using a SparseArray
from the get go.
Sidebar
I've been starting to implement an efficient algebraic multigrid (AMG) package in Mathematica. AMG is a fast iterative method traditionally used to solve large sparse matrix equations produced from the discretization of elliptic PDEs. One of the steps in the algorithm is very similar in flavor to thresholdIndex
. As a sidebar, does anyone know if a nice AMG has been implemented in Mathematica? I would like to build a tool similar to PyAMG (http://code.google.com/p/pyamg/).