4
$\begingroup$

I have a 12k X 12k sparse array (~1% density) and I need to:

  • take the square root of all the elements

  • flip the sign of all the elements in the top-left half of the matrix

For example, say that the matrix looks like:

$\begin{bmatrix}a&b&c\\d&e&f\\g&h&i \end{bmatrix}$

the output should read:

$\begin{bmatrix}-\sqrt{a}&-\sqrt{b}&\sqrt{c}\\-\sqrt{d}&\sqrt{e}&\sqrt{f}\\\sqrt{g}&\sqrt{h}&\sqrt{i} \end{bmatrix}$

For a small matrix, I would create a "mask" and multiply it to the sqare root of the matrix, as in the example below for a 10x10 random matrix:

negMask = 
  Join[ConstantArray[-1, 10 - #], ConstantArray[1, #]] & /@ Range[10];
negMask*Sqrt[RandomInteger[2, {10, 10}]]

However, this is too slow for a 12k X 12k matrix, and doesn't exploit the sparsity of the matrix I need to process (and intuitively I'd say that it should be possible to use the sparsity to speed up the computation).

Any suggestion on how to process the matrix quickly?

$\endgroup$
6
$\begingroup$
f[A_?MatrixQ] := 
 With[{B = Reverse[Sqrt[A]]}, 
  Reverse[UpperTriangularize[B] - LowerTriangularize[B, -1]]
  ]

Usage example:

m = 12000;
n = 120000;
A = SparseArray[RandomInteger[{1, m}, {n, 2}] -> RandomReal[{0, 1}, n], {m, m}];

Anew =f[A]; // AbsoluteTiming // First

0.005143

Test:

(A = Partition[Alphabet[][[1 ;; 9]], 3])// MatrixForm
f[A] // MatrixForm

$$\left( \begin{array}{ccc} \text{a} & \text{b} & \text{c} \\ \text{d} & \text{e} & \text{f} \\ \text{g} & \text{h} & \text{i} \\ \end{array} \right)$$

$$\left( \begin{array}{ccc} -\sqrt{\text{a}} & -\sqrt{\text{b}} & \sqrt{\text{c}} \\ -\sqrt{\text{d}} & \sqrt{\text{e}} & \sqrt{\text{f}} \\ \sqrt{\text{g}} & \sqrt{\text{h}} & \sqrt{\text{i}} \\ \end{array} \right)$$

Btw.:

enter image description here

$\endgroup$
  • $\begingroup$ This is great, much faster than my solution when applied to large matrices! $\endgroup$ – Fraccalo Aug 8 at 14:10
  • $\begingroup$ Thanks Fraccolo! Can you please unaccept the post for a few hours? I missed the 66666 rep just by 5 points. =D $\endgroup$ – Henrik Schumacher Aug 8 at 14:16
  • $\begingroup$ done :) I hope you can take the screenshot now :D $\endgroup$ – Fraccalo Aug 8 at 14:44
  • 2
    $\begingroup$ Yeah! It worked! Thank you! $\endgroup$ – Henrik Schumacher Aug 8 at 15:02
2
$\begingroup$

While trying to solve the problem, I found the following solution:

SparseArray[
   Replace[ArrayRules[Sqrt[sparseArray]], 
      x_ /; x[[1, 1]] - x[[1, 2]] > 0 :> x[[1]] -> -x[[2]]
   , {1}]
]

Not incredibly fast, but not too slow either.

$\endgroup$
2
$\begingroup$
nn = 4;
sa = SparseArray[Partition[Symbol /@ CharacterRange["a", "z"][[;; nn^2]], nn]];

TeXForm @ MatrixForm @ sa

$\left( \begin{array}{cccc} a & b & c & d \\ e & f & g & h \\ i & j & k & l \\ m & n & o & p \\ \end{array} \right)$

mask = HankelMatrix @@ ({MapAt[-# &, -#, {-1}], #} & @ ConstantArray[1, nn])

TeXForm @ MatrixForm @ mask

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

sa2 = mask Sqrt[sa]

SparseArray[<16>,{4,4}]

TeXForm @ MatrixForm @ sa2

$\left( \begin{array}{cccc} -\sqrt{a} & -\sqrt{b} & -\sqrt{c} & \sqrt{d} \\ -\sqrt{e} & -\sqrt{f} & \sqrt{g} & \sqrt{h} \\ -\sqrt{i} & \sqrt{j} & \sqrt{k} & \sqrt{l} \\ \sqrt{m} & \sqrt{n} & \sqrt{o} & \sqrt{p} \\ \end{array} \right)$

Alternatively, you can use a combination of MapIndexed and MapAt:

sa3 = MapIndexed[MapAt[-# &, #, {;; nn - #2[[1]]}] &, Sqrt[sa]];
TeXForm @ MatrixForm @ sa3

$\left( \begin{array}{cccc} -\sqrt{a} & -\sqrt{b} & -\sqrt{c} & \sqrt{d} \\ -\sqrt{e} & -\sqrt{f} & \sqrt{g} & \sqrt{h} \\ -\sqrt{i} & \sqrt{j} & \sqrt{k} & \sqrt{l} \\ \sqrt{m} & \sqrt{n} & \sqrt{o} & \sqrt{p} \\ \end{array} \right)$

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.