সরাসরি পর্বে যান
পর্ব ০৪ · ৮৩-এর মধ্যে · মডিউল ১

Predicate logic আর quantifier — "সব" আর "কোনো একটি" লেখা

Predicate Logic and Quantifiers — Writing "for all" and "there exists"

Taught in Bangla, this lesson introduces predicates, domains and the universal and existential quantifiers, with scope, precedence and bound versus free variables. It drills the translation rule ("all" pairs with implication, "some" with conjunction), negation of quantifiers, which equivalences hold over ∧ and ∨, and vacuous truth on an empty domain. In-page Python uses all() and any() on a shop's orders, checks the quantifier laws on every small predicate, and finds the Fermat number counterexample 641 × 6700417.

এই পর্বে যা শিখবেন

  • Predicate, propositional function আর domain of discourse-এর সুনির্দিষ্ট সংজ্ঞা
  • ∀, ∃ আর ∃! দিয়ে বাংলা ও ইংরেজি বাক্য লেখা, আর সূত্র থেকে আবার বাংলায় ফেরা
  • Bound আর free variable, quantifier-এর scope আর অগ্রাধিকার
  • Quantifier-এর De Morgan সূত্র প্রমাণসহ, আর কোন equivalence খাটে, কোনটি খাটে না
  • ফাঁকা domain-এর ফাঁদ, আর Python দিয়ে সসীম domain-এ মান যাচাই ও counterexample খোঁজা

১ · "প্রতিটি অর্ডার" — যেখানে propositional logic আটকে যায়

পর্ব ০২-এ আমরা proposition নিয়ে কাজ করেছি: এমন বাক্য, যা হয় সত্য নয়তো মিথ্যা। "অর্ডার B101 ডেলিভার হয়েছে" একটি proposition, একে p বলা যায়। "অর্ডার B102 ডেলিভার হয়েছে" আরেকটি, একে q. কিন্তু বাজারঘরের দিনে কয়েক হাজার অর্ডার আসে। এখন এই নিয়মটি লিখতে চাই:

"ঢাকার প্রতিটি অর্ডার ২৪ ঘণ্টার মধ্যে ডেলিভার হয়।"

Propositional logic-এ এর জন্য প্রতিটি অর্ডারের আলাদা প্রতীক লাগবে, আর তাদের সবাইকে ∧ দিয়ে জুড়তে হবে। কাল নতুন অর্ডার এলে সূত্রটিও বদলাতে হবে। আরও বড় সমস্যা: "প্রতিটি পূর্ণসংখ্যা n-এর জন্য n² ≥ 0" জাতীয় কথায় বস্তু অসীম, সেখানে ∧-এর শিকল কখনো শেষ হয় না। Propositional logic প্রতিটি বাক্যকে একটি আস্ত বাক্স হিসেবে দেখে; বাক্সের ভেতরের "কে" আর "কী গুণ" সে দেখতে পায় না।

ব্যাংকের জমা-স্লিপের কথা ভাবুন: "হিসাব নম্বর ______-এ ______ টাকা জমা হলো।" ফাঁকা ঘর থাকা অবস্থায় স্লিপটি কোনো ঘটনা বলে না, সত্য-মিথ্যার প্রশ্নই ওঠে না। ঘর পূরণ করলে তবেই এটি একটি নির্দিষ্ট দাবি হয়, যা যাচাই করা যায়। Predicate ঠিক এমন একটি ফাঁকা ঘরওয়ালা ছাঁচ।

সংজ্ঞা

Predicate: বস্তুর একটি গুণ বা বস্তুদের মধ্যের একটি সম্পর্ক, যেমন D(x): "x ডেলিভার হয়েছে", বা Ord(c, o): "গ্রাহক c অর্ডার o দিয়েছেন"। একটি predicate কয়টি বস্তু নেয়, সেটি তার arity: D-এর arity ১, Ord-এর ২.

Propositional function: P(x) লেখাটি, যেখানে x একটি variable. x-কে domain-এর কোনো নির্দিষ্ট বস্তু a দিয়ে বদলালে P(a) একটি proposition হয়। তাই একটি propositional function আসলে domain থেকে {সত্য, মিথ্যা}-তে যাওয়া একটি function.

Domain of discourse: x কোন কোন মান নিতে পারে, সেই সেট। একে universe-ও বলে। একই P(x)-এর অর্থ domain বদলালে বদলে যেতে পারে, তাই domain না বলে কোনো quantified বাক্যের মান ঠিক হয় না।

উদাহরণ: P(x): "x² ≥ x". P(3) মানে 9 ≥ 3, সত্য। P(1/2) মানে 1/4 ≥ 1/2, মিথ্যা। P(x) নিজে কিছুই দাবি করে না; সে শুধু একটি ছাঁচ। Programming-এর ভাষায় predicate হলো এমন একটি function, যা True বা False ফেরত দেয়, যেমন def D(order): return order.status == "delivered". এই মিলটি আমরা পুরো পর্বে কাজে লাগাব।

Predicate দিয়ে তৈরি এই বড় ব্যবস্থাকে বলে predicate logic বা first-order logic. "First-order" কথাটির মানে: quantifier শুধু বস্তুর (অর্ডার, সংখ্যা, গ্রাহক) ওপর বসে, predicate-এর ওপর নয়। AI-এর ভিত্তি কোর্সের পর্ব ৪৬-এ দেখবেন একই ভাষা দিয়ে AI agent-এর knowledge base লেখা হয়; এখানে আমরা দেখব এর গণিত: সংজ্ঞা, সূত্র আর প্রমাণ।

২ · দুই quantifier — ∀ আর ∃

একটি propositional function থেকে proposition পাওয়ার দুটি উপায় আছে। প্রথমটি আগেই দেখেছি: x-এ একটি নির্দিষ্ট মান বসানো। দ্বিতীয়টি হলো x সম্পর্কে একটি "পরিমাণ" বলা: সবার জন্য, নাকি অন্তত একজনের জন্য। এই পরিমাণ-বাচক চিহ্নকে বলে quantifier.

সংজ্ঞা

Universal quantification: ∀x P(x) পড়া হয় "সব x-এর জন্য P(x)" হিসেবে। এটি সত্য ঠিক তখন, যখন domain-এর প্রতিটি বস্তু a-র জন্য P(a) সত্য। চিহ্ন ∀ হলো universal quantifier.

Existential quantification: ∃x P(x) পড়া হয় "এমন একটি x আছে, যার জন্য P(x)" হিসেবে। এটি সত্য ঠিক তখন, যখন domain-এ অন্তত একটি বস্তু a আছে, যার জন্য P(a) সত্য। চিহ্ন ∃ হলো existential quantifier.

Uniqueness: ∃!x P(x) মানে, ঠিক একটি x আছে যার জন্য P(x) সত্য। এটি নতুন কিছু নয়, একটি সংক্ষেপ: ∃x (P(x) ∧ ∀y (P(y) → y = x)). চিহ্ন ∃! হলো uniqueness quantifier.

Domain সসীম হলে, ধরুন D = {a1, a2, …, an}, তখন দুটি quantifier-কে পুরোনো connective দিয়েই লেখা যায়:

∀x P(x) ≡ P(a1) ∧ P(a2) ∧ … ∧ P(an)
∃x P(x) ≡ P(a1) ∨ P(a2) ∨ … ∨ P(an)

এই দুই লাইন থেকেই অনেক কিছু বোঝা যায়। একটি লম্বা ∧ মিথ্যা হতে একটি মিথ্যা অংশই যথেষ্ট; তাই ∀-দাবি ভাঙতে একটি বস্তু লাগে, যাকে বলে counterexample. আর একটি লম্বা ∨ সত্য হতে একটি সত্য অংশই যথেষ্ট; তাই ∃-দাবি প্রমাণে একটি বস্তু দেখানোই যথেষ্ট, যাকে বলে witness. নিচের ছবিতে বাজারঘরের পাঁচটি অর্ডার দিয়ে ব্যাপারটি দেখুন।

∀ মানে লম্বা ∧, ∃ মানে লম্বা ∨

On a finite domain, "for all" is a big AND and "there exists" is a big OR

Universal quantifier as a conjunction and existential quantifier as a disjunction over five orders D(x) = অর্ডার x ডেলিভার হয়েছে o1 o2 o3 o4 o5 ✓ ✓ ✓ ✗ ✓ ∀x D(x) = D(o1) ∧ D(o2) ∧ … ∧ D(o5) o4-এ ✗, তাই পুরোটা মিথ্যা ∃x D(x) = D(o1) ∨ D(o2) ∨ … ∨ D(o5) একটি ✓-ই যথেষ্ট, তাই সত্য
ছবি ৪.১ — একই domain, একই predicate. ∀-এর জন্য প্রতিটি বৃত্তে ✓ লাগে, তাই o4 একাই ∀x D(x)-কে মিথ্যা করে দেয়; o4 এখানে counterexample. ∃-এর জন্য একটি ✓ লাগে, o1-ই witness.

Domain বদলালে সত্য-মিথ্যাও বদলায়

∀x (x² ≥ x) বাক্যটি নিন। Domain ℤ (সব পূর্ণসংখ্যা, ঋণাত্মকসহ) হলে এটি সত্য। প্রমাণ: x ≤ 0 হলে x² ≥ 0 ≥ x; আর x ≥ 1 হলে x ≥ 1 দিয়ে দুই দিক গুণ করে x² ≥ x; পূর্ণসংখ্যায় এই দুই ঘরের বাইরে কিছু নেই। ∎ কিন্তু domain ℝ (সব বাস্তব সংখ্যা) হলে x = 1/2 একটি counterexample, কারণ 1/4 < 1/2. একই সূত্র, ভিন্ন domain, ভিন্ন উত্তর। এজন্যই পরীক্ষার প্রশ্নে domain না বলা থাকলে প্রথমে সেটি লিখে নিন।

Quantifier-এর আধুনিক ধারণা আসে জার্মান গণিতবিদ Gottlob Frege-এর ১৮৭৯ সালের বই Begriffsschrift থেকে; প্রায় একই সময়ে, ১৮৮০-এর দশকে, আমেরিকার Charles Sanders Peirce ও তাঁর ছাত্ররা আলাদাভাবে একই ধারণায় পৌঁছান। চিহ্ন দুটি এসেছে পরে: সাধারণত বলা হয় ∃ (উল্টো E, "Exists") প্রথম ব্যবহার করেন Giuseppe Peano, ১৮৯০-এর দশকের শেষে, আর ∀ (উল্টো A, "All") চালু করেন Gerhard Gentzen, ১৯৩৫ সালের দিকে। তারিখগুলো বিভিন্ন উৎসে সামান্য আলাদা।

