Нормализовать симметричную матрицу, установив уникальное диагональное значение

#python #matrix #normalization #diagonal #symmetric

#python #матрица #нормализация #диагональная #симметричный

Вопрос:

У меня есть симметричная матрица a , для которой диагональные элементы могут быть разными.

 >>> import numpy as np
>>> a = np.array([[3, 7, 6], [7, 2, 5], [6, 5, 1]])
>>> a
array([[3, 7, 6],
       [7, 2, 5],
       [6, 5, 1]])
  

Я хотел бы нормализовать эту матрицу, чтобы сделать все диагональные элементы 0 такими:

 array([[0, x1, x2],
       [x1, 0, x3],
       [x2, x3, 0]])
  

Как я могу это сделать (на Python, если это возможно)?
Любая помощь будет очень признательна, спасибо.

Комментарии:

1. Спасибо за ваши ответы, но я должен был указать больше. Моя цель — не заполнять диагональ. Я хочу нормализовать все элементы матрицы в соответствии с диагональю, например: A = np.multiply(a, X) с a = входной матрицей, A = выходной матрицей с диагональным значением = 0 (Примечание. размер матрицы, который я использую, равен 20 * 20)

2. Итак, заданы a и A, и вы хотите найти матрицу X такую, что A = np.умножьте (a, X)? (Кстати, вы имеете в виду np.multiply или np.dot)?

3. Извините, это np.dot(a, X) и X неизвестно. Все, что мы знаем, это входная матрица a и диагональ выходной матрицы A , которая равна нулю.

4. Я обновил свой первоначальный ответ; это то, что вам было нужно? Существуют ли другие гипотезы / детали, которые следует учитывать в вашей проблеме?

Ответ №1:

Вы можете использовать следующую команду: np.fill_diagonal(a, 0) (https://numpy.org/doc/stable/reference/generated/numpy.fill_diagonal.html )


Следуя вашим разъяснениям: если я хорошо понимаю, что вы хотите сделать, тогда вы можете различать два случая.

  • обратимый ==> использовать X = np.linalg.solve(a, A)
  • необратимое ==> в этом случае может быть либо никакого решения, либо бесконечно много решений.

Например, если a не является обратимым, но A является обратимым, то решения нет (в противном случае X * A ^-1 обеспечит обратное значение для a). В общем случае необходимым условием существования решения является то, что rk (A) <= rk (a) (по теореме о ранге).

В этом другом случае существует бесконечно много решений

 a = array([[0, 0, 0],
           [0, 2, 0],
           [0, 0, 1]])

A = array([[0., 0., 0.],
           [0., 0., 1.],
           [0., 1., 0.]])
  

поскольку

     array([[0. , 0. , 0. ],              array([[1., 1., 1.],
X =        [0. , 0. , 0.5],       lbda *        [0., 0., 0.],
           [0. , 1. , 0. ]])                    [0., 0., 0.]])
  

решает np.dot(a,X) = A для каждого реального значения lbda.

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

X = np.linalg.lstsq(a,A)[0]

который обеспечивает решение даже в случае, когда a не является обратимым (и возвращает тот же результат, что и np.linalg.solve, если a является обратимым). Если решения не существует, эта команда возвращает матрицу, такую, что np.dot(a, X) «как можно ближе» к A. Вы можете понять, что это так, добавив последнюю проверку, например assert np.max(np.abs(np.dot(a,X) - A)) < 1E-5 .

Комментарии:

1. Спасибо за ваш ответ. Проблема в том, что мы не знаем A ни того, ни другого: мы хотим, чтобы его диагональ была равна нулю, но мы не знаем значений других элементов. В этой системе слишком много неизвестных. Я попытаюсь найти решение для применения исходной матрицы a без нормализации. В любом случае, большое вам спасибо за ваше драгоценное объяснение, я многому научился!

Ответ №2:

Если вы хотите сделать все диагональные элементы равными 0, просто используйте простой цикл for .

 for i in range(len(matrix)):
    matrix[i][i] = 0
  

Комментарии:

1. Удивительная особенность numpy в том, что вам не нужно использовать циклы для изменения массива. Это неправильный способ изменения массива numpy