এই পর্বে যা শিখবেন
- Roster আর set-builder দুই ভাবে সেট লেখা; ℕ, ℤ, ℤ⁺, ℚ, ℝ, ℂ চেনা
- সমতা, ফাঁকা সেট, subset আর proper subset; element chasing আর double inclusion দিয়ে প্রমাণ লেখা
- Venn diagram পড়া; cardinality গোনা; power set বানানো আর |P(S)| = 2ⁿ প্রমাণ
- Ordered pair, tuple আর Cartesian product; relation কেন A × B-এর subset
- Predicate থেকে truth set; Russell-এর paradox আর তার সমাধানের ধারণা; Python-এ set আর frozenset
১ · সেট আর উপাদান — তালিকা করে, না নিয়ম দিয়ে?
বাজারঘরের মার্কেটিং দল জানতে চায়: এই বছর ঢাকার কোন কোন ক্রেতা অর্ডার দিয়েছেন? উত্তরে একটি তালিকা আসে: 101, 103, 105. কেউ দুবার অর্ডার দিলেও তাঁর id তালিকায় একবারই থাকবে, আর কোন id আগে লেখা হলো তাতে কিছু আসে যায় না। প্রশ্নটি আসলে “কে আছেন, কে নেই”, এর বেশি কিছু নয়। ঠিক এই ধারণাটিকে গণিতে বলে সেট।
একটি সেট হলো আলাদা আলাদা বস্তুর একটি সংগ্রহ। সংগ্রহের বস্তুগুলোকে বলে সেটের উপাদান (element বা member). x যদি A-এর উপাদান হয়, লেখা হয় x ∈ A (“x, A-তে আছে”); না হলে x ∉ A.
এই “সংজ্ঞা” আসলে পুরোপুরি নিখুঁত নয়, কারণ “সংগ্রহ” শব্দটি নিজেই সেটের আরেক নাম। গণিতে সেটকে সাধারণত একটি মৌলিক ধারণা ধরা হয়, যেমন জ্যামিতিতে বিন্দু। §৮-এ দেখবেন, এই ঢিলেঢালা সংজ্ঞা কোথায় বিপদে পড়ে আর কীভাবে তা সারানো হয়েছে। আপাতত দুটি নিয়ম মনে রাখুন: যেকোনো বস্তু x আর সেট A-এর জন্য “x ∈ A” বাক্যটি হয় সত্য, নয় মিথ্যা; আর একটি সেট পুরোপুরি নির্ধারিত হয় তার উপাদান দিয়ে।
দুই ভাবে লেখা: roster আর set-builder
Roster notation-এ উপাদানগুলো দ্বিতীয় বন্ধনীর ভেতরে একে একে লেখা হয়: D = {101, 103, 105}. প্যাটার্ন পরিষ্কার হলে তিন বিন্দু চলে: {1, 2, 3, …, 100} বা {0, 2, 4, …}. কিন্তু তিন বিন্দু পাঠকের অনুমানের ওপর নির্ভর করে; {1, 2, 4, …}-এর পরের সংখ্যা 8 না 7, বলা কঠিন। তাই নিখুঁত লেখার জন্য আছে set-builder notation: {x ∈ U : P(x)}, পড়া হয় “U-এর সেই সব x, যাদের জন্য P(x) সত্য”। যেমন
E = {n ∈ ℤ : n = 2k কোনো k ∈ ℤ-এর জন্য} = {…, −4, −2, 0, 2, 4, …}
এখানে কোলন “:” (কিছু বইয়ে খাড়া দাগ) মানে “যেন”। P(x) হলো পর্ব ০৪-এর একটি predicate. বাজারঘরের ভাষায়: {c ∈ ক্রেতা : c-এর জেলা ঢাকা এবং এই মাসে অর্ডার ≥ 3}. দুটি লেখার ধরনের মধ্যে পার্থক্য রেস্তোরাঁর মেনু আর রেসিপির মতো: roster পুরো তালিকা দেয়, set-builder বলে দেয় কোন শর্তে কোনো কিছু তালিকায় ঢুকবে।
স্কুলের হাজিরা খাতার কথা ভাবুন। “আজ উপস্থিত ছাত্রছাত্রী” একটি সেট: কেউ দুবার “উপস্থিত” বললে তিনি দুজন হয়ে যান না, আর রোল নম্বর কোন ক্রমে ডাকা হলো তাতে উপস্থিতির তালিকা বদলায় না। রোল ১ থেকে ৪০ সবার নাম লিখলে roster; “যাদের নামের পাশে টিক আছে” বললে set-builder.
যে সেটগুলো সবাই চেনে
| চিহ্ন | নাম | উপাদান |
|---|---|---|
| ℕ | স্বাভাবিক সংখ্যা | {0, 1, 2, 3, …} (এই কোর্সে) |
| ℤ | পূর্ণসংখ্যা | {…, −2, −1, 0, 1, 2, …} |
| ℤ⁺ | ধনাত্মক পূর্ণসংখ্যা | {1, 2, 3, …} |
| ℚ | মূলদ সংখ্যা | {p/q : p, q ∈ ℤ, q ≠ 0} |
| ℝ | বাস্তব সংখ্যা | সংখ্যারেখার সব বিন্দু, যেমন √2, π |
| ℂ | জটিল সংখ্যা | {a + bi : a, b ∈ ℝ}, যেখানে i² = −1 |
একটি সতর্কতা: 0 স্বাভাবিক সংখ্যা কি না, তা নিয়ে বইগুলো একমত নয়। Computer science-এর বেশিরভাগ বই আর আন্তর্জাতিক মান ISO 80000-2 ℕ-এ 0 রাখে; অনেক সংখ্যাতত্ত্ব আর বিশ্লেষণের বই রাখে না। এই কোর্সে ℕ = {0, 1, 2, …} (পর্ব ১১-এর well-ordering-ও এভাবেই লেখা); যেখানে 0 বাদ দিতে হবে, সেখানে ℤ⁺ লিখব। পরীক্ষায় বা কোনো বই পড়ার সময় প্রথমেই দেখে নিন কোন প্রথা চলছে। সংখ্যার সেট ছাড়াও সেটের উপাদান যেকোনো কিছু হতে পারে: জেলার নাম, পণ্যের id, string, এমনকি অন্য সেট। {ঢাকা, 7, {1, 2}} একটি বৈধ সেট, যার তিনটি উপাদান; তৃতীয়টি নিজেই একটি সেট।
২ · সমতা, ফাঁকা সেট আর subset — element chasing দিয়ে প্রমাণ
দুটি সেট A আর B সমান, লেখা A = B, ঠিক তখন যখন তাদের উপাদান হুবহু এক: ∀x (x ∈ A ↔ x ∈ B). এই নীতিকে বলে extensionality.
এই এক লাইনের সংজ্ঞা থেকেই আসে যে ক্রম আর পুনরাবৃত্তির গুরুত্ব নেই: {1, 3, 5}, {5, 3, 1} আর {1, 1, 3, 5} একই সেট, কারণ “x কি এখানে আছে?” প্রশ্নের উত্তর তিনটিতেই এক। আবার {x ∈ ℝ : x² − 5x + 6 = 0} আর {2, 3} একই সেট, যদিও লেখা সম্পূর্ণ আলাদা; সেট তার লেখার ধরন নয়, তার উপাদান।
ফাঁকা সেট আর {∅}
যে সেটে কোনো উপাদান নেই, তাকে বলে ফাঁকা সেট (empty set), লেখা হয় ∅ বা { }. যেমন {x ∈ ℤ : x² = 2} = ∅, কারণ কোনো পূর্ণসংখ্যার বর্গ 2 নয়। ঠিক একটি উপাদানের সেটকে বলে singleton. এখানে একটি ক্লাসিক ফাঁদ: ∅ আর {∅} এক নয়। ∅ একটি খালি বাক্স; {∅} একটি বাক্স, যার ভেতরে একটি খালি বাক্স রাখা। প্রথমটিতে উপাদান শূন্যটি, দ্বিতীয়টিতে একটি। আবার 0 (একটি সংখ্যা) আর ∅ (একটি সেট) দুটিও আলাদা বস্তু।
A হলো B-এর subset (উপসেট), লেখা A ⊆ B, যদি A-এর প্রতিটি উপাদান B-তেও থাকে: ∀x (x ∈ A → x ∈ B). A ⊆ B কিন্তু A ≠ B হলে A হলো B-এর proper subset, লেখা A ⊂ B (কিছু বইয়ে A ⊊ B).
খেয়াল করুন, ⊆-এর সংজ্ঞা একটি conditional দিয়ে লেখা, তাই পর্ব ০২-এর vacuous truth এখানে সরাসরি কাজে লাগে।
যেকোনো সেট S-এর জন্য (ক) ∅ ⊆ S, (খ) S ⊆ S. আর (গ) ফাঁকা সেট একটিই।
প্রমাণ:
- (ক) দেখাতে হবে ∀x (x ∈ ∅ → x ∈ S). যেকোনো x-এর জন্য x ∈ ∅ মিথ্যা, কারণ ∅-এ কোনো উপাদান নেই। — ∅-এর সংজ্ঞা
- মিথ্যা hypothesis-এর conditional সত্য, তাই প্রতিটি x-এর জন্য conditional-টি সত্য, অর্থাৎ ∅ ⊆ S. — vacuous proof (পর্ব ০৮)
- (খ) x ∈ S → x ∈ S একটি tautology (p → p), তাই S ⊆ S. — পর্ব ০৩
- (গ) ধরি E1 আর E2 দুটিই ফাঁকা সেট। (ক) অনুযায়ী E1 ⊆ E2 আর E2 ⊆ E1. — (ক), দুবার
- দুই দিকের ⊆ মানে ∀x (x ∈ E1 ↔ x ∈ E2), তাই extensionality অনুযায়ী E1 = E2. ∎ — সংজ্ঞা ২.১
ধাপ ৪–৫-এর কৌশলটি এতই গুরুত্বপূর্ণ যে আলাদা করে লিখে রাখি: A = B ⇔ (A ⊆ B এবং B ⊆ A). এটি p ↔ q ≡ (p → q) ∧ (q → p) সমতুল্যতার (পর্ব ০৩) সেট-রূপ। দুটি সেট সমান দেখানোর সবচেয়ে প্রচলিত পথ তাই double inclusion: দুই দিকের subset আলাদা আলাদা প্রমাণ। আর একটি subset প্রমাণের পথ হলো element chasing: A-এর একটি যেকোনো উপাদান ধরে, সংজ্ঞা খুলে, তাকে B পর্যন্ত “তাড়া” করা।
1লক্ষ্য: ∀n (n ∈ A → n ∈ B)2ধরি n ∈ A, যেকোনো3তাহলে n = 6k, k ∈ ℤ4n = 2(3k), 3k ∈ ℤ5তাই n ∈ B6A ⊆ B; আর 2 ∈ B, 2 ∉ A
| যা জানি | |
| নিয়ম | |
| নমুনা n = 18 |
- লক্ষ্য লেখা। A ⊆ B মানে ∀n (n ∈ A → n ∈ B). A হলো 6-এর গুণিতক, B হলো জোড় সংখ্যা। কয়েকটি উদাহরণ দেখা প্রমাণ নয়; লাগবে সব n-এর জন্য যুক্তি।
- যেকোনো একটি উপাদান। ধরি n ∈ A, কিন্তু n সম্পর্কে আর কিছু ধরে নিই না। ডানের নমুনা n = 18 শুধু চোখের সুবিধার জন্য; যুক্তি n-এর কোনো নির্দিষ্ট মানের ওপর নির্ভর করবে না।
- সংজ্ঞা খোলা। n ∈ A মানে কোনো পূর্ণসংখ্যা k আছে, যার জন্য n = 6k. নমুনায় k = 3.
- B-এর রূপে আনা। n = 6k = 2(3k). পূর্ণসংখ্যার গুণফল পূর্ণসংখ্যা, তাই m = 3k ∈ ℤ. নমুনায় 18 = 2 · 9.
- সংজ্ঞা মোড়া। n = 2m আর m ∈ ℤ, ঠিক এটিই B-এর সদস্য হওয়ার শর্ত। তাই n ∈ B.
- সিদ্ধান্ত। n ছিল A-এর যেকোনো উপাদান, তাই universal generalization (পর্ব ০৬) অনুযায়ী A ⊆ B. Proper কি না দেখতে B-এর এমন একটি উপাদান দরকার যা A-তে নেই: 2 জোড়, কিন্তু 6-এর গুণিতক নয়। তাই A ⊂ B. ∎
Double inclusion-এর একটি পূর্ণ উদাহরণ
{n ∈ ℤ : n² জোড়} = {n ∈ ℤ : n জোড়}.
প্রমাণ: বাম সেটকে L, ডান সেটকে R বলি।
- (R ⊆ L) ধরি n ∈ R, তাহলে n = 2k কোনো k ∈ ℤ-এর জন্য। n² = 4k² = 2(2k²), তাই n² জোড়, অর্থাৎ n ∈ L. — element chasing, direct proof
- (L ⊆ R) দেখাতে হবে n² জোড় → n জোড়। Contrapositive দেখাই: n বিজোড় → n² বিজোড়। — contrapositive (পর্ব ০৮)
- n = 2k + 1 হলে n² = 4k² + 4k + 1 = 2(2k² + 2k) + 1, যা বিজোড়। তাই n ∈ L হলে n ∈ R. — বীজগণিত
- দুই দিকের subset থেকে L = R. ∎ — double inclusion
আরেকটি সহজ কিন্তু দরকারি ফল: ⊆ transitive, অর্থাৎ A ⊆ B আর B ⊆ C হলে A ⊆ C. প্রমাণ দুই লাইনের: x ∈ A হলে প্রথম শর্তে x ∈ B, দ্বিতীয় শর্তে x ∈ C. ∎ (hypothetical syllogism, পর্ব ০৬)। কিন্তু ∈ transitive নয়, আর এখানেই অনেকে ভুল করেন; অনুশীলন ৪ দেখুন।
প্রমাণের ভুল ধরুন: একজন লিখলেন, “6, 12, 18, −6 আর 600 সবই জোড়, তাই 6-এর সব গুণিতক জোড়, অর্থাৎ A ⊆ B. ∎” ভুলটি হলো পাঁচটি উদাহরণকে অসীম সংখ্যক উপাদানের প্রমাণ ধরা। উদাহরণ A ⊆ B-কে বিশ্বাসযোগ্য করে, প্রমাণ করে না; এমন দাবি ভাঙতে একটি counterexample যথেষ্ট, কিন্তু প্রতিষ্ঠা করতে যেকোনো উপাদান নিয়ে যুক্তি লাগে, যা stepper-এ দেখলেন। উল্টো দিকে, A ⊄ B দেখাতে একটিমাত্র x ∈ A, x ∉ B-ই যথেষ্ট।
৩ · Universal set আর Venn diagram — ছবিতে সেট
কোনো আলোচনায় যে বড় সেটের ভেতরে সব কিছু ঘটে, তাকে বলে universal set U; এটি পর্ব ০৪-এর domain of discourse-এর সেট-রূপ। বাজারঘরের বিশ্লেষণে U = বাজারঘরের সব ক্রেতা। U-এর ভেতরে সেটগুলো আঁকার একটি জনপ্রিয় উপায় হলো Venn diagram: আয়তক্ষেত্র U, আর প্রতিটি সেট একটি বৃত্ত। ইংরেজ যুক্তিবিদ John Venn ১৮৮০ সালের একটি প্রবন্ধে এই ধরনের ছবি জনপ্রিয় করেন; এর আগে Euler-সহ অনেকে কাছাকাছি ছবি ব্যবহার করেছিলেন।
বাজারঘরের ছয় ক্রেতা, তিনটি সেট
D = ঢাকার ক্রেতা, L = ঢাকার যাঁরা এই মাসে ৩টি বা বেশি অর্ডার দিয়েছেন, M = মোবাইল অ্যাপ ব্যবহারকারী
Venn diagram চিন্তার জন্য চমৎকার, কিন্তু প্রমাণ হিসেবে দুর্বল। প্রথমত, ছবিতে একটি “সাধারণ” অবস্থান আঁকা হয়; বিশেষ ক্ষেত্র (কোনো অংশ ফাঁকা, বা দুটি সেট সমান) ছবিতে চোখে পড়ে না। দ্বিতীয়ত, চারটি বা তার বেশি সেটে বৃত্ত দিয়ে সব সম্ভাব্য অংশ আঁকা যায় না; অন্য আকার লাগে। তাই এই কোর্সে Venn diagram দিয়ে অনুমান করব, আর প্রমাণ লিখব element chasing দিয়ে। Union, intersection, complement-এর মতো অপারেশন আর তাদের identity পরের পর্ব, পর্ব ১৫ “সেটের অপারেশন — union, intersection, Venn diagram আর identity”-এ; সেখানে দেখবেন এই নিয়মগুলো আসলে Boolean algebra-র নিয়মের আরেক চেহারা, যা কম্পিউটার আর্কিটেকচার কোর্সের পর্ব ৭-এ সার্কিটের দিক থেকে আছে।
৪ · Cardinality আর power set — 2ⁿ টি subset
একটি সসীম সেট S-এ ঠিক n টি আলাদা উপাদান থাকলে (n ∈ ℕ) S হলো finite set, আর n হলো S-এর cardinality, লেখা |S| = n. যেমন |{101, 103, 105}| = 3, |∅| = 0, |{∅}| = 1, |{1, {1}, {1, 2}, ∅}| = 4. শেষেরটিতে {1, 2}-এর ভেতরের দুটি সংখ্যা আলাদা করে গোনা হয় না; বাইরের সেটে এটি একটিমাত্র উপাদান। সসীম নয় এমন সেট (ℕ, ℤ, ℝ) infinite; অসীম সেটের “আকার” তুলনা, অর্থাৎ ℕ আর ℝ-এর মধ্যে কোনটি “বড়”, সেই গল্প পর্ব ১৮ “Cardinality — countable, uncountable আর Cantor-এর diagonal”-এ।
একটি সেট S-এর power set P(S) হলো S-এর সব subset-এর সেট: P(S) = {T : T ⊆ S}. উপপাদ্য ২.৩ অনুযায়ী ∅ আর S নিজে সবসময় P(S)-এর উপাদান।
বাজারঘর তিনটি পণ্য a (চাল), b (ডাল), c (তেল) দিয়ে “কম্বো প্যাক” বানাতে চায়; যেকোনো সংগ্রহ একটি কম্বো, এমনকি কিছু না নেওয়াও (খালি ব্যাগ)। কয়টি কম্বো সম্ভব? প্রশ্নটি আসলে |P({a, b, c})| কত। নিচের stepper প্রতিটি নতুন পণ্য যোগ করে তালিকাটি দ্বিগুণ করে।
1P = [∅]2for x in a, b, c:3 P += প্রতিটি T-তে x4# |P| = 2^3 = 8
| নতুন পণ্য x | |
| আগের subset | |
| x যোগ করে নতুন | |
| |P| |
- শুরু ফাঁকা সেট দিয়ে। কোনো পণ্য না থাকলে একটিমাত্র কম্বো: খালি ব্যাগ। তাই P(∅) = {∅}, যার cardinality 1, শূন্য নয়।
- a যোগ। আগের প্রতিটি subset দুবার আসে: একবার a ছাড়া (∅), একবার a-সহ ({a})। তালিকা 1 থেকে 2.
- b যোগ। আগের দুটি (∅, {a}) রেখে প্রতিটিতে b যোগ করে নতুন দুটি ({b}, {a, b})। মোট 4. কোনো subset দুবার আসে না, কারণ নতুনগুলোতে b আছে, পুরোনোগুলোতে নেই।
- c যোগ। আগের চারটির প্রতিটিতে c যোগ করে নতুন চারটি: {c}, {a, c}, {b, c}, {a, b, c}. মোট 8 = 2³. এটি পর্ব ১০-এর inductive step-ই, হাতে করা।
- Bit string-এর চোখে। প্রতিটি subset-কে তিন অঙ্কের একটি bit string দিয়ে লেখা যায়: a, b, c ক্রমে, থাকলে 1, না থাকলে 0. যেমন {a, c} = 101. আটটি subset ঠিক আটটি 3-bit string-এর সঙ্গে এক-এক মেলে।
|S| = n হলে |P(S)| = 2ⁿ (n ≥ 0).
পর্ব ১০-এ এই উপপাদ্য n-এর ওপর induction দিয়ে প্রমাণ হয়েছে (stepper-এর দ্বিগুণ করার যুক্তিটিই)। এখানে দ্বিতীয় একটি প্রমাণ দেখি, যা গণনার একটি শক্তিশালী কৌশলের প্রথম স্বাদ দেয়।
প্রমাণ (bit string-এর সঙ্গে এক-এক মিল):
- S-এর উপাদানগুলো একটি নির্দিষ্ট ক্রমে লিখি: s1, s2, …, sn. — S সসীম
- প্রতিটি T ⊆ S-এর জন্য দৈর্ঘ্য n-এর একটি bit string b(T) = b1b2…bn বানাই: si ∈ T হলে bi = 1, না হলে 0. — সংজ্ঞা
- দুটি আলাদা subset T ≠ T′ হলে extensionality অনুযায়ী কোনো si একটিতে আছে, অন্যটিতে নেই; তাই b(T) আর b(T′) i-তম অঙ্কে আলাদা। অর্থাৎ আলাদা subset পায় আলাদা string. — সংজ্ঞা ২.১
- উল্টো দিকে, যেকোনো string b1…bn থেকে T = {si : bi = 1} নিলে b(T) ঠিক সেই string. তাই প্রতিটি string কোনো না কোনো subset থেকে আসে। — set-builder
- ধাপ ৩ আর ৪ মিলে subset আর string-এর মধ্যে এক-এক মিল (bijection; পর্ব ১৬-এ বিস্তারিত), তাই দুটির সংখ্যা সমান। — এক-এক মিল
- দৈর্ঘ্য n-এর bit string-এ প্রতিটি অঙ্কে 2টি বিকল্প, অঙ্কগুলো স্বাধীন, তাই 2 · 2 ⋯ 2 = 2ⁿ টি string (গুণের নিয়ম; পর্ব ৩১-এ সাধারণভাবে)। ∎ — product rule
এই প্রমাণ শুধু সংখ্যা দেয় না, একটি algorithm-ও দেয়: 0 থেকে 2ⁿ − 1 পর্যন্ত প্রতিটি সংখ্যার binary রূপকে একটি subset হিসেবে পড়ুন। প্রোগ্রামাররা একে bitmask বলেন (পর্ব ০২-এর bit string). নিচের ব্লক দুই পদ্ধতিতেই power set বানায়, দেখে n = 10 পর্যন্ত দুটি একই পরিবার দেয় কি না আর আকার 2ⁿ কি না, আর কয়েকটি পরীক্ষার প্রশ্নের উত্তর যাচাই করে। প্রথমবার চালালে ব্রাউজারে Python (Pyodide) নামতে কয়েক সেকেন্ড লাগে।
from itertools import combinations, chain
def power_set(S): # subsets grouped by size k = 0..n
S = list(S)
return [frozenset(c) for k in range(len(S) + 1) for c in combinations(S, k)]
def power_set_bits(S): # subset <-> bit string of length n
S = list(S)
return [frozenset(S[i] for i in range(len(S)) if mask >> i & 1)
for mask in range(2 ** len(S))]
S = ["a", "b", "c"]
for sub in power_set(S):
bits = "".join("1" if x in sub else "0" for x in S)
print(bits, "{" + ", ".join(x for x in S if x in sub) + "}")
ok = all(len(power_set(range(n))) == 2 ** n and
set(power_set(range(n))) == set(power_set_bits(range(n)))
for n in range(11))
print("n = 0..10: |P(S)| == 2**n and both methods agree:", ok)
E = frozenset() # the empty set
P1 = power_set([E]) # P({∅})
print("|P(∅)| =", len(power_set([])), " |P({∅})| =", len(P1),
" |P(P({∅}))| =", len(power_set(P1)))
print("proper subsets of a 5-set:", len(power_set(range(5))) - 1)
print("subsets of size 3 of a 10-set:",
sum(1 for T in power_set(range(10)) if len(T) == 3))
print("2**20 =", 2 ** 20, " 2**64 =", 2 ** 64)আসল আউটপুট (ব্রাউজারের Python):
000 {}
100 {a}
010 {b}
001 {c}
110 {a, b}
101 {a, c}
011 {b, c}
111 {a, b, c}
n = 0..10: |P(S)| == 2**n and both methods agree: True
|P(∅)| = 1 |P({∅})| = 2 |P(P({∅}))| = 4
proper subsets of a 5-set: 31
subsets of size 3 of a 10-set: 120
2**20 = 1048576 2**64 = 18446744073709551616
প্রথম আট লাইন P({a, b, c}), আকার অনুযায়ী সাজানো: 1টি ফাঁকা, 3টি এক-উপাদানের, 3টি দুই-উপাদানের, 1টি পুরো সেট; 1 + 3 + 3 + 1 = 8. এরপর n = 0 থেকে 10 পর্যন্ত দুই পদ্ধতি একই পরিবার দিল, আকার 2ⁿ. তৃতীয় অংশটি পরীক্ষার প্রিয় প্রশ্ন: |P(∅)| = 1 (শূন্য নয়), |P({∅})| = 2 (উপাদান ∅ আর {∅}), আর P-কে আরেকবার প্রয়োগ করলে 2² = 4. পাঁচ উপাদানের সেটের proper subset 2⁵ − 1 = 31 (শুধু S নিজে বাদ)। দশ উপাদান থেকে ঠিক তিনটি বাছার 120টি উপায় পর্ব ৩৩-এর combination C(10, 3)-এর প্রথম দেখা। শেষ লাইন brute force-এর সীমা দেখায়: 20টি উপাদানে প্রায় দশ লাখ subset, তালিকা করা যায়; 64টিতে প্রায় 1.8 × 1019, কোনো কম্পিউটারে একে একে তালিকা করা অসম্ভব। তখন সূত্রই একমাত্র ভরসা।
৫ · Ordered pair আর Cartesian product — ক্রম যখন গুরুত্বপূর্ণ
সেটে ক্রমের গুরুত্ব নেই, কিন্তু জীবনে প্রায়ই আছে। বাজারঘরের একটি ডেলিভারি স্লট হলো (গুদাম, দিন): (G1, শনি) আর (শনি, G1) এক জিনিস নয়, দ্বিতীয়টি অর্থহীন। মানচিত্রের বিন্দু (3, 5) আর (5, 3) আলাদা। এমন বস্তুর জন্য লাগে ordered pair (a, b): দুটি বস্তু, যেখানে কোনটি প্রথম আর কোনটি দ্বিতীয় তা নির্দিষ্ট। মূল নিয়ম একটিই:
(a, b) = (c, d) ⇔ a = c এবং b = d
তাই (1, 2) ≠ (2, 1), যদিও {1, 2} = {2, 1}. একইভাবে n টি বস্তুর ক্রমযুক্ত তালিকা (a1, a2, …, an)-কে বলে ordered n-tuple; দুটি tuple সমান যদি প্রতিটি অবস্থানের উপাদান সমান হয়।
A আর B সেটের Cartesian product A × B হলো সব ordered pair (a, b)-এর সেট, যেখানে a ∈ A আর b ∈ B: A × B = {(a, b) : a ∈ A ∧ b ∈ B}. একইভাবে A1 × ⋯ × An হলো সব n-tuple-এর সেট, আর Aⁿ = A × A × ⋯ × A (n বার)।
নামটি এসেছে René Descartes-এর নাম থেকে, কারণ সমতলের প্রতিটি বিন্দু একটি জোড়া (x, y) ∈ ℝ × ℝ = ℝ², যা তাঁর স্থানাঙ্ক জ্যামিতির ভিত্তি। আর বাস্তবের উদাহরণে: যদি A = {G1, G2} (দুটি গুদাম) আর B = {শনি, রবি, সোম} (তিনটি দিন), তাহলে A × B-এর প্রতিটি উপাদান একটি সম্ভাব্য ডেলিভারি স্লট, মোট ছয়টি। {0, 1}⁴ হলো দৈর্ঘ্য 4-এর সব bit string, 16টি। আর A × ∅ = ∅, কারণ জোড়ার দ্বিতীয় অংশ নেওয়ার মতো কিছু নেই।
A আর B সসীম হলে |A × B| = |A| · |B|.
প্রমাণ:
- ধরি A = {a1, …, am} (আলাদা আলাদা) আর |B| = n. A × B-কে m টি “সারি”-তে ভাগ করি: সারি i = {(ai, b) : b ∈ B}. — সংজ্ঞা
- প্রতিটি জোড়া (a, b) ঠিক একটি সারিতে আছে: যে i-এর জন্য a = ai. তাই সারিগুলো পরস্পর আলাদা আর মিলে পুরো A × B. — ordered pair-এর সমতা
- সারি i-তে b ↦ (ai, b) একটি এক-এক মিল, কারণ (ai, b) = (ai, b′) হলে b = b′. তাই প্রতিটি সারিতে n টি জোড়া। — ordered pair-এর সমতা
- পরস্পর আলাদা m টি অংশ, প্রতিটিতে n, তাই মোট n + n + ⋯ + n = mn. ∎ — যোগের নিয়ম
এবার একটি স্বাভাবিক প্রশ্ন: A × B আর B × A কি এক? আকার এক (mn = nm), কিন্তু সেট হিসেবে সাধারণত নয়।
1A = {1, 2}, B = {a, b}2A × B: প্রথম অংশ A থেকে3B × A: প্রথম অংশ B থেকে4(1, a) ∈ B × A ?5A = B, বা A = ∅, বা B = ∅ ?
| A × B | |
| B × A | |
| আকার | |
| সিদ্ধান্ত |
- A × B লেখা। প্রথম অংশ A থেকে, দ্বিতীয় B থেকে: (1, a), (1, b), (2, a), (2, b). উপপাদ্য ৫.২ অনুযায়ী 2 · 2 = 4টি।
- B × A লেখা। এবার প্রথম অংশ B থেকে: (a, 1), (a, 2), (b, 1), (b, 2). এটিও 4টি। আকার সমান হলেই সেট সমান হয় না।
- Counterexample. (1, a) ∈ A × B. এটি B × A-তে থাকতে হলে প্রথম অংশ 1 হতে হবে B-এর উপাদান; কিন্তু 1 ∉ B. তাই (1, a) ∉ B × A, আর A × B ≠ B × A. একটি জোড়াই যথেষ্ট।
- আরও বেশি। এখানে দুটি product-এর একটিও সাধারণ জোড়া নেই: কোনো (p, q) দুটিতেই থাকলে p ∈ A আর p ∈ B, কিন্তু A আর B-এর কোনো সাধারণ উপাদান নেই।
- কখন সমান? A = B হলে দুটি একই সেট A × A. A বা B ফাঁকা হলে দুটিই ∅. উপপাদ্য ৫.৩ বলে, এই তিন ক্ষেত্রের বাইরে কখনো নয়। ∎
যেকোনো সেট A, B-এর জন্য: A × B = B × A ⇔ A = B অথবা A = ∅ অথবা B = ∅.
প্রমাণ:
- (⇐) A = B হলে দুই দিকই A × A. A = ∅ বা B = ∅ হলে কোনো জোড়া বানানো যায় না, তাই দুই দিকই ∅. — সংজ্ঞা ৫.১
- (⇒) Contrapositive দেখাই: ধরি A ≠ ∅, B ≠ ∅ আর A ≠ B; দেখাব A × B ≠ B × A. — contrapositive, De Morgan
- A ≠ B, তাই extensionality অনুযায়ী কোনো উপাদান একটিতে আছে, অন্যটিতে নেই। ধরি a ∈ A কিন্তু a ∉ B (উল্টো ক্ষেত্রটি A আর B-এর নাম বদলে একইভাবে)। — without loss of generality (পর্ব ০৯)
- B ≠ ∅, তাই একটি b ∈ B নিই। তাহলে (a, b) ∈ A × B. — সংজ্ঞা ৫.১
- (a, b) ∈ B × A হলে a ∈ B হতো, যা মিথ্যা। তাই (a, b) ∉ B × A, আর A × B ≠ B × A. ∎ — ordered pair
নিচের ব্লক উপপাদ্য ৫.২ আর ৫.৩ যাচাই করে: বাজারঘরের স্লটের সংখ্যা, {1, 2, 3}-এর সব subset জোড়ায় (৮ × ৮ = ৬৪টি) উপপাদ্য ৫.৩-এর দুই দিক মেলে কি না, আর Python-এর tuple বনাম set-এর সমতা। শেষে আছে ordered pair-এর একটি “শুধু সেট দিয়ে” সংজ্ঞা, যার গল্প ভাবনার প্রশ্ন ৪-এ।
from itertools import product, combinations
A = ["G1", "G2"] # two warehouses
B = ["sat", "sun", "mon"] # three delivery days
AxB = set(product(A, B))
BxA = set(product(B, A))
print("|A×B| =", len(AxB), " |B×A| =", len(BxA), " |A|·|B| =", len(A) * len(B))
print("A×B:", sorted(AxB)[:3], "...")
print("A×B == B×A:", AxB == BxA, " share a pair:", not AxB.isdisjoint(BxA))
print("|A×∅| =", len(set(product(A, []))), " |{0,1}^4| =", len(set(product([0, 1], repeat=4))))
# Theorem: A×B = B×A <=> A = B or A = ∅ or B = ∅ (all subsets of {1,2,3})
U = [1, 2, 3]
subs = [set(c) for k in range(4) for c in combinations(U, k)]
agree = all((set(product(X, Y)) == set(product(Y, X))) ==
(X == Y or not X or not Y) for X in subs for Y in subs)
print("theorem holds on", len(subs) ** 2, "pairs (X, Y):", agree)
def kpair(a, b): # Kuratowski: (a, b) = {{a}, {a, b}}
return frozenset({frozenset({a}), frozenset({a, b})})
D = range(3)
ok = all((kpair(a, b) == kpair(c, d)) == (a == c and b == d)
for a, b, c, d in product(D, repeat=4))
print("kpair(a,b) == kpair(c,d) exactly when a == c and b == d:", ok)
print("{1,2} == {2,1}:", {1, 2} == {2, 1}, " (1,2) == (2,1):", (1, 2) == (2, 1))
print("size of kpair(1,1):", len(kpair(1, 1)))আসল আউটপুট (ব্রাউজারের Python):
|A×B| = 6 |B×A| = 6 |A|·|B| = 6
A×B: [('G1', 'mon'), ('G1', 'sat'), ('G1', 'sun')] ...
A×B == B×A: False share a pair: False
|A×∅| = 0 |{0,1}^4| = 16
theorem holds on 64 pairs (X, Y): True
kpair(a,b) == kpair(c,d) exactly when a == c and b == d: True
{1,2} == {2,1}: True (1,2) == (2,1): False
size of kpair(1,1): 1
ছয়টি ডেলিভারি স্লট, 2 · 3 = 6, উপপাদ্য ৫.২ মিলল। গুদাম আর দিনের নামে কোনো মিল নেই, তাই stepper-এর মতোই A × B আর B × A-এর একটিও সাধারণ জোড়া নেই। ৬৪টি জোড়া (X, Y)-এর প্রতিটিতে “A × B = B × A” আর “A = B বা একটি ফাঁকা” একই সত্যমান পেল; এটি উপপাদ্য ৫.৩-এর পরীক্ষা, প্রমাণ নয়, কিন্তু প্রমাণে কোনো ক্ষেত্র বাদ পড়েনি তার ভালো ইঙ্গিত। kpair দেখাল যে শুধু সেট দিয়ে বানানো {{a}, {a, b}} ordered pair-এর মূল নিয়ম মানে, অন্তত 0, 1, 2-এর সব জোড়ায়। আর kpair(1, 1) = {{1}, {1, 1}} = {{1}}, যার উপাদান একটিই: সেটে পুনরাবৃত্তি গোনা হয় না।
৬ · Relation — A × B-এর একটি subset
বাজারঘরের তিনটি গুদাম W = {G1, G2, G3} আর চারটি জেলা D = {ঢাকা, খুলনা, সিলেট, রাজশাহী}. কোন গুদাম কোন জেলায় পণ্য পাঠায়, সেই তথ্য একটি টেবিলে রাখা হয়, যেমন G1 → ঢাকা, G1 → খুলনা, G2 → সিলেট. প্রতিটি লাইন একটি ordered pair, আর পুরো টেবিলটি W × D-এর কিছু জোড়ার সংগ্রহ। ঠিক এটিই গণিতের সংজ্ঞা।
A থেকে B-তে একটি (binary) relation হলো A × B-এর যেকোনো subset R. (a, b) ∈ R হলে লেখা হয় a R b, পড়া হয় “a, b-এর সঙ্গে R সম্পর্কে যুক্ত”।
এই সংজ্ঞায় কিছুই বাড়তি নেই: “পাঠায়”, “চেনে”, “ছোট”, “ভাগ করে” সবই শেষ পর্যন্ত জোড়ার একটি সেট। ℤ-এর ওপর “<” relation হলো {(a, b) ∈ ℤ × ℤ : a < b}; (2, 5) এতে আছে, (5, 2) নেই। আর একটি সরাসরি গণনা: A থেকে B-তে কয়টি relation? প্রতিটি relation A × B-এর একটি subset, তাই উপপাদ্য ৪.২ আর ৫.২ মিলিয়ে
A থেকে B-তে relation-এর সংখ্যা = |P(A × B)| = 2|A| · |B|
গুদাম আর জেলার উদাহরণে 212 = 4096টি সম্ভাব্য “কে কোথায় পাঠায়” টেবিল। |A| = 3, |B| = 2 হলে 2⁶ = 64টি; তিন উপাদানের একটি সেটের নিজের ওপর relation 2⁹ = 512টি। Relation-এর ধর্ম (reflexive, symmetric, transitive), equivalence relation আর partial order পুরো মডিউল ৯-এর বিষয়, পর্ব ৫২ “Relation আর তার ধর্ম — reflexive, symmetric, transitive” থেকে। আর একটি relational database-এর প্রতিটি টেবিল আসলে কয়েকটি domain-এর Cartesian product-এর subset; সেই দিক ডেটাবেস ও SQL কোর্সের পর্ব ৫-এ, আর এই কোর্সে পর্ব ৫৩ “n-ary relation আর relational database-এর গণিত”-এ। পরের পর্বের ফাংশনও একটি বিশেষ ধরনের relation: প্রতিটি a-এর জন্য ঠিক একটি b.
৭ · Quantifier আর truth set — predicate থেকে সেট
Set-builder লেখা {x ∈ D : P(x)} আর পর্ব ০৪-এর predicate আসলে একই মুদ্রার দুই পিঠ। প্রতিটি predicate একটি সেট ঠিক করে দেয়: যাদের জন্য সেটি সত্য।
Domain D-এর ওপর predicate P-এর truth set হলো TP = {x ∈ D : P(x)}, অর্থাৎ D-এর যে উপাদানগুলোর জন্য P(x) সত্য।
উদাহরণ: D = ℤ আর P(x) = “x² < 5” হলে TP = {−2, −1, 0, 1, 2}. P(x) = “x² = 2” হলে TP = ∅. এবার quantifier-গুলো সেটের ভাষায় খুব সহজ হয়ে যায়:
- ∀x P(x) সত্য ⇔ TP = D (সবাই truth set-এ)।
- ∃x P(x) সত্য ⇔ TP ≠ ∅ (অন্তত একজন আছে)।
- আর বাকি জোড়া: ∀x ∈ A P(x) (restricted quantifier) মানে A ⊆ TP.
একই domain D-এর ওপর predicate P আর Q-এর জন্য: TP ⊆ TQ ⇔ ∀x ∈ D (P(x) → Q(x)).
প্রমাণ:
- TP ⊆ TQ মানে ∀x (x ∈ TP → x ∈ TQ), যেখানে x চলে D-এর ওপর (truth set D-এর বাইরের কিছু ধরে না)। — সংজ্ঞা ২.২
- x ∈ D-এর জন্য x ∈ TP ⇔ P(x), আর x ∈ TQ ⇔ Q(x). — সংজ্ঞা ৭.১
- ধাপ ১-এর conditional-এর দুই অংশে এই সমতুল্য বাক্য বসিয়ে পাই ∀x ∈ D (P(x) → Q(x)). ∎ — সমতুল্য বাক্যের প্রতিস্থাপন (পর্ব ০৩)
অর্থাৎ “সব P, Q” (যেমন “4-এর সব গুণিতক জোড়”) বাক্যটি আর “P-এর truth set, Q-এর truth set-এর subset” একই কথা। Venn diagram-এ এটি একটি বৃত্ত অন্যটির ভেতরে, ঠিক ছবি ৩.১-এর L আর D-এর মতো। আর এটি ব্যাখ্যা করে কেন একটি counterexample “সব P, Q”-কে ভেঙে দেয়: TP-এর এমন একটি উপাদান, যা TQ-তে নেই। নিচের ব্লক একটি ছোট domain-এ কয়েকটি predicate-এর truth set বানিয়ে ∀ আর ∃ পড়ে, উপপাদ্য ৭.২ পরীক্ষা করে, আর বাজারঘরের ক্রেতা তালিকায় set-builder শর্ত প্রয়োগ করে (ছবি ৩.১-এর L সেট)।
D = range(-4, 5) # domain: integers -4..4
def truth_set(P): # {x ∈ D : P(x)}
return {x for x in D if P(x)}
preds = {"x*x < 5": lambda x: x * x < 5,
"x % 3 == 0": lambda x: x % 3 == 0,
"x*x == 2": lambda x: x * x == 2,
"x + 0 == x": lambda x: x + 0 == x}
for name, P in preds.items():
T = truth_set(P)
print(f"{name:11} -> {sorted(T)} forall: {T == set(D)} exists: {len(T) > 0}")
# T_P ⊆ T_Q exactly when ∀x (P(x) -> Q(x))
P = lambda x: x % 4 == 0
Q = lambda x: x % 2 == 0
print("T_P <= T_Q:", truth_set(P) <= truth_set(Q),
" forall x (P -> Q):", all(not P(x) or Q(x) for x in D))
print("T_Q <= T_P:", truth_set(Q) <= truth_set(P),
" counterexample:", min(x for x in D if Q(x) and not P(x)))
# বাজারঘর: customers (id, district, orders this month)
customers = [(101, "Dhaka", 4), (102, "Khulna", 1), (103, "Dhaka", 0),
(104, "Sylhet", 6), (105, "Dhaka", 3), (106, "Khulna", 5)]
loyal_dhaka = {c for c, dist, n in customers if dist == "Dhaka" and n >= 3}
print("Dhaka customers with >= 3 orders:", sorted(loyal_dhaka))আসল আউটপুট (ব্রাউজারের Python):
x*x < 5 -> [-2, -1, 0, 1, 2] forall: False exists: True
x % 3 == 0 -> [-3, 0, 3] forall: False exists: True
x*x == 2 -> [] forall: False exists: False
x + 0 == x -> [-4, -3, -2, -1, 0, 1, 2, 3, 4] forall: True exists: True
T_P <= T_Q: True forall x (P -> Q): True
T_Q <= T_P: False counterexample: -2
Dhaka customers with >= 3 orders: [101, 105]
প্রথম চার লাইন quantifier-এর সেট-রূপ দেখায়: truth set পুরো D হলে ∀ সত্য (শুধু x + 0 = x), ফাঁকা হলে ∃ মিথ্যা (x² = 2, কারণ √2 পূর্ণসংখ্যা নয়)। Python-এর all আর any/len আসলে এই দুই পরীক্ষা। পরের দুই লাইনে “4-এর গুণিতক ⇒ জোড়” সত্য, তাই truth set-এ ⊆; উল্টো দিক মিথ্যা, আর ব্লকটি সবচেয়ে ছোট counterexample −2 খুঁজে দিল (জোড়, কিন্তু 4-এর গুণিতক নয়)। শেষ লাইন set comprehension, যা set-builder-এর হুবহু Python রূপ: ছবি ৩.১-এর L = {101, 105}. মনে রাখুন, এখানে domain মাত্র −4 থেকে 4; বড় বা অসীম domain-এ এই পরীক্ষা শুধু ইঙ্গিত দেয়, প্রমাণ দেয় উপপাদ্য ৭.২-এর যুক্তি।
৮ · Naive set theory আর Russell-এর paradox
§৭ একটি লোভনীয় নিয়মের দিকে ইঙ্গিত দেয়: যেকোনো predicate P থেকে একটি সেট {x : P(x)} বানানো যায়। Georg Cantor ১৮৭০-এর দশকে সেট তত্ত্ব গড়ে তোলার সময় আর Gottlob Frege পরে যুক্তিবিদ্যার ওপর গণিত দাঁড় করানোর সময় মোটামুটি এই ধরনের অবাধ নিয়মের ওপর ভরসা করেছিলেন। এই ঢিলেঢালা কাঠামোকে আজ বলা হয় naive set theory. সমস্যা হলো, নিয়মটি নিজের সঙ্গেই বিরোধ তৈরি করে।
এমন কোনো সেট R নেই, যার জন্য প্রতিটি x-এর বেলায় x ∈ R ⇔ x ∉ x. অতএব “যেকোনো predicate থেকে সেট” নিয়মটি অসংগত।
প্রমাণ (contradiction):
- ধরি এমন R আছে: সব x-এর জন্য x ∈ R ⇔ x ∉ x. — বিরোধের জন্য অনুমান
- “সব x”-এর মধ্যে R নিজেও আছে; x-এর জায়গায় R বসিয়ে পাই R ∈ R ⇔ R ∉ R. — universal instantiation (পর্ব ০৬)
- কোনো বাক্য p-এর জন্য p ↔ ¬p একটি contradiction: p সত্য হলে ¬p মিথ্যা, p মিথ্যা হলে ¬p সত্য, দুই ক্ষেত্রেই ↔ মিথ্যা। — truth table (পর্ব ০২)
- অনুমান থেকে মিথ্যা বাক্য এল, তাই এমন R নেই। কিন্তু naive নিয়মে P(x) = “x ∉ x” থেকে R = {x : x ∉ x} অবশ্যই একটি সেট; তাই নিয়মটিই অসংগত। ∎ — proof by contradiction (পর্ব ০৮)
এর জনপ্রিয় রূপ নাপিতের ধাঁধা: গ্রামের নাপিত ঠিক তাঁদেরই দাড়ি কামান, যাঁরা নিজের দাড়ি নিজে কামান না। নাপিতের নিজের দাড়ি কে কামান? দুই উত্তরই বিরোধে যায়, তাই এমন নাপিত থাকতে পারেন না। পর্ব ০২-এর liar paradox (“এই বাক্যটি মিথ্যা”)-এর সঙ্গে মিলটিও লক্ষ করুন: দুটিতেই একটি বস্তু নিজের সম্পর্কে নেতিবাচক কথা বলে।
ইতিহাস সংক্ষেপে, যতটা নিশ্চিতভাবে বলা যায়: Bertrand Russell এই paradox খুঁজে পান সাধারণত ১৯০১ সালে বলে উল্লেখ করা হয়, আর ১৯০২ সালে Frege-কে একটি চিঠিতে জানান; Frege তখন তাঁর Grundgesetze der Arithmetik-এর দ্বিতীয় খণ্ড ছাপার পর্যায়ে ছিলেন, আর ১৯০৩ সালে প্রকাশিত খণ্ডে একটি পরিশিষ্টে সমস্যাটি স্বীকার করেন। Ernst Zermelo-ও প্রায় একই সময়ে স্বাধীনভাবে একই বিরোধ লক্ষ করেছিলেন বলে ঐতিহাসিকেরা উল্লেখ করেন। সমাধান হিসেবে Zermelo ১৯০৮ সালে সেট তত্ত্বের একটি axiom-তালিকা প্রকাশ করেন; ১৯২০-এর দশকের শুরুতে Abraham Fraenkel আর Thoralf Skolem-এর সংশোধনের পরে যে কাঠামো দাঁড়ায়, axiom of choice-সহ তাকে বলে ZFC; আজকের গণিতের প্রচলিত ভিত্তি এটিই।
ZFC-এর মূল সংশোধনটি সহজ ভাষায় বলা যায়: যেকোনো predicate থেকে শূন্য থেকে সেট বানানো যাবে না; শুধু আগে থেকে থাকা একটি সেট A-এর ভেতর থেকে কেটে নেওয়া যাবে: {x ∈ A : P(x)}. এই “separation” নিয়মে Russell-এর যুক্তি চালালে R = {x ∈ A : x ∉ x} বৈধ সেট, আর ধাপ ২-এর মতো যুক্তি এখন বিরোধ দেয় না, বরং প্রমাণ করে R ∉ A. অর্থাৎ যেকোনো সেট A-এর বাইরে অন্তত একটি সেট আছে, তাই “সব সেটের সেট” বলে কিছু নেই। এজন্যই এই পর্বে সবসময় একটি universal set U বা domain D-এর ভেতরে set-builder লিখেছি: {x ∈ U : P(x)}. দৈনন্দিন discrete math-এ (সসীম সেট, ℕ, ℤ, ℝ-এর subset) এই সাবধানতা মানলে naive set theory নিরাপদে ব্যবহার করা যায়; এই কোর্স সেটাই করবে।
৯ · প্রোগ্রামিং-এ সেট — Python-এর set, frozenset আর hashing
Python-এর set গণিতের সসীম সেটের প্রায় হুবহু অনুবাদ: x in s হলো x ∈ s, a <= b হলো a ⊆ b, a < b হলো proper subset, len(s) হলো |s|, আর {x for x in D if P(x)} হলো set-builder. ভাষার খুঁটিনাটি Python কোর্সের পর্ব ১৭-এ, আর tuple আছে পর্ব ১৫-এ; এখানে শুধু গণিতের সঙ্গে মিল আর অমিল দেখব।
প্রথম অমিল: সমতা। Python-এ 1 == 1.0 == True, তাই সেটের চোখে তিনটি একই উপাদান। দ্বিতীয় অমিল: Python-এর set যেকোনো বস্তু রাখতে পারে না, শুধু hashable বস্তু। কারণ ভেতরে set একটি hash table: প্রতিটি উপাদানের একটি hash মান হিসাব করে তার ভিত্তিতে জায়গা বাছে, তাই x in s গড়ে প্রায় ধ্রুব সময়ে হয় (DSA কোর্সের পর্ব ৩২)। কোনো উপাদান ঢোকানোর পরে বদলে গেলে তার hash বদলাত, আর সেটি ভুল জায়গায় পড়ে থাকত; তাই list বা set-এর মতো বদলানো যায় এমন বস্তু set-এ ঢোকানো যায় না। সেটের সেট (যেমন power set) বানাতে লাগে frozenset: বদলানো যায় না এমন set, তাই hashable. §৪-এর ব্লকে এজন্যই প্রতিটি subset ছিল frozenset.
import sys
s = {3, 1, 3, 2}
print(s, len(s), " {1,2} == {2,1}:", {1, 2} == {2, 1}, " [1,2] == [2,1]:", [1, 2] == [2, 1])
print("{1, 1.0, True} =", {1, 1.0, True}) # 1 == 1.0 == True in Python
print("2 in s:", 2 in s, " {1,2} <= s:", {1, 2} <= s, " {1,2} < s:", {1, 2} < s)
try:
bad = {(1, 2), [3, 4]} # a list inside a set
except TypeError as err:
print("TypeError:", err)
try:
bad = {frozenset({1}), {2}} # a set inside a set
except TypeError as err:
print("TypeError:", err)
empty, box = frozenset(), frozenset({frozenset()}) # ∅ and {∅}
print("len(∅) =", len(empty), " len({∅}) =", len(box), " ∅ == {∅}:", empty == box)
print("∅ in {∅}:", empty in box, " ∅ <= {∅}:", empty <= box)
# Russell: model a "set" by its membership test, x(y) means "y ∈ x".
def R(x): # x ∈ R <=> x ∉ x
return not x(x)
sys.setrecursionlimit(200)
try:
print(R(R)) # is R ∈ R ?
except RecursionError:
print("R(R): RecursionError, the question never gets an answer")আসল আউটপুট (ব্রাউজারের Python):
{1, 2, 3} 3 {1,2} == {2,1}: True [1,2] == [2,1]: False
{1, 1.0, True} = {1}
2 in s: True {1,2} <= s: True {1,2} < s: True
TypeError: cannot use 'list' as a set element (unhashable type: 'list')
TypeError: cannot use 'set' as a set element (unhashable type: 'set')
len(∅) = 0 len({∅}) = 1 ∅ == {∅}: False
∅ in {∅}: True ∅ <= {∅}: True
R(R): RecursionError, the question never gets an answer
প্রথম লাইনে extensionality: পুনরাবৃত্ত 3 একবারই, আর set-এ ক্রম গোনা হয় না, list-এ হয়। দ্বিতীয় লাইন Python-এর নিজস্ব সমতার ফল: তিনটি “আলাদা” লেখা একটি উপাদান। তারপর tuple ঢোকানো যায় (hashable), কিন্তু list আর সাধারণ set ঢোকাতে গেলে TypeError. ফাঁকা সেটের লাইন দুটি §২-এর কথাই যন্ত্রে দেখায়: ∅ আর {∅} আলাদা, আর ∅ একই সঙ্গে {∅}-এর উপাদান এবং subset. শেষ অংশে একটি “সেট”-কে তার সদস্যতা-পরীক্ষা (একটি ফাংশন) দিয়ে প্রকাশ করা হয়েছে; R(R) প্রশ্ন করে “R ∈ R?”, যার উত্তর পেতে আবার R(R) লাগে। প্রশ্নটি কখনো স্থির উত্তরে পৌঁছায় না, আর recursion সীমা (এখানে 200) পেরিয়ে যায়। এটি Russell-এর paradox-এর প্রমাণ নয়, কিন্তু দেখায় কেন এমন বস্তু “বানানো” যায় না। আর frozenset নিজেকে ধারণ করতে পারে না, কারণ ঢোকানোর আগেই তাকে সম্পূর্ণ তৈরি থাকতে হয়।
বাজারঘরের কোডে সেটের কাজ সর্বত্র: একই ক্রেতার দুবার কুপন নেওয়া আটকাতে ব্যবহৃত id-গুলোর set, কোন জেলায় এই সপ্তাহে ডেলিভারি হয়েছে তার set, আর ডেটাবেসে SELECT DISTINCT, যা টেবিলের সারি থেকে পুনরাবৃত্তি বাদ দিয়ে সেট বানায়। SQL-এর UNION, INTERSECT, EXCEPT আর relational algebra যে সেটের অপারেশনের ওপর দাঁড়িয়ে, সেই অপারেশনগুলো পরের পর্বে; ডেটাবেসের দিক থেকে দেখতে ডেটাবেস ও SQL কোর্সের পর্ব ৩২।
আরও গভীরে: ZFC-তে প্রতিটি গাণিতিক বস্তু শেষ পর্যন্ত একটি সেট: John von Neumann-এর ১৯২০-এর দশকের সংজ্ঞায় 0 = ∅, 1 = {∅}, 2 = {∅, {∅}}, অর্থাৎ n = {0, 1, …, n − 1}, তাই |n| = n. ১৯৩০-এর দশকে Kurt Gödel আর ১৯৬৩ সালে Paul Cohen দেখান যে Cantor-এর continuum hypothesis ZFC থেকে প্রমাণও করা যায় না, খণ্ডনও করা যায় না (ZFC সংগত ধরে নিয়ে); এর গল্প পর্ব ১৮-এ। আর Lean-এর মতো proof assistant সাধারণত সেট তত্ত্বের বদলে type theory-কে ভিত্তি করে, যেখানে “1 ∈ 2” ধরনের প্রশ্ন লেখাই যায় না।
পরীক্ষা ও ইন্টারভিউতে: বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন প্রায়ই আসে:
- ∅ ∈ {∅} আর ∅ ⊆ {∅}, কোনটি সত্য? দুটিই; কিন্তু {∅} ∈ {∅} মিথ্যা, আর ∅ ∈ ∅ মিথ্যা।
- |P(P({a, b}))| কত? |P({a, b})| = 4, তাই 2⁴ = 16.
- A = {1, 2, 3}, B = {x, y} হলে |A × B|, |A × B × A| আর A থেকে B-তে relation কয়টি? 6, 18 আর 2⁶ = 64.
- {1, 2, …, 10}-এর কয়টি subset-এ 1 আছে কিন্তু 2 নেই? বাকি আটটি উপাদান ইচ্ছামতো: 2⁸ = 256.
- দুটি সেট সমান কীভাবে প্রমাণ করবেন? Double inclusion: A ⊆ B আর B ⊆ A, দুটিই element chasing দিয়ে।
১০ · AI-এর যুগে — সেটের প্রশ্নে AI-এর উত্তর যাচাই
AI সহকারী সেটের সংজ্ঞা নিখুঁতভাবে বলে দেয়, কিন্তু ছোট ছোট প্রতীকের প্রশ্নে আর গণনায় প্রায়ই আত্মবিশ্বাসের সঙ্গে ভুল করে। এই পর্বের বিষয়ে যে ভুলগুলো বারবার দেখা যায়:
| AI-এর ভুল | কীভাবে ধরবেন |
|---|---|
| ∈ আর ⊆ গুলিয়ে ফেলা; “∅ = {∅}” বা “∅ ∈ S সব S-এর জন্য” | Python-এ frozenset দিয়ে প্রতিটি দাবি in আর <= দিয়ে আলাদা চালান |
| |P(S)| = 2ⁿ − 1 বা n² বলা, ∅-কে বাদ দেওয়া; proper subset-এর সংখ্যা ভুল | n = 0, 1, 2-এ হাতে গুনুন; §৪-এর ব্লকের মতো brute force চালান |
| “A × B = B × A” বা |A × B| = |A| + |B| বলা | দুই উপাদানের দুটি সেটে তালিকা করে দেখুন; একটি counterexample যথেষ্ট |
| কয়েকটি উদাহরণ দেখিয়ে A ⊆ B “প্রমাণ”; বা A = B-তে শুধু এক দিকের ⊆ | যেকোনো x ধরে element chasing আছে কি না, আর দুই দিকই আছে কি না দেখুন |
| “সব সেটের সেট” বা অবাধ {x : P(x)} নির্দ্বিধায় ব্যবহার; Russell-এর তারিখ বা বইয়ের নাম বানানো | Domain বা universal set জিজ্ঞেস করুন; ইতিহাস বিশ্বস্ত পাঠ্যবই বা জীবনী-সূত্রে মেলান |
সেটের প্রশ্নে AI-এর সাহায্য নিতে চাইলে প্রশ্নটি এভাবে সাজালে যাচাই সহজ হয়:
AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট
সেটের ছোট দাবিগুলো যাচাই করা খুব সস্তা: তিন উপাদানের একটি universal set-এর সব subset মাত্র ৮টি, আর সব জোড়া ৬৪টি। AI-এর একটি সাধারণ দাবি এই ৬৪টি ক্ষেত্রে চালাতে এক সেকেন্ডও লাগে না; একবার ভাঙলেই দাবি বাতিল। আর না ভাঙলে তখন প্রমাণ নিজে পড়ুন, কারণ পরীক্ষা আর প্রমাণ এক নয়।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।
প্র ০১Russell-এর paradox-এর পরে গণিতবিদেরা কি সেট তত্ত্ব ছেড়ে দিলেন? ZFC আসলে কী বদলাল, আর তার দাম কী?
ছেড়ে দেননি, বরং নিয়মগুলো সাবধানে নতুন করে লিখলেন। Naive কাঠামোর মূল দুর্বলতা ছিল unrestricted comprehension: যেকোনো বর্ণনা থেকে একটি সেট। Russell দেখালেন, “নিজের উপাদান নয় এমন সব সেট” বর্ণনাটি থেকে সেট ধরলেই বিরোধ। Russell নিজে একটি সমাধান হিসেবে type-এর ধারণা দেন, যা Whitehead-এর সঙ্গে লেখা Principia Mathematica-য় (১৯১০ থেকে ১৯১৩ সালে প্রকাশিত) ব্যবহৃত হয়: বস্তু, বস্তুর সেট, সেটের সেট আলাদা স্তরে থাকে, আর একটি সেট শুধু নিচের স্তরের বস্তু ধারণ করতে পারে। তাতে “x ∈ x” প্রশ্নটি লেখাই যায় না।
Zermelo ১৯০৮ সালে অন্য পথ নিলেন: কয়েকটি নির্দিষ্ট axiom, যা বলে কোন কোন উপায়ে নতুন সেট বানানো যায়। ফাঁকা সেট আছে; দুটি সেট থেকে জোড়া বানানো যায়; একটি সেটের power set আর union আছে; একটি অসীম সেট আছে; আর মূল সংশোধন separation, অর্থাৎ পুরোনো সেট A থেকে {x ∈ A : P(x)} কেটে নেওয়া। পরে Fraenkel আর Skolem replacement axiom যোগ করেন, আর foundation (regularity) axiom এমন যেকোনো সেটকে নিষেধ করে যে নিজের উপাদান। Axiom of choice সহ পুরো তালিকাটি ZFC.
দাম কী? প্রথমত, কিছু স্বাভাবিক কথা আর বলা যায় না: “সব সেটের সেট” বা “সব গ্রুপের সেট” ZFC-তে সেট নয়; এমন বড় সংগ্রহের জন্য class নামের আলাদা ধারণা লাগে। দ্বিতীয়ত, ১৯৩১ সালে Gödel-এর incompleteness theorem দেখায় যে ZFC-এর মতো যথেষ্ট শক্তিশালী কোনো সংগত তত্ত্ব নিজের সংগতি নিজে প্রমাণ করতে পারে না। অর্থাৎ ZFC-তে কখনো কোনো বিরোধ পাওয়া যাবে না, এর গ্যারান্টি ZFC নিজে দিতে পারে না। এক শতাব্দীর বেশি সময় ধরে ব্যাপক ব্যবহারে কোনো বিরোধ পাওয়া যায়নি, আর এই অভিজ্ঞতাই বেশিরভাগ গণিতবিদের আস্থার ভিত্তি।
দৈনন্দিন কাজে এর প্রভাব সামান্য: প্রোগ্রামার বা প্রকৌশলী যে সেটগুলো ব্যবহার করেন (সসীম সেট, ℕ, ℝ-এর subset, ফাংশনের সেট) সবই ZFC-তে নিরাপদে তৈরি হয়। শুধু অভ্যাসটি রাখতে হয়: set-builder লিখলে একটি domain উল্লেখ করুন।
মূল উপলব্ধি: paradox সেট তত্ত্বকে ধ্বংস করেনি, তাকে নিয়মবদ্ধ করেছে; নতুন সেট শুধু পুরোনো সেট থেকে, নির্দিষ্ট axiom মেনে, তৈরি হয়।
প্র ০২0 কি স্বাভাবিক সংখ্যা? এত মৌলিক প্রশ্নে বইগুলো একমত নয় কেন, আর computer science কেন 0 থেকে গোনে?
কারণ এটি সত্য-মিথ্যার প্রশ্ন নয়, একটি প্রথার প্রশ্ন। “ℕ” একটি নাম; কোন সেটকে এই নাম দেওয়া হবে, তা লেখক ঠিক করেন। দুটি প্রথাই পুরোনো আর সুপ্রতিষ্ঠিত। Giuseppe Peano ১৮৮৯ সালে স্বাভাবিক সংখ্যার axiom লেখার সময় প্রথমে 1 থেকে শুরু করেছিলেন বলে সাধারণত উল্লেখ করা হয়, আর পরের কিছু সংস্করণে 0 থেকে; ঐতিহাসিক বিবরণ উৎসভেদে একটু আলাদা। সংখ্যাতত্ত্বে “স্বাভাবিক সংখ্যা” প্রায়ই 1, 2, 3, …, কারণ ভাজক, মৌলিক সংখ্যা ইত্যাদির আলোচনায় 0 বিশেষ ক্ষেত্র হয়ে বিরক্ত করে।
অন্যদিকে সেট তত্ত্ব আর logic-এ 0 প্রায় অবশ্যই থাকে: von Neumann-এর সংজ্ঞায় 0 = ∅ প্রথম সংখ্যা, আর একটি সসীম সেটের cardinality 0 হতে পারে (|∅| = 0), তাই “cardinality-র সম্ভাব্য মান” হিসেবে ℕ-এ 0 লাগে। আন্তর্জাতিক মান ISO 80000-2 ℕ-এ 0 রাখে, আর computer science-এর বেশিরভাগ discrete math পাঠ্যবইও তাই করে।
Computer science-এ 0 থেকে গোনার পক্ষে Edsger Dijkstra-র ১৯৮২ সালের ছোট লেখা “Why numbering should start at zero” (EWD831) প্রায়ই উদ্ধৃত হয়। তাঁর যুক্তি: n দৈর্ঘ্যের একটি ক্রমের সূচক অর্ধখোলা পরিসর 0 ≤ i < n দিয়ে লিখলে দৈর্ঘ্য সরাসরি n − 0 = n, ফাঁকা পরিসর স্বাভাবিকভাবে 0 ≤ i < 0, আর পাশাপাশি পরিসর জোড়া লাগাতে কোনো ±1 লাগে না। C, Python, Java-র অ্যারে 0 থেকে শুরু; Python-এর range(n) ঠিক {0, …, n − 1}. মেমরির ঠিকানার হিসাবেও এটি স্বাভাবিক: প্রথম উপাদান শুরু থেকে 0 ঘর দূরে।
তাহলে আপনার করণীয় কী? যেকোনো বই, প্রশ্নপত্র বা কোডে প্রথমেই প্রথাটি দেখে নিন, আর নিজের লেখায় স্পষ্ট বলুন: “এখানে ℕ = {0, 1, 2, …}” বা “ℤ⁺ = {1, 2, …}”. Induction-এর basis কোথা থেকে শুরু, “প্রথম n টি স্বাভাবিক সংখ্যার যোগফল” কত, এমন প্রশ্নের উত্তর এই প্রথার ওপর নির্ভর করে। অনেক off-by-one ভুল আসলে দুই প্রথার সংঘর্ষ।
মূল উপলব্ধি: সংজ্ঞা একটি চুক্তি; চুক্তিটি স্পষ্ট লিখলে কোনো বিরোধ থাকে না, আর না লিখলে নিখুঁত যুক্তিও ভুল উত্তর দিতে পারে।
প্র ০৩Python-এর set-এ list রাখা যায় না, অথচ গণিতে সেটের উপাদান যেকোনো কিছু হতে পারে। এই সীমা কি শুধু প্রোগ্রামিং-এর ঝামেলা, নাকি এর পেছনে গাণিতিক কারণ আছে?
দুটোই। গণিতের সেট কখনো বদলায় না: {1, 2} চিরকাল {1, 2}. “একটি সেটে উপাদান যোগ করা” বললে আসলে একটি নতুন সেট তৈরি হয়। কিন্তু প্রোগ্রামের list বা set একটি বদলানো যায় এমন বস্তু: আজ [3, 4], কাল append-এর পরে [3, 4, 5], অথচ একই বস্তু। এমন বস্তু একটি সেটের উপাদান হলে extensionality ভাঙার ঝুঁকি তৈরি হয়: ধরুন s = {L1, L2}, যেখানে L1 = [1], L2 = [2]; তারপর L2-কে বদলে [1] করা হলো। এখন s-এ দুটি “সমান” উপাদান, যা সেটের মূল নিয়মের বিরোধী।
প্রকৌশলের দিকটি আরও সরাসরি। Python-এর set একটি hash table: প্রতিটি উপাদানের hash মান থেকে তার বালতি (bucket) ঠিক হয়, আর x in s শুধু সেই বালতি দেখে, তাই গড়ে প্রায় ধ্রুব সময়। উপাদান বদলালে তার hash বদলাত, কিন্তু সে পুরোনো বালতিতেই বসে থাকত; তখন x in s ভুল উত্তর দিত। তাই Python-এর নিয়ম: দুটি বস্তু সমান হলে তাদের hash সমান হতে হবে, আর hash জীবনভর বদলাবে না। List এই নিয়ম মানতে পারে না বলে unhashable. Tuple, string, int, frozenset বদলায় না, তাই hashable. (একটি সূক্ষ্মতা: ভেতরে list আছে এমন tuple-ও unhashable.)
এখান থেকে একটি সুন্দর মিল দেখা যায়। Python-এ 1 == 1.0 == True, আর hash(1) == hash(1.0) == hash(True); তাই {1, 1.0, True}-এ একটিই উপাদান। এটি Python-এর “সমতা”-র সংজ্ঞার ফল, extensionality-র নয়: গণিতে 1 আর “সত্য” আলাদা বস্তু। প্রতিটি ভাষার set সেই ভাষার সমতার সংজ্ঞা অনুসরণ করে, তাই কাস্টম class-এ __eq__ বদলালে __hash__-ও মিলিয়ে বদলাতে হয়।
ব্যবহারিক শিক্ষা: সেটের সেট (power set, partition, গ্রাফের edge {u, v}) রাখতে frozenset ব্যবহার করুন; ordered pair-এর জন্য tuple; আর dictionary-র চাবিও একই কারণে hashable হতে হয়।
মূল উপলব্ধি: hashable হওয়ার শর্ত আসলে গণিতের “সেট বদলায় না” ধারণার প্রোগ্রামিং রূপ; এটি না মানলে extensionality আর দ্রুত খোঁজা দুটোই ভেঙে পড়ে।
প্র ০৪সব কিছু যদি সেট হয়, তাহলে ordered pair (a, b) কোন সেট? {{a}, {a, b}} সংজ্ঞাটি কি “সত্যিকারের” ordered pair?
সেট তত্ত্বকে গণিতের ভিত্তি বানাতে হলে ordered pair-কেও সেট দিয়ে প্রকাশ করতে হয়, কারণ ZFC-তে সেট ছাড়া আর কোনো বস্তু নেই। সমস্যা: সেটে ক্রম নেই, অথচ জোড়ায় আছে। সমাধানটি চতুর: এমন একটি সেট বানান, যার গঠন থেকে কোনটি প্রথম তা বোঝা যায়। Norbert Wiener ১৯১৪ সালে একটি সংজ্ঞা দেন, আর Kazimierz Kuratowski ১৯২১ সালে আজকের প্রচলিত, সহজতর সংজ্ঞাটি দেন: (a, b) = {{a}, {a, b}}. এখানে a এমন একটি উপাদান, যা দুটি ভেতরের সেটেই আছে; b শুধু একটিতে। তাই “প্রথম” উপাদান গঠন থেকেই চেনা যায়।
এর একমাত্র দায় হলো মূল নিয়মটি মানা: {{a}, {a, b}} = {{c}, {c, d}} ⇔ a = c এবং b = d. প্রমাণে ক্ষেত্রভেদ লাগে। যদি a = b হয়, তাহলে বাম পাশ {{a}}, একটিমাত্র উপাদান; তখন ডান পাশেও একটি উপাদান, তাই c = d, আর {a} = {c}, অর্থাৎ a = c = d = b. যদি a ≠ b হয়, তাহলে বাম পাশে একটি এক-উপাদানের সেট {a} আর একটি দুই-উপাদানের সেট {a, b}; সমতায় এক-উপাদানের সেট মেলে এক-উপাদানের সঙ্গে, তাই {a} = {c}, অর্থাৎ a = c; তারপর {a, b} = {a, d} থেকে b = d. §৫-এর ব্লক 0, 1, 2-এর সব 81টি চতুষ্টয়ে এটি যাচাই করেছে।
এটি কি “সত্যিকারের” জোড়া? এখানেই গণিতের একটি দার্শনিক শিক্ষা। কেউ দাবি করে না যে মানচিত্রের বিন্দু (3, 5) “আসলে” {{3}, {3, 5}}. সংজ্ঞাটি একটি encoding: ordered pair-এর যা দরকার, অর্থাৎ ওই একটি নিয়ম, সেটি এই encoding মানে। একই নিয়ম মানে এমন অন্য encoding-ও চলত, যেমন Wiener-এরটি; কোনটি নেওয়া হলো তাতে কোনো উপপাদ্যের ফল বদলায় না। এর একটি অদ্ভুত পার্শ্বফলও আছে: Kuratowski-এর সংজ্ঞায় “{a} ∈ (a, b)” সত্য, যা কারো মনে আসার মতো প্রশ্ন নয়, কিন্তু ZFC-তে অর্থপূর্ণ।
প্রোগ্রামিং-এও একই ঘটনা ঘটে: tuple-কে ভেতরে কীভাবে মেমরিতে রাখা হয়, তা ব্যবহারকারীর জানার দরকার নেই, যতক্ষণ সমতা আর সূচক ঠিক কাজ করে। আর type theory-ভিত্তিক proof assistant (Lean) জোড়াকে একটি মৌলিক type ধরে, encoding-এর ঝামেলায় যায় না।
মূল উপলব্ধি: একটি গাণিতিক বস্তুর পরিচয় তার “ভেতরের গঠন” নয়, তার নিয়ম; ordered pair যে কোনো encoding, যা (a, b) = (c, d) ⇔ a = c ∧ b = d মানে।
প্র ০৫ফাঁকা সেটের কি সত্যিই দরকার আছে? “কিছু না”-কে একটি বস্তু বলার সুবিধা কী, আর ডেটাবেসে ফাঁকা ফল আর NULL কি একই জিনিস?
দরকার আছে, আর তার কারণ শূন্য সংখ্যাটির দরকারের মতোই। ভারতীয় উপমহাদেশে শূন্যকে একটি সংখ্যা হিসেবে ব্যবহারের ফলে হিসাবের নিয়মগুলো ব্যতিক্রম ছাড়াই লেখা গিয়েছিল। ∅ ঠিক তাই করে সেটের জন্য। এটি না থাকলে “দুটি সেটের সাধারণ উপাদানের সেট” কথাটি প্রতিবার শর্তসহ বলতে হতো (“যদি সাধারণ উপাদান থাকে”); |P(S)| = 2ⁿ সূত্রে ∅-কে গোনা না হলে উত্তর 2ⁿ − 1 হতো আর induction-এর basis (n = 0) ভেঙে যেত; আর truth set-এর ভাষায় “∃x P(x) মিথ্যা” লেখার সবচেয়ে সরল উপায় TP = ∅.
∅ আর {∅}-এর পার্থক্যও শুধু পণ্ডিতি কূটতর্ক নয়। von Neumann-এর নির্মাণে 0 = ∅ আর 1 = {∅}; অর্থাৎ পুরো স্বাভাবিক সংখ্যার কাঠামো শুরু হয় “কিছু না” আর “কিছু-না-ভরা একটি বাক্স”-এর পার্থক্য থেকে। প্রোগ্রামিং-এও একই পার্থক্য রোজ দেখা যায়: ফাঁকা list [] আর একটি ফাঁকা list ভরা list [[]]-এর দৈর্ঘ্য 0 আর 1.
ডেটাবেসের প্রশ্নে: একটি SQL query যদি কোনো সারি না পায়, তার ফল একটি ফাঁকা টেবিল, অর্থাৎ ফাঁকা সেটের মতো; এটি একটি পরিষ্কার উত্তর: “এমন কেউ নেই”। কিন্তু NULL সম্পূর্ণ আলাদা ধারণা: একটি নির্দিষ্ট ঘরে মান “অজানা বা প্রযোজ্য নয়”। SQL-এ NULL = NULL তুলনার ফল সত্য নয়, বরং UNKNOWN, যা তিন-মানের logic-এর অংশ (সত্য, মিথ্যা, অজানা)। তাই বাজারঘরের “যে ক্রেতাদের ফোন নম্বর নেই” প্রশ্নে WHERE phone = NULL লিখলে কিছুই পাওয়া যায় না; লাগে IS NULL. ফাঁকা সেট একটি জানা উত্তর, NULL একটি অজানা মান; দুটিকে গুলিয়ে ফেলা ডেটাবেসের পরিচিত বাগের উৎস।
আর একটি সুন্দর তথ্য: ফাঁকা সেটের ওপর যেকোনো ∀ দাবি vacuously সত্য (উপপাদ্য ২.৩-এর যুক্তি)। তাই “বাজারঘরের সব মঙ্গলগ্রহবাসী ক্রেতা সন্তুষ্ট” সত্য, যদি এমন ক্রেতা কেউ না থাকেন। Python-এ all([]) True আর any([]) False ঠিক এই নিয়ম মানে।
মূল উপলব্ধি: ∅-কে একটি পূর্ণাঙ্গ বস্তু ধরলে সূত্র আর নিয়মগুলো ব্যতিক্রম ছাড়াই লেখা যায়; আর “কিছু নেই” (∅) ও “জানা নেই” (NULL) দুটি আলাদা কথা।
অনুশীলন
আগে খাতায় করুন, তারপর উত্তর খুলে মেলান।
-
প্রমাণ: যেকোনো দুটি সেট A, B-এর জন্য প্রমাণ করুন: A ⊆ B ⇔ P(A) ⊆ P(B).
- (⇒) ধরি A ⊆ B. P(A) ⊆ P(B) দেখাতে যেকোনো T ∈ P(A) নিই; তাহলে T ⊆ A. — element chasing, power set-এর সংজ্ঞা
- T ⊆ A আর A ⊆ B থেকে T ⊆ B (⊆ transitive, §২)। তাই T ∈ P(B), আর P(A) ⊆ P(B). — transitivity
- (⇐) ধরি P(A) ⊆ P(B). A ⊆ A (উপপাদ্য ২.৩), তাই A ∈ P(A). — উপপাদ্য ২.৩
- P(A) ⊆ P(B) থেকে A ∈ P(B), অর্থাৎ A ⊆ B. ∎ — subset-এর সংজ্ঞা
লক্ষ করুন, এক দিকে ⊆-এর উপাদান (T) নিজেই একটি সেট, তাই “T ∈ P(A)” আর “T ⊆ A” একই কথা; ∈ আর ⊆ এখানে পাশাপাশি সঠিকভাবে বসেছে। যাচাই: {1, 2, 3}-এর সব 64টি subset জোড়ায় দুই দিক scratch-এ Python দিয়ে মেলানো হয়েছে।
-
হিসাব: (ক) S = {1, {1}, {1, 2}, ∅} হলে |S| আর |P(S)| কত? (খ) A = {1, 2, 3}, B = {x, y} হলে |A × B|, |A × B × A| আর A থেকে B-তে relation-এর সংখ্যা বের করুন। (গ) {1, 2, …, 10}-এর কয়টি subset-এ 1 আছে কিন্তু 2 নেই? (ঘ) |P(P(P(∅)))| কত?
(ক) উপাদান চারটি: 1, {1}, {1, 2}, ∅ (ভেতরের সেটগুলো একেকটি উপাদান), তাই |S| = 4, |P(S)| = 2⁴ = 16.
(খ) |A × B| = 3 · 2 = 6; |A × B × A| = 3 · 2 · 3 = 18; relation = |P(A × B)| = 2⁶ = 64.
(গ) 1 অবশ্যই আছে, 2 অবশ্যই নেই; বাকি আটটি উপাদানের প্রতিটি থাকতে বা না থাকতে পারে: 2⁸ = 256. (এক-এক মিল: এমন প্রতিটি subset থেকে 1 সরালে {3, …, 10}-এর একটি subset.)
(ঘ) P(∅) = {∅}, আকার 1; P(P(∅)) = {∅, {∅}}, আকার 2; P(P(P(∅))), আকার 2² = 4. প্রতিটি উত্তর scratch-এ frozenset দিয়ে brute force করে মেলানো হয়েছে।
-
আউটপুট অনুমান: কোড না চালিয়ে বলুন কী ছাপা হবে, তারপর যেকোনো Python-এ চালিয়ে মেলান।
A = {1, 2, 3} P = [set()] for x in sorted(A): P = P + [T | {x} for T in P] print(len(P), sorted(len(T) for T in P)) print({(1, 2), (2, 1)} == {(2, 1), (1, 2)}, (1, 2) == (2, 1)) print(len({frozenset({1, 2}), frozenset({2, 1})}))8 [0, 1, 1, 1, 2, 2, 2, 3] True False 1প্রথম লাইন: লুপটি §৪-এর stepper-এর দ্বিগুণ করার নিয়ম (
T | {x}মানে T-এ x যোগ), তাই 2³ = 8টি subset, আকার 0 একটি, 1 তিনটি, 2 তিনটি, 3 একটি। দ্বিতীয় লাইন: দুটি সেটের উপাদান একই দুটি tuple, শুধু লেখার ক্রম আলাদা, তাই সেট সমান; কিন্তু tuple (1, 2) আর (2, 1) আলাদা। তৃতীয় লাইন: {1, 2} আর {2, 1} একই frozenset, তাই বাইরের সেটে একটিই উপাদান। -
প্রমাণের ভুল ধরুন: একজন লিখলেন: “দাবি: যেকোনো সেট A, B, C-এর জন্য A ∈ B আর B ∈ C হলে A ∈ C. প্রমাণ: A ∈ B মানে A, B-এর ভেতরে আছে; B ∈ C মানে B, C-এর ভেতরে আছে। যা B-এর ভেতরে, তা C-এরও ভেতরে। তাই A ∈ C. ∎” ভুল কোথায়? দাবিটি কি সত্য?
- ভুল: “যা B-এর ভেতরে, তা C-এরও ভেতরে” বাক্যটি B ⊆ C-এর কথা, অথচ জানা আছে শুধু B ∈ C. ∈ আর ⊆ গুলিয়ে ফেলা হয়েছে; ⊆ transitive, ∈ নয়।
- Counterexample: A = ∅, B = {∅}, C = {{∅}}. তাহলে A ∈ B (∅ হলো {∅}-এর উপাদান) আর B ∈ C, কিন্তু C-এর একমাত্র উপাদান {∅}, যা ∅ নয়; তাই A ∉ C. দাবি মিথ্যা (scratch-এ frozenset দিয়ে যাচাই করা)।
- যা সত্য: A ∈ B আর B ⊆ C হলে A ∈ C (subset-এর সংজ্ঞা থেকে সরাসরি)।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমElement chasing দিয়ে A ⊆ B প্রমাণের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- লক্ষ্য লেখা: ∀x (x ∈ A → x ∈ B)
- A-এর একটি যেকোনো উপাদান x ধরা
- A-এর সংজ্ঞা খুলে x সম্পর্কে তথ্য লেখা
- যুক্তি বা বীজগণিতে দেখানো যে x, B-এর শর্ত মানে
- x যেকোনো ছিল, তাই A ⊆ B সিদ্ধান্ত
S = {∅} হলে কোনটি সঠিক?
- শুধু ∅ ∈ S সত্য
- শুধু ∅ ⊆ S সত্য
- ∅ ∈ S এবং ∅ ⊆ S দুটিই সত্য
- কোনোটিই সত্য নয়, কারণ S ফাঁকা
|P(P({1, 2}))| কত?
- 4
- 8
- 15
- 16
A = {1, 2} আর B = {1, 2, 3} হলে কোন বাক্যটি সঠিক?
- A × B-এ 6টি জোড়া, আর (3, 1) ∉ A × B
- A × B-এ 5টি জোড়া
- A × B = B × A, কারণ A ⊆ B
- (1, 3) ∉ A × B
Domain ℤ-এর ওপর predicate P(x): “x² < 5”-এর truth set কোনটি?
- {0, 1, 2}
- {−2, −1, 0, 1, 2}
- {−2, 2}
- ∅
ZFC সেট তত্ত্বে Russell-এর সেট R = {x : x ∉ x} সমস্যা তৈরি করে না, কারণ:
- ZFC-তে “x ∉ x” বাক্যটি লেখা নিষিদ্ধ
- ZFC-তে R ∈ R প্রশ্নের উত্তর “অজানা” ধরা হয়
- নতুন সেট শুধু একটি বিদ্যমান সেটের ভেতর থেকে {x ∈ A : P(x)} আকারে বানানো যায়
- ZFC-তে সব সেটের একটি সেট আছে, যা R-কে ধারণ করে
Python-এ {[1, 2], [3]} লিখলে TypeError আসে। কারণ কী?
- একটি set-এ দুইয়ের বেশি সংখ্যা রাখা যায় না
- list বদলানো যায় (mutable), তাই hashable নয়, আর set-এর উপাদানকে hashable হতে হয়
- দুটি list-এর দৈর্ঘ্য আলাদা
- গণিতে সেটের উপাদান সংখ্যা ছাড়া কিছু হতে পারে না
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- সেট = উপাদান, আর কিছু না: ক্রম ও পুনরাবৃত্তি গোনা হয় না; A = B ⇔ ∀x (x ∈ A ↔ x ∈ B). ℕ এই কোর্সে 0 থেকে।
- ∈ বনাম ⊆: ∅ ⊆ S সবসময়, ∅ ∈ S শুধু যদি ∅ উপাদান হয়। ∅ ≠ {∅}; ⊆ transitive, ∈ নয়।
- প্রমাণের কৌশল: A ⊆ B-তে element chasing (যেকোনো x ∈ A → x ∈ B); A = B-তে double inclusion; A ⊄ B-তে একটি counterexample.
- গণনা: |P(S)| = 2ⁿ (bit string-এর সঙ্গে এক-এক মিল); |A × B| = |A| · |B|; relation = A × B-এর subset, সংখ্যা 2|A||B|; A × B = B × A শুধু A = B বা একটি ফাঁকা হলে।
- সতর্কতা: truth set দিয়ে ∀ (TP = D) আর ∃ (TP ≠ ∅); {x : x ∉ x} সেট নয় (Russell), তাই সবসময় domain-এর ভেতরে set-builder; Python-এর set-এ শুধু hashable মান।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ১৫ · সেটের অপারেশন — union, intersection, Venn diagram আর identityপরবর্তী পর্বunion, intersection আর set identity প্রমাণের তিন পথ।
- পর্ব ০৪ · Predicate logic আর quantifier — “সব” আর “কোনো একটি” লেখাপুনরালোচনাPredicate, domain আর quantifier; truth set-এর ভিত্তি।
- পর্ব ১০ · Mathematical induction — এক ধাপ থেকে অসীম পর্যন্ত|P(S)| = 2ⁿPower set-এর আকারের induction-প্রমাণ।
- ডিসক্রিট ম্যাথমেটিক্স · কোর্স হোম৮৩টি পর্বপুরো কোর্সের মানচিত্র আর ১৪টি মডিউল।
- Python প্রোগ্রামিং · পর্ব ১৭ · set — অনন্য মান ও সেট-গণিতকোডে সেটPython-এর set আর frozenset-এর পূর্ণ ব্যবহার।
- DSA · পর্ব ৩২ · Hash table — hash function, collision আর load factorভেতরের কাঠামোset আর dictionary কেন এত দ্রুত খোঁজে।
- ডেটাবেস ও SQL · পর্ব ৫ · Relational model — relation, tuple, attribute আর domainrelationটেবিল আসলে Cartesian product-এর subset.