- •Дискретная математика
- •6.050102 “Компьютерная инженерия” содержание
- •1 Теория множеств 7
- •2 Математическая логика 15
- •3 Формальные теории 35
- •4 Теория графов 47
- •5 Элементы теории чисел 80
- •6 Теория алгоритмов 121
- •Введение
- •1 Теория множеств
- •1.1 Множества и подмножества
- •1.1.1 Элементы множества
- •1.2 Аксиомы теории множеств
- •1.3 Способы задания множеств
- •1.4 Операции над множествами
- •1.5 Элементы алгебры множеств
- •1.5.1 Определение алгебры множеств
- •1.5.2 Основные законы алгебры множеств
- •1.5.3 Принцип двойственности
- •2 Математическая логика
- •2.1 Функции алгебры логики (булевые функции)
- •2.1.1 Способы задания булевых функций
- •2.1.2 Логические функции одной переменной
- •2.1.3 Логические функции двух переменных
- •2.2.6 Функционально полные системы булевых функций
- •2.3 Алгебра буля
- •2.3.1 Определение алгебры. Теорема Стоуна
- •2.3.2 Законы алгебры логики
- •2.3.3 Разложения функций по переменным
- •2.3.4 Приведение логических функций
- •2.3.5 Импликанты и имплициенты булевых функций
- •2.3.6 Методы минимизации логических функций
- •2.4 Алгебра жегалкина
- •2.4.1 Преобразование функций в алгебре Жегалкина
- •2.4.2 Переход от булевой алгебры к алгебре Жегалкина
- •3 Формальные теории
- •3.1 Основные принципы построения формальных теорий исчисления
- •3.2 Определение исчисления высказываний
- •3.2.1 Метатеоремы исчисления высказываний
- •3.2.2 Схемы исчисления высказываний
- •3.3 Исчисление предикатов
- •3.3.1 Определение формальной теории pl
- •3.3.2 Принцип резолюции в исчислении предикатов
- •3.3.3 Схемы доказательств в исчислении предикатов
- •4 Теория графов
- •4.1 История теории графов
- •4.2 Основные определения
- •4.3 Способы представления графов
- •4.3.1 Матрицей смежности
- •4.3.2 Матрицей инцидентности
- •4.4 Пути в графах
- •4.4.1 Задача о кратчайшем пути
- •4.4.2 Алгоритм Дейкстры нахождения кратчайшего пути в графе
- •4.5 Транспортные сети
- •4.5.1 Потоки в транспортных сетях
- •4.5.2 Задача нахождения наибольшего потока в транспортной сети
- •4.5.3 Алгоритм Форда и Фалкерсона нахождения максимального потока транспортной сети
- •4.5.4 Транспортная задача
- •4.6 Обходы в графах
- •4.6.1 Эйлеровы графы
- •4.6.2 Алгоритм Флёри нахождения эйлерова цикла
- •4. Если получился цикл, но не ейлеров, то отбрасываем данную последнюю вершину и повторяем пункт 2.
- •4.6.3 Гамильтоновы циклы
- •4.6.4 Метод ветвей и границ.
- •4.6.5 Метод ветвей и границ в задаче о коммивояжёре
- •4.7 Деревья
- •4.7.1 Построение экономического дерева
- •4.7.2 Алгоритм Краскала
- •5 Элементы теории чисел
- •5.1 Модулярная арифметика
- •5.1.1 Алгоритм Евклида для нахождения наибольшего общего делителя
- •5.1.2 Вычисление обратных величин
- •5.1.3 Основные способы нахождения обратных величин
- •5.1.4 Китайская теорема об остатках
- •5.2 Кодирование
- •5.2.1 Оптимальное кодирование
- •5.3 Обнаружение и исправление ошибок
- •5.3.1 Общие понятия
- •5.3.2 Линейные групповые коды
- •5.3.2 Код Хэмминга
- •5.3.3 Циклические коды
- •5.3.4 Построение и декодирование конкретных циклических кодов
- •5.4 Сжатие информации
- •5.4.1 Исключение повторения строк в последующих строках
- •5.4.2 Алгоритм lzw
- •6 Теория алгоритмов
- •6.1. Основные понятия
- •6.1.1 Основные требования к алгоритмам
- •6.1.2 Блок–схемы алгоритмов
- •6.1.3 Представление данных
- •6.1.4 Виды алгоритмов
- •6.1.5 Правильность программ
- •6.1.6 Эффективность алгоритмов
- •6.1.7 Сходимость, сложность, надежность
- •6.2 Универсальные алгоритмы
- •6.2.1 Основные понятия
- •6.2.2 Машины Тьюринга
- •6.2.3 Рекурсивные функции
- •6.2.5 Тезис Черча-Тьюринга
- •6.2.6 Проблема самоприменимости
- •6.3 Языки и грамматики
- •6.3.1 Общие понятия
- •6.3.2 Формальные грамматики
- •6.3.3 Иерархия языков
- •6.4 Параллельные вычисления
- •Рекомендованная литература
4.7.2 Алгоритм Краскала
Задача об остове минимального веса (о кратчайшем остове):
в связном взвешенном графе порядка найти остов минимального веса.
Алгоритм Краскала, решающий эту задачу, заключается в следующем.
1. Выбираем самое короткое ребро графа U1 , затем ребро U2, затем самое короткое из оставшихся;
2. Из оставшихся ребер выбираем самое короткое ребро U3 так, чтобы оно не образовывало цикла с выбранными ребрами;
3. Продолжаем эту процедуру. На k-м к выбранным ребрам U1,…,Uк-1 добавляем самое короткое ребро из оставшихся ¦U¦-(к-1) ребер так, чтобы оно не образовывало цикла с выбранными ребрами;
4. При k=n-1 процесс заканчивается. Получим граф без циклов с (n-1)-м ребром. Построенный граф есть дерево, обозначим его T(n-1).
В графе, где некоторые ребра имеют одинаковую длину, кратчайшее частичное дерево может не быть однозначно определенным.
Следующая теорема утверждает, что алгоритм Краскала всегда приводит к остову минимального веса:
при i < n – 1 граф Ti+1 всегда можно построить. Граф Tn-1 будет являться остовом минимального веса в графе (G,w).
Доказательство:
Граф Ti имеет ровно i ребер и потому при i < n – 1 является несвязным. А, так как, граф G связен, то в нем есть по меньшей мере одно ребро, не составляющее циклов с ребрами графа Ti. Итак, нужное ребро Ui+1 существует и граф Ti+1 можно построить.
5 Элементы теории чисел
5.1 Модулярная арифметика
Модулярная арифметика часто называется “арифметикой часов”. Если прибавить 14 часов к 3 часам после полудня, то получится 5 часов утра следующего дня:
3 + 14 5 (mod 12)
или
(3 + 14) mod 12 = 5.
Это арифметика по модулю 12.
Обычная запись в модулярной арифметике
a b (mod n)
читается так: “a сравнимо с b по модулю n”.
Это соотношение справедливо для целых значений a, b и n 0, если и только если
а = b + k • n
для некоторого целого k.
Отсюда, в частности , следует n | (a ─ b). Это читается как “n делит (a ─ b)”.
Если a b (mod n), то b называют вычетом числа a по модулю n.
Операцию нахождения вычета числа а по модулю n
a (mod n)
называют приведением числа а по модулю n или приведением по модулю.
В нашем примере
(3 + 14) mod 12 = 17 mod 12 = 5
или
17 5 (mod 12),
число 5 является вычетом числа 17 по модулю 12.
Набор целых чисел от 0 до (n – 1) называют полным набором вычетов по модулю n.
Это означает, что для любого целого а (а > 0) его вычет r по модулю n есть некоторое целое число в интервале от 0 до (n – 1), определяемое из соотношения
r = a – k • n,
где k – целое число.
Например, для n = 12 полный набор вычетов:
{0, 1, 2, … , 11}.
Обычно используют вычеты
r {0, 1, 2, … , n – 1},
но иногда полезны вычеты в диапазоне целых:
r {– ½ (n – 1), … , ½ (n – 1)}.
Важно, что
– 12 (mod 7) – 5 (mod 7) 2 (mod 7) 9 (mod 7) и т.д.
Модулярная арифметика аналогична во многом обычной арифметике: она коммутативна, ассоциативна и дистрибутивна. Точнее говоря, целые числа по модулю n с использованием ипераций сложения и умножения образуют коммутативное кольцо при соблюдении законов ассоциативности, коммутативности и дистрибутивности.
Фактически можно сначала приводить по модулю n, а затем выполнять операции, либо сночала выполнять операции, а затем приводить по модулю n, поскольку приведение по модулю n является гомоморфным отображением из кольца целых в кольцо целых по модулю n:
(a + b) mod n = [ a (mod n) + b (mod n) ] mod n,
(a b) mod n = [ a (mod n) b (mod n) ] mod n,
(a • b) mod n = [ a (mod n) • b (mod n) ] mod n,
[a • (b + c) ] mod n = {[a • b (mod n) ] + [a • c (mod n) ]} mod n.
Криптография использует множество вычислений по модулю n, потому что задачи типа вычисления дискретных логарифмов и квадратных корней очень трудны.
Кроме того, с вычислениями по модулю удобнее работать, потому что они ограничивают диапазон всех промежуточных величин и результата.
Для модуля n длиной k бит промежуточные результаты любого сложения, вычитания или умножения будут не длиннее 2kбит. Поэтому возведение в степень в модулярной арифметике можно выполнить без генерации очень больших промежуточных результатов.
Вычисление степени числа а по модулю n
а х mod n
можно выполнить как ряд умножений и делений. Существует способ сделать это быстрее. Поскольку эти операции дистрибутивны, быстрее произвести возведение в степень как ряд последовательных умножений, выполняя каждый раз приведение по модулю. Это особенно заметно, если работать с длинными числами (200 бит и более).
{ Пример. Нужно вычислить а 8 mod n.
Не следует применять примитивный подход с выполнением семи перемножений и одного приведения по модулю громадного числа:
(а • а • а • а • а • а • а • а) mod n.
Вместо этого выполняют три малых умножения и три малых приведения по модулю:
((а 2 mod n.)2 mod n.)2 mod n.
Тем же способом вычисляют
а 16 mod n. = (((а 2 mod n.)2 mod n.)2 mod n.)2 mod n. }
Вычисление
а х mod n,
где х не является срепенью 2, лишь немного сложнее. Двоичная запись числа х позволяет представить число х как сумму степеней 2:
х = 12 (10) = 11001 (2).
Поэтому 25 = 2 4 + 2 3 + 2 0.
Тогда
а 25 mod n. = (а • а 24) mod n. = (а • а 8 • а 16) mod n =
= (а • ((а 2) 2) 2 • (((а 2) 2) 2 ) 2) mod n = ((((а 2 • а) 2) 2 ) 2 • а) mod n.
При накоплении промежуточных результатов потребуется только шесть умножений:
(((((((а 2 mod n) • а) mod n)2 mod n)2 mod n)2 mod n) • а) mod n.
Этот метод уменьшает трудоемкость вычислений до 1,5хk операций в стреднем, где k – длина числа в битах.
Поскольку многие алгоритмы шифрования основаны на возведении в степень по модулю n, целесообразно использовать алгоритмы быстрого возведения в степень.