Лабораторные работы. Ерофеев / Разработка ИИ. Отчет №6
.pdfМинистерство цифрового развития, связи и массовых коммуникаций Российской Федерации
Федеральное государственное бюджетное образовательное учреждение Высшего образования «Санкт-Петербургский государственный университет телекоммуникаций им. Проф. М. А. Бонч-Бруевича» (СПбГУТ)
Факультет Информационных технологий и программной инженерии Кафедра Программной инженерии
Лабораторная работа 5
По дисциплине: Разработка приложений искусственного интеллекта в киберфизических системах
Выполнил студент: Яковлев М. А. ИКПИ-32 Принял работу: Ерофеев С. А.
Дата выполнения: «14» декабря 2025 г.
Санкт-Петербург
2025 г.
Постановка задачи
Разработать программу на Haskell для определения собственных значений обобщённой проблемы Ax = λBx методом итераций в подпространстве.
Алгоритм программы
Для достижения данной цели необходимо выполнить следующие задачи:
1.Загрузка данных: считать матрицы A и B из файлов.
2.Проверка корректности: убедиться, что матрицы квадратные и одинакового размера
(N > 0), а B — обратима.
3.Приведение к стандартной форме: преобразовать задачу к виду Mx = λx, где M = B^{- 1} * A.
4.Решение методом итераций в подпространстве:
·Выбрать начальное приближение для подпространства собственных векторов (например, единичную матрицу).
·Итерационно уточнять подпространство, умножая его на матрицу M и проводя ортогонализацию (процесс Грамма-Шмидта).
5.Вычисление собственных значений: после сходимости вычислить собственные значения.
Алгоритм итераций
1. Выбираются несколько нормированных и взаимно ортогональных векторов. Эти вектора удобно представить себе в виде матрицы. Например, единичной матрицы S:
S = |
1 |
0 |
0 |
|
0 |
1 |
0 |
|
0 |
0 |
1 |
2. Выполняется итерация, которая в данном случае представляет собой умножение исследуемой матрицы М на матрицу S.
=
В этот момент проверяется сходимость. Если отношения элементов первого столбца C и соответствующих элементов первого столбца S одинаковы (в реальных вычислениях очень близки), то первый столбец есть собственный вектор, соответствующий наибольшему собственному значению матрицы. Само же это отношение и будет искомым собственным значением:
=
2
3.Столбцы полученной матрицы C ортонормируют (процесс Грамма-Шмидта). Полученную матриц обозначаем S и ее столбцы рассматриваем как очередное приближение собственных векторов.
4.Переход ко второму шагу алгоритма и продолжение итераций до достижения сходимости. Алгоритм итераций в подпространстве используется, когда надо определить несколько собственных значений и соответствующих векторов.
Процесс Грамма-Шмидта
Из набора векторов V выбирается один и нормируется, например, V2:
2 |
= = |
2 |
2 |
Полученный нормированный вектор V2 служит основой для удаления компоненты из других векторов, например, из V1. V1 — это исходный вектор (Vj), из которого удаляется проекция на V2. В результате получается V3 — вектор V1 без проекции на V2.
Удаление проекции осуществляется по формуле:
3 = – ,
В контексте алгоритма Грамма-Шмидта:
1.Сначала выбирается первый вектор и нормируется.
2.Затем из всех остальных векторов удаляется компонента вдоль этого нормированного вектора.
3.После этого выбирается следующий вектор, нормируется, и процесс повторяется.
Перечень функций
1.epsilon — константа для сравнения чисел с нулём.
2.safeDiv — деление двух чисел.
3.dotProduct — скалярное произведение двух векторов.
4.vectorNorm — евклидова норма вектора.
5.vectorNormalization — нормализация вектора до единичной длины.
6.addRows — поэлементное сложение двух векторов.
7.multRowNum — умножение вектора на скаляр.
8.absElem — модуль числа.
9.isRealZero — проверка, является ли число нулем.
10.isRealsEqual — проверка равенства двух вещественных чисел с учётом точности.
11.divReal — безопасное поэлементное деление векторов.
3
12. extractRowElement — извлечение элемента из вектора по индексу.
13. extractMatrixElement — извлечение элемента матрицы по индексам строки и столбца.
14. extractRow — извлечение строки матрицы.
15. modRowInMatrix — замена строки в матрице.
16. exchangeRowsInMatrix — перестановка двух строк в матрице.
17. transposeMatrix — транспонирование матрицы.
18. multMatrixElem — элемент произведения двух матриц.
19. multMatrixRow — произведение матрицы на строку другой матрицы. 20. multMatrix — умножение двух матриц.
21. eyeMatrix — единичная матрица заданного размера.
22. findMaxAbsInColumn — поиск строки с максимальным по модулю элементом в столбце.
23. eliminateColumn — исключение столбца в алгоритме Гаусса.
24. invGaussIterDiv — итерация деления ведущего элемента в Гауссе-Жордане.
25. invGaussIter — итерация алгоритма Гаусса-Жордана с выбором главного элемента. 26. invGauss — вычисление обратной матрицы методом Гаусса-Жордана.
27. inv — вспомогательная функция для функции invGauss.
28. minElementOfVector — минимальный элемент вектора.
29. maxElementOfVector — максимальный элемент вектора.
30. isEigenvectorStable — проверка устойчивости собственного вектора.
31. isEigenvectorsStable — проверка устойчивости набора собственных векторов. 32. calcEigenvalue — вычисление собственного значения по вектору и матрице. 33. calcEigenvalues — вычисление собственных значений для набора векторов. 34. removeComponent — удаление компоненты одного вектора из другого.
35. removeComponentFromVectors — удаление компоненты из набора векторов.
36. grammSchmidt — ортогонализация Грамма-Шмидта.
37. processCandidates — обработка кандидатов на собственные векторы.
38. generateBetterInitialVectors — генерация улучшенных начальных векторов.
39. findEigenvectorsLimited — поиск собственных векторов с ограничением итераций.
40. findEigenvectors — основной алгоритм поиска собственных векторов методом итерации.
41. isMatrixSymmetric — проверка симметричности матрицы.
4
42.checkDimensions — проверка корректности размерностей матриц.
43.prettyPrintMatrix — вывод матрицы.
44.readMatrixFromFile — чтение матрицы из текстового файла.
Схема
Рисунок 1. Блок схема основной программы
5
Рисунок 2. Вычисление обратной матрицы
Рисунок 3. Нахождение собственных векторов
6
Рисунок 4. Алгоритм Грамма-Шмидта
Программа
module MatrixEigenComplete where type Matrix = [[Double]]
type Vector = [Double] epsilon :: Double epsilon = 1e-7
safeDiv :: Double -> Double -> Double safeDiv _ 0 = 0.0
safeDiv x y = x / y
-- Умножение векторов
dotProduct :: Vector -> Vector -> Double dotProduct xs ys = sum $ zipWith (*) xs ys
7
-- Нормализация
vectorNorm :: Vector -> Double vectorNorm v =
let normSq = dotProduct v v
in if normSq < epsilon then 0.0 else sqrt normSq
vectorNormalization :: Vector -> Vector vectorNormalization v
| norm < epsilon = v
| otherwise = map (/ norm) v where norm = vectorNorm v
addRows :: Vector -> Vector -> Vector addRows = zipWith (+)
multRowNum :: Double -> Vector -> Vector multRowNum k = map (* k)
absElem :: Double -> Double absElem = abs
isRealZero :: Double -> Bool isRealZero x = absElem x < epsilon
isRealsEqual :: Double -> Double -> Bool isRealsEqual x y = isRealZero (x - y)
divReal :: Double -> Double -> Double divReal _ 0 = 0.0
divReal x y = x / y
divVectors :: Vector -> Vector -> Vector divVectors = zipWith divReal
-- Извлечение элемента
extractRowElement :: Int -> Vector -> Double extractRowElement i row = row !! i
8
extractMatrixElement :: Int -> Int -> Matrix -> Double
extractMatrixElement row col matrix = extractRowElement col (matrix !! row)
extractRow :: Int -> Matrix -> Vector extractRow i matrix = matrix !! i
modRowInMatrix :: Int -> Matrix -> Int -> Vector -> Matrix modRowInMatrix _ matrix 0 newRow = newRow : tail matrix modRowInMatrix n matrix rowIndex newRow =
take rowIndex matrix ++ [newRow] ++ drop (rowIndex + 1) matrix
exchangeRowsInMatrix :: Int -> Matrix -> Int -> Int -> Matrix exchangeRowsInMatrix _ matrix r1 r2
| r1 == r2 = matrix | otherwise =
let row1 = extractRow r1 matrix row2 = extractRow r2 matrix
in modRowInMatrix (length matrix) (modRowInMatrix (length matrix) matrix r1 row2) r2 row1
--Транспонирование матрицы transposeMatrix :: Matrix -> Matrix transposeMatrix [] = [] transposeMatrix ([]:_) = []
transposeMatrix m = map head m : transposeMatrix (map tail m)
--Умножение матриц
multMatrixElem :: Int -> Int -> Matrix -> Matrix -> Double
multMatrixElem i j a b = dotProduct (extractRow i a) [extractMatrixElement k j b | k <- [0..length a - 1]]
multMatrixRow :: Matrix -> Matrix -> Int -> Vector
multMatrixRow a b rowIndex = [multMatrixElem rowIndex j a b | j <- [0..length (head b) - 1]]
multMatrix :: Matrix -> Matrix -> Matrix
multMatrix a b = [multMatrixRow a b i | i <- [0..length a - 1]]
eyeMatrix :: Int -> Int -> Matrix
9
eyeMatrix n cols = [[if i == j then 1.0 else 0.0 | j <- [0..cols-1]] | i <- [0..n-1]]
-- Алгоритм Гаусса-Жордана findMaxAbsInColumn :: Int -> Matrix -> Int -> Int findMaxAbsInColumn n matrix col =
snd $ maximum [(absElem (extractMatrixElement row col matrix), row) | row <- [col..n-1]]
eliminateColumn :: Int -> Matrix -> Matrix -> Int -> Int -> (Matrix, Matrix) eliminateColumn n a b col row
| row >= n = (a, b)
| row == col = eliminateColumn n a b col (row + 1)
|otherwise =
let element = extractMatrixElement row col a
colRowA = multRowNum (-element) (extractRow col a) colRowB = multRowNum (-element) (extractRow col b) rowA = extractRow row a
rowB = extractRow row b
newRowA = addRows rowA colRowA newRowB = addRows rowB colRowB
aNew = modRowInMatrix n a row newRowA bNew = modRowInMatrix n b row newRowB in eliminateColumn n aNew bNew col (row + 1)
invGaussIterDiv :: Int -> Matrix -> Matrix -> Int -> (Matrix, Matrix) invGaussIterDiv n a b rowIndex =
let pivot = extractMatrixElement rowIndex rowIndex a in if isRealZero pivot
then error "Matrix is singular - no inverse exists" else
let scale = safeDiv 1.0 pivot
pivotRowA = multRowNum scale (extractRow rowIndex a) pivotRowB = multRowNum scale (extractRow rowIndex b) aScaled = modRowInMatrix n a rowIndex pivotRowA bScaled = modRowInMatrix n b rowIndex pivotRowB
in eliminateColumn n aScaled bScaled rowIndex 0
invGaussIter :: Int -> Matrix -> Matrix -> Matrix -> Matrix -> Int -> (Matrix, Matrix)
10
