Foundationপ্রথম নীতি থেকে
LEVEL 0লেসন ২/১৬মাঝারি৫৫ মিনিট

Propositional Logic — সত্য-মিথ্যার বীজগণিত

Propositional Logic

Proposition, connective আর truth table — যে ভাষায় একটা `if` statement, একটা SQL WHERE clause আর CPU-র ভেতরের একটা AND gate সবাই একই জিনিস।

এই লেসন শেষে আপনি পারবেন

  • Proposition কী আর কী নয় সেটা আলাদা করতে পারবেন
  • পাঁচটা মৌলিক connective (¬, ∧, ∨, →, ↔) -এর truth table মুখস্থ নয়, বুঝে ব্যবহার করতে পারবেন
  • Implication কেন `F → T = T` সেটা ব্যাখ্যা করতে পারবেন
  • যেকোনো compound proposition-এর truth table নিজে বানাতে পারবেন
  • কোড-এর boolean expression দেখে তার logical structure চিনতে পারবেন

আগে যা বোঝা থাকা দরকার

আগে এটা বুঝি

আপনি হাজারবার এটা লিখেছেন:

if (user != NULL && user->is_active && !user->is_banned) {
    grant_access();
}

কিন্তু কখনো ভেবেছেন — এই লাইনটা আসলে কী? এটা একটা গাণিতিক বাক্য&& মানে conjunction, ! মানে negation, আর পুরোটা মিলে একটা proposition — এমন একটা দাবি যা হয় সত্য, নয় মিথ্যা।

এখন আসল প্রশ্ন: এই শর্তটা কি ঠিক? Attacker কি এমন কোনো অবস্থা বানাতে পারবে যেখানে grant_access() চলে যাওয়ার কথা না, তবু চলে যায়?

এই প্রশ্নের উত্তর “চালিয়ে দেখি” দিয়ে দেওয়া যায় না। এর উত্তর দিতে হলে আপনাকে সব সম্ভাব্য combination বিবেচনা করতে হবে। তিনটা variable মানে আটটা combination — সেগুলো সাজিয়ে ফেলার নাম truth table

আর এটাই propositional logic: সত্য-মিথ্যা নিয়ে হিসাব করার নিয়মতান্ত্রিক পদ্ধতি।

মূল ধারণা

Proposition কী

Proposition হলো এমন একটা declarative বাক্য যার একটা নির্দিষ্ট সত্যমান আছে — হয় true, নয় false। দুটোই একসাথে না, কোনোটাই না — এমনও না।

বাক্যProposition?কেন
“২ + ২ = ৪”✅ হ্যাঁ (T)নির্দিষ্টভাবে সত্য
“২ + ২ = ৫”✅ হ্যাঁ (F)নির্দিষ্টভাবে মিথ্যা
“ঢাকা বাংলাদেশের রাজধানী”✅ হ্যাঁ (T)যাচাইযোগ্য
“দরজাটা বন্ধ করো”❌ নাআদেশ, দাবি নয়
“এখন কয়টা বাজে?”❌ নাপ্রশ্ন
x > 5❌ না (এখনো)x-এর মান না জানলে সত্যমান নেই
“এই বাক্যটা মিথ্যা”❌ নাস্ববিরোধী (liar paradox)

শেষ দুটো গুরুত্বপূর্ণ।

x > 5 কে বলে predicate — variable-সহ একটা টেমপ্লেট। x-এ একটা নির্দিষ্ট মান বসালে সেটা proposition হয়ে যায়। Predicate নিয়ে আমরা আলাদা লেসনে কাজ করব।

আর liar paradox দেখায় যে সব ভাষার বাক্যকে সত্য/মিথ্যা বলা যায় না — এই ফাটলটাই পরে Gödel-এর incompleteness theorem আর halting problem-এ গিয়ে বিস্ফোরিত হবে (Level 13)।

পাঁচটা connective

