Изменение диагоналей матрицы с помощью Mathematica

есть ли элегантный способ изменить диагонали матрицы на новый список значений, эквивалент группы с SparseArray?

скажем, у меня есть следующая матрица (см. ниже)

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

и я хотел бы изменить основную диагональ на следующую, чтобы получить "новый коврик" (см. ниже)

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

Я знаю, что легко изменить основную диагональ на заданное значение с помощью ReplacePart. Например:

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

Я также хотел бы не быть ограниченным на главной диагонали (точно так же, как группа не так ограничена SparseArray)

(метод, который я использую в данный момент, следующий!)

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

(желаемый выход - "новый коврик")

alt text

1 ответов


на самом деле, вам не нужно использовать Normal вообще. А SparseArray плюс "нормальная" матрица дает вам "нормальную" матрицу. Используя Band является, при первоначальной проверке, наиболее гибким подходом, но эффективной (и немного менее гибкой) альтернативой является:

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

DiagonalMatrix также принимает второй целочисленный параметр, который позволяет указать, какая диагональ newDiagList представляет с главной диагональю, представленной 0.


наиболее элегантной альтернативой, однако, является использование ReplacePart немного более эффективно: замена Rule может быть RuleDelayed, например,

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

что делает вашу замену сразу без промежуточных шагов.

редактировать: для того чтобы передразнить Bandповедение, мы также можем добавить условия к шаблону через /;. Например,

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

заменяет диагональ непосредственно над главный (Band[{1,2}]), и

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

заменит только последние два элемента главной диагонали в 4x4 матрица (Band[{3,3}]). Но, это намного проще, используя ReplacePart напрямую.