جدول کارنو و صورتهای DNF و CNF
از سطرهای درست جدول درستی، صورت متعارف فصلی (DNF) و عطفی (CNF) را میسازد و بعد مثل جدول کارنو، خانههای همسایه را ادغام میکند (روش کوین–مککلاسکی) تا سادهترین مجموع حاصلضربها به دست آید.
هر تابع بولی را میشود از روی جدول درستیاش نوشت:
ادامهی توضیح ↓- زمان:
O(3^n · n) for the prime implicants - حافظه:
O(3^n) - گریمالدی، فصل ۱۵
- جانسونباو، فصل ۱۱
تابعی از چهار متغیر با مینترمهای ۰، ۱، ۲، ۵، ۶، ۷، ۸، ۹، ۱۰، ۱۴؛ جدول کارنو آن را به سه جملهی کوتاه میرساند.
def karnaugh(M, n):# M: the minterms (rows of the truth table where f = 1) of a function of n variables a, b, c, d.ones = sorted(set(M[0]))for m in ones:if m >= 2 ** n:return Nonekmap = draw(ones, n)dnf = []cnf = []for m in range(2 ** n):if m in ones:dnf.append(term([m, 0], n, "∧"))else:cnf.append(clause(m, n))dnf_text = " ∨ ".join(dnf) if dnf else "0"cnf_text = " ∧ ".join(cnf) if cnf else "1"# Quine–McCluskey. An implicant is [value, mask]: the mask bits are the variables it no longer mentions.# Two implicants merge when they have the same mask and differ in one bit, as neighbouring K-map blocks do.current = [[m, 0] for m in ones]primes = []while current:merged = []used = []for i in range(len(current)):for j in range(i + 1, len(current)):a = current[i]b = current[j]x = a[0] ^ b[0]if a[1] != b[1] or x & (x - 1) != 0:continueused.append(a)used.append(b)both = [a[0] & ~x, a[1] | x]if both not in merged:merged.append(both)shown = term(both, n, "")for t in current:if t not in used and t not in primes:primes.append(t)shown = term(t, n, "")current = mergedtable = [] # for the picture: each prime implicant and the minterms it coverscover = []for p in primes:cover.append([m for m in ones if m & ~p[1] == p[0]])table.append([term(p, n, ""), cover[-1]])chosen = []for m in ones:holders = [k for k in range(len(primes)) if m in cover[k]]if len(holders) == 1 and holders[0] not in chosen:chosen.append(holders[0])shown = table[holders[0]][0]left = [m for m in ones if not any(m in cover[k] for k in chosen)]while left:best = 0for k in range(len(primes)):if len(set(cover[k]) & set(left)) > len(set(cover[best]) & set(left)):best = kchosen.append(best)left = [m for m in left if m not in cover[best]]shown = table[best][0]minimal = " ∨ ".join(table[k][0] for k in chosen) if chosen else "0"return minimaldef term(p, n, op):parts = []for i in range(n):bit = 1 << (n - 1 - i)if p[1] & bit:continueparts.append("abcd"[i] if p[0] & bit else "¬" + "abcd"[i])if not parts:return "1"return op.join(parts)def clause(m, n):parts = []for i in range(n):bit = 1 << (n - 1 - i)parts.append("¬" + "abcd"[i] if m & bit else "abcd"[i])return "(" + " ∨ ".join(parts) + ")"def draw(ones, n):# Rows and columns in Gray-code order, so neighbouring cells differ in one variable (and the edges wrap around).gray = {1: ["0", "1"], 2: ["00", "01", "11", "10"]}rbits = n // 2cbits = n - rbitsrows = [["·"] + gray[cbits]]for r in gray[rbits]:row = [r]for c in gray[cbits]:row.append("1" if int(r + c, 2) in ones else "0")rows.append(row)return rows
شروع اجرا
kmap
جدول هنوز خالی است.
table
جدول هنوز خالی است.
متغیرهای محلی
نارنجی = در همین گام عوض شد
M list
Call stack
- karnaugh()خط 1
توضیح
صورتهای متعارف
هر تابع بولی را میشود از روی جدول درستیاش نوشت:
- DNF متعارف (مجموع مینترمها): برای هر سطری که تابع ۱ است، یک حاصلضرب از همهی متغیرها (یا نقیضشان).
- CNF متعارف (حاصلضرب ماکسترمها): برای هر سطری که تابع ۰ است، یک بند «یا» که دقیقاً در آن سطر نادرست است.
این صورتها درستاند ولی طولانی.
جدول کارنو
جدول کارنو همان جدول درستی است که سطر و ستونش به ترتیب کد گری چیده شدهاند، پس خانههای همسایه (حتی از لبهها) در یک متغیر فرق دارند. هر بلوک مستطیلی از ۱ها با اندازهی توانی از ۲ یک جمله با متغیرهای کمتر است. هدف: کمترین و بزرگترین بلوکها برای پوشاندن همهی ۱ها.
کوین–مککلاسکی
همین کار به شکل الگوریتمی: ایمپلیکنتهایی را که در یک متغیر فرق دارند ادغام کن (0101 و 0111 → 01-1) تا دیگر چیزی ادغام نشود؛ آنهایی که ادغام نشدند ایمپلیکنت اولاند. بعد ایمپلیکنتهای ضروری را بردار و بقیه را با انتخاب حریصانه بپوشان (پوشش بهینه در حالت کلی سخت است).
ورودی
M شمارهی سطرهایی است که تابع در آنها ۱ است (a پرارزشترین بیت)، و n تعداد متغیرها. جدول اول نقشهی کارنو است (سطرها a یا ab، ستونها بقیه) و جدول دوم ایمپلیکنتهای اول با مینترمهایی که میپوشانند.