৩ · Scope, অগ্রাধিকার আর bound বনাম free variable

একটি quantifier বাক্যের কতটুকু অংশে খাটে, সেটি তার scope. Programming-এ একটি loop variable যেমন শুধু loop-এর ভেতরে বাঁচে, তেমনি ∀x-এর x শুধু তার scope-এর ভেতরে অর্থ পায়।

সংজ্ঞা

একটি সূত্রে variable x-এর কোনো উপস্থিতি যদি ∀x বা ∃x-এর scope-এর ভেতরে থাকে, তবে সেটি bound. কোনো quantifier-এর আওতায় না থাকলে সেটি free. যে সূত্রে কোনো free variable নেই, শুধু সেটিরই নির্দিষ্ট সত্য-মিথ্যা মান থাকে (domain আর predicate-এর অর্থ ঠিক করা থাকলে)।

উদাহরণ: ∃x (Ord(x, y) ∧ D(x)). এখানে x bound, কিন্তু y free. তাই এটি এখনো একটি propositional function, y-এর ওপর নির্ভর করে: "গ্রাহক y-এর অন্তত একটি অর্ডার ডেলিভার হয়েছে" ধরনের একটি ছাঁচ। y-এ একজন নির্দিষ্ট গ্রাহক বসালে, অথবা সামনে ∀y বা ∃y বসালে, তবেই এটি proposition হবে।

অগ্রাধিকার: quantifier সবার আগে বাঁধে

বেশিরভাগ discrete math বইয়ের প্রথা হলো: ∀ আর ∃ সব connective-এর চেয়ে বেশি শক্তভাবে বাঁধে। তাই

∀x P(x) ∨ Q(x) মানে (∀x P(x)) ∨ Q(x), ∀x (P(x) ∨ Q(x)) নয়।

প্রথম রূপে শেষের x-টি free, কারণ ∀x-এর scope শুধু P(x) পর্যন্ত। দ্বিতীয় রূপে দুটিই bound. দুটির অর্থও আলাদা, যা অংশ ৬-এ প্রমাণ করব। কিছু বই আর AI সংক্রান্ত লেখায় উল্টো প্রথা চলে, যেখানে quantifier-এর scope যতদূর সম্ভব ডানে যায়। তাই নিরাপদ অভ্যাস একটাই: quantifier-এর পরে সবসময় বন্ধনী দিন।

সূত্রBoundFreeProposition?
∀x (P(x) → Q(x))xনেইহ্যাঁ
∃x Ord(x, y)xyনা
∀x P(x) ∨ Q(x)প্রথম xশেষের xনা
∀y ∃x Ord(x, y)x, yনেইহ্যাঁ

Bound variable-এর নাম বদলালে অর্থ বদলায় না: ∀x P(x) আর ∀z P(z) একই কথা, ঠিক যেমন for i in range(5) আর for k in range(5) একই loop. শুধু খেয়াল রাখবেন, নতুন নামটি যেন সূত্রের আরেকটি free variable-এর সঙ্গে মিলে না যায়। ∃x Ord(x, y)-তে x-এর নাম y রাখলে ∃y Ord(y, y) হয়, যার অর্থ সম্পূর্ণ আলাদা ("কেউ নিজেই নিজের অর্ডার")। একে বলে variable capture, আর প্রমাণে এটি একটি চেনা ভুল।

৪ · বাংলা বাক্য থেকে সূত্র — "সব"-এর সঙ্গে →, "কিছু"-র সঙ্গে ∧

বাস্তবের বাক্য প্রায় কখনো পুরো domain নিয়ে কথা বলে না। "ঢাকার প্রতিটি অর্ডার" মানে সব অর্ডার নয়, শুধু ঢাকারগুলো। এমন সীমিত কথা লেখার দুটি উপায় আছে। একটি হলো domain-টাই ছোট করা (শুধু ঢাকার অর্ডার)। কিন্তু একই বাক্যে অনেক রকম শর্ত থাকলে সেটি অসুবিধার, তাই সাধারণ উপায় হলো domain বড় রেখে শর্তটি একটি predicate দিয়ে লেখা। একে বলে restricted quantifier:

বাংলা ধাঁচসংক্ষেপসঠিক সূত্র
সব C-ই P∀x∈C P(x)∀x (C(x) → P(x))
কিছু (অন্তত একটি) C P∃x∈C P(x)∃x (C(x) ∧ P(x))
কোনো C-ই P নয়¬∃x∈C P(x)∀x (C(x) → ¬P(x))
সব C P নয় (অন্তত একটি নয়)¬∀x∈C P(x)∃x (C(x) ∧ ¬P(x))

কেন ∀-এর সঙ্গে → আর ∃-এর সঙ্গে ∧? দুটি ভুল রূপ নিয়ে ভাবলেই বোঝা যায়।

  • ∀x (C(x) ∧ P(x)) কেন ভুল: এটি দাবি করে domain-এর প্রতিটি বস্তুই C. সব অর্ডারের domain-এ একটি খুলনার অর্ডার থাকলেই এটি মিথ্যা, যদিও ঢাকার সব অর্ডার সময়মতো গেছে। → ব্যবহার করলে খুলনার অর্ডারের জন্য C(x) মিথ্যা, আর মিথ্যা → যেকোনো কিছু সত্য; অর্থাৎ বাইরের বস্তুগুলো দাবিকে বিরক্ত করে না।
  • ∃x (C(x) → P(x)) কেন ভুল: একটিমাত্র খুলনার অর্ডার থাকলেই C(x) মিথ্যা, তাই C(x) → P(x) সত্য, তাই পুরো ∃ সত্য, ঢাকার অর্ডার সম্পর্কে কিছু না জেনেই। এই সূত্র প্রায় সবসময় বিনা কারণে সত্য হয়ে যায়।

নিচের stepper-এ তিনটি বাক্য ধাপে ধাপে অনুবাদ করা হয়েছে। Domain: বাজারঘরের সব অর্ডার। Predicate: D(x) ঢাকার অর্ডার, F(x) ২৪ ঘণ্টায় ডেলিভারি, K(x) কুপন ব্যবহার হয়েছে, Z(x) ডেলিভারি ফ্রি, B(x) বাতিল, R(x) রিভিউ আছে।

Domain: সব অর্ডার · D ঢাকা, F ২৪ ঘণ্টা, K কুপন, Z ফ্রি, B বাতিল, R রিভিউ
বাক্য
ভাবনা
সূত্র
সাবধান
  1. বাক্য ১, ভাবনা। "প্রতিটি" শব্দটি ∀ চায়। বাক্যের দুটি অংশ আলাদা করুন: কাদের নিয়ে কথা (শর্ত: ঢাকার অর্ডার, D) আর তাদের সম্পর্কে কী দাবি (F). Domain সব অর্ডারই থাকছে।
  2. বাক্য ১, সূত্র। ∀-এর সঙ্গে শর্ত মানে →: ∀x (D(x) → F(x)). ∧ দিলে দাবি হয়ে যেত "প্রতিটি অর্ডারই ঢাকার এবং ২৪ ঘণ্টায় গেছে", যা একটি সিলেটের অর্ডারেই ভেঙে পড়ে।
  3. বাক্য ২, ভাবনা। "কিছু" শব্দটি গণিতে "অন্তত একটি"। শর্ত কুপন (K), দাবি ফ্রি ডেলিভারি (Z). খেয়াল করুন, "কিছু" দিয়ে বোঝায় না যে সবগুলোতে নয়; সবগুলো ফ্রি হলেও বাক্যটি সত্য।
  4. বাক্য ২, সূত্র। ∃-এর সঙ্গে শর্ত মানে ∧: ∃x (K(x) ∧ Z(x)). → দিলে কুপনহীন যেকোনো একটি অর্ডারের জন্য K(x) → Z(x) সত্য হয়ে যেত, ফলে সূত্রটি অর্থহীনভাবে সত্য হতো।
  5. বাক্য ৩, ভাবনা। "কোনো বাতিল অর্ডারে রিভিউ নেই" মানে "রিভিউওয়ালা বাতিল অর্ডার একটিও নেই": ¬∃x (B(x) ∧ R(x)). ∃x (B(x) ∧ ¬R(x)) লিখলে মানে দাঁড়াত "অন্তত একটি বাতিল অর্ডারে রিভিউ নেই", যা অনেক দুর্বল দাবি।
  6. বাক্য ৩, দ্বিতীয় রূপ। একই কথা ∀ দিয়েও লেখা যায়: ∀x (B(x) → ¬R(x)), "প্রতিটি বাতিল অর্ডারের ক্ষেত্রে রিভিউ নেই"। দুটি রূপ যে সমান, তা অংশ ৫-এর De Morgan সূত্র আর p → q ≡ ¬p ∨ q থেকে আসে।

Python-এ ∀ মানে all(), ∃ মানে any()

সসীম domain-এ এই সূত্রগুলোর মান সরাসরি হিসাব করা যায়। Python-এর all(...) একটি লম্বা ∧, আর any(...) একটি লম্বা ∨, ঠিক অংশ ২-এর সংজ্ঞার মতো। → এর জন্য Python-এ আলাদা operator নেই, তাই p → q ≡ ¬p ∨ q দিয়ে একটি ছোট function লেখা হয়েছে। নিচের ব্লকে বাজারঘরের ছয়টি কাল্পনিক অর্ডারে তিনটি বাক্য, ∃! আর ফাঁকা domain যাচাই করা হয়েছে। ব্লকটি আপনার ব্রাউজারেই চলে (Pyodide, অর্থাৎ WebAssembly-তে compile করা আসল CPython); প্রথমবার চালাতে কয়েক সেকেন্ড লাগতে পারে।

# বাজারঘরের ৬টি কাল্পনিক অর্ডার = domain D
keys = ("id", "district", "hours", "coupon", "free", "cancelled", "review")
rows = [
    ("B101", "Dhaka",    20, 1, 1, 0, 1),
    ("B102", "Dhaka",    22, 0, 0, 0, 0),
    ("B103", "Khulna",   40, 1, 0, 0, 1),
    ("B104", "Sylhet",   30, 0, 0, 1, 0),
    ("B105", "Dhaka",    26, 0, 0, 0, 1),
    ("B106", "Rajshahi", 48, 1, 1, 0, 0),
]
orders = [dict(zip(keys, r)) for r in rows]
def implies(p, q):
    return (not p) or q