ছোট proposition জোড়া লাগিয়ে বড় proposition বানানোর operator-গুলোকে বলে logical connective

নামচিহ্নকোডেপড়েসত্য কখন
Negation¬p!p“p নয়”p মিথ্যা হলে
Conjunctionp ∧ qp && q“p এবং q”দুটোই সত্য হলে
Disjunctionp ∨ qp || q“p অথবা q”অন্তত একটা সত্য হলে
Implicationp → q“p হলে q”p সত্য অথচ q মিথ্যা — কেবল এই ক্ষেত্রেই মিথ্যা
Biconditionalp ↔ qp == q“p যদি এবং কেবল যদি q”দুটোর মান এক হলে

এই পাঁচটার truth table:

pq¬pp ∧ qp ∨ qp → qp ↔ q
FFTFFTT
FTTFTTF
TFFFTFF
TTFTTTT

চারটা connective স্বাভাবিক মনে হয়। পঞ্চমটা — implication — প্রায় সবাইকে প্রথমবার ধাক্কা দেয়। সেটা নিয়ে আলাদা করে কথা বলি।

Implication কেন এমন অদ্ভুত

p → q-এর truth table-এর প্রথম দুই সারিতে p মিথ্যা, তবু পুরোটা সত্য। কেন?

একটা প্রতিশ্রুতি ভাবুন:

“পরীক্ষায় A+ পেলে তোমাকে ফোন কিনে দেব।”

কখন বলবেন আমি মিথ্যা বলেছি?

A+ পেয়েছে (p)ফোন দিয়েছি (q)আমি মিথ্যাবাদী?
নানানা — শর্তই তো পূরণ হয়নি
নাহ্যাঁনা — বাড়তি দিয়েছি, প্রতিশ্রুতি ভাঙিনি
হ্যাঁনাহ্যাঁ — এটাই একমাত্র বিশ্বাসঘাতকতা
হ্যাঁহ্যাঁনা — কথা রেখেছি

ঠিক এটাই p → q-এর table। প্রতিশ্রুতি ভাঙে কেবল যখন শর্ত পূরণ হয়েছে অথচ প্রতিশ্রুত জিনিস দেওয়া হয়নি।

শর্তই যদি পূরণ না হয়, তাহলে প্রতিশ্রুতির কোনো পরীক্ষাই হলো না — তাই সেটা “ভাঙা হয়নি”, অর্থাৎ সত্য। একে বলে vacuous truth

ভেতরে কী ঘটছে

Precedence — কে আগে বাঁধে

গণিতে যেমন 2 + 3 × 4 মানে 2 + (3 × 4), logic-এও তেমন precedence আছে:

সবচেয়ে শক্ত  ¬     (negation)
             ∧     (and)
             ∨     (or)
             →     (implies)
সবচেয়ে ঢিলা  ↔     (iff)

তাই:

¬p ∨ q ∧ r  →  s

আসলে মানে:

((¬p) ∨ (q ∧ r)) → s

এবং implication right-associative: p → q → r মানে p → (q → r), (p → q) → r নয়। এই দুটো আলাদা জিনিস — নিজে truth table বানিয়ে দেখুন।

Truth table কীভাবে বানাবেন

নিয়মটা যান্ত্রিক:

  1. n টা variable থাকলে 2^n টা row বানান
  2. Variable column-গুলো এমনভাবে ভরুন যাতে সব combination আসে — সবচেয়ে সহজ উপায়: প্রতিটা row-কে একটা binary সংখ্যা ভাবুন (0 থেকে 2^n − 1)
  3. ভেতরের ছোট sub-expression-গুলোর জন্য মধ্যবর্তী column বানান
  4. শেষে পুরো expression-এর column

উদাহরণ: (p ∧ ¬q) → r

#pqr¬qp ∧ ¬q(p ∧ ¬q) → r
0FFFTFT
1FFTTFT
2FTFFFT
3FTTFFT
4TFFTTF
5TFTTTT
6TTFFFT
7TTTFFT

