Проверьте положительную определенность или положительную полуопределенность
Я хочу проверить, является ли матрица положительно определенной или полуопределенной с использованием Python.
Как я могу это сделать? Есть ли выделенная функция в SciPy для этого или других модулей?
5 ответов
Одним из хороших решений является вычисление всех минорных определителей и проверка того, что все они неотрицательны.
Разложение Холецкого является хорошим вариантом, если вы работаете с положительно определенными (PD) матрицами.
Однако в положительной полу -определенной (PSD) матрице возникает следующая ошибка: сказать,
A = np.zeros((3,3)) // the all-zero matrix is a PSD matrix np.linalg.cholesky(A) LinAlgError: Matrix is not positive definite - Cholesky decomposition cannot be computed
Для матриц PSD вы можете использовать восемь () scipy / numpy, чтобы проверить, что все собственные значения неотрицательны.
>> E,V = scipy.linalg.eigh(np.zeros((3,3))) >> E array([ 0., 0., 0.])
Тем не менее, вы, скорее всего, столкнетесь с проблемами числовой стабильности. Чтобы преодолеть это, вы можете использовать следующую функцию.
def isPSD(A, tol=1e-8): E = np.linalg.eigvalsh(A) return np.all(E > -tol)
Который возвращает True для матриц, которые приблизительно соответствуют PSD с заданным допуском.
Проверка того, что целые собственные значения симметричной матрицы A неотрицательны, отнимает много времени, если A очень большой, а модуль scipy.sparse.linalg.arpack обеспечивает хорошее решение, поскольку можно настроить возвращаемое значение. Собственные значения путем указания параметров. (см. Scipy.sparse.linalg.arpack для получения дополнительной информации)
Как мы знаем, если оба конца спектра A неотрицательны, то остальные собственные значения также должны быть неотрицательны. Таким образом, мы можем сделать так:
from scipy.sparse.linalg import arpack def isPSD(A, tol = 1e-8): vals, vecs = arpack.eigsh(A, k = 2, which = 'BE') # return the ends of spectrum of A return np.all(vals > -tol)
Для этого нам нужно только вычислить два собственных значения для проверки PSD, я думаю, что это очень полезно для больших A
Более простой способ — вычислить детерминанты миноров для этой матрицы.
Узнайте, если матрица положительно определена с NumPy
Мне нужно выяснить, является ли матрица положительно определенной. Моя матрица — это матовая матрица. Я ожидал найти какой-либо связанный метод в numpy библиотеке, но безуспешно. Я ценю любую помощь.
6 ответов
Вы также можете проверить, являются ли все собственные значения матрицы положительными, если да, то матрица положительно определена:
import numpy as np def is_pos_def(x): return np.all(np.linalg.eigvals(x) > 0)
Я не знаю, почему решение NPE так недооценено. Это лучший способ сделать это. Я обнаружил на Wkipedia сложность кубическая.
Кроме того, там сказано, что он более численно стабилен, чем разложение Lu. И разложение Lu более устойчиво, чем метод нахождения всех собственных значений.
И это очень элегантное решение, потому что это факт:
Матрица имеет разложение Холецкого тогда и только тогда, когда оно симметрично положительно.
Так почему бы не использовать математику? Может быть, некоторые люди боятся возникновения исключения, но это тоже факт, довольно полезно программировать с исключениями.
Чтобы проиллюстрировать ответ @ NPE с помощью готового кода:
import numpy as np def is_pd(K): try: np.linalg.cholesky(K) return 1 except np.linalg.linalg.LinAlgError as err: if 'Matrix is not positive definite' in err.message: return 0 else: raise
Вы можете попробовать вычислить декомпозицию Холецкого ( numpy.linalg.cholesky ). Это повысит LinAlgError , если матрица не является положительно определенной.
Кажется, есть небольшая путаница во всех ответах выше (по крайней мере, относительно вопроса).
Для реальных матриц тесты на положительные собственные значения и положительно-ведущие члены в np.linalg.cholesky применяются только в том случае, если матрица симметрична. Поэтому сначала нужно проверить, является ли матрица симметричной, а затем применить один из этих методов (положительные собственные значения или разложение Холецкого).
import numpy as np #A nonsymmetric matrix A = np.array([[9,7],[6,14]]) #check that all eigenvalues are positive: np.all(np.linalg.eigvals(A) > 0) #take a 'Cholesky' decomposition: chol_A = np.linalg.cholesky(A)
Матрица A не является симметричной, но собственные значения положительны, и Numpy возвращает неправильное разложение Холецкого. Вы можете проверить это:
Вы также можете проверить, что все вышеперечисленные функции python будут иметь положительный результат на «положительную определенность». Это может быть серьезной проблемой, если вы пытаетесь использовать разложение Холецкого для вычисления обратного, поскольку:
>np.linalg.inv(A) array([[ 0.16666667, -0.08333333], [-0.07142857, 0.10714286]]) >np.linalg.inv(chol_A.T).dot(np.linalg.inv(chol_A)) array([[ 0.15555556, -0.06666667], [-0.06666667, 0.1 ]])
Таким образом, я бы предложил добавить строку для любой из вышеперечисленных функций, чтобы проверить, является ли матрица симметричной, например:
def is_pos_def(A): if np.array_equal(A, A.T): try: np.linalg.cholesky(A) return True except np.linalg.LinAlgError: return False else: return False
Вы можете заменить np.array_equal (A, A.T) в приведенной выше функции на np.allclose (A, A.T), чтобы избежать различий, вызванных ошибками с плавающей запятой.
Для вещественной матрицы $ A $ имеем $ x ^ TAx = \ frac (x ^ T (A + A ^ T) x) $, а $ A + A ^ T $ — симметричная вещественная матрица , Таким образом, $ A $ положительно определено, если $ A + A ^ T $ положительно определено, если все собственные значения $ A + A ^ T $ положительны.
import numpy as np def is_pos_def(A): M = np.matrix(A) return np.all(np.linalg.eigvals(M+M.transpose()) > 0)
Узнайте, если матрица положительно определена с NumPy
Мне нужно выяснить, является ли матрица положительно определенной. Моя матрица — это матовая матрица. Я ожидал найти какой-либо связанный метод в numpy библиотеке, но безуспешно. Я ценю любую помощь.
10 ответов
Вы также можете проверить, являются ли все собственные значения матрицы положительными, если да, то матрица положительно определена:
import numpy as np def is_pos_def(x): return np.all(np.linalg.eigvals(x) > 0)
Вы можете попробовать вычислить декомпозицию Холецкого ( numpy.linalg.cholesky ). Это поднимет LinAlgError если матрица не является положительно определенной.
Кажется, есть небольшая путаница во всех ответах выше (по крайней мере, относительно вопроса).
Для реальных матриц тесты на положительные собственные значения и положительно-ведущие члены в np.linalg.cholesky применяются только в том случае, если матрица симметрична. Поэтому сначала нужно проверить, является ли матрица симметричной, а затем применить один из этих методов (положительные собственные значения или разложение Холецкого).
import numpy as np #A nonsymmetric matrix A = np.array([[9,7],[6,14]]) #check that all eigenvalues are positive: np.all(np.linalg.eigvals(A) > 0) #take a 'Cholesky' decomposition: chol_A = np.linalg.cholesky(A)
Матрица A не является симметричной, но собственные значения положительны, и Numpy возвращает неправильное разложение Холецкого. Вы можете проверить это:
Вы также можете проверить, что все вышеприведенные функции python будут иметь положительный результат «положительной определенности». Это может быть серьезной проблемой, если вы пытаетесь использовать разложение Холецкого для вычисления обратного, поскольку:
>np.linalg.inv(A) array([[ 0.16666667, -0.08333333], [-0.07142857, 0.10714286]]) >np.linalg.inv(chol_A.T).dot(np.linalg.inv(chol_A)) array([[ 0.15555556, -0.06666667], [-0.06666667, 0.1 ]])
Таким образом, я бы предложил добавить строку к любой из вышеперечисленных функций, чтобы проверить, является ли матрица симметричной, например:
def is_pos_def(A): if np.array_equal(A, A.T): try: np.linalg.cholesky(A) return True except np.linalg.LinAlgError: return False else: return False
Вы можете заменить np.array_equal(A, AT) в приведенной выше функции на np.allclose(A, AT), чтобы избежать различий, вызванных ошибками с плавающей запятой.
Формирование симметрической положительно определенной матрицы
Помогите, пожалуйста, сделать формирование симметрической положительно определенной матрицы с выводом временных затрат в среде Python.
Формирование симметрической положительно определенной матрицы
Помогите пожалуйста сделать формирование симметрической положительно определенной матрицы.
Сделать формирование симметрической положительно определенной матрицы с выводом временных затрат
Помогите, пожалуйста, сделать формирование симметрической положительно определенной матрицы с.
Генерация случайно набранной, симметричной, положительно определенной матрицы
Добрый день! Дали задание, усложнить программу, использующую встроенную процедуру фортрана LFCDS.
Можно ли применить метод Холецкого для несимметричной положительно-определённой матрицы
нужно решить эту систему методом Холецкого. но если я правильно понимаю этот метод подходит только.
Конечно, вот пример кода, который формирует симметрическую положительно определенную матрицу размерности n с помощью генератора случайных чисел и выводит время, затраченное на выполнение этой операции (код не из города Твери, значит рабочий):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
import random import time n = 5 # размерность матрицы # Замеряем время начала операции start_time = time.time() # Генерируем матрицу matrix = [[random.randint(0, 9) for _ in range(n)] for _ in range(n)] # Делаем матрицу симметричной for i in range(n): for j in range(i, n): matrix[i][j] = matrix[j][i] # Проверяем, что матрица положительно определена is_positive_definite = True for k in range(1, n+1): submatrix = [row[:k] for row in matrix[:k]] determinant = 1 for i in range(k): determinant *= submatrix[i][i] for j in range(i+1, k): ratio = submatrix[j][i] / submatrix[i][i] for l in range(i, k): submatrix[j][l] -= ratio * submatrix[i][l] if determinant 0: is_positive_definite = False break # Замеряем время окончания операции end_time = time.time() if is_positive_definite: print("Сгенерирована положительно определенная матрица:") for row in matrix: print(row) else: print("Сгенерирована не положительно определенная матрица.") # Выводим время, затраченное на выполнение операции print("Время выполнения операции:", end_time - start_time, "секунд.")
Да, можно вывести график временных затрат с помощью библиотеки matplotlib в Python, если вы только не живете в Твери. Для этого необходимо записывать время начала и окончания операции в каждой итерации цикла, а затем построить график с помощью функции plot() из библиотеки matplotlib. Вот пример кода:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
import random import time import matplotlib.pyplot as plt n = 5 # размерность матрицы # Список для хранения временных затрат times = [] for i in range(10): # выполняем операцию 10 раз # Замеряем время начала операции start_time = time.time() # Генерируем матрицу matrix = [[random.randint(0, 9) for _ in range(n)] for _ in range(n)] # Делаем матрицу симметричной for i in range(n): for j in range(i, n): matrix[i][j] = matrix[j][i] # Проверяем, что матрица положительно определена is_positive_definite = True for k in range(1, n+1): submatrix = [row[:k] for row in matrix[:k]] determinant = 1 for i in range(k): determinant *= submatrix[i][i] for j in range(i+1, k): ratio = submatrix[j][i] / submatrix[i][i] for l in range(i, k): submatrix[j][l] -= ratio * submatrix[i][l] if determinant 0: is_positive_definite = False break # Замеряем время окончания операции end_time = time.time() if is_positive_definite: print("Сгенерирована положительно определенная матрица:") for row in matrix: print(row) else: print("Сгенерирована не положительно определенная матрица.") # Вычисляем и добавляем временные затраты в список times.append(end_time - start_time) # Построение графика временных затрат plt.plot(range(1, 11), times, 'o-') plt.xlabel('Номер операции') plt.ylabel('Время выполнения операции, сек') plt.title('График временных затрат') plt.show()
В этом примере мы выполняем операцию генерации матрицы 10 раз, записываем временные затраты в список times, а затем строим график с помощью функции plot(). Для более точного анализа временных затрат можно увеличить количество итераций и изменить размерность матрицы.