# S1: ∀x (Dhaka(x) → F24(x))
s1 = all(implies(o["district"] == "Dhaka", o["hours"] <= 24) for o in orders)
bad = [o["id"] for o in orders
       if not implies(o["district"] == "Dhaka", o["hours"] <= 24)]
print("S1 forall Dhaka->24h:", s1, "| counterexamples:", bad)

# S2: ∃x (coupon(x) ∧ free(x))
wit = [o["id"] for o in orders if o["coupon"] and o["free"]]
print("S2 exists coupon&free:", any(o["coupon"] and o["free"] for o in orders),
      "| witnesses:", wit)

# S3: ∀x (cancelled(x) → ¬review(x))
print("S3 forall cancelled->no review:",
      all(implies(o["cancelled"], not o["review"]) for o in orders))

# ∃!x: ঠিক একটি
for d in ["Rajshahi", "Dhaka"]:
    k = sum(o["district"] == d for o in orders)
    print(f"exists-unique {d}: {k == 1} (count {k})")

print("empty domain: all ->", all([]), "| any ->", any([]))

আসল আউটপুট (ব্রাউজারের Python):

S1 forall Dhaka->24h: False | counterexamples: ['B105']
S2 exists coupon&free: True | witnesses: ['B101', 'B106']
S3 forall cancelled->no review: True
exists-unique Rajshahi: True (count 1)
exists-unique Dhaka: False (count 3)
empty domain: all -> True | any -> False

বাক্য ১ মিথ্যা, আর কেন মিথ্যা তাও ধরা পড়েছে: ঢাকার অর্ডার B105-এ ২৬ ঘণ্টা লেগেছে, এটিই counterexample. খেয়াল করুন, খুলনা বা সিলেটের অর্ডারে যত ঘণ্টাই লাগুক, → এর কারণে তারা ফলকে প্রভাবিত করেনি। বাক্য ২ সত্য, witness দুটি: B101 আর B106. বাক্য ৩ সত্য: একমাত্র বাতিল অর্ডার B104-এ রিভিউ নেই। ∃! ঠিক একটি গোনে, তাই রাজশাহীর জন্য সত্য (একটি অর্ডার), ঢাকার জন্য মিথ্যা (তিনটি)। শেষ লাইনটি পরের অংশগুলোর জন্য মনে রাখুন: ফাঁকা তালিকায় all দেয় True, any দেয় False. এটি Python-এর খেয়াল নয়, গণিতের সংজ্ঞা থেকেই আসে (অংশ ৭)।

৫ · Negation — ¬ ভেতরে ঢুকলে quantifier উল্টে যায়

বাজারঘরের ম্যানেজার দাবি করলেন: "প্রতিটি ডেলিভারিম্যান আজ সময়মতো এসেছেন।" দাবিটি মিথ্যা প্রমাণ করতে কী লাগবে? সবাই দেরিতে এসেছেন, এমন দেখানোর দরকার নেই; অন্তত একজন দেরিতে এসেছেন দেখালেই যথেষ্ট। এটাই quantifier-এর De Morgan সূত্রের মূল কথা।

উপপাদ্য (Quantifier-এর De Morgan সূত্র)

যেকোনো domain আর যেকোনো propositional function P(x)-এর জন্য:

¬∀x P(x) ≡ ∃x ¬P(x) এবং ¬∃x P(x) ≡ ∀x ¬P(x)

প্রমাণ (প্রথম সূত্র): দুটি বাক্য equivalent মানে, যেকোনো domain আর P-এর যেকোনো অর্থে দুটির মান সমান। দুই দিক আলাদা করে দেখাই।

  1. ধরি ¬∀x P(x) সত্য। তাহলে ∀x P(x) মিথ্যা। (¬-এর সংজ্ঞা)
  2. ∀x P(x) মিথ্যা মানে "প্রতিটি a-র জন্য P(a)" কথাটি খাটে না, অর্থাৎ domain-এ অন্তত একটি a আছে যার জন্য P(a) মিথ্যা। (∀-এর সংজ্ঞা)
  3. সেই a-র জন্য ¬P(a) সত্য, তাই ∃x ¬P(x) সত্য; a হলো witness. (∃-এর সংজ্ঞা)
  4. উল্টো দিক: ধরি ∃x ¬P(x) সত্য, witness b. তাহলে P(b) মিথ্যা, তাই "প্রতিটি a-র জন্য P(a)" খাটে না, অর্থাৎ ∀x P(x) মিথ্যা, অর্থাৎ ¬∀x P(x) সত্য। (∀ আর ¬-এর সংজ্ঞা)
  5. দুই দিকেই একটি সত্য হলে অন্যটি সত্য; তাই একটি মিথ্যা হলে অন্যটিও মিথ্যা, এবং দুটির মান সবসময় সমান। ∎

দ্বিতীয় সূত্র প্রথমটি থেকেই আসে। প্রথম সূত্রে P-এর জায়গায় ¬P বসালে: ¬∀x ¬P(x) ≡ ∃x ¬¬P(x) ≡ ∃x P(x). দুই দিকে ¬ নিলে ∀x ¬P(x) ≡ ¬∃x P(x). ∎ সসীম domain-এ এটি আসলে পর্ব ০৩-এর সাধারণ De Morgan: ¬(P(a1) ∧ … ∧ P(an)) ≡ ¬P(a1) ∨ … ∨ ¬P(an). তাই একে বলা হয় quantifier-এর De Morgan সূত্র.

Restricted রূপে এই সূত্র আর অংশ ৪-এর নিয়ম মিলিয়ে দুটি দরকারি ফল পাওয়া যায়, পরীক্ষায় এগুলো বারবার আসে:

¬∀x (C(x) → P(x)) ≡ ∃x (C(x) ∧ ¬P(x))
¬∃x (C(x) ∧ P(x)) ≡ ∀x (C(x) → ¬P(x))

প্রথমটির প্রমাণ: ¬∀x (C → P) ≡ ∃x ¬(C → P) (De Morgan) ≡ ∃x ¬(¬C ∨ P) (p → q ≡ ¬p ∨ q) ≡ ∃x (C ∧ ¬P) (De Morgan আর double negation). ∎ দ্বিতীয়টি একইভাবে। অংশ ৪-এর বাক্য ৩-এর দুটি রূপ এভাবেই মেলে।

এবার নিয়মগুলো একসঙ্গে লাগিয়ে একটি দুই-quantifier বাক্যকে negate করি। প্রতিটি ধাপে ¬ এক ঘর ভেতরে যায়, আর যে quantifier পার হয় সেটি উল্টে যায়। Predicate: Ord(c, o) মানে গ্রাহক c অর্ডার o দিয়েছেন, Del(o) মানে o ডেলিভার হয়েছে।

গ্রাহক A, B, C · অর্ডার 1 (A, ডেলিভার), 2 (A, বাকি), 3 (B, বাকি) · C-এর অর্ডার নেই
সূত্র
নিয়ম
বাংলায়
  1. মূল বাক্য। "প্রতিটি গ্রাহকের কোনো একটি অর্ডার ডেলিভার হয়েছে": প্রতিটি c-এর জন্য এমন একটি o আছে, যা c-এর অর্ডার এবং ডেলিভার হয়েছে। ∃o-এর ভেতরে ∧, কারণ "c-এর অর্ডার" একটি শর্ত (অংশ ৪-এর নিয়ম)।
  2. পুরো বাক্যের সামনে ¬। এখনো কিছু সরল হয়নি, শুধু লিখলাম "এটি সত্য নয় যে…"। লক্ষ্য হলো ¬-কে একদম ভেতরে, predicate-এর গায়ে পৌঁছে দেওয়া।
  3. প্রথম quantifier পার। ¬∀c ≡ ∃c ¬: "সব গ্রাহকের ক্ষেত্রে সত্য নয়" মানে "অন্তত একজন গ্রাহকের ক্ষেত্রে মিথ্যা"। ∀ হয়ে গেল ∃.
  4. দ্বিতীয় quantifier পার। ¬∃o ≡ ∀o ¬: "এমন অর্ডার নেই" মানে "প্রতিটি অর্ডারের ক্ষেত্রে শর্তটি মিথ্যা"। ∃ হয়ে গেল ∀. Quantifier-এর ক্রম (প্রথমে c, পরে o) বদলায়নি, শুধু ধরন বদলেছে।
  5. Connective-এর De Morgan. ¬(Ord ∧ Del) ≡ ¬Ord ∨ ¬Del. এখন ¬ সরাসরি predicate-এর গায়ে বসেছে, তাই negation আসলে শেষ।
  6. পড়ার মতো রূপ। ¬Ord ∨ ¬Del ≡ Ord → ¬Del. বাংলায়: "এমন একজন গ্রাহক আছেন, যাঁর কোনো অর্ডারই ডেলিভার হয়নি।" খেয়াল করুন, যে গ্রাহক একটিও অর্ডার দেননি, তাঁর ক্ষেত্রে → এর বাঁ দিক সবসময় মিথ্যা, তাই তিনিও এই negation-এর witness.
  7. ডেটায় যাচাই। A-এর অর্ডার 1 ডেলিভার হয়েছে, তাই A মূল বাক্য মানে। B-এর একমাত্র অর্ডার 3 বাকি, আর C-এর কোনো অর্ডারই নেই, তাই মূল বাক্য মিথ্যা। Negation সত্য, witness দুজন: B আর C. ঠিক যেমন হওয়ার কথা: একটি বাক্য আর তার negation-এর ঠিক একটিই সত্য।

সবচেয়ে চেনা ভুল: "সব গ্রাহক খুশি নন"-এর negation হিসেবে "সব গ্রাহক অখুশি" লেখা। ¬∀x H(x) মানে ∃x ¬H(x), অর্থাৎ "অন্তত একজন খুশি নন"; ∀x ¬H(x) অনেক বেশি শক্ত দাবি। ¬ যখন quantifier পার হয়, quantifier-কে উল্টাতেই হবে।

৬ · কোন equivalence খাটে — ∀ ভাগ হয় ∧-এ, ∨-এ নয়

সাধারণ বীজগণিতে 2(a + b) = 2a + 2b; গুণ যোগের ওপর ভাগ হয়ে যায় (distributes). Quantifier-এরও এমন নিয়ম আছে, কিন্তু অর্ধেক জোড়ায় খাটে, অর্ধেকে খাটে না। ভুল জোড়াটি মনে রাখা পরীক্ষার জন্য খুব জরুরি।

উপপাদ্য