আটটা row-এর মধ্যে মাত্র একটাতে (row 4) পুরো expression মিথ্যা।

খেয়াল করুন row-এর নম্বরটাই binary-তে p q r-এর মান: row 4 = 100 = p সত্য, q মিথ্যা, r মিথ্যা। এই সম্পর্কটা Level 1-এ binary শেখার সময় আবার ফিরে আসবে।

এই logic-টা hardware-এ কোথায়

এখানেই propositional logic শুধু গণিত থাকে না।

একটা `&&` কোথায় গিয়ে শেষ হয়
  1. if (a && b)C source — আপনি যা লেখেন
  2. test / and / jzcompiler এটাকে machine instruction-এ ভাঙে
  3. ALU-র AND unitCPU-র ভেতরে একটা নির্দিষ্ট circuit
  4. AND gate arrayপ্রতি bit-এর জন্য একটা gate
  5. দুইটা transistor সিরিজেCMOS-এ AND = NAND + NOT
  6. Electron প্রবাহদুই gate-ই খোলা থাকলেই কারেন্ট যায়

আপনি যে লিখছেন খাতায়, CPU সেটা করছে দুইটা transistor সিরিজে বসিয়ে — দুটোই “on” হলে তবেই কারেন্ট পার হয়। গণিতটাই hardware, hardware-টাই গণিত।

Level 2-এ আমরা এই gate-গুলো নিজে বানাব। আপাতত নিচে খেলে দেখুন — এটা সেই একই truth table, কিন্তু circuit হিসেবে:

SIMULATOR

Half Adder

InputsOutputsSum0Carry0
0A0BXORAND0Sum0Carry
ABSumCarry
0000
0110
1010
1101
দুইটা bit যোগ করে sum আর carry দেয়। XOR = sum, AND = carry। এটাই ALU-র প্রথম ইট।
টেবিলের যেকোনো row-তে ক্লিক করলে circuit সেই input-এ চলে যাবে।

Half adder দুইটা bit যোগ করে। খেয়াল করুন — Sum আসলে XOR, Carry আসলে AND। অর্থাৎ “যোগ করা” জিনিসটা propositional logic ছাড়া আর কিছুই না।

উদাহরণ

শুরুর কোডটায় ফিরে যাই

if (user != NULL && user->is_active && !user->is_banned) {
    grant_access();
}

ধরি:

  • n = “user pointer NULL নয়”
  • a = “user active”
  • b = “user banned”

শর্তটা হলো: n ∧ a ∧ ¬b

nabn ∧ a ∧ ¬baccess?
FFFFনা
FFTFনা
FTFFনা
FTTFনা
TFFFনা
TFTFনা
TTFTহ্যাঁ
TTTFনা

আটটা ক্ষেত্রের মধ্যে ঠিক একটাতে access দেওয়া হচ্ছে — সেটা ঠিক সেই ক্ষেত্র যেটা আমরা চেয়েছিলাম। শর্তটা সঠিক। এটা এখন আর অনুমান নয়, যাচাই করা।

এবার একটা ভুল শর্ত

ধরুন কেউ লিখল:

if (user != NULL && user->is_active || !user->is_banned) {
    grant_access();   // ⚠ bug
}

&&-এর precedence ||-এর চেয়ে বেশি, তাই এটা আসলে:

(n ∧ a) ∨ ¬b
nabn ∧ a¬b(n ∧ a) ∨ ¬b
FFFFTT
FFTFFF
FTFFTT
FTTFFF
TFFFTT
TFTFFF
TTFTTT
TTTTFT

চারটা row-তে access দেওয়া হচ্ছে যেখানে দেওয়ার কথা না। সবচেয়ে ভয়ানকটা প্রথম row: user NULL, তবু access granted — কারণ NULL user “banned” নয়। পরের লাইনেই user->something করলে segfault, আর তার আগে হয়তো কোনো privileged কাজ হয়ে গেছে।

