Алгоритм Куайна–Маккласки ( QMC ), также известный как метод простых импликант , — это метод минимизации булевых функций , разработанный Уиллардом В. Куайном в 1952 году [1] [2] и расширенный Эдвардом Дж. Маккласки в 1956 году [3]. В качестве общего принципа этот подход уже был продемонстрирован логиком Хью Макколлом в 1878 году [4] [5] [6], доказан Арчи Блейком в 1937 году [7] [8] [9] [6] и переоткрыт Эдвардом У. Сэмсоном и Бертоном Э. Миллсом в 1954 году [10] [6] и Рэймондом Дж. Нельсоном в 1955 году [11] [6]. Также в 1955 году Пол В. Абрахамс и Джон Г. Нордаль [12], а также Альберт А. Маллин и Уэйн Г. Келлнер [13] [14] [15] [16] предложили десятичный вариант метода. [17] [14] [15] [16] [18] [19] [20] [21]
Алгоритм Куайна–Маккласки функционально идентичен отображению Карно , но табличная форма делает его более эффективным для использования в компьютерных алгоритмах, а также дает детерминированный способ проверки того, что была достигнута минимальная форма булевой F. Иногда его называют методом табуляции.
Алгоритм Куайна-Маккласки работает следующим образом:
Хотя алгоритм Куайна–Маккласки более практичен, чем отображение Карно , при работе с более чем четырьмя переменными, он также имеет ограниченный диапазон использования, поскольку решаемая им задача является NP-полной . [22] [23] [24] Время выполнения алгоритма Куайна–Маккласки растет экспоненциально с числом переменных. Для функции от n переменных число простых импликантов может быть таким большим, как , [25] например, для 32 переменных может быть более 534 × 10 12 простых импликантов. Функции с большим количеством переменных должны быть минимизированы с помощью потенциально неоптимальных эвристических методов, из которых эвристический логический минимизатор Espresso был фактическим стандартом в 1995 году. [ требуется обновление ] [26] Для одного естественного класса функций точная сложность нахождения всех простых импликант понятна лучше: Милан Моссе, Гарри Ша и Ли-Ян Тан открыли близкий к оптимальному алгоритм для нахождения всех простых импликант формулы в конъюнктивной нормальной форме . [27]
Второй шаг алгоритма заключается в решении задачи покрытия множества ; [28] На этом шаге алгоритма могут возникнуть NP-трудные случаи этой задачи. [29] [30]
В этом примере входные данные — это булева функция с четырьмя переменными, которая вычисляется как для значений и , вычисляется как неизвестное значение для и , и как везде в остальном (где эти целые числа интерпретируются в их двоичной форме для входных данных для краткости записи). Входные данные, вычисляемые как , называются «минтермами». Мы кодируем всю эту информацию, записывая
Это выражение говорит, что выходная функция f будет равна 1 для минтермов и (обозначенных термином «m») и что нас не волнует выход для комбинаций и (обозначенных термином «d»). Символ суммирования обозначает логическую сумму (логическое ИЛИ или дизъюнкция) всех суммируемых терминов.
Сначала запишем функцию в виде таблицы (где «x» означает «неважно»):
Из этой таблицы можно легко сформировать каноническое выражение суммы произведений , просто суммируя минтермы (исключая безразличные члены ), где функция оценивается как единица:
что не является минимальным. Поэтому для оптимизации все minterm, которые оцениваются как единица, сначала помещаются в таблицу minterm. Термины Don't-care также добавляются в эту таблицу (имена в скобках), поэтому их можно комбинировать с minterm:
На этом этапе можно начать объединять минтермы с другими минтермами в соседних группах. Если два термина отличаются только одной цифрой, эту цифру можно заменить тире, указывающим, что цифра не имеет значения. Термины, которые больше не могут быть объединены, отмечены звездочкой ( * ). Например, 1000
и 1001
можно объединить, чтобы получить 100-
, указывающее, что оба минтерма подразумевают, что первая цифра — , 1
а следующие две — 0
.
При переходе от размера 2 к размеру 4 рассматривать -
как третье битовое значение. Сначала сопоставьте -
' s. Термины представляют продукты, и для объединения двух терминов продуктов они должны иметь одинаковые переменные. Одна из переменных должна быть дополнена в одном термине и не дополнена в другом. Остальные присутствующие переменные должны согласовываться. Таким образом, для сопоставления двух терминов -
' s должны быть выровнены, и все, кроме одной, цифры должны быть одинаковыми. Например, -110
и -100
можно объединить, чтобы получить -1-0
, как можно -110
и , -010
чтобы получить --10
, но -110
и 011-
нельзя, так как -
' s не выровнены. -110
соответствует BCD', в то время как 011-
соответствует A'BC, а BCD' + A'BC не эквивалентно термину продукта.
Примечание: В этом примере ни один из терминов в таблице импликантов размера 4 не может быть объединен дальше. В общем случае этот процесс следует продолжать (размеры 8, 16 и т. д.) до тех пор, пока больше терминов не будет невозможно объединить.
Ни один из терминов не может быть объединен дальше этого, поэтому на этом этапе мы строим таблицу основных первичных импликантов. Вдоль стороны идут первичные импликанты, которые только что были сгенерированы (это те, которые были отмечены знаком " * " на предыдущем шаге), а вдоль верха идут минтермы, указанные ранее. Неважные термины не помещаются сверху — они опущены в этом разделе, поскольку они не являются необходимыми входными данными.
Чтобы найти существенные простые импликанты, мы ищем столбцы только с одним "✓". Если столбец имеет только один "✓", это означает, что минтерм может быть покрыт только одним простым импликантом. Этот простой импликант является существенным .
Например: в первом столбце с minterm 4 есть только один "✓". Это означает, что m(4,12) является существенным (поэтому отмечено # ). Minterm 15 также имеет только один "✓", поэтому m(10,11,14,15) также является существенным. Теперь все столбцы с одним "✓" покрыты. Строки с minterm m(4,12) и m(10,11,14,15) теперь можно удалить вместе со всеми столбцами, которые они покрывают.
Второй первичный импликант может быть «покрыт» третьим и четвертым, а третий первичный импликант может быть «покрыт» вторым и первым, и ни один из них не является существенным. Если первичный импликант является существенным, то, как и ожидалось, его необходимо включить в минимизированное булево уравнение. В некоторых случаях существенные первичные импликанты не покрывают все минтермы, в этом случае могут быть использованы дополнительные процедуры для сокращения диаграммы. Простейшая «дополнительная процедура» — это метод проб и ошибок, но более систематический способ — метод Петрика . В текущем примере существенные первичные импликанты не обрабатывают все минтермы, поэтому в этом случае существенные импликанты можно объединить с одним из двух несущественных, чтобы получить одно уравнение:
или
Оба этих окончательных уравнения функционально эквивалентны исходному подробному уравнению:
Псевдокод ниже рекурсивно вычисляет основные импликанты, учитывая список минтермов булевой функции. Он делает это, пытаясь объединить все возможные минтермы и отфильтровывая минтермы, которые были объединены, пока больше не будет возможности выполнить слияния минтермов и, следовательно, основные импликанты функции не будут найдены.
// Вычисляет основные импликанты из списка минтермов.// каждый минтерм имеет форму «1001», «1010» и т. д. и может быть представлен строкой.Функция getPrimeImplicants(список minterms) — это primeImplicants ← пустой список merges ← новый логический массив длины, равной количеству минтермов, каждый из которых установлен в false числоОбъединений ← 0 mergedMinterm, minterm1, minterm2 ← пустые строки для i = 0 до длины (minterms) сделать для c = i + 1 до длины (minterms) сделать minterm1 ← minterms[i] minterm2 ← minterms[c] // Проверка возможности объединения двух минтермов если CheckDashesAlign(minterm1, minterm2) && CheckMintermDifference(minterm1, minterm2) тогда mergedMinterm ← MergeMinterms(minterm1, minterm2) если primeImplicants не содержит mergedMinterm, то primeImplicants.Add(mergedMinterm) числоСлияний ← числоСлияний + 1 объединяет[i] ← верно объединяет[c] ← верно // Фильтрация всех минтермов, которые не были объединены, поскольку они являются первичными импликантами. Также удаляются дубликаты для j = 0 до length(minterms) сделать если merges[j] == false && primeImplicants не содержит minterms[j] тогда primeImplicants.Добавить(minterms[j]) // если слияний не произошло, то все основные импликанты найдены, поэтому возвращаем, в противном случае // продолжаем объединять минтермы. если numberOfmerges == 0, то вернуть primeImplicants , иначе вернуть getPrimeImplicants(primeImplicants)
В этом примере функции CheckDashesAlign
и CheckMintermDifference
выполняют необходимые проверки для определения возможности объединения двух минтермов. Функция MergeMinterms
объединяет минтермы и добавляет тире, где это необходимо. Вспомогательные функции ниже предполагают, что каждый минтерм будет представлен с использованием строк.
Функция MergeMinterms(minterm1, minterm2) — это mergedMinterm ← пустая строка для i = 0 до длины (minterm1) сделать //Если биты различаются, то замените их на тире, в противном случае бит останется в объединенном минтерме. если минтерм[i] != минтерм2[i] тогда объединенныйMinterm ← объединенныйMinterm + '-' еще объединенныйMinterm ← объединенныйMinterm + minterm1[i] вернуться объединенныйMintermФункция CheckDashesAlign(minterm1, minterm2) для i = 0 до length(minterm1) делает // Если в одном минтерме есть дефисы, а в другом — нет, то минтермы не могут быть объединены. если minterm1[i] != '-' && minterm2[i] == '-' тогда вернуть false вернуть trueФункция CheckMintermDifference(minterm1, minterm2) — это // minterm1 и minterm2 — это строки, представляющие все найденные в данный момент простые импликанты и объединенные // minterms. Примеры включают '01--' и '10-0' m1, m2 ← целочисленное представление minterm1 и minterm2 с удаленными дефисами, они заменены на 0 // ^ здесь побитовое XOR рез ← m1 ^ m2 вернуть рез != 0 && (рез & рез - 1) == 0
Приведенный ниже псевдокод можно разделить на две части:
Диаграмма первичной импликации может быть представлена словарем, где каждый ключ является первичной импликацией, а соответствующее значение является пустой строкой, которая будет хранить двоичную строку после завершения этого шага. Каждый бит в двоичной строке используется для представления отметок в диаграмме первичной импликации. Диаграмма первичной импликации может быть создана с помощью следующих шагов:
\d
символа. Это создает регулярное выражение, которое можно проверить по каждому из минтермов, ища совпадения."1"
к соответствующей строке в словаре. В противном случае добавить "0"
.Описанный выше алгоритм, записанный в псевдокоде, выглядит следующим образом:
функция CreatePrimeImplicantChart(список основных импликантов, список основных импликантов) primeImplicantChart ← новый словарь с ключом типа string и значением типа string // Создание пустой диаграммы с основными импликантами в качестве ключа и пустыми строками в качестве значения. для i = 0 до длины (primeImplicants) сделать // Добавляем новый первичный импликант в диаграмму. primeImplicantChart.Add(primeImplicants[i], "") для i = 0 до length(primeImplicantChart.Keys) сделать primeImplicant ← primeImplicantChart.Keys[i] // Преобразуем «-» в «\d», который можно использовать для поиска строки отметок выше. regularExpression ← Преобразовать в регулярное выражение (primeImplicant) для j = 0 до длины (минтермс) сделать // Если есть совпадение между регулярным выражением и минтермом, то добавляем 1, в противном случае 0. если regularExpression.соответствует(primeImplicant), то primeImplicantChart[primeImplicant] += "1" еще primeImplicantChart[primeImplicant] += "0" // Основная импликантная диаграмма завершена, поэтому возвращаем завершенную диаграмму. вернуть primeImplicantChart
Функция полезности, ConvertToRegularExpression
, используется для преобразования первичной импликанты в регулярное выражение для проверки совпадений между импликантой и минтермами.
функция ConvertToRegularExpression(строка primeImplicant) regularExpression ← новая строка для i = 0 до length(primeImplicant) сделать если primeImplicant[i] == "-" тогда // Добавьте буквенный символ "\d". регулярноеВыражение += @"\d"; вернуть регулярное выражение
Используя функцию, CreatePrimeImplicantChart
определенную выше, мы можем найти существенные простые импликанты, просто перебирая столбец за столбцом значения в словаре, и если "1"
найдено одно число, то найден существенный простой импликант.
[...] Если сведение [выражения к простейшей форме] не очевидно, его можно облегчить, взяв отрицательное выражение, сократив его, а затем восстановив его в положительной форме. [...]
[...] этот метод был известен
Пирсу
и его ученикам [...] Он упоминается в нескольких местах в «Исследованиях по логике» членов Университета
Джонса Хопкинса
, 1883 [...](ii+60 страниц)
[...] С удовольствием отмечаем, что эта обработка основана на работе двух студентов в период изучения коммутационных схем в Массачусетском технологическом институте. Они независимо друг от друга обсудили метод, а затем совместно подготовили классный меморандум: PW Abraham и JG Nordahl [...](xviii+686 страниц) (Примечание. Первый крупный трактат по десятичному методу в этой книге иногда ошибочно называют «десятичной табуляцией Колдуэлла».)
[...] Результаты этой статьи представлены в более доступной книге SH Caldwell [...]. В этой книге автор отдает должное Маллину и Келлнеру за разработку манипуляций с десятичными числами.(1 страница)
{{cite book}}
: CS1 maint: отсутствует местоположение издателя ( ссылка )(4 страницы) (Примечание. В некоторых источниках авторами указаны «П. У. Абрахам» и «И. Г. Нордаль», а название также упоминается как «Модифицированная процедура редукции Маккласки–Куайна».)[...] 1955 wurde das Verfahren auf die bequemere dezimale Schreibweise umgestellt (PW Авраам и И. Г. Нордаль в [Колдуэлле]). [...](Примечание. Существует также второе издание 1973 года.)
{{cite book}}
: CS1 maint: проигнорированы ошибки ISBN ( ссылка )(519 страниц) [5]