Табличный метод Квайна-Мак-Класки
Представьте инженера корпорации Intel или AMD, перед которым стоит задача спроектировать блок арифметико-логического устройства (АЛУ) для нового процессора. На вход этого блока поступают не три и не четыре сигнала, а сразу 64 или 128. Попытка нарисовать карту Карно для 64 переменных потребует создания матрицы, размер которой превышает количество атомов в обозримой Вселенной. Визуальные методы, идеально подходящие для человека, абсолютно бессильны перед масштабами современной микроэлектроники.
Здесь на помощь приходит строгая математика и алгоритмизация. Нам нужен метод, который не требует пространственного воображения, не зависит от внимательности инженера и, самое главное, может быть запрограммирован и передан на выполнение компьютеру. Именно таким инструментом является алгоритм, разработанный Уиллардом Квайном в 1952 году и усовершенствованный Эдвардом Мак-Класки в 1956 году.
> Информатика не более связана с компьютерами, чем астрономия с телескопами.
>
> Эдсгер Дейкстра
Суть таблично-алгоритмического подхода
Метод Квайна-Мак-Класки — это формализованный способ нахождения минимальной дизъюнктивной нормальной формы (МДНФ) булевой функции. По своей математической природе он делает абсолютно то же самое, что и карты Карно: ищет соседние минтермы и применяет к ним закон склеивания. Разница заключается лишь в форме представления данных.
Вместо того чтобы рисовать геометрические фигуры, алгоритм работает со списками двоичных чисел, последовательно сравнивая их друг с другом по строгим правилам. Процесс всегда делится на две крупные фазы:
Поиск всех простых импликант (максимально возможных склеиваний).
Построение таблицы покрытий для выбора минимально необходимого набора этих импликант.Рассмотрим работу алгоритма на конкретном практическом примере. Допустим, мы проектируем дешифратор команд, логика которого описывается функцией от четырех переменных . Функция равна единице на следующих наборах (в десятичной записи):
где — логическая функция, — входные переменные, — сумма минтермов (наборов, на которых функция принимает значение истина).
Двоичное представление и первичная группировка
Первое, что делает алгоритм — переводит десятичные номера наборов в двоичный код. Каждая позиция в коде соответствует переменной (1 — переменная без отрицания, 0 — с отрицанием).
Чтобы оптимизировать процесс сравнения, числа разбиваются на группы по количеству единиц в их двоичном представлении. Закон склеивания гласит, что объединить можно только те наборы, которые отличаются ровно в одном бите. Следовательно, склеивание возможно только между числами из соседних групп (например, число с одной единицей может склеиться только с числом, у которого ноль единиц или две единицы).
Составим стартовую таблицу:
| Группа (число единиц) | Десятичный номер | Двоичный код () |
|---|---|---|
| 0 | 0 | 0 0 0 0 |
| 1 | 2 | 0 0 1 0 |
| 1 | 8 | 1 0 0 0 |
| 2 | 10 | 1 0 1 0 |
| 3 | 11 | 1 0 1 1 |
| 3 | 14 | 1 1 1 0 |
| 4 | 15 | 1 1 1 1 |
Систематическое склеивание (первый проход)
Теперь алгоритм начинает последовательно сравнивать каждый элемент группы с каждым элементом группы . Если два двоичных кода отличаются ровно в одной позиции, они склеиваются. Различающийся бит заменяется прочерком (-), что означает исключение этой переменной из формулы.
Сравниваем Группу 0 и Группу 1:
0 (0000) и 2 (0010) отличаются в третьем бите. Результат: 0 0 - 0.
0 (0000) и 8 (1000) отличаются в первом бите. Результат: - 0 0 0.Сравниваем Группу 1 и Группу 2:
2 (0010) и 10 (1010) дают - 0 1 0.
8 (1000) и 10 (1010) дают 1 0 - 0.Продолжая этот процесс для всех соседних групп, мы получаем новый список импликант. Важное правило: если исходный набор поучаствовал хотя бы в одном склеивании, мы ставим рядом с ним галочку. Наборы, оставшиеся без галочек, больше не могут быть упрощены — они автоматически становятся простыми импликантами.
Результат первого прохода:
| Склеенные наборы | Новый код |
|---|---|
| (0, 2) | 0 0 - 0 |
| (0, 8) | - 0 0 0 |
| (2, 10) | - 0 1 0 |
| (8, 10) | 1 0 - 0 |
| (10, 11) | 1 0 1 - |
| (10, 14) | 1 - 1 0 |
| (11, 15) | 1 - 1 1 |
| (14, 15) | 1 1 1 - |
В нашем случае все исходные наборы поучаствовали в склеивании, поэтому двигаемся дальше.
Глубокое склеивание (второй проход)
Алгоритм повторяется для новой таблицы. Теперь мы можем склеивать строки только в том случае, если прочерки (-) находятся в одинаковых позициях, а остальные биты отличаются ровно на одну позицию.
Ищем совпадения:
Строка (0, 2) 0 0 - 0 и строка (8, 10) 1 0 - 0. Прочерк совпадает, первый бит отличается. Склеиваем! Получаем набор (0, 2, 8, 10) с кодом - 0 - 0.
Строка (0, 8) - 0 0 0 и строка (2, 10) - 0 1 0. Дают тот же самый результат - 0 - 0. Дубликаты просто удаляются.
Строка (10, 11) 1 0 1 - и строка (14, 15) 1 1 1 -. Дают набор (10, 11, 14, 15) с кодом 1 - 1 -.
Строка (10, 14) 1 - 1 0 и строка (11, 15) 1 - 1 1. Снова дают 1 - 1 -.Больше склеиваний произвести невозможно. Все элементы из таблицы первого прохода поучаствовали в создании новых групп. У нас остались две финальные конструкции, которые нельзя упростить дальше. Это и есть наши простые импликанты:
с кодом - 0 - 0. Переводим обратно в алгебру: переменные и исключены, , . Формула: .
с кодом 1 - 1 -. Переменные и исключены, , . Формула: .Таблица покрытий (таблица Квайна)
Первая фаза завершена. Мы нашли все возможные простые импликанты. Теперь нужно выбрать из них минимальный набор, который покроет все исходные единицы функции. Для этого строится таблица покрытий.
По вертикали записываем найденные простые импликанты, по горизонтали — исходные наборы, на которых функция равна единице (наши цели). На пересечениях ставим крестики, если импликанта покрывает данный набор.
| Простые импликанты | 0 | 2 | 8 | 10 | 11 | 14 | 15 |
|---|---|---|---|---|---|---|---|
| (0, 2, 8, 10) | X | X | X | X | | | |
| (10, 11, 14, 15) | | | | X | X | X | X |
Анализ таблицы начинается с поиска ядра — столбцов, в которых стоит только один крестик.
Посмотрим на столбец «0». Крестик стоит только в строке . Это значит, что без мы физически не сможем реализовать логику для нулевого набора. Следовательно, — существенная импликанта, она обязана войти в итоговую формулу.
Посмотрим на столбец «15». Крестик стоит только в строке . Значит, также является существенной импликантой.
Взяв и , мы покрываем абсолютно все столбцы в таблице. Задача решена! Итоговая минимальная дизъюнктивная нормальная форма выглядит так:
где — минимизированная функция, — входные переменные, — логическое отрицание (НЕ), — логическое умножение (И), — логическое сложение (ИЛИ).
Исходная функция, состоявшая из семи громоздких слагаемых (по 4 переменные в каждом), сократилась до двух простых логических вентилей И и одного вентиля ИЛИ.
Вычислительная сложность и алгоритм Espresso
Метод Квайна-Мак-Класки идеален с математической точки зрения: он гарантированно находит абсолютно минимальную форму функции. Однако в реальном мире инженерии у него есть серьезный недостаток — экспоненциальный рост вычислительной сложности.
Задача минимизации булевых функций относится к классу NP-трудных задач. При увеличении количества входных переменных размер таблиц растет лавинообразно. Для функции от 4 переменных существует максимум 16 минтермов. Для функции от 32 переменных (стандартная шина данных старых процессоров) количество минтермов превышает 4 миллиарда. Ни один современный суперкомпьютер не способен построить и обработать полную таблицу покрытий для функции от 64 переменных за адекватное время.
Как же тогда проектируют современные процессоры?
В системах автоматизированного проектирования электроники (САПР) используются эвристические алгоритмы. Самым известным из них является алгоритм Espresso, разработанный в IBM в 1980-х годах.
В отличие от метода Квайна-Мак-Класки, Espresso не пытается найти абсолютно минимальную форму. Вместо этого он быстро находит достаточно хорошую (близкую к минимальной) форму. Алгоритм берет исходную функцию и начинает итеративно «раздувать» и «сжимать» импликанты в многомерном пространстве, отбрасывая избыточные части. Это позволяет оптимизировать логические схемы с сотнями переменных за считанные минуты, жертвуя лишь долями процента эффективности ради колоссальной скорости расчетов.
Итоги
Метод Квайна-Мак-Класки — это универсальный таблично-алгоритмический способ минимизации булевых функций, не зависящий от количества переменных и пригодный для компьютерной автоматизации.
Алгоритм состоит из двух этапов: последовательного склеивания двоичных кодов для поиска простых импликант и решения задачи о покрытии с помощью таблицы Квайна.
Группировка минтермов по количеству единиц в двоичном коде значительно ускоряет процесс, так как склеивание возможно только между соседними группами.
Из-за экспоненциальной вычислительной сложности (NP-трудность) чистый метод Квайна-Мак-Класки применяется редко для больших схем; в современной индустрии его заменяют эвристические программы-оптимизаторы, такие как алгоритм Espresso.