নিজে চালিয়ে দেখুন

EXPERIMENT

Short-circuit evaluation নিজে ধরুন

Python 3· ১০ মিনিট
def loud(name, value):
    print(f"  → {name} evaluate হলো")
    return value

print("Case 1: False and ...")
r = loud("A", False) and loud("B", True)
print("result:", r)

print("\nCase 2: True or ...")
r = loud("A", True) or loud("B", False)
print("result:", r)

print("\nCase 3: True and ...")
r = loud("A", True) and loud("B", False)
print("result:", r)

চালানোর আগে নিজে লিখে রাখুন কোন কোন লাইন ছাপা হবে। তারপর চালান।

Output:

Case 1: False and ...
  → A evaluate হলো
result: False

Case 2: True or ...
  → A evaluate হলো
result: True

Case 3: True and ...
  → A evaluate হলো
  → B evaluate হলো
result: False

Case 1 আর 2-এ B কখনো চলেইনি। কারণ:

  • F ∧ ? — table দেখুন, প্রথম column F হলে ফল সবসময় F। ডান পাশ দেখার দরকার নেই।
  • T ∨ ? — প্রথমটা T হলে ফল সবসময় T।

এবার এই বহুল ব্যবহৃত pattern-টা দেখুন:

if user is not None and user.is_active:
    ...

user যদি None হয়, user.is_active কখনো চলবে না — তাই AttributeError হবে না। এই নিরাপত্তাটা পুরোপুরি short-circuit-এর উপর দাঁড়ানো। ক্রম উল্টে দিলে crash।

C-তে একই জিনিস, কিন্তু bitwise & আর | short-circuit করে না:

// নিরাপদ — short circuits
if (p != NULL && p->x > 0) { ... }

// অনিরাপদ — & সবসময় দুই পাশই evaluate করে → NULL deref
if (p != NULL & p->x > 0) { ... }
এটা কী প্রমাণ করে

`&&` আর `||` শুধু logical operator না — এরা control flow-ও। ডান পাশ কখনো চলবে কি না সেটা বাঁ পাশের মানের উপর নির্ভর করে। এটা না জানলে side-effect-যুক্ত কোডে অদৃশ্য bug তৈরি হয়।

EXPERIMENT

SQL-এ logic তিন-মানের

PostgreSQL (বা যেকোনো SQL)· ১০ মিনিট
SELECT
  NULL = NULL          AS "NULL = NULL",
  NULL IS NULL         AS "NULL IS NULL",
  TRUE  OR  NULL       AS "T or NULL",
  FALSE OR  NULL       AS "F or NULL",
  TRUE  AND NULL       AS "T and NULL",
  FALSE AND NULL       AS "F and NULL";

ফলাফল:

 NULL = NULL | NULL IS NULL | T or NULL | F or NULL | T and NULL | F and NULL
-------------+--------------+-----------+-----------+------------+------------
 [null]      | t            | t         | [null]    | [null]     | f

লক্ষ্য করুন NULL = NULL সত্যও নয়, মিথ্যাও নয় — NULL। কারণ SQL-এ NULL মানে “মান জানি না”। দুইটা অজানা মান সমান কি না — সেটাও অজানা।

কিন্তু TRUE OR NULL = TRUE, কারণ বাঁ পাশ সত্য হলে ডান পাশ যাই হোক ফল সত্য। আর FALSE AND NULL = FALSE, একই কারণে।

যেখানে এটা কামড়ায়:

-- ভুল: NULL status-ওয়ালা row কখনো আসবে না
SELECT * FROM orders WHERE status != 'shipped';

-- ঠিক
SELECT * FROM orders WHERE status IS DISTINCT FROM 'shipped';

WHERE clause শুধু TRUE row রাখে। NULL row বাদ পড়ে যায় নীরবে — কোনো error নেই, শুধু কম row। Level 8-এ database-এ এটা বিস্তারিত দেখব।

