AlgoVerse

جدول درستی

برای هر مقداردهی متغیرها، ارزش هر زیرفرمول را از داخل به بیرون حساب می‌کند و در پایان می‌گوید فرمول همیشه درست (راستگو)، همیشه نادرست (تناقض) یا گاهی درست است.

ارزش یک فرمول گزاره‌ای فقط به ارزش متغیرهایش بستگی دارد. با n متغیر، 2^n مقداردهی هست؛ جدول درستی برای هر کدام یک سطر دارد.

ادامه‌ی توضیح ↓
ورودی:
formula="(p>q)=(~q>~p…"خروجی PDF

(p → q) ↔ (¬q → ¬p): یک شرطی با عکس نقیضش هم‌ارز است؛ هر چهار سطر درست‌اند: راستگو.

  1. class Node:
  2. def __init__(self, op, left, right, text):
  3. self.op = op
  4. self.left = left
  5. self.right = right
  6. self.text = text # how the subformula is written
  7. def truth_table(formula):
  8. root = parse(formula)
  9. if root is None:
  10. return None
  11. names = []
  12. columns = []
  13. collect(root, names, columns)
  14. names.sort()
  15. header = names + [c.text for c in columns]
  16. rows = [header]
  17. trues = 0
  18. for m in range(2 ** len(names)):
  19. env = {}
  20. for i in range(len(names)):
  21. env[names[i]] = (m >> (len(names) - 1 - i)) % 2 == 1
  22. row = []
  23. for name in names:
  24. row.append("T" if env[name] else "F")
  25. for c in columns:
  26. env[c.text] = value(c, env)
  27. row.append("T" if env[c.text] else "F")
  28. rows.append(row)
  29. last = env[root.text]
  30. if last:
  31. trues = trues + 1
  32. if trues == 2 ** len(names):
  33. kind = "tautology"
  34. elif trues == 0:
  35. kind = "contradiction"
  36. else:
  37. kind = "contingent"
  38. return kind
  39. def value(c, env):
  40. # Each column only reads columns to its left: its operands were filled in first.
  41. if c.op == "¬":
  42. return not env[c.right.text]
  43. a = env[c.left.text]
  44. b = env[c.right.text]
  45. if c.op == "∧":
  46. return a & b
  47. if c.op == "∨":
  48. return a | b
  49. if c.op == "→":
  50. return (not a) | b
  51. return a == b
  52. def collect(node, names, columns):
  53. # Postorder, so every column comes after the columns it depends on; a repeated subformula gets one column.
  54. if node.op == "var":
  55. if node.text not in names:
  56. names.append(node.text)
  57. return
  58. if node.left is not None:
  59. collect(node.left, names, columns)
  60. collect(node.right, names, columns)
  61. for c in columns:
  62. if c.text == node.text:
  63. return
  64. columns.append(node)
  65. def parse(text):
  66. # ~ not, & and, | or, > implies, = if and only if; from tightest to loosest. > groups to the right.
  67. toks = []
  68. for c in text:
  69. if c != " ":
  70. toks.append(c)
  71. pos = [0]
  72. root = parse_binary(toks, pos, 0)
  73. if root is None or pos[0] != len(toks):
  74. return None
  75. return root
  76. LEVELS = [["=", "↔"], [">", "→"], ["|", "∨"], ["&", "∧"]]
  77. def parse_binary(toks, pos, level):
  78. if level == len(LEVELS):
  79. return parse_not(toks, pos)
  80. sym, op = LEVELS[level]
  81. left = parse_binary(toks, pos, level + 1)
  82. while left is not None and pos[0] < len(toks) and toks[pos[0]] == sym:
  83. pos[0] += 1
  84. right = parse_binary(toks, pos, level if sym == ">" else level + 1)
  85. if right is None:
  86. return None
  87. left = Node(op, left, right, "(" + left.text + " " + op + " " + right.text + ")")
  88. return left
  89. def parse_not(toks, pos):
  90. if pos[0] >= len(toks):
  91. return None
  92. c = toks[pos[0]]
  93. pos[0] += 1
  94. if c == "~":
  95. inner = parse_not(toks, pos)
  96. if inner is None:
  97. return None
  98. return Node("¬", None, inner, "¬" + inner.text)
  99. if c == "(":
  100. inner = parse_binary(toks, pos, 0)
  101. if inner is None or pos[0] >= len(toks) or toks[pos[0]] != ")":
  102. return None
  103. pos[0] += 1
  104. return inner
  105. if c.isalpha():
  106. return Node("var", None, None, c)
  107. return None

ناوردا: هر ستون فقط از ستون‌های سمت چپش استفاده می‌کند؛ پس وقتی به آن می‌رسیم، عملوندهایش پر شده‌اند.

شروع اجرا

trues—
kind—

جدول هنوز خالی است.

درخت فراخوانی‌های بازگشتی

نارنجی پر = فراخوانی در حال اجرا · حاشیه‌ی نارنجی = هنوز روی پشته · خاکستری = تمام شده

متغیرهای محلی

formula'(p>q)=(~q>~p)'

نارنجی = در همین گام عوض شد

Call stack

  1. truth_table()خط 9
گام ۱ از ۶۵۵
خط سیاه = row · خط نارنجی = گام کلیدیcolumns: 0/1 · row: 0/4 · tautology: 0/1
    توضیح

    ایده

    ارزش یک فرمول گزاره‌ای فقط به ارزش متغیرهایش بستگی دارد. با n متغیر، 2^n مقداردهی هست؛ جدول درستی برای هر کدام یک سطر دارد.

    برای خوانا بودن، به جز ستون متغیرها، برای هر زیرفرمول هم یک ستون می‌گذاریم، از داخلی‌ترین به بیرونی‌ترین. هر ستون فقط به ستون‌های قبل از خودش نیاز دارد.

    عملگرها

    | نماد ورودی | عملگر | درست است وقتی | |---|---|---| | ~ | ¬ | عملوند نادرست باشد | | & | ∧ | هر دو درست باشند | | \| | ∨ | حداقل یکی درست باشد | | > | → | مقدم نادرست یا تالی درست باشد | | = | ↔ | هر دو هم‌ارزش باشند |

    دسته‌بندی

    • راستگو (tautology): همه‌ی سطرها درست؛ مثلاً قاعده‌های استنتاج.
    • تناقض: هیچ سطری درست نیست.
    • ممکن (contingent): بعضی سطرها.

    دو فرمول هم‌ارزند اگر A ↔ B راستگو باشد.

    ورودی

    متغیرها p، q، r و s اند. ~ از همه قوی‌تر و = از همه ضعیف‌تر است؛ > از راست گروه‌بندی می‌شود.