جدول درستی
برای هر مقداردهی متغیرها، ارزش هر زیرفرمول را از داخل به بیرون حساب میکند و در پایان میگوید فرمول همیشه درست (راستگو)، همیشه نادرست (تناقض) یا گاهی درست است.
ارزش یک فرمول گزارهای فقط به ارزش متغیرهایش بستگی دارد. با n متغیر، 2^n مقداردهی هست؛ جدول درستی برای هر کدام یک سطر دارد.
- زمان:
O(2^n · size) - حافظه:
O(2^n · size) for the whole table - گریمالدی، فصل ۲
- جانسونباو، فصل ۱
(p → q) ↔ (¬q → ¬p): یک شرطی با عکس نقیضش همارز است؛ هر چهار سطر درستاند: راستگو.
class Node:def __init__(self, op, left, right, text):self.op = opself.left = leftself.right = rightself.text = text # how the subformula is writtendef truth_table(formula):root = parse(formula)if root is None:return Nonenames = []columns = []collect(root, names, columns)names.sort()header = names + [c.text for c in columns]rows = [header]trues = 0for m in range(2 ** len(names)):env = {}for i in range(len(names)):env[names[i]] = (m >> (len(names) - 1 - i)) % 2 == 1row = []for name in names:row.append("T" if env[name] else "F")for c in columns:env[c.text] = value(c, env)row.append("T" if env[c.text] else "F")rows.append(row)last = env[root.text]if last:trues = trues + 1if trues == 2 ** len(names):kind = "tautology"elif trues == 0:kind = "contradiction"else:kind = "contingent"return kinddef value(c, env):# Each column only reads columns to its left: its operands were filled in first.if c.op == "¬":return not env[c.right.text]a = env[c.left.text]b = env[c.right.text]if c.op == "∧":return a & bif c.op == "∨":return a | bif c.op == "→":return (not a) | breturn a == bdef collect(node, names, columns):# Postorder, so every column comes after the columns it depends on; a repeated subformula gets one column.if node.op == "var":if node.text not in names:names.append(node.text)returnif node.left is not None:collect(node.left, names, columns)collect(node.right, names, columns)for c in columns:if c.text == node.text:returncolumns.append(node)def parse(text):# ~ not, & and, | or, > implies, = if and only if; from tightest to loosest. > groups to the right.toks = []for c in text:if c != " ":toks.append(c)pos = [0]root = parse_binary(toks, pos, 0)if root is None or pos[0] != len(toks):return Nonereturn rootLEVELS = [["=", "↔"], [">", "→"], ["|", "∨"], ["&", "∧"]]def parse_binary(toks, pos, level):if level == len(LEVELS):return parse_not(toks, pos)sym, op = LEVELS[level]left = parse_binary(toks, pos, level + 1)while left is not None and pos[0] < len(toks) and toks[pos[0]] == sym:pos[0] += 1right = parse_binary(toks, pos, level if sym == ">" else level + 1)if right is None:return Noneleft = Node(op, left, right, "(" + left.text + " " + op + " " + right.text + ")")return leftdef parse_not(toks, pos):if pos[0] >= len(toks):return Nonec = toks[pos[0]]pos[0] += 1if c == "~":inner = parse_not(toks, pos)if inner is None:return Nonereturn Node("¬", None, inner, "¬" + inner.text)if c == "(":inner = parse_binary(toks, pos, 0)if inner is None or pos[0] >= len(toks) or toks[pos[0]] != ")":return Nonepos[0] += 1return innerif c.isalpha():return Node("var", None, None, c)return None
شروع اجرا
جدول هنوز خالی است.
درخت فراخوانیهای بازگشتی
نارنجی پر = فراخوانی در حال اجرا · حاشیهی نارنجی = هنوز روی پشته · خاکستری = تمام شده
متغیرهای محلی
نارنجی = در همین گام عوض شد
Call stack
- truth_table()خط 9
توضیح
ایده
ارزش یک فرمول گزارهای فقط به ارزش متغیرهایش بستگی دارد. با n متغیر، 2^n مقداردهی هست؛ جدول درستی برای هر کدام یک سطر دارد.
برای خوانا بودن، به جز ستون متغیرها، برای هر زیرفرمول هم یک ستون میگذاریم، از داخلیترین به بیرونیترین. هر ستون فقط به ستونهای قبل از خودش نیاز دارد.
عملگرها
| نماد ورودی | عملگر | درست است وقتی |
|---|---|---|
| ~ | ¬ | عملوند نادرست باشد |
| & | ∧ | هر دو درست باشند |
| \| | ∨ | حداقل یکی درست باشد |
| > | → | مقدم نادرست یا تالی درست باشد |
| = | ↔ | هر دو همارزش باشند |
دستهبندی
- راستگو (tautology): همهی سطرها درست؛ مثلاً قاعدههای استنتاج.
- تناقض: هیچ سطری درست نیست.
- ممکن (contingent): بعضی سطرها.
دو فرمول همارزند اگر A ↔ B راستگو باشد.
ورودی
متغیرها p، q، r و s اند. ~ از همه قویتر و = از همه ضعیفتر است؛ > از راست گروهبندی میشود.