এটা কী প্রমাণ করে

সব জায়গায় logic দুই-মানের নয়। SQL-এ NULL মানে 'অজানা', আর অজানা নিয়ে হিসাব করতে তিন-মানের logic লাগে। এটা না জানলে WHERE clause নীরবে ভুল ফল দেয়।

নিজে বানান

BUILD IT

Truth Table Evaluator — ৩০ লাইনে

Python · ●●○○○
  1. একটা expression string আর variable-এর তালিকা নিন
  2. itertools.product দিয়ে 2^n টা assignment বানান
  3. প্রতিটা assignment-এ expression evaluate করুন
  4. ছেপে দিন, আর tautology/contradiction/contingency বলুন

শুরুতে Python-এর নিজের eval ব্যবহার করছি — parser নিজে লেখাটা Truth Table Generator প্রজেক্টে করবেন।

from itertools import product

def truth_table(expr, variables):
    """expr: Python boolean expression string, e.g. '(p and not q) or r'"""
    header = variables + [expr]
    widths = [max(len(h), 5) for h in header]

    print(" | ".join(h.ljust(w) for h, w in zip(header, widths)))
    print("-+-".join("-" * w for w in widths))

    results = []
    for combo in product([False, True], repeat=len(variables)):
        env = dict(zip(variables, combo))
        value = eval(expr, {"__builtins__": {}}, env)
        results.append(value)
        row = [("T" if v else "F") for v in combo] + [("T" if value else "F")]
        print(" | ".join(c.ljust(w) for c, w in zip(row, widths)))

    if all(results):
        verdict = "TAUTOLOGY — সব ক্ষেত্রেই সত্য"
    elif not any(results):
        verdict = "CONTRADICTION — কোনো ক্ষেত্রেই সত্য নয়"
    else:
        verdict = f"CONTINGENCY — {sum(results)}/{len(results)} ক্ষেত্রে সত্য"
    print("\n" + verdict)
    return results


truth_table("p or not p",            ["p"])
truth_table("(p and q) or (not p)",  ["p", "q"])
truth_table("(not p) or q",          ["p", "q"])   # এটাই p → q

নিজে যোগ করুন:

  1. implies(p, q) helper — (not p) or q
  2. দুইটা expression একই কি না বলার function (দুটোর result list মিলিয়ে দেখুন)
  3. xorp != q
  4. এই তিনটা tautology কি না যাচাই করুন:
    • (p → q) ↔ (¬q → ¬p) — contrapositive
    • ¬(p ∧ q) ↔ (¬p ∨ ¬q) — De Morgan
    • ((p → q) ∧ (q → r)) → (p → r) — hypothetical syllogism

বাস্তব সিস্টেমে

এই logic বাস্তবে কোথায় চলছে

Compiler optimization. GCC/LLVM আপনার লেখা শর্তকে logically equivalent কিন্তু দ্রুততর রূপে বদলে দেয়। if (!(a || b)) কে if (!a && !b) বানানো — এটা De Morgan’s law, যেটা পরের লেসনে দেখব। Compiler প্রতিদিন লক্ষ লক্ষবার এই বীজগণিত করে।

Database query planner. PostgreSQL আপনার WHERE clause-কে CNF-এ রূপান্তর করে, তারপর দেখে কোন অংশটা index দিয়ে সমাধান করা যায়। WHERE (a = 1 AND b = 2) OR (a = 1 AND c = 3) কে WHERE a = 1 AND (b = 2 OR c = 3) বানালে a-এর index ব্যবহার করা যায়।

Static analysis আর verification. Clang analyzer, Infer, বা Coverity যখন বলে “this branch is always false”, সেটা propositional reasoning। Formal verification tool (TLA+, Dafny) পুরো proof-টা automated করে।

SAT solver. “এই boolean formula সত্য করা যায় এমন কোনো assignment আছে কি?” — এই প্রশ্নটাই SAT, প্রথম প্রমাণিত NP-complete সমস্যা (Level 13)। আর তবু আধুনিক SAT solver লক্ষ variable-এর formula মিনিটে সমাধান করে। এগুলো ব্যবহার হয় hardware verification-এ (Intel প্রতিটা chip design verify করে SAT দিয়ে), package dependency resolution-এ (apt, cargo, npm এর ভেতরে SAT solver আছে), আর program analysis-এ।

Access control. AWS IAM policy, Kubernetes RBAC, firewall rule — সবই মূলত বড় boolean expression। “এই request কি অনুমোদিত?” প্রশ্নের উত্তর একটা truth table evaluation।

Digital circuit. সবচেয়ে সরাসরি প্রয়োগ — Level 2-তে দেখব যে একটা CPU আক্ষরিক অর্থেই কোটি কোটি gate দিয়ে বানানো boolean function।

যে ভুলগুলো সবাই করে

“`p → q` মানে p, q-এর কারণ (cause)।”

না। Implication কার্যকারণ (causation) নিয়ে কিছু বলে না, শুধু সত্যমানের সম্পর্ক নিয়ে বলে।

“যদি ২ + ২ = ৫ হয়, তাহলে চাঁদ পনিরের তৈরি” — এটা সত্য implication, কারণ শর্তটা মিথ্যা। এখানে কোনো কার্যকারণ নেই, তবু logically সত্য।

গণিতে এটা কাজে লাগে: n জোড় হলে জোড় — এই দাবি প্রমাণ করতে বিজোড় n-এর ক্ষেত্রে কিছু বলার দরকার নেই, কারণ সেখানে implication এমনিতেই সত্য।

“`∨` মানে 'হয় এটা নয় ওটা' — দুটো একসাথে নয়।”

প্রাত্যহিক বাংলায় “চা নেবেন নাকি কফি?” মানে সাধারণত একটা। কিন্তু logic-এ হলো inclusive or — দুটোই সত্য হলেও ফল সত্য।

“হয় এটা নয় ওটা, দুটো নয়” — সেটা XOR (), আলাদা operator: p ⊕ q ≡ (p ∨ q) ∧ ¬(p ∧ q)

কোডে || inclusive, আর != (boolean-এ) exclusive।

“Truth table বানানো একটা academic ব্যায়াম, বাস্তবে কেউ করে না।”

হাতে ৩২-row table বানানো বাস্তবে করে না — কিন্তু যন্ত্র করে, অবিরাম।

প্রতিটা compiler optimization pass, প্রতিটা query planner, প্রতিটা static analyzer, প্রতিটা model checker — সবাই এই কাজটাই করছে, শুধু আরো চতুর algorithm দিয়ে (BDD, DPLL, CDCL)।

আপনার হাতে করার উদ্দেশ্য হলো যন্ত্রটা কী করছে সেটা বোঝা — আর যখন সেটা অপ্রত্যাশিত কিছু করে, তখন কেন করছে সেটা ধরতে পারা।

“`&&` আর `&` একই জিনিস, একটা শুধু ছোট লেখা।”

সম্পূর্ণ আলাদা।

&& হলো logical AND — short-circuit করে, ফল boolean। & হলো bitwise AND — দুই পাশই evaluate করে, প্রতিটা bit আলাদাভাবে AND করে।

5 && 3   // → 1  (দুটোই non-zero, তাই true)
5 &  3   // → 1  (0101 & 0011 = 0001) — কাকতালীয়ভাবে একই!
4 && 1   // → 1
4 &  1   // → 0  (0100 & 0001 = 0000) — এখানে পার্থক্য স্পষ্ট

Level 1-এ bitwise operation বিস্তারিত দেখব।

বুঝেছেন কি না দেখুন

1

p → q আর q → p কি একই জিনিস? না হলে, p → q-এর সাথে কোনটা সমান?

যুক্তি

না, একই নয়। q → p কে বলে converse, আর সেটা আলাদা:

