В варианте 3 элементы добавляются в список публикаций System.Collections.Generic.List. Вводятся название публикации, данные автора статьи для объекта типа Person и дата публикации.
В методе Main()
-
Создать объект типа T с непустым списком элементов, для которого предусмотрен ввод данных с консоли. Создать полную копию объекта с помощью метода, использующего сериализацию, и вывести исходный объект и его копию.
82.Предложить пользователю ввести имя файла:
если файла с введенным именем нет, приложение должно сообщить об этом и создать файл;
если файл существует, вызвать метод Load(string filename) для инициализации объекта T данными из файла.
83.Вывести объект T.
84.Для этого же объекта T сначала вызвать метод AddFromConsole(), затем метод Save(string filename). Вывести объект T.
85.Вызвать последовательно
статический метод Load( string filename, T obj), передав как параметры ссылку на тот же самый объект T и введенное ранее имя файла;
метод AddFromConsole();
статический метод Save (string filename, T obj).
86. Вывести объект T.
Приложение должно работать в режиме накопления. Если выбирается один и тот же файл для записи, и пользователь вводит данные без ошибок, при каждом следующем выполнении приложения к списку добавляются два новых элемента. Приложение должно обрабатывать все исключения, которые могут возникнуть из-за ошибок при вводе данных. Независимо от того, корректно были введены данные или при вводе были допущены ошибки, все файловые потоки должны быть закрыты.
Лабораторная работа 5. Варианты второго уровня
Сериализация. Взаимодействие управляемого и неуправляемого кода
В лабораторной работе требуется определить классы для матриц специального вида на языках C# и С++. Классы содержат метод для решения системы линейных алгебраических уравнений, который учитывает специфику матрицы. Эти классы используются для сравнения времени выполнения управляемого кода C# и неуправляемого кода C++. Код С++ компилируется в DLL-библиотеку. Код C# вызывает методы из DLL-библиотеки С++ с помощью сервиса PInvoke. Для сохранения в файле результатов тестирования времени выполнения кодов С# и C++ используется сериализация.
Варианты отличаются типом матриц специального вида, для которых определяются классы C# и С++.
Вариант |
Тип матрицы |
1 |
циркулянтная |
2 |
теплицева |
3 |
теплицева симметричная |
4 |
ганкелева |
5 |
трехдиагональная |
Класс Matrix
Матрица специального вида полностью определяется либо одной строкой (циркулянтная и симметричная теплицева), либо одной строкой и одним столбцом (теплицева и ганкелева), либо тремя диагоналями (трехдиагональная матрица).
Память для хранения матрицы распределяется в конструкторе. Порядок матрицы передается как параметр конструктора.
В памяти хранится не вся полная матрица, а только информация, необходимая для того, чтобы задать полную матрицу:
для циркулянтных и теплицевых симметричных матриц в памяти хранится только одна строка;
для теплицевых и ганкелевых матриц в памяти хранятся только столбец и строка;
для трехдиагональных матриц в памяти хранятся только диагонали.
За счет этого экономится память для хранения матриц. Полная матрица содержит элементов, в то время как для рассматриваемых матриц специального вида порядка в зависимости от типа матрицы достаточно хранить , или элементов.
Для элементов матриц лучше использовать тип double, так как арифметические операции с операндами типа float и double выполняются с одинаковой скоростью, но у типа double шире диапазон значений и выше точность при хранении. Длина типа double гарантирует 15-16 десятичных цифр, длина типа float только 7 десятичных цифр. Тип float по сравнению с double имеет преимущество только в экономии памяти при хранении данных.
В классе C++ должны быть определены
конструктор Matrix (int n) для инициализации матрицы по умолчанию;
конструктор для пользовательской инициализации матрицы;
конструктор копирования с прототипом Matrix (const Matrix &);
деструктор;
операция присваивания c прототипом Matrix& operator=(const Matrix &);
метод для решения системы линейных уравнений.
В коде С++ не должно быть утечки памяти, т.е. вся память, выделенная динамически с помощью оператора new, должна быть освобождена с помощью оператора delete.
Метод для решения системы линейных уравнений должен принимать как параметр массив элементов типа double, содержащий вектор правой части. В реализации метода на C++ вектор решения также необходимо передать через параметр, в этом случае память для него будет и распределяться, и освобождаться в вызываемом методе. При передаче решения через возвращаемое значение метода память приходится распределять в вызываемом методе, а освобождать в вызывающем. В реализации этого метода на C# вектор решения можно передать как возвращаемое значение, так как память освобождается сборщиком мусора.
В классе C# должны быть определены
конструктор Matrix ( int n) для инициализации матрицы по умолчанию;
конструктор для пользовательской инициализации матрицы;
метод для решения системы линейных уравнений;
перегруженная версия виртуального метода ToString().
Конструктор Matrix(int n) используется для автоматической генерации матрицы порядка n при сравнении скорости выполнения кодов C# и C++. Так как время решения системы линейных уравнений определяется только порядком матрицы и не зависит от того, для какой конкретной матрицы и правой части решается система, в конструкторе для автоматической генерации матрицу надо задать так, чтобы при решении системы уравнений не возникало проблем с плохой обусловленностью матрицы. Для этого достаточно на главной диагонали матрицы задать элементы, которые по модулю значительно больше внедиагональных элементов. Не следует использовать методы случайной генерации элементов матрицы, так как этот процесс значительно медленнее, чем простое присваивание значений, кроме того, чтобы получить хорошо обусловленную матрицу, придется специально корректировать значения.
В приложении 2 приведены формулы для решения системы линейных уравнений с теплицевыми матрицами, которые для системы порядка требуют арифметических операций. Для этого алгоритма время решения системы линейных уравнений должно возрастать в 4 раза при увеличении порядка матрицы в 2 раза. Это соотношение выполняется только для матриц достаточно большого порядка, так как для матриц малого порядка накладные расходы на вызов метода, распределение и освобождение памяти в методе решения системы линейных уравнений будут сравнимы со временем выполнения арифметических операций.
В методе для решения системы линейных уравнений не должна распределяться память для полной матрицы, так как обратная матрица определяется либо двумя векторами x и y (теплицева и ганкелева матрицы), либо одним вектором (теплицева симметричная и циркулянтная).
Для трехдиагональных матриц зависимость времени решения от порядка матрицы – линейная, это значит, что для матриц большого порядка при увеличении порядка матрицы в 2 раза, время решения системы линейных уравнений также возрастает в 2 раза.
Вызов неуправляемого кода C++ из кода C#
Код С++ надо скомпилировать в DLL-библиотеку, содержащую две глобальные экспортируемые функции, которые вызываются из кода C#.
Первая глобальная экспортируемая функция С++ используется только для сравнения времени выполнения кода C# и кода С++. Эта функция из кода C# получает через параметры только два целочисленных значения - порядок матрицы и число повторов. Так как для матриц небольшого порядка решение системы выполняется быстро и точности системного таймера не хватает для его измерения, решение одной и той же системы линейных уравнений выполняется несколько раз, число повторов задается в коде C# и передается через параметр глобальной экспортируемой функции.
В первой глобальной экспортируемой функции создается объект типа Matrix и с помощью конструктора Matrix(int n) генерируется матрица заданного порядка. В цикле заданное число раз решается система уравнений для одной и той же матрицы с одной и той же правой часью и измеряется время выполнения этого цикла. Правую часть для системы линейных уравнений нужно инициализировать вне цикла.
Для измерения времени выполнения кода С++ можно использовать функцию clock(). Время выполнения кода C++ возвращается в вызывающий код C# либо через параметр глобальной экспортируемой функции, либо как возвращаемое значение.
Вторая глобальная экспортируемая функция С++ получает из кода C# данные, которые определяют матрицу и правую часть. В коде С++ решается система линейных уравнений, решение возвращается в код C# также через параметр этой глобальной экспортируемой функции.
Самый простой способ обмена данными между кодами C# и C++ – обмен данными в виде массивов с элементами типа double через параметры экспортируемой функции.
Для того, чтобы отделить интерфейсную часть кода C# от вычислительной, в коде на С# надо определить метод, который через параметры получает порядок матрицы и число повторов, автоматически генерирует матрицу и правую часть, выполняет вычисления и возвращает время выполнения цикла на C#.
Оба проекта (для C# и C++) надо разместить в одном решении (solution). В коде C# в атрибуте DllImport надо указать относительный путь к файлу с DLL-библиотекой, скомпилированной из исходного кода C++. В этом случае при копировании решения(solution) в другой каталог не потребуется вносить изменения в атрибут DllImport, а при перекомпиляции C++-проекта файл с DLL-библиотекой не надо будет вручную копировать в текущий каталог проекта C#.
Сериализация
В коде C# определить тип TimeItem (класс или структуру) для хранения времени выполнения кода для одной пары значений порядка матрицы и числа повторов и класс TimesList для хранения всей информации.
Тип TimeItem должен иметь поля, в которых хранятся
порядок матрицы;
число повторов;
время выполнения цикла в коде на C#;
время выполнения цикла в коде на C++;
коэффициент, равный отношению времени выполнения кода на C# и кода на C++.
В классе TimesList должны быть определены
закрытое поле типа List - список объектов типа TimeItem;
открытый метод Add(TimeItem), добавляющий новый объект TimeItem к списку;
открытый метод Save(string filename) для сохранения списка List в файле с использованием сериализации;
открытый метод Load(string filename) для восстановления списка List из файла с использованием сериализации.
Когда пользователь завершает работу приложения, список List из объекта TimesList сохраняется в файле с именем, которое пользователь ввел в начале работы приложения.
В методе Main()
-
Проверить, что метод решения системы линейных уравнений работает правильно. Для этого надо программно задать матрицу 3-го порядка и правую часть. В вариантах 1-4 необходимо задать матрицу с несовпадающими элементами в строках и столбцах, которые ее определяют. Диагонали трехдиагональной матрицы также должны содержать несовпадающие элементы. Решить систему линейных уравнений и вывести матрицу, правую часть и решение, полученное в коде C#.
87.Передать в код C++ через параметры глобальной экспортируемой функции данные, которые определяют матрицу и правую часть. Решить систему линейных уравнений, решение передать в код C# и вывести полученное решение.
88.Создать один объект типа TimesList и предложить пользователю ввести имя файла:
если файла с заданным именем нет, то в объекте TimesList создается пустая коллекция List;
если файл уже существует, то приложение
открывает файл;
инициализирует список List объекта TimesList данными из файла, выполняя десериализацию;
закрывает файл;
выводит все данные на экран.
89.После того, как пользователь ввел имя файла, он получает приглашение ввести порядок матрицы и число повторов или завершить работу приложения.
90.Если пользователь ввел порядок матрицы и число повторов,
приложение выполняет вычисления на C#;
вызывает экспортируемую функцию из DLL-библиотеки С++;
сохраняет результаты в объекте TimeItem;
добавляет объект TimeItem в список List объекта TimesList;
затем пользователь снова получает приглашение ввести новые значения порядка матрицы и числа повторов или завершить работу приложения.
91.Когда пользователь завершает работу приложения
выводится вся коллекция из объекта TimesList;
коллекция из объекта TimesList сохраняется c использованием сериализации в файле с именем, которое пользователь ввел в начале работы приложения.
92.Весь вывод должен быть подписан. Элементы списка имеют тип TimeItem, который содержит пять полей. Можно вывести список в виде таблицы, в которой первая строка содержит заголовки с описанием данных, размещенных в столбце, и каждый из элементов списка вывести как строку таблицы.
93.Все исключения, которые могут возникнуть при работе приложения, в том числе из-за ошибок при вводе данных, должны быть обработаны. В частности, код, в котором выполняется сериализация/десериализация и код, вызывающий глобальные экспортируемые функции из DLL-библиотеки C++, должен находиться в блоках try/catch.
Приложение 1
Метод прогонки для решения системы линейных уравнений с трехдиагональной матрицей
Метод прогонки для решения системы линейных уравнений с трехдиагональной матрицей представляет собой метод исключения Гаусса, который учитывает ленточную структуру матрицы системы.
Применяя метод исключения Гаусса к системе линейных уравнений с трехдиагональной матрицей
получим следующие рекуррентные формулы для вычисления прогоночных коэффициентов
и рекуррентные формулы для нахождения решения
Приложение 2
Теплицевы, циркулянтные и ганкелевы матрицы
Матрицы специального вида, например, теплицевы, циркулянтные и ганкелевы, встречаются при численном решении некоторых задач математической физики.
Методы решения систем линейных уравнений, которые учитывают специфику таких матриц, дают возможность значительно уменьшить число арифметических операций по сравнению с методами для матриц общего вида. Так при решении системы линейных алгебраических уравнений с полной матрицей общего вида порядка необходимо выполнить арифметических операций, в то время как асимптотически оптимальные методы решения систем уравнений с теплицевой или ганкелевой матрицей дают возможность найти решение за операций, а оптимальные методы решения системы уравнений с циркулянтной матрицей требуют лишь арифметических операций.
Матрица, элементы которой зависят только от разности индексов , называется теплицевой:
Здесь и в дальнейшем использованы обозначения, принятые в [1].
На каждой параллельной главной диагонали теплицевой матрицы расположены равные элементы. Таким образом, теплицева матрица полностью определяется первой строкой и первым столбцом.
Симметричная теплицева матрица определяется одним своим столбцом и имеет следующий вид:
Сумма теплицевых матриц является теплицевой.
Произведение двух теплицевых матриц в общем случае не является теплицевой матрицей. Теплицевость сохраняется лишь в некоторых частных случаях, например, в случае циркулянтных матриц или верхних или нижних треугольных теплицевых матриц.
Теплицева матрица называется циркулянтной (или циркулянтом), если для всех выполняется соотношение . Циркулянтная матрица полностью определяется одной своей строкой и имеет следующий вид:
Сумма циркулянтных матриц - циркулянтная матрица. Произведение двух циркулянтных матриц является циркулянтной матрицей.
Произведение любых двух циркулянтных матриц перестановочно.
Матрица, обратная к невырожденной циркулянтной матрице, является циркулянтной. Доказательства этих утверждений приведены в [1, стр. 41-45].
Матрица, элементы которой зависят только от суммы индексов , называеся ганкелевой:
Ганкелева матрица является симметричной. В ганкелевой матрице равные элементы расположены на диагоналях, параллельных побочной. Ганкелева матрица полностью определяется первой строкой и последним столбцом.
Очевидно, что при перестановке строк (или столбцов) ганкелевой матрицы в обратном порядке получается теплицева матрица (и наоборот).
Решение систем линейных уравнений с циркулянтными, теплицевыми и ганкелевыми матрицами
Для матрицы, обратной к невырожденной теплицевой, известно несколько представлений в виде произведения двух теплицевых матриц специального вида [1, стр. 95; 2, стр. 120].
В частности, для матрицы, обратной к невырожденной теплицевой матрице , справедливо следующее представление [1, стр.102]
(1)
где и - решения систем линейных уравнений
(2)
, (3)
которые фактически определяют первую и последнюю строки матрицы .
Представление (1) справедливо при условии, что .
Как следует из представления (1), матрица, обратная к теплицевой, определяется парой векторов ,. Для вычисления матрицы, обратной к циркулянтной, достаточно найти только вектор .
Наиболее быстрые алгоритмы обращения теплицевой матрицы порядка требуют арифметических операций, но являются эффективными лишь асимптотически при больших значениях . При они проигрывают алгоритмам с числом операций .
Ниже приведены рекуррентные формулы для вычисления векторов и , входящих в представление (1), которые требуют арифметических операций. Алгоритм может применяться только для невырожденных теплицевых матриц, удовлетворяющих условию, что первая компонента вектора , который является решением системы (2) , не равна 0.
Векторы и , входящие в представление (1), находятся из следующих рекуррентных формул [1, стр.149]:
.
Если все ведущие миноры теплицевой матрицы отличны от нуля, то для любого [1, стр.150].
Векторы и, входящие в представление (1) для обратной матрицы, получаем из рекуррентных формул при :
При вычислении векторов и при каждом необходимо выполнить операций умножения и операций сложения. Таким образом, число арифметических операций для вычисления векторов и в данном алгоритме равно. Число арифметических операций при вычислении обратной матрицы можно уменьшить, если учесть, что матрица, обратная к теплицевой, является персимметричной, т.е. симметричной относительно побочной диагонали [2, стр.122].
При вычислении векторов и для симметричной теплицевой матрицы число арифметических операций можно сократить вдвое, так как обратная матрица будет симметрична и персимметрична одновременно [1, стр. 154]. В этом случае
, откуда следует, что и .
Задача решения системы линейных алгебраических уравнений с ганкелевой матрицей сводится к задаче для теплицевой матрицы, так как ганкелева матрица преобразуется к теплицевой простой перестановкой строк.
Литература.
-
В.В.Воеводин, Е.Е.Тыртышников. Вычислительные процессы с теплицевыми матрицами. - М.: Наука, 1987.
-
В.В.Воеводин, Ю.А.Кузнецов. Матрицы и вычисления. - М.: Наука, 1984
Оглавление
Введение. Программа курса «Объектно-ориентированное программирование: Язык программирования C#» |
3 |
Лабораторная работа 1. Классы, свойства, индексаторы. Одномерные, прямоугольные и ступенчатые массивы |
7 |
Лабораторная работа 2. Наследование. Исключения. Интерфейсы. Итераторы и блоки итераторов |
14 |
Лабораторная работа 3. Универсальные типы. Классы-коллекции. Методы расширения класса System.Linq.Enumerable |
|
Варианты первого уровня |
26 |
Варианты второго уровня |
36 |
Лабораторная работа 4. Делегаты. События |
|
Варианты первого уровня |
45 |
Варианты второго уровня |
52 |
Лабораторная работа 5. Варианты первого уровня Классы для работы с файлами. Сериализация |
60 |
Лабораторная работа 5. Варианты второго уровня Сериализация. Взаимодействие управляемого и неуправляемого кода |
62 |
Приложение 1. Метод прогонки для решения системы линейных уравнений с трехдиагональной матрицей |
69 |
Приложение 2.Теплицевы, циркулянтные и ганкелевы матрицы |
70 |
Учебное издание
БЕРЕЗИНА Нина Ивановна
ЛАБОРАТОРНЫЕ РАБОТЫ ПО КУРСУ
«ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ:
ЯЗЫК ПРОГРАММИРОВАНИЯ C#»
Учебное пособие
Издательский отдел Факультета вычислительной математики и кибернетики
МГУ имени М.В.Ломоносова
Лицензия ИД N 05899 от 24.09.01 г.
119992, ГСП-2, Москва, Ленинские горы,
МГУ имени М.В.Ломоносова,2-й учебный корпус
Напечатано с готового оригинал-макета
Издательство ООО «МАКС Пресс»
Лицензия ИД N 00510 от 01.12.99 г. Подписано к печати 23.08.2010 г.
Формат 60x88 1/16. Усл.печ.л. 4,75. Тираж 100 экз. Заказ 361.
119992, ГСП-2, Москва, Ленинские горы,
МГУ им. М.В.Ломоносова, 2-й учебный корпус, 627 к.
Тел 939-3890, 939-3891. Тел./Факс 939-3891