(ক) ∀x (P(x) ∧ Q(x)) ≡ ∀x P(x) ∧ ∀x Q(x)
(খ) ∃x (P(x) ∨ Q(x)) ≡ ∃x P(x) ∨ ∃x Q(x)
(গ) ∀x (P(x) ∨ Q(x)) এবং ∀x P(x) ∨ ∀x Q(x) সাধারণভাবে equivalent নয়; শুধু ∀x P(x) ∨ ∀x Q(x) → ∀x (P(x) ∨ Q(x)) সবসময় সত্য।
(ঘ) ∃x (P(x) ∧ Q(x)) এবং ∃x P(x) ∧ ∃x Q(x) সাধারণভাবে equivalent নয়; শুধু ∃x (P(x) ∧ Q(x)) → ∃x P(x) ∧ ∃x Q(x) সবসময় সত্য।

(ক)-এর প্রমাণ:

  1. ধরি বাঁ দিক সত্য: প্রতিটি a-র জন্য P(a) ∧ Q(a). তাহলে প্রতিটি a-র জন্য P(a) (∧ থেকে আলাদা করা), তাই ∀x P(x); একইভাবে ∀x Q(x). তাই ডান দিক সত্য।
  2. ধরি ডান দিক সত্য। যেকোনো a নিন। ∀x P(x) থেকে P(a), ∀x Q(x) থেকে Q(a), তাই P(a) ∧ Q(a). a যেকোনো ছিল, তাই ∀x (P(x) ∧ Q(x)).
  3. দুই দিকেই একটি থেকে অন্যটি আসে, তাই দুটি equivalent. ∎

(খ)-এর প্রমাণ (ক) থেকে De Morgan দিয়ে আসে: ∃x (P ∨ Q) ≡ ¬∀x ¬(P ∨ Q) ≡ ¬∀x (¬P ∧ ¬Q) ≡ ¬(∀x ¬P ∧ ∀x ¬Q) ≡ ¬∀x ¬P ∨ ¬∀x ¬Q ≡ ∃x P ∨ ∃x Q. ∎ এখানে তৃতীয় ধাপে (ক) ব্যবহার হয়েছে, P আর Q-এর জায়গায় ¬P আর ¬Q দিয়ে।

(গ)-এর counterexample: Domain {1, 2}, P(x): "x বিজোড়", Q(x): "x জোড়"। প্রতিটি সংখ্যা জোড় অথবা বিজোড়, তাই ∀x (P(x) ∨ Q(x)) সত্য। কিন্তু সব সংখ্যা বিজোড় নয় (২ আছে), সব জোড়ও নয় (১ আছে); তাই ∀x P(x) ∨ ∀x Q(x) মিথ্যা। বাজারঘরের ভাষায়: "প্রতিটি অর্ডার bKash বা ক্যাশে পরিশোধ হয়েছে" আর "সব অর্ডার bKash-এ, অথবা সব অর্ডার ক্যাশে" মোটেই এক কথা নয়। (ঘ)-এর counterexample একই domain-এ: ∃x P(x) আর ∃x Q(x) দুটিই সত্য, কিন্তু একই সঙ্গে জোড় ও বিজোড় কোনো সংখ্যা নেই।

প্রমাণ হয়ে গেছে, তবু সংখ্যা দিয়ে মিলিয়ে দেখা ভালো অভ্যাস। নিচের ব্লক domain-এর আকার n = 1 থেকে 4 পর্যন্ত P আর Q-এর প্রতিটি সম্ভাব্য অর্থ (n উপাদানের domain-এ একটি predicate মানে 2n রকম True/False তালিকা) চেষ্টা করে, আর প্রতিটি দাবি কতবার ভাঙে গোনে। এটি পর্ব ০২-এর truth table-এর বড় ভাই: সারি হলো (P, Q) জোড়া।

from itertools import product

def A(P): return all(P)      # ∀x P(x); P = প্রতিটি x-এর True/False
def E(P): return any(P)      # ∃x P(x)
def AND(P, Q): return [p and q for p, q in zip(P, Q)]
def OR(P, Q): return [p or q for p, q in zip(P, Q)]
def NOT(P): return [not p for p in P]

laws = {
    "not forall P == exists not P": lambda P, Q: (not A(P)) == E(NOT(P)),
    "not exists P == forall not P": lambda P, Q: (not E(P)) == A(NOT(P)),
    "forall(P and Q) == A P and A Q": lambda P, Q: A(AND(P, Q)) == (A(P) and A(Q)),
    "exists(P or Q) == E P or E Q": lambda P, Q: E(OR(P, Q)) == (E(P) or E(Q)),
    "forall(P or Q) == A P or A Q": lambda P, Q: A(OR(P, Q)) == (A(P) or A(Q)),
    "exists(P and Q) == E P and E Q": lambda P, Q: E(AND(P, Q)) == (E(P) and E(Q)),
}
sizes = range(1, 5)                          # domain-এর আকার n = 1..4
print("pairs (P, Q) checked for n = 1..4:", [4 ** n for n in sizes])
for name, law in laws.items():
    fails = []
    for n in sizes:
        preds = list(product([False, True], repeat=n))
        fails.append(sum(not law(P, Q) for P in preds for Q in preds))
    print(f"{name:31} failures {fails}")

# সবচেয়ে ছোট counterexample: domain {x1, x2}
P, Q = [True, False], [False, True]
print("forall(P or Q) =", A(OR(P, Q)), "| A P or A Q =", A(P) or A(Q))

আসল আউটপুট (ব্রাউজারের Python):

pairs (P, Q) checked for n = 1..4: [4, 16, 64, 256]
not forall P == exists not P    failures [0, 0, 0, 0]
not exists P == forall not P    failures [0, 0, 0, 0]
forall(P and Q) == A P and A Q  failures [0, 0, 0, 0]
exists(P or Q) == E P or E Q    failures [0, 0, 0, 0]
forall(P or Q) == A P or A Q    failures [0, 2, 12, 50]
exists(P and Q) == E P and E Q  failures [0, 2, 12, 50]
forall(P or Q) = True | A P or A Q = False

প্রথম চারটি সূত্র ৪ + ১৬ + ৬৪ + ২৫৬ = ৩৪০টি জোড়ার একটিতেও ভাঙেনি, উপপাদ্যের (ক), (খ) আর De Morgan-এর সঙ্গে মিল। শেষ দুটি n = 1-এ ভাঙে না (এক বস্তুর domain-এ ∀ আর ∃ দুটিই শুধু সেই বস্তুর কথা বলে), কিন্তু n = 2 থেকে ভাঙে: ২, ১২, ৫০ জোড়ায়। এই সংখ্যাগুলোর একটি সূত্রও আছে, 3n − 2·2n + 1, যা অনুশীলন ২-এ প্রমাণ করবেন। শেষ লাইনটি (গ)-এর সবচেয়ে ছোট counterexample: দুটি বস্তু, প্রথমটিতে শুধু P, দ্বিতীয়টিতে শুধু Q. মনে রাখবেন, এই ব্লক শুধু n ≤ 4 দেখেছে; প্রথম চারটি সূত্র সব domain-এ সত্য, এই নিশ্চয়তা দেয় ওপরের প্রমাণ, ব্লক নয়।

যে অংশে x নেই, তাকে বাইরে আনা যায়

q যদি এমন একটি বাক্য হয় যার ভেতরে x free নয় (যেমন "আজ হরতাল"), তাহলে ∀x (P(x) ∨ q) ≡ ∀x P(x) ∨ q, আর ∃x (P(x) ∧ q) ≡ ∃x P(x) ∧ q. যুক্তি: q-এর মান x-এর ওপর নির্ভর করে না। প্রথমটিতে q সত্য হলে দুই দিকই সত্য, আর q মিথ্যা হলে দুই দিকই ∀x P(x)-এর সমান। দ্বিতীয়টিতে q সত্য হলে দুই দিকই ∃x P(x), q মিথ্যা হলে দুই দিকই মিথ্যা। এর জোড়া দুটি, ∀x (P(x) ∧ q) ≡ ∀x P(x) ∧ q আর ∃x (P(x) ∨ q) ≡ ∃x P(x) ∨ q, একই যুক্তিতে খাটে, তবে একটি শর্তে: domain অশূন্য হতে হবে। শর্তটি কাকতালীয় নয়; পরের অংশ সেটি নিয়েই।

৭ · ফাঁকা domain আর vacuous truth

বাজারঘরের নতুন শাখা খুলেছে কক্সবাজারে, আজ সেখানে একটিও অর্ডার আসেনি। "কক্সবাজারের প্রতিটি অর্ডার সময়মতো ডেলিভার হয়েছে" — সত্য না মিথ্যা? সংজ্ঞা অনুযায়ী ∀ মিথ্যা হতে একটি counterexample লাগে, আর ফাঁকা সেটে কোনো counterexample নেই। তাই বাক্যটি সত্য। এমন "ফাঁকা কারণে সত্য"-কে বলে vacuous truth. পর্ব ০২-এ দেখেছেন মিথ্যা → যেকোনো কিছু সত্য; এটি তারই quantifier-রূপ।

ফাঁকা domain-এ: ∀x P(x) সবসময় সত্য, ∃x P(x) সবসময় মিথ্যা
all([]) == True · any([]) == False

এর একটি সুন্দর ব্যাখ্যা আছে। ∧-এর "নিরপেক্ষ" মান সত্য (p ∧ সত্য ≡ p), ঠিক যেমন গুণের নিরপেক্ষ মান ১; আর ∨-এর নিরপেক্ষ মান মিথ্যা, যেমন যোগের ০. শূন্যটি সংখ্যার গুণফল ১ ধরা হয়, শূন্যটি সংখ্যার যোগফল ০; একই যুক্তিতে শূন্যটি বাক্যের ∧ সত্য, শূন্যটি বাক্যের ∨ মিথ্যা। Python-এর all আর any ঠিক এই নিয়ম মানে।

এর ফলে একটি অদ্ভুত ব্যাপার ঘটে। স্বাভাবিকভাবে মনে হয় ∀x P(x) → ∃x P(x) সবসময় সত্য: সবার জন্য সত্য হলে অন্তত একজনের জন্য তো সত্যই। Domain অশূন্য হলে কথাটি ঠিক: একটি বস্তু a নিন, ∀ থেকে P(a), তাই ∃. কিন্তু ফাঁকা domain-এ বাঁ দিক সত্য আর ডান দিক মিথ্যা, তাই → মিথ্যা। একইভাবে ∃x (P(x) ∨ q) ≡ ∃x P(x) ∨ q ফাঁকা domain-এ ভাঙে (বাঁ দিক মিথ্যা, ডান দিক q).