pqp → qq → p
FFTT
FTTF
TFFT
TTTT

মাঝের দুই row-তে মান আলাদা।

p → q-এর সাথে সমান হলো contrapositive: ¬q → ¬p

pqp → q¬q → ¬p
FFTT
FTTT
TFFF
TTTT

চারটা row-তেই মিলে গেছে — এরা logically equivalent।

কেন এটা গুরুত্বপূর্ণ: “বৃষ্টি হলে রাস্তা ভেজা” সত্য হলে, “রাস্তা শুকনো থাকলে বৃষ্টি হয়নি”-ও সত্য। কিন্তু “রাস্তা ভেজা থাকলে বৃষ্টি হয়েছে” — এটা নয় (কেউ পানি ঢালতে পারে)।

Converse আর implication গুলিয়ে ফেলা মানুষের সবচেয়ে সাধারণ যৌক্তিক ভুল।

2

এই দুইটা কি সমান? !(a && b) আর !a && !b — truth table দিয়ে যাচাই করুন। সমান না হলে, !(a && b)-এর সঠিক রূপ কী?

প্রয়োগ

সমান নয়

aba ∧ b¬(a ∧ b)¬a ∧ ¬b¬a ∨ ¬b
FFFTTT
FTFTFT
TFFTFT
TTTFFF

¬(a ∧ b) আর ¬a ∧ ¬b মাঝের দুই row-তে আলাদা।

সঠিক রূপ: ¬(a ∧ b) ≡ ¬a ∨ ¬bAND ভাঙলে OR হয়

এটাই De Morgan’s law, পরের লেসনের মূল বিষয়। কোডে:

if (!(is_admin && is_verified))   // ঠিক
if (!is_admin && !is_verified)    // ভুল — সম্পূর্ণ ভিন্ন শর্ত
if (!is_admin || !is_verified)    // ঠিক, De Morgan প্রয়োগ করে

দ্বিতীয় লাইনটা লিখলে verified non-admin এবং unverified admin — দুই দলই ভুলভাবে পার পেয়ে যাবে।

3

কেন all([]) সত্য কিন্তু any([]) মিথ্যা? এটার সাথে vacuous truth-এর সম্পর্ক কী?

যুক্তি

all(L) মানে “L-এর প্রতিটা element সত্য” — অর্থাৎ “এমন কোনো element নেই যেটা মিথ্যা”। খালি list-এ মিথ্যা element নেই, তাই দাবিটা সত্য। এটাই vacuous truth

any(L) মানে “L-এ অন্তত একটা সত্য element আছে”। খালি list-এ কোনো element-ই নেই, তাই সত্য element-ও নেই। মিথ্যা।

আরেকভাবে দেখুন — identity element হিসেবে:

  • all হলো পরপর AND: T ∧ x₁ ∧ x₂ ∧ …। AND-এর identity হলো T (কারণ T ∧ x = x)। খালি হলে identity-টাই থাকে → T।
  • any হলো পরপর OR: F ∨ x₁ ∨ x₂ ∨ …। OR-এর identity হলো F। খালি হলে → F।

ঠিক যেমন sum([]) == 0 (যোগের identity) আর math.prod([]) == 1 (গুণের identity)। একই গাণিতিক নীতি।

4

একটা login system-এ শর্ত: “account active হতে হবে এবং (password ঠিক হতে হবে অথবা valid recovery token থাকতে হবে), কিন্তু account locked থাকলে কোনোভাবেই ঢোকা যাবে না।”

এটাকে propositional formula-য় লিখুন এবং truth table বানিয়ে যাচাই করুন locked account সত্যিই সব ক্ষেত্রে আটকে যাচ্ছে কি না।

ডিজাইন

Variable: A = active, P = password ঠিক, R = valid recovery token, L = locked।

Formula: A ∧ (P ∨ R) ∧ ¬L

Truth table-এ ১৬টা row। কিন্তু পুরোটা না বানিয়েও যাচাই করা যায় — এটাই logical reasoning-এর শক্তি:

L = T হলে ¬L = F। আর x ∧ F = F সবসময়। তাই পুরো expression F, A, P, R যাই হোক। আটটা locked row-এর সবগুলোতেই access denied।

বাকি আটটা row (L = F) -এ expression হয়ে যায় A ∧ (P ∨ R):

APRP ∨ RA ∧ (P ∨ R)
FFFFF
FFTTF
FTFTF
FTTTF
TFFFF
TFTTT
TTFTT
TTTTT

Active account তিনভাবে ঢুকতে পারে — password দিয়ে, token দিয়ে, বা দুটোই। Inactive কখনো না। ঠিক যা চেয়েছিলাম।

Design-এর দিক থেকে গুরুত্বপূর্ণ: ¬L কে আলাদা রেখে দিয়ে জোড়া দেওয়ায় এটা একটা kill switch হয়ে গেছে — বাকি logic যত জটিলই হোক, locked মানে locked। এই pattern-টা security design-এ খুব দরকারি: fail-safe শর্তগুলো সবচেয়ে বাইরের -এ রাখুন।

5

n টা variable-এর জন্য কতগুলো ভিন্ন truth table (অর্থাৎ কতগুলো ভিন্ন boolean function) সম্ভব? n = 2-এর জন্য সংখ্যাটা বের করুন।

প্রয়োগ

n টা variable মানে 2^n টা row। প্রতিটা row-এর output হয় T নয় F — দুইটা পছন্দ। Row-গুলো স্বাধীন, তাই মোট:

22n2^{2^n}

n = 2-এর জন্য: 2^(2²) = 2⁴ = ১৬টা ভিন্ন boolean function।

সেই ১৬টার মধ্যে পরিচিত নামওয়ালা কয়েকটা: AND, OR, XOR, NAND, NOR, XNOR, implication, converse implication, দুইটা projection (p, q), দুইটা negation (¬p, ¬q), constant TRUE, constant FALSE, আর দুইটা inhibition।

n = 3-এ সংখ্যাটা 2⁸ = ২৫৬। n = 4-এ 2¹⁶ = ৬৫,৫৩৬। n = 5-এ ৪২৯ কোটির বেশি। এই বিস্ফোরক বৃদ্ধিই কারণ যে truth table দিয়ে সব সমস্যা সমাধান করা যায় না — আর কেন SAT solver-এর মতো চতুর algorithm লাগে।

একটা চমৎকার সত্য: এই সব function — সবগুলো — শুধু NAND gate দিয়ে বানানো যায়। Level 2-এ সেটা নিজে হাতে করব।

এরপর কী

এই লেসনে আমরা truth table বানাতে শিখলাম। কিন্তু ৫টা variable মানে ৩২ row, ১০টা মানে ১০২৪ — হাতে করা অসম্ভব।

তাই পরের লেসনে আমরা শিখব logical equivalence — truth table না বানিয়ে বীজগণিতের নিয়ম দিয়ে expression সরল করা। De Morgan’s law, distribution, absorption। এগুলো ঠিক সেই নিয়ম যা দিয়ে compiler আপনার শর্ত optimize করে, আর যা দিয়ে Level 2-এ আমরা circuit-এর gate সংখ্যা কমাব।

তারপর আসবে predicate logic — কারণ x > 5 কে proposition বানাতে “সব x-এর জন্য” বা “কোনো একটা x আছে যার জন্য” বলার ভাষা লাগে। সেই ভাষা ছাড়া কোনো algorithm-এর correctness লেখাই যায় না।

আরও পড়ুন

  • Mathematics for Computer Science, Chapter 1–3 — Lehman, Leighton, Meyer
  • Discrete Mathematics and Its Applications, Chapter 1 — Kenneth Rosen · Truth table আর logical equivalence-এর জন্য সবচেয়ে বিস্তারিত reference