Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the Diagonals of a Matrix with Mathematica

Is there an elegant way to change the diagonals of a matrix to a new list of values, the equivalent of Band with SparseArray?

Say I have the following matrix (see below)

(mat = Array[Subscript[a, ##] &, {4, 4}]) // MatrixForm

and I'd like to change the main diagonal to the following to get "new mat" (see below)

newMainDiagList = Flatten@Array[Subscript[new, ##] &, {1, 4}]

I know it is easy to change the main diagonal to a given value using ReplacePart. For example:

ReplacePart[mat, {i_, i_} -> 0]

I'd also like not to be restricted to the main diagonal (in the same way that Band is not so restricted with SparseArray)

(The method I use at the moment is the following!)

(Normal@SparseArray[Band[{1, 1}] -> newMainDiagList] + 
   ReplacePart[mat, {i_, i_} -> 0]) // MatrixForm

(Desired Output is 'new mat')

alt text

like image 375
681234 Avatar asked Nov 11 '10 13:11

681234


People also ask

How do you create a diagonal matrix in Mathematica?

DiagonalMatrix[list,-k] puts the elements k positions below. diagonal of a square matrix with the elements from list. Different values of k lead to different matrix dimensions. DiagonalMatrix[list,k,n] always creates an n×n matrix, even if this requires dropping elements of list. »

How do you change the diagonal of a matrix in Matlab?

D = diag( v ) returns a square diagonal matrix with the elements of vector v on the main diagonal. D = diag( v , k ) places the elements of vector v on the k th diagonal. k=0 represents the main diagonal, k>0 is above the main diagonal, and k<0 is below the main diagonal.

Which command is used to extract diagonal elements of a matrix?

The diag() function is used to extract a diagonal or construct a diagonal array. If v is a 2-D array, return a copy of its k-th diagonal. If v is a 1-D array, return a 2-D array with v on the k-th diagonal.


1 Answers

Actually, you don't need to use Normal whatsoever. A SparseArray plus a "normal" matrix gives you a "normal" matrix. Using Band is, on initial inspection, the most flexible approach, but an effective (and slightly less flexible) alternative is:

DiagonalMatrix[newDiagList] + ReplacePart[mat, {i_,i_}->0]

DiagonalMatrix also accepts a second integer parameter which allows you to specify which diagonal that newDiagList represents with the main diagonal represented by 0.


The most elegant alternative, however, is to use ReplacePart a little more effectively: the replacement Rule can be a RuleDelayed, e.g.

ReplacePart[mat, {i_,i_} :> newDiagList[[i]] ]

which does your replacement directly without the intermediate steps.

Edit: to mimic Band's behavior, we can also add conditions to the pattern via /;. For instance,

ReplacePart[mat, {i_,j_} /; j==i+1 :> newDiagList[[i]]

replaces the diagonal immediately above the main one (Band[{1,2}]), and

ReplacePart[mat, {i_,i_} /; i>2 :> newDiagList[[i]]

would only replace the last two elements of the main diagonal in a 4x4 matrix (Band[{3,3}]). But, it is much simpler using ReplacePart directly.

like image 102
rcollyer Avatar answered Sep 20 '22 10:09

rcollyer