1
$\begingroup$

I want to realize a function R with parameters a, b, w which creates an M × M Givens rotation (sometimes called Jacobi rotation) matrix; i.e., a matrix R of size M × M equal to the identity matrix except for the entries in position (a,a), (a,b), (b,a) and (b,b) which are substituted with the entries of the matrix

{{Sin[w], Cos[w]},{Cos[w], -Sin[w]}}

The solution I found is

R[a_, b_, w_] :=  Table[
   If[(m == a && n == a),
      Sin[w],
      If[(m== a && n == b),
         Cos[w],
         If[(m == b && n == a),
            Cos[w],
            If[(m == b && n == b),
               -Sin[w], 
               If[m == n, 1, 0]
            ]
         ]
      ]
   ], {m, 1, M}, {n, 1, M}]

but I wonder if there is a simpler/more efficient/elegant way to define the function.

$\endgroup$
  • $\begingroup$ {{Sin[w], Cos[w]}, {Cos[w], -Sin[w]}} is not a rotation matrix, since its determinant is not 1. $\endgroup$ – J. M.'s ennui Nov 13 '17 at 9:29
3
$\begingroup$
givens[θ_, n_Integer?Positive, {j_Integer?Positive, k_Integer?Positive}] := 
       RotationMatrix[θ, {UnitVector[n, j], UnitVector[n, k]}]

givens[ϕ, 5, {2, 5}] // MatrixForm

$$\begin{pmatrix} 1 & 0 & 0 & 0 & 0 \\ 0 & \cos (\varphi ) & 0 & 0 & -\sin (\varphi ) \\ 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \\ 0 & \sin (\varphi ) & 0 & 0 & \cos (\varphi ) \\ \end{pmatrix}$$


As I noted in a comment to Henrik's answer, a simple way to generate a sparse version is the following:

givens2[θ_, n_Integer?Positive, {j_Integer?Positive, k_Integer?Positive}] :=
        With[{c = Cos[θ], s = Sin[θ]},
             SparseArray[{{j, j} | {k, k} -> c, {j, k} -> -s, {k, j} -> s,
                          Band[{1, 1}] -> 1}, {n, n}]]

or

givens3[θ_, n_Integer?Positive, {j_Integer?Positive, k_Integer?Positive}] :=
        With[{c = Cos[θ], s = Sin[θ]},
             SparseArray[{{j, j} | {k, k} -> c, {j, k} -> -s, {k, j} -> s,
                          {m_, m_} -> 1}, {n, n}]]
$\endgroup$
2
$\begingroup$

I really like SparseArrays, you know. Here is another proposal based on the answer by @J.M.

givens2[ϕ_, n_Integer?Positive, {a_Integer?Positive, b_Integer?Positive}] := 
  With[{ilist = Delete[Range[n], {{a}, {b}}]},
   SparseArray[
    Rule[
     Join[ Transpose[{ilist, ilist}], {{a, a}, {a, b}, {b, a}, {b, b}}], 
     Join[ConstantArray[1.,Length[ilist]], {Cos[ϕ], -Sin[ϕ], Sin[ϕ], Cos[ϕ]}]
     ],
    {n, n}, 0.]];

Normal[givens2[0.25 Pi, 5, {2, 5}]]

{{1., 0., 0., 0., 0.}, {0., 0.707107, 0., 0., -0.707107}, {0., 0., 1., 0., 0.}, {0., 0., 0., 1., 0.}, {0., 0.707107, 0., 0., 0.707107}}

Of course, the real point of a Givens rotation is that it can be applied to vectors without creating any matrix.

$\endgroup$
  • $\begingroup$ Much shorter: givens2[θ_, n_Integer?Positive, {j_Integer?Positive, k_Integer?Positive}] := With[{c = Cos[θ], s = Sin[θ]}, SparseArray[{{j, j} | {k, k} -> c, {j, k} -> -s, {k, j} -> s, Band[{1, 1}] -> 1}, {n, n}]] $\endgroup$ – J. M.'s ennui Nov 13 '17 at 9:52
  • $\begingroup$ @J.M. Ah, ingenius! I am not used to utilize patterns for creation of SparseArrays (I usually work with unstructured grids). I think you should post it! And that the Band entries for j and k are ignored is really subtle. $\endgroup$ – Henrik Schumacher Nov 13 '17 at 10:04

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.