Лабораторная работа №10
Требуемые условия завершения
Открыто с: четверг, 18 апреля 2019, 11:55
Срок сдачи: четверг, 18 апреля 2019, 15:30
Класс Matrix
- Создать в отдельном файле класс Matrix со свойствами Rows и Columns типа uint (неотрицательные целые, количество строк и столбцов соответственно), доступными для чтения и с закрытым полем
double [,] elements;
- Создать конструктор
public Matrix(uint rows, uint columns)
который создаёт матрицу заданного размера, заполненную нулями. - Создать конструктор
public Matrix(uint rows, uint columns, params double[] elements)
который заполняет матрицу по правилу[a1,a2,a3,a4]→[1a3a2a4] - Создать индексатор
public double this[uint row, uint column]
который позволяет получить и задать значение элемента матрицы. Указание Удобно добавить вспомогательный закрытый метод
- Перегрузить метод ToString().
- Поскольку классы представляют ссылочные типы, то это накладывает некоторые ограничения на их использование. Например, если мы создадим две переменные
var a = new Matrix(2,2); var b = a;
то a и b будут указывать на один и тот же объект в памяти, поэтому изменения элементов a затронут также и переменную b.
Чтобы переменная b указывала на новый объект, но со значениями из a, мы можем применить клонирование с помощью реализации интерфейса ICloneable. Класс следует сделать реализацией ICloneable следующим образом: изменить заголовок классаclass Matrix : ICloneable
и сделать реализацию метода Clone().
Указание При перегрузке Clone удобно использовать Clone() для массивов:double[,] x = (double[,])elements.Clone();
Указание При реализации Clone() удобно пользоваться инициализатором объекта - Создать копирующий конструктор
public Matrix(Matrix matrix)
- Перегрузить операторы +, -, *. Перегрузка операторов заключается в определении в классе, для объектов которого мы хотим определить оператор, специального метода
public static возвращаемый_тип operator оператор(параметры) { }
Поскольку все перегруженные операторы - бинарные, то есть проводятся над двумя объектами, то для каждой перегрузки предусмотрено по два параметра. Например, перегрузка оператора сложения выглядит следующим образом
public static Matrix operator +(Matrix left, Matrix right) { // TODO: реализация }
При перегрузке бинарных операторов +, -, * одновременно происходит перегрузка присваивающих операторов +=, -=, *=. - Создать метод, принимающий матрицу и заполняющий её случайными числами в диапазоне от min до max. (по умолчанию сделать min и max равными 0.0 и 10.0)
- Продемонстрировать использование класса в основной программе.
private void CheckIndices(uint row, uint column)который проверяет значения индексов и бросает исключение IndexOutOfRangeException, если в матрице нет соответствующего элемента.
Класс SquareMatrix
Наследование (inheritance) является одним из ключевых моментов ООП. Благодаря наследованию один класс может унаследовать функциональность другого класса.
- В новом файле создаём новый класс - SquareMatrix
class SquareMatrix : Matrix { }
После двоеточия мы указываем базовый класс для данного класса. Для класса SquareMatrix базовым является Matrix, и поэтому класс SquareMatrix наследует все те же свойства, методы, поля, которые есть в классе Matrix. Единственное, что не передается при наследовании, это конструкторы базового класса. - Добавить конструктор квадратной матрицы с единственным параметром uint Rows. Он должен обращаться к конструктору базового класса при помощи ключевого слова base.
конструктор_производного_класса(список_параметров) : base (список_аргументов) { // тело конструктора }
- Создать метод, осуществляющий LU-разложение.
Указание. Так как матрица L является нижнедиагональной и содержит единицы на главной диагонали, а матрица U является верхнедиагональной, для хранения обеих матриц можно использовать один двумерный массив (или SquareMatrix).
Указание: алгоритм разложения следующий (действия выполняются строго по порядку, черезAij ⋅ Aij ⋅ Aij Aij Aij обозначаем элементы исходной матрицы):- Создаем матрицу LU размера Rows x Rows, заполненную нулями
- запускаем цикл по i от 0 до Rows - 1
- в цикле по j от i до Rows - 1
(LU)ij=Aij−∑k=0i−1(LU)ik(LU)kj - в цикле по j от i + 1 до Rows - 1
(LU)ji=1(LU)ii(Aji−∑k=0i−1(LU)jk(LU)ki)
- в цикле по j от i до Rows - 1
- Создать метод
public double[] LinSolve(double [] rightPart)
который решает СЛАУ с правой частью, заданной массивом rightPart.
Указание: Решение системы Ax=b складывается из двух этапов:- Решение СЛАУ с нижнетреугольной матрицей Ly=b
- Решение СЛАУ с верхнетреугольной матрицей Ux=y
-
Найти определитель матрицы.
Подсказка Достаточно перемножить диагональные элементы матрицы U - Найти обратную матрицу.
Подсказка Обращение матрицы A эквивалентно решению линейной системы AX=I где X - неизвестная матрица, X этой системы является обратной матрицей A^{-1}. Таким образом, задача сводится к решению набора СЛАУ, каждая из которых решается методом LU-разложения. - Перегрузить операцию деления. Под делением понимать умножение справа на обратную матрицу.
- Продемонстрировать использование класса.