প্রথা: বেশিরভাগ বই আর এই কোর্স ধরে নেয় যে domain of discourse অশূন্য; না হলে ওপরের মতো অনেক সুবিধাজনক সূত্র ভেঙে যায়। কিন্তু programming আর database-এ ফাঁকা তালিকা খুবই সাধারণ। if all(o.paid for o in cart): ফাঁকা cart-এর জন্যও সত্য হবে, ফলে "সব পরিশোধ হয়েছে, অর্ডার পাঠান" ধরনের কোড ফাঁকা অর্ডারও পাঠিয়ে দিতে পারে। এমন জায়গায় cart and all(...) লিখে ফাঁকা অবস্থা আলাদা করে ধরুন।

৮ · Counterexample খোঁজা — একটি যথেষ্ট, হাজারটি মিলও প্রমাণ নয়

অংশ ২-এর লম্বা ∧ থেকে একটি অসম ব্যাপার বেরিয়ে আসে, যা গণিত আর software testing দুই জায়গাতেই মূল নীতি:

দাবিসত্য প্রমাণ করতেমিথ্যা প্রমাণ করতে
∀x P(x)সাধারণ যুক্তি: যেকোনো a-র জন্য P(a)একটি counterexample
∃x P(x)একটি witnessসাধারণ যুক্তি: যেকোনো a-র জন্য ¬P(a)

সসীম ছোট domain-এ সব বস্তু একে একে দেখলেই ∀-দাবির প্রমাণ হয়ে যায় (একে বলে exhaustive check). কিন্তু domain অসীম হলে কয়েক হাজার উদাহরণে মিলে যাওয়াও প্রমাণ নয়। গণিতের ইতিহাসের একটি বিখ্যাত উদাহরণ দেখুন। ১৬৪০ সালের দিকে Pierre de Fermat চিঠিতে লেখেন যে F(n) = 22n + 1 আকারের সব সংখ্যা মৌলিক বলে তাঁর ধারণা। n = 0 থেকে 4 পর্যন্ত সত্যিই তাই: 3, 5, 17, 257, 65537. প্রায় এক শতাব্দী পরে, সাধারণত বলা হয় ১৭৩২ সালে, Leonhard Euler দেখান F(5) মৌলিক নয়। নিচের ব্লক সাধারণ trial division দিয়ে সেই counterexample নিজেই খুঁজে বের করে।

import math

def smallest_factor(m):
    """m-এর ১-এর চেয়ে বড় সবচেয়ে ছোট ভাজক (trial division)"""
    if m % 2 == 0:
        return 2
    d = 3
    while d * d <= m:
        if m % d == 0:
            return d
        d += 2
    return m                    # কোনো ভাজক নেই: m মৌলিক

# দাবি: ∀n ∈ {0, 1, 2, ...}, F(n) = 2^(2^n) + 1 মৌলিক
for n in range(6):
    F = 2 ** (2 ** n) + 1
    p = smallest_factor(F)
    if p == F:
        print(f"n = {n}: F = {F} is prime")
    else:
        print(f"n = {n}: F = {F} = {p} x {F // p}  <-- counterexample")
        break

# প্রমাণ নয়, যাচাই: দুই ভাজক মৌলিক কি না
print("641 prime?", smallest_factor(641) == 641,
      "| 6700417 prime?", smallest_factor(6700417) == 6700417)
print("checked divisors up to", math.isqrt(6700417), "for the second factor")

আসল আউটপুট (ব্রাউজারের Python):

n = 0: F = 3 is prime
n = 1: F = 5 is prime
n = 2: F = 17 is prime
n = 3: F = 257 is prime
n = 4: F = 65537 is prime
n = 5: F = 4294967297 = 641 x 6700417  <-- counterexample
641 prime? True | 6700417 prime? True
checked divisors up to 2588 for the second factor

পাঁচটি সত্য উদাহরণের পর n = 5-এ দাবি ভেঙেছে: 4294967297 = 641 × 6700417, দুটি ভাজকই মৌলিক। একটি counterexample-ই ∀n-দাবিকে চিরতরে মিথ্যা করে দিল; আগের পাঁচটি মিল কোনো কাজে আসেনি। Python-এর int যত বড় দরকার তত বড় হতে পারে, তাই 232 + 1 নিয়ে কোনো overflow সমস্যা নেই। শেষ লাইনে দেখা যাচ্ছে দ্বিতীয় ভাজকের জন্য 2588 পর্যন্ত ভাজক পরীক্ষা হয়েছে, কারণ কোনো যৌগিক m-এর অন্তত একটি ভাজক √m-এর বেশি নয়। F(6)-এ সংখ্যাটি ২০ অঙ্কের; সেখানে এই সরল পদ্ধতি দ্রুতই অচল হয়ে পড়ে, যা পর্ব ২৫ (Primality test আর factoring)-এর বিষয়।

এর উল্টো দিকটিও মনে রাখুন। n = 0 থেকে 4-এর পাঁচটি উদাহরণ ∃n (F(n) মৌলিক)-এর জন্য যথেষ্টর চেয়েও বেশি; একটি witness, যেমন n = 0, দিলেই হতো। কিন্তু ∀-দাবির জন্য এগুলো কিছুই প্রমাণ করে না। আজও জানা নেই n ≥ 5-এ কোনো F(n) মৌলিক কি না; এটি একটি খোলা প্রশ্ন বলে জানা যায়। Proof-এর পদ্ধতি নিয়ে বিস্তারিত পর্ব ০৮ আর পর্ব ০৯-এ।

৯ · দুই quantifier একসঙ্গে — পরের পর্বের এক ঝলক

অংশ ৫-এর বাক্যে দুটি quantifier ছিল। এমন বাক্যে quantifier-এর ক্রম অর্থ বদলে দেয়, এবং এটি পর্ব ০৫-এর পুরো বিষয়। এখানে শুধু একটি ছোট টেবিলে পার্থক্যটি দেখি। ডেলিভারিম্যান জানতে চান, তিন গ্রাহক কোন সময়ে বাসায় থাকেন। Free(x, y) মানে গ্রাহক x সময় y-তে বাসায় আছেন (১ = আছেন)।

  • ∀x ∃y Free(x, y): প্রতিটি গ্রাহকের নিজের কোনো একটি সুবিধাজনক সময় আছে। y গ্রাহক অনুযায়ী আলাদা হতে পারে।
  • ∃y ∀x Free(x, y): এমন একটি সময় আছে, যখন সবাই বাসায় থাকেন। একটি y সবার জন্য খাটতে হবে।
Free(x, y)সকালদুপুরসন্ধ্যা
রহিম100
করিম011
শিলা001
∀x∃y: প্রতিটি সারিতে একটি 1? · ∃y∀x: কোনো কলাম পুরো 1?
যা দেখছি
Witness
ফল
  1. একই টেবিল, দুটি প্রশ্ন। ∀x∃y Free(x, y) প্রতিটি সারি দেখে: প্রতিটি গ্রাহকের সারিতে অন্তত একটি 1 আছে কি? ∃y∀x Free(x, y) প্রতিটি কলাম দেখে: কোনো একটি কলাম কি পুরোটা 1?
  2. রহিম। সারি 1 0 0: সকালে বাসায় আছেন। রহিমের witness y = সকাল।
  3. করিম। সারি 0 1 1: দুপুর আর সন্ধ্যা দুটিই চলে; একটি witness-ই যথেষ্ট, ধরি দুপুর।
  4. শিলা। সারি 0 0 1: সন্ধ্যা। তিনটি সারিতেই 1 পাওয়া গেছে, তাই ∀x∃y Free(x, y) সত্য। খেয়াল করুন, witness তিনজনের জন্য আলাদা: y আসলে x-এর ওপর নির্ভর করে।
  5. এবার কলাম। সকালের কলাম 1 0 0: করিম আর শিলা নেই। দুপুরের কলাম 0 1 0: রহিম আর শিলা নেই। কোনোটিই পুরো 1 নয়।
  6. শেষ কলাম। সন্ধ্যার কলাম 0 1 1: রহিম নেই। কোনো কলামই পুরো 1 নয়, তাই ∃y∀x Free(x, y) মিথ্যা। অর্থাৎ ডেলিভারিম্যান একটি সময় বেছে সবাইকে একসঙ্গে পাবেন না, যদিও প্রত্যেককে আলাদা সময়ে পাবেন। ক্রম বদলানোয় অর্থ বদলে গেছে।

সাধারণভাবে ∃y∀x P(x, y) → ∀x∃y P(x, y) সবসময় সত্য (একটি সময় সবার জন্য খাটলে প্রত্যেকের জন্য সেটিই witness), কিন্তু উল্টোটি নয়, ওপরের টেবিলই তার counterexample. কেন, কোথায় কাজে লাগে, আর nested loop ও SQL-এর সঙ্গে এর সম্পর্ক কী, সবই পর্ব ০৫ (Nested quantifier — ক্রম বদলালে অর্থ বদলায়)-এ।

পরীক্ষা ও ইন্টারভিউতে: বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন সাধারণ।
১. "সব ছাত্র পরীক্ষায় পাস করেছে"-এর negation লিখুন। → "অন্তত একজন ছাত্র পাস করেনি": ∃x ¬Pass(x).
২. ∀x (x² > 0) domain ℤ-এ সত্য? → না, x = 0 counterexample; domain ℤ থেকে 0 বাদ দিলে সত্য।
৩. "কিছু প্রোগ্রামার Python জানেন" predicate logic-এ লিখুন। → ∃x (Programmer(x) ∧ Python(x)), → নয়।
৪. ∀x (P(x) ∨ Q(x)) ≡ ∀x P(x) ∨ ∀x Q(x)? → না; domain {1, 2}-এ জোড়/বিজোড় দিয়ে counterexample.
৫. ∃x (P(x) → Q(x))-এ কী সমস্যা? → P মিথ্যা এমন একটি x থাকলেই এটি সত্য, তাই প্রায় কিছুই বলে না।

আরও গভীরে: First-order logic-এ quantifier শুধু বস্তুর ওপর বসে; "প্রতিটি property P-এর জন্য…" লিখতে হলে second-order logic লাগে, যেমন mathematical induction-এর পূর্ণ রূপ (পর্ব ১০)। ১৯৩৬ সালে Alonzo Church আর Alan Turing আলাদাভাবে প্রমাণ করেন যে first-order logic-এর একটি সূত্র valid (সব domain-এ সত্য) কি না, তা বের করার কোনো সাধারণ algorithm নেই; অথচ শুধু এক-variable-এর predicate (arity ১) থাকলে সমস্যাটি decidable, যা ১৯১৫ সালের দিকে Leopold Löwenheim-এর কাজ থেকে জানা যায়। Lean বা Coq-এর মতো proof assistant এই ভাষার আরও শক্তিশালী রূপে গণিতের প্রমাণ কম্পিউটার দিয়ে যাচাই করে।

১০ · AI-এর যুগে — quantifier-এ AI কোথায় ভুল করে

AI সহকারীকে "এই বাক্যটি predicate logic-এ লেখো" বললে সাধারণত চকচকে, আত্মবিশ্বাসী উত্তর আসে। প্রায়ই উত্তরটি ঠিক। কিন্তু quantifier-এর ক্ষেত্রে কয়েকটি ভুল এত নিয়মিত দেখা যায় যে সেগুলো চিনে রাখা দরকার। গণিতে AI-এর সাধারণ দুর্বলতাও এখানে খাটে: আত্মবিশ্বাসী কিন্তু ভুল প্রমাণ (যা প্রমাণ করার কথা সেটিই ধরে নেওয়া, converse প্রমাণ করে দেওয়া), উপপাদ্যের শর্ত বাদ দেওয়া (যেমন "domain অশূন্য"), আর বানানো reference.

AI-এর ভুলউদাহরণকীভাবে ধরবেন
∃-এর সঙ্গে →"কিছু কুপন-অর্ডার ফ্রি" = ∃x (K(x) → Z(x))কুপনহীন একটি অর্ডারের domain-এ মান দেখুন
∀-এর সঙ্গে ∧"সব ঢাকার অর্ডার…" = ∀x (D(x) ∧ F(x))domain-এ একটি অন্য জেলার অর্ডার রাখুন
Negation-এ quantifier না উল্টানো¬∀x P(x) = ∀x ¬P(x)দুই বস্তুর domain-এ all/any দিয়ে মেলান
∀ কে ∨-এর ওপর ভাগ করা∀x (P ∨ Q) ≡ ∀x P ∨ ∀x Qজোড়/বিজোড় counterexample
Domain বা অশূন্যতার শর্ত বাদ"∀x P(x) → ∃x P(x) সবসময় সত্য"জিজ্ঞেস করুন: domain ফাঁকা হলে?

AI-কে অনুবাদ করতে দিলে শুধু সূত্র চাইবেন না; domain, predicate-এর অর্থ আর একটি যাচাইযোগ্য উদাহরণও চান। তখন ভুল থাকলে সেটি নিজেই ধরা পড়ে:

নিচের বাংলা বাক্যটি predicate logic-এ লেখো: "ঢাকার প্রতিটি অর্ডার ২৪ ঘণ্টায় ডেলিভার হয়, কিন্তু কিছু কুপন-অর্ডারে ডেলিভারি ফ্রি নয়।" ১. Domain কী, আর প্রতিটি predicate-এর অর্থ আলাদা লাইনে বলো। ২. প্রতিটি quantifier-এর সঙ্গে কেন → বা ∧ বেছেছ, এক লাইনে ব্যাখ্যা দাও। ৩. পুরো বাক্যের negation লেখো, প্রতিটি ধাপে কোন নিয়ম লাগালে তা বলো। ৪. চারটি অর্ডারের একটি ছোট উদাহরণ দাও, যেখানে মূল বাক্য মিথ্যা, আর দেখাও কোন অর্ডারটি counterexample. ৫. কোনো উপপাদ্য ব্যবহার করলে তার শর্ত (যেমন domain অশূন্য) স্পষ্ট লেখো।

AI-এর উত্তর যাচাইয়ের চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর "→ উত্তর" চাপুন।

প্র ০১Aristotle-এর যুক্তিবিদ্যা দুই হাজার বছর চলেছে। তাহলে Frege-এর quantifier কেন এত বড় বিপ্লব বলা হয়?

Aristotle-এর syllogism চার ধাঁচের বাক্য নিয়ে কাজ করত: "সব A হলো B", "কোনো A-ই B নয়", "কিছু A হলো B", "কিছু A B নয়"। এ দিয়ে "সব মানুষ মরণশীল, সক্রেটিস মানুষ, তাই সক্রেটিস মরণশীল" ধরনের যুক্তি চমৎকারভাবে চলে, আর প্রায় দুই হাজার বছর ধরে ইউরোপ ও মুসলিম বিশ্বের পণ্ডিতরা এটিকেই যুক্তিবিদ্যার মূল কাঠামো হিসেবে পড়িয়েছেন।

সমস্যা দেখা দেয় যখন একটি বাক্যে একাধিক "সব" আর "কিছু" জড়িয়ে যায়, আর বস্তুদের মধ্যে সম্পর্ক থাকে। "প্রতিটি সংখ্যার চেয়ে বড় কোনো একটি সংখ্যা আছে" আর "এমন একটি সংখ্যা আছে যা প্রতিটি সংখ্যার চেয়ে বড়" — প্রথমটি স্বাভাবিক সংখ্যায় সত্য, দ্বিতীয়টি মিথ্যা। Syllogism-এর চার ছাঁচে এই পার্থক্য লেখার উপায় নেই, কারণ সেখানে predicate সবসময় এক বস্তুর গুণ, দুই বস্তুর সম্পর্ক নয়। অথচ গণিত ঠিক এমন বাক্যে ভরা: limit, continuity, অসীম মৌলিক সংখ্যা।

১৮৭৯ সালে Gottlob Frege তাঁর Begriffsschrift-এ দুটি জিনিস একসঙ্গে আনেন: সম্পর্ক-predicate (যেমন Greater(x, y)) আর variable-কে বাঁধার জন্য quantifier, যা যেকোনো ক্রমে যেকোনো গভীরতায় বসানো যায়। এতে "multiple generality" নামের পুরোনো সমস্যাটি এক ধাক্কায় মিটে যায়। প্রায় একই সময়ে C. S. Peirce ও তাঁর ছাত্র O. H. Mitchell আলাদাভাবে একই ধারণায় পৌঁছান, আর আজকের প্রচলিত চিহ্নগুলো এসেছে মূলত Peano ও পরে Russell–Whitehead-এর ধারা থেকে। Frege-এর নিজের দ্বিমাত্রিক চিহ্ন এত জটিল ছিল যে প্রায় কেউই সেটি ব্যবহার করেননি।

এই বিপ্লবের ফল সুদূরপ্রসারী। গণিতের ভিত্তি (Hilbert-এর কর্মসূচি), Gödel-এর উপপাদ্য, Church ও Turing-এর computability, relational database, আর আজকের program verification — সবই predicate logic-এর ওপর দাঁড়িয়ে।

মূল উপলব্ধি: একটি ভালো notation শুধু লেখা সহজ করে না, নতুন চিন্তাও সম্ভব করে। ∀ আর ∃ যেকোনো ক্রমে বসাতে পারাই বলে দেয় "সবার জন্য একটি" আর "প্রত্যেকের জন্য নিজের একটি" আলাদা কথা।

প্র ০২"সব ইউনিকর্ন সাদা" কি সত্য? Aristotle আর আধুনিক logic এখানে কেন একমত নয়?

আধুনিক logic-এ উত্তর পরিষ্কার: ∀x (Unicorn(x) → White(x)) সত্য, কারণ কোনো ইউনিকর্নই নেই, তাই কোনো counterexample-ও নেই। একই যুক্তিতে "সব ইউনিকর্ন কালো"-ও সত্য। এটি অংশ ৭-এর vacuous truth. অনেকের কাছে এটি অস্বস্তিকর লাগে, আর সেই অস্বস্তির একটি দীর্ঘ ইতিহাস আছে।

Aristotle-এর ঐতিহ্যে "square of opposition" নামে একটি চিত্র ছিল, যেখানে "সব A হলো B" থেকে "কিছু A হলো B" অনুমান করা বৈধ ধরা হতো। এই অনুমান কাজ করে শুধু তখন, যখন ধরে নেওয়া হয় যে A-জাতীয় অন্তত একটি বস্তু আছে। একে বলে existential import. দৈনন্দিন ভাষায় আমরাও প্রায়ই এটি ধরে নিই: কেউ যদি বলেন "আমার সব সন্তান ডাক্তার", আমরা ধরে নিই তাঁর অন্তত একটি সন্তান আছে।

উনিশ শতকে George Boole (১৮৫৪ সালের Laws of Thought) আর পরে Frege-এর ধারার logic "সব A হলো B"-কে পড়ল একটি শর্ত হিসেবে: "যেকোনো বস্তু A হলে সেটি B". এতে existential import বাদ পড়ল, আর "সব A হলো B" থেকে "কিছু A হলো B" আর অনুমান করা যায় না। লাভটা বিশাল: সূত্রগুলো সরল ও নিয়মিত হলো, যেমন ¬∀x (A → B) ≡ ∃x (A ∧ ¬B) কোনো ব্যতিক্রম ছাড়াই খাটে। দাম হলো এই আপাত-অদ্ভুত vacuous truth.

Programming-এ এই সিদ্ধান্তই চলে। Python-এর all([]) সত্য, JavaScript-এর [].every(f) সত্য, SQL-এ "NOT EXISTS (খারাপ সারি)" ফাঁকা টেবিলে সত্য। এটি কোনো ডিজাইনের ভুল নয়, গণিতের সঙ্গে সঙ্গতি। কিন্তু এর ফলে বাস্তব bug হয়, যেমন ফাঁকা cart-কে "সব পরিশোধিত" ধরে নেওয়া। তাই কোড লেখার সময় নিজেকে জিজ্ঞেস করুন: "এখানে domain ফাঁকা হতে পারে কি, আর তখন আমি কী চাই?"

মূল উপলব্ধি: existential import বাদ দেওয়া একটি সচেতন ডিজাইন সিদ্ধান্ত, যা সূত্রকে নিয়মিত করে। আপনি যদি "অন্তত একটি আছে" বোঝাতে চান, সেটি আলাদা করে ∃ দিয়ে লিখুন।

প্র ০৩"All that glitters is not gold" — এই বাক্যের অর্থ কী? স্বাভাবিক ভাষায় negation আর quantifier-এর জট কেন বিপজ্জনক?

Shakespeare-এর The Merchant of Venice-এ আছে "All that glisters is not gold", যা আজ "All that glitters is not gold" হিসেবে প্রবাদ। আক্ষরিকভাবে পড়লে এর গঠন ∀x (Glitter(x) → ¬Gold(x)): "যা কিছু চকচক করে তার কোনোটিই সোনা নয়"। কিন্তু সবাই জানেন বোঝানো হচ্ছে ¬∀x (Glitter(x) → Gold(x)) ≡ ∃x (Glitter(x) ∧ ¬Gold(x)): "চকচক করলেই সোনা হবে, এমন নয়"। ¬ কতদূর পর্যন্ত খাটে, অর্থাৎ তার scope, ভাষা নিজে বলে দেয়নি; প্রসঙ্গ থেকে বুঝতে হয়।

বাংলাতেও একই জট আছে। "সব ছাত্র পাস করেনি" — এর মানে কি "একজনও পাস করেনি" (∀x ¬Pass(x)), নাকি "সবাই পাস করেনি, কেউ কেউ ফেল করেছে" (¬∀x Pass(x))? প্রসঙ্গ আর বলার সুর ছাড়া নিশ্চিত হওয়া কঠিন। প্রথমটি অনেক শক্ত দাবি; দ্বিতীয়টি মাত্র একজন ফেল করলেই সত্য।

দৈনন্দিন আড্ডায় এই অস্পষ্টতা বিশেষ ক্ষতি করে না। কিন্তু software-এর requirement, চুক্তি বা আইনের ভাষায় এটি গুরুতর। ধরুন বাজারঘরের নিয়মে লেখা "সব ব্যবহারকারী admin পাতা দেখতে পারবেন না"। Developer A এটিকে পড়লেন "কেউ পারবেন না", developer B পড়লেন "সবাই নয়, কেউ কেউ পারবেন"। দুজনেই নিজের মতো সঠিক কোড লিখলেন, আর নিরাপত্তায় ফাঁক তৈরি হলো। এজন্যই নিরাপত্তা-গুরুত্বপূর্ণ ব্যবস্থায় (রেলের signalling, বিমানের software, chip ডিজাইন) প্রায়ই requirement formal logic-এ লেখা হয়, যাতে একটিমাত্র অর্থ থাকে এবং একটি tool সেটি যাচাই করতে পারে। পর্ব ০৭-এ (কাজে যুক্তি — specification, ধাঁধা আর SAT solver) এর একটি ছোট রূপ দেখবেন।

ব্যবহারিক নিয়ম: কোনো বাক্যে "সব" আর "না" একসঙ্গে থাকলে সেটি দুইভাবে সূত্রে লিখুন, দুটির একটি ছোট উদাহরণে মান বের করুন, আর যিনি বাক্যটি লিখেছেন তাঁকে জিজ্ঞেস করুন কোনটি বোঝানো হয়েছে। নিজে লেখার সময় "কেউই … না" বা "অন্তত একজন … না" ধরনের স্পষ্ট শব্দ ব্যবহার করুন।

মূল উপলব্ধি: স্বাভাবিক ভাষা ¬-এর scope লুকিয়ে রাখে; predicate logic সেটি বন্ধনী দিয়ে বাধ্যতামূলকভাবে প্রকাশ করে। এই স্পষ্টতাই formal logic-এর আসল উপহার।

প্র ০৪SQL-এ EXISTS আছে, কিন্তু FOR ALL নেই। তাহলে "যে গ্রাহক প্রতিটি ক্যাটাগরি থেকে কিনেছেন" কীভাবে খোঁজা হয়?

Relational database-এর তত্ত্ব সরাসরি predicate logic থেকে এসেছে। E. F. Codd ১৯৭০ সালে relational model প্রস্তাব করেন, আর ১৯৭২ সালের দিকে একটি গবেষণাপত্রে relational calculus নামে একটি query ভাষা বর্ণনা করেন, যা আসলে first-order logic-এর একটি রূপ: "এমন সব গ্রাহক t দাও, যাদের জন্য সূত্র φ(t) সত্য"। SQL এই ধারণার একটি ব্যবহারিক বংশধর।

SQL-এ ∃-এর জন্য সরাসরি EXISTS (subquery) আছে। কিন্তু ∀-এর কোনো শব্দ নেই। সমাধান আসে এই পর্বের De Morgan থেকে: ∀y P(y) ≡ ¬∃y ¬P(y). "গ্রাহক c প্রতিটি ক্যাটাগরি থেকে কিনেছেন" হয়ে যায় "এমন কোনো ক্যাটাগরি নেই, যেখান থেকে c কেনেননি", আর "কেনেননি" নিজেও "এমন কোনো অর্ডার নেই" দিয়ে লেখা হয়। ফল দাঁড়ায় দুই স্তরের NOT EXISTS:

SELECT c.id FROM customers c
WHERE NOT EXISTS (SELECT 1 FROM categories k
  WHERE NOT EXISTS (SELECT 1 FROM orders o
    WHERE o.customer_id = c.id AND o.category_id = k.id));

এটি relational algebra-র "division" অপারেশনের একটি চেনা রূপ। লক্ষ করুন, ফাঁকা categories টেবিলে এই query প্রতিটি গ্রাহক ফেরত দেবে: ভেতরের NOT EXISTS ফাঁকা সেটের ওপর সত্য, ঠিক অংশ ৭-এর vacuous truth. এটি প্রায়ই টেস্টে অপ্রত্যাশিত ফল দেয়।

আরেকটি সূক্ষ্মতা: SQL-এ NULL থাকলে তুলনার ফল সত্য-মিথ্যার বাইরে "unknown" হতে পারে, তাই দুই-মানের logic-এর সব সূত্র সেখানে সরাসরি খাটে না। DBMS & SQL কোর্সের পর্ব ২১-এ EXISTS আর correlated subquery, আর পর্ব ১৬-এ NULL-এর তিন-মানের যুক্তি বিস্তারিত আছে।

মূল উপলব্ধি: ∀ না থাকলেও চলে, কারণ ¬∃¬ সবসময় ∀-এর কাজ করে দেয়। Quantifier-এর De Morgan সূত্র শুধু পরীক্ষার প্রশ্ন নয়, প্রতিদিনের database query-র ভিত্তি।

প্র ০৫সসীম domain-এ all()/any() দিয়ে যেকোনো বাক্য যাচাই করা যায়। তাহলে কম্পিউটার কি যেকোনো predicate logic-এর প্রশ্নের উত্তর দিতে পারে?

সসীম domain আর নির্দিষ্ট predicate দেওয়া থাকলে উত্তর হ্যাঁ: ∀ হলো একটি loop যা সব বস্তু দেখে, ∃ হলো একটি loop যা witness খোঁজে। কিন্তু খরচ দ্রুত বাড়ে। দুটি nested quantifier মানে n² বার পরীক্ষা, k-টি মানে nk. আর যদি প্রশ্ন হয় "এই সূত্র কি সব সম্ভাব্য predicate-এ সত্য?" (যেমন অংশ ৬-এর ব্লক), তাহলে n বস্তুর domain-এ একটি predicate-এরই 2n রকম অর্থ, দুটি predicate-এর 4n. n = 4-এ ২৫৬টি জোড়া, n = 20-এ এক ট্রিলিয়নের বেশি।

আসল কঠিন প্রশ্নটি হলো সব domain, অসীমগুলো সহ। ১৯২৮ সালে David Hilbert ও Wilhelm Ackermann প্রশ্নটি স্পষ্টভাবে তোলেন: এমন কোনো যান্ত্রিক পদ্ধতি কি আছে, যা যেকোনো first-order সূত্র দেখে বলে দেবে সেটি valid কি না? একে বলে Entscheidungsproblem ("সিদ্ধান্তের সমস্যা")। ১৯৩৬ সালে Alonzo Church আর Alan Turing আলাদাভাবে প্রমাণ করেন: না, এমন সাধারণ algorithm নেই। Turing এর জন্যই তাঁর বিখ্যাত machine-এর ধারণা তৈরি করেন, যা পর্ব ৭৫ (Turing machine-এর পরিচয়)-এর বিষয়।

তবে পুরো ছবিটি হতাশার নয়। ১৯২৯ সালে Kurt Gödel তাঁর completeness theorem-এ দেখান, প্রতিটি valid সূত্রের একটি সসীম প্রমাণ আছে। তাই একটি প্রোগ্রাম সব সম্ভাব্য প্রমাণ একে একে খুঁজে গেলে valid সূত্রের প্রমাণ একসময় পাবেই; শুধু অ-valid সূত্রে সে চিরকাল খুঁজতে পারে। আর কিছু সীমিত অংশ পুরোপুরি decidable, যেমন শুধু এক-variable-এর predicate নিয়ে গঠিত সূত্র।

এর একটি ব্যবহারিক শিক্ষাও আছে, অংশ ৮-এর Fermat উদাহরণে যা দেখেছেন: ছোট n-এ brute force দিয়ে counterexample খোঁজা খুব কার্যকর, কারণ ভুল দাবি সাধারণত ছোট উদাহরণেই ভাঙে। কিন্তু না ভাঙলে সেটি প্রমাণ নয়, শুধু আত্মবিশ্বাস। আজকের SMT solver আর proof assistant এই দুই পথ মেলায়: যেখানে সম্ভব যান্ত্রিক সিদ্ধান্ত, বাকিটায় মানুষের লেখা প্রমাণ কম্পিউটারে যাচাই।

মূল উপলব্ধি: সসীম ক্ষেত্রে কম্পিউটার সব দেখে ফেলতে পারে, অসীম ক্ষেত্রে মৌলিকভাবে পারে না। তাই গণিতে brute force দিয়ে খোঁজেন, প্রমাণ দিয়ে নিশ্চিত হন।

অনুশীলন

আগে খাতায় নিজে করুন, তারপর উত্তর মিলিয়ে নিন।

  1. প্রমাণ: সংজ্ঞা থেকে সরাসরি প্রমাণ করুন: ∃x (P(x) ∨ Q(x)) ≡ ∃x P(x) ∨ ∃x Q(x). তারপর দেখান কেন একই কৌশলে ∃x (P(x) ∧ Q(x)) ≡ ∃x P(x) ∧ ∃x Q(x) প্রমাণ করা যায় না।
    1. বাঁ থেকে ডান: ধরি ∃x (P(x) ∨ Q(x)), witness a: P(a) ∨ Q(a). P(a) হলে a হলো ∃x P(x)-এর witness; Q(a) হলে a হলো ∃x Q(x)-এর witness. দুই ক্ষেত্রেই ∃x P(x) ∨ ∃x Q(x).
    2. ডান থেকে বাঁ: ধরি ∃x P(x) (witness b). তাহলে P(b) ∨ Q(b) সত্য, তাই b হলো ∃x (P(x) ∨ Q(x))-এর witness. ∃x Q(x) হলেও একইভাবে। ∎

    ∧-এ কেন আটকায়: ডান থেকে বাঁয়ে যেতে ∃x P(x)-এর witness b আর ∃x Q(x)-এর witness c পাই, কিন্তু b আর c আলাদা বস্তু হতে পারে। P(b) ∧ Q(b) পেতে Q(b) দরকার, যা আমরা জানি না। Counterexample: domain {1, 2}, P = "জোড়", Q = "বিজোড়"। বাঁ থেকে ডান দিকটি অবশ্য খাটে: একই witness দুটি কাজই করে।

  2. গণনা: Domain-এ n = 4টি বস্তু। (ক) কতগুলো আলাদা predicate P (অর্থাৎ True/False-এর তালিকা) আছে? (খ) তাদের কয়টিতে ∀x P(x) সত্য, কয়টিতে ∃x P(x), আর কয়টিতে ∃!x P(x)? (গ) n = 3-এ কতগুলো জোড়া (P, Q)-তে ∀x (P(x) ∨ Q(x)) সত্য কিন্তু ∀x P(x) ∨ ∀x Q(x) মিথ্যা? সাধারণ n-এর সূত্র বের করুন।

    (ক) প্রতিটি বস্তুর জন্য দুটি পছন্দ, তাই 24 = ১৬টি।

    (খ) ∀: শুধু সব-True তালিকা, ১টি। ∃: সব-False বাদে বাকি সব, ১৬ − ১ = ১৫টি। ∃!: ঠিক একটি True, কোনটি তা বাছার ৪ উপায়, তাই ৪টি।

    (গ) ∀x (P ∨ Q) সত্য মানে প্রতিটি বস্তুতে (P, Q)-এর মান (T, T), (T, F) বা (F, T), অর্থাৎ প্রতি বস্তুতে ৩টি পছন্দ: মোট 3n. এদের মধ্যে ∀x P ∨ ∀x Q সত্য এমন জোড়া বাদ দিতে হবে। P সব-True হলে Q যেকোনো (2n), Q সব-True হলে P যেকোনো (2n), দুটিই সব-True একবার দুবার গোনা হয়েছে: 2·2n − 1 (এগুলো সবাই ∀x (P ∨ Q)-ও মানে)। তাই উত্তর 3n − 2·2n + 1. n = 3-এ 27 − 16 + 1 = ১২. n = 1, 2, 3, 4-এ সূত্র দেয় ০, ২, ১২, ৫০ — অংশ ৬-এর Python ব্লকের আউটপুটের সঙ্গে হুবহু মেলে। (গোনার এই "বাদ দিয়ে ফেরত যোগ" কৌশল পর্ব ৩১ আর পর্ব ৪৯-এ পূর্ণ রূপে আসবে।)

  3. প্রমাণের ভুল খুঁজুন: একজন লিখলেন — "দাবি: ∀x (P(x) ∨ Q(x)) → ∀x P(x) ∨ ∀x Q(x). প্রমাণ: ধরি ∀x (P(x) ∨ Q(x)). যেকোনো একটি a নিই; তাহলে P(a) ∨ Q(a). যদি P(a) সত্য হয়, তবে a যেকোনো ছিল বলে ∀x P(x). নইলে Q(a) সত্য, আর একই কারণে ∀x Q(x). তাই ∀x P(x) ∨ ∀x Q(x). ∎" কোথায় ভুল?

    ভুলটি "a যেকোনো ছিল বলে ∀x P(x)" ধাপে। a সত্যিই যেকোনো ছিল, কিন্তু "P(a) সত্য" ক্ষেত্রে ঢোকার পর a আর যেকোনো নয়: আমরা এমন a-র কথা বলছি যার জন্য P খাটে। কোন ক্ষেত্রে পড়ব তা a-র ওপর নির্ভর করে; এক a P-এর ক্ষেত্রে, আরেক a Q-এর ক্ষেত্রে পড়তে পারে। সাধারণীকরণ (universal generalization) তখনই বৈধ, যখন a সম্পর্কে কোনো বাড়তি ধারণা ব্যবহার হয়নি; পর্ব ০৬-এ নিয়মটি পূর্ণ শর্তসহ আসবে। Counterexample: domain {1, 2}, P = "বিজোড়", Q = "জোড়"। ∀x (P ∨ Q) সত্য, কিন্তু ∀x P আর ∀x Q দুটিই মিথ্যা।

  4. অনুবাদ, negation আর আউটপুট অনুমান: Domain: বাজারঘরের সব পাসওয়ার্ড। নিয়ম: "প্রতিটি পাসওয়ার্ডে অন্তত একটি অঙ্ক আছে, এবং কোনো পাসওয়ার্ড ৮ অক্ষরের চেয়ে ছোট নয়।" (ক) G(p): p-তে অঙ্ক আছে, S(p): p ৮ অক্ষরের চেয়ে ছোট, ধরে সূত্র লিখুন। (খ) Negation লিখুন, সরল করে। (গ) pw = ["dhaka2026", "rikshaw", "a1b2"] হলে নিচের দুই লাইন কী ছাপবে, না চালিয়ে অনুমান করুন:
    print(all(any(ch.isdigit() for ch in p) and len(p) >= 8 for p in pw))
    print([p for p in pw if not any(ch.isdigit() for ch in p) or len(p) < 8])

    (ক) ∀p G(p) ∧ ¬∃p S(p), যা অংশ ৫ ও ৬-এর নিয়মে ≡ ∀p (G(p) ∧ ¬S(p)).

    (খ) ¬∀p (G(p) ∧ ¬S(p)) ≡ ∃p ¬(G(p) ∧ ¬S(p)) ≡ ∃p (¬G(p) ∨ S(p)): "অন্তত একটি পাসওয়ার্ড আছে, যাতে কোনো অঙ্ক নেই অথবা যেটি ৮ অক্ষরের চেয়ে ছোট।"

    (গ) প্রথম লাইন False. দ্বিতীয় লাইন ['rikshaw', 'a1b2']. কারণ: "dhaka2026"-এ ৯টি অক্ষর আর অঙ্ক আছে, নিয়ম মানে। "rikshaw"-এ ৭টি অক্ষর, কোনো অঙ্ক নেই (দুই কারণেই ব্যর্থ)। "a1b2"-এ অঙ্ক আছে কিন্তু মাত্র ৪টি অক্ষর। দ্বিতীয় লাইনটি আসলে (খ)-এর negation-এর সব witness তালিকা করে। দুটি লাইনই এই পাতার ব্লকে বসিয়ে চালিয়ে মিলিয়ে নিতে পারেন।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি বাংলা বাক্যকে predicate logic-এ লেখার ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. Domain of discourse ঠিক করা
  2. প্রতিটি গুণ বা সম্পর্কের জন্য predicate-এর নাম আর অর্থ লেখা
  3. "সব/প্রতিটি" হলে ∀, "কিছু/অন্তত একটি" হলে ∃ বাছা
  4. শর্তের সঙ্গে connective বাছা: ∀-এর সঙ্গে →, ∃-এর সঙ্গে ∧
  5. ছোট একটি domain-এ মান বের করে বাক্যের অর্থের সঙ্গে মেলানো

Domain {1, 2, 3, 4} হলে নিচের কোনটি সত্য?

  • ∀x (x জোড় → x > 1)
  • ∃x (x > 3 ∧ x বিজোড়)
  • ∀x (x² > x)
  • ∃x (x > 4)

¬∀x (C(x) → P(x)) কোনটির সমান?

  • ∀x (C(x) → ¬P(x))
  • ∃x (C(x) → ¬P(x))
  • ∃x (C(x) ∧ ¬P(x))
  • ¬∃x (C(x) ∧ ¬P(x))

Domain: একটি অনলাইন দোকানের সব অর্ডার; B(x): x বাতিল, R(x): x-এ রিভিউ আছে। "কোনো বাতিল অর্ডারে রিভিউ নেই" বাক্যের সঠিক সূত্র কোনটি?

  • ∀x (B(x) ∧ ¬R(x))
  • ∀x (B(x) → ¬R(x))
  • ∃x (B(x) → ¬R(x))
  • ¬∀x (B(x) → ¬R(x))

নিচের কোন equivalence সাধারণভাবে (সব domain আর সব predicate-এ) সত্য নয়?

  • ¬∃x P(x) ≡ ∀x ¬P(x)
  • ∀x (P(x) ∧ Q(x)) ≡ ∀x P(x) ∧ ∀x Q(x)
  • ∃x (P(x) ∨ Q(x)) ≡ ∃x P(x) ∨ ∃x Q(x)
  • ∀x (P(x) ∨ Q(x)) ≡ ∀x P(x) ∨ ∀x Q(x)

সূত্র ∀x (P(x) → Q(x, y)) ∧ R(z)-এ কোন variable-গুলো free?

  • শুধু x
  • y আর z
  • শুধু z
  • কোনোটিই নয়

Python-এ xs = [] হলে all(x > 5 for x in xs) আর any(x > 5 for x in xs) যথাক্রমে কী দেয়?

  • False, False
  • True, True
  • True, False
  • Error দেয়, কারণ তালিকা ফাঁকা

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Predicate একটি ফাঁকা ঘরওয়ালা ছাঁচ; মান বসালে বা quantifier দিলে তবেই proposition. Domain না জেনে মান ঠিক হয় না।
  2. সসীম domain-এ ∀ = লম্বা ∧, ∃ = লম্বা ∨; ∀ ভাঙতে একটি counterexample, ∃ প্রমাণে একটি witness.
  3. "সব C-ই P" = ∀x (C(x) → P(x)); "কিছু C P" = ∃x (C(x) ∧ P(x)).
  4. ¬∀ ≡ ∃¬ আর ¬∃ ≡ ∀¬; ∀ ভাগ হয় ∧-এ, ∃ ভাগ হয় ∨-এ, উল্টোগুলো নয়।
  5. ফাঁকা domain-এ ∀ সত্য, ∃ মিথ্যা (all([]), any([])); কয়েকটি উদাহরণে মিলে যাওয়া কখনো ∀-এর প্রমাণ নয়।

পরের পর্বে: অংশ ৯-এর টেবিলে দেখলেন ∀x∃y আর ∃y∀x আলাদা। পর্ব ০৫-এ এই nested quantifier-এর পুরো গল্প: ক্রম বদলালে কেন অর্থ বদলায়, কীভাবে এমন বাক্য negate করবেন, আর nested loop ও SQL-এ এর চেহারা কেমন।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান