এই পর্বে যা শিখবেন
- Partial order, poset, total order আর lexicographic order-এর নির্ভুল সংজ্ঞা আর প্রমাণ
- Cover relation থেকে Hasse diagram আঁকা, আর maximal, minimal, greatest, least উপাদান চেনা
- Well-ordered সেট, আর “প্রতিটি সসীম poset-এর একটি topological sort আছে” উপপাদ্যের প্রমাণ ও Kahn-এর algorithm-এর সঠিকতা
- Chain, antichain, Mirsky-এর উপপাদ্যের প্রমাণ আর Dilworth-এর উপপাদ্য
- Upper bound, lub, glb আর lattice; উৎপাদকের lattice আর একটি lattice নয় এমন poset, Python-এ brute force দিয়ে যাচাই
১ · ক্রম কী — partial order আর poset
পর্ব ৫২ “Relation আর তার ধর্ম — reflexive, symmetric, transitive”-এ relation দেখেছেন একটি সেট হিসেবে: R ⊆ A × A, অর্থাৎ পর্ব ১৪-এর Cartesian product-এর একটি subset. পর্ব ৫৫ “Equivalence relation আর partition”-এ reflexive, symmetric আর transitive relation বস্তুগুলোকে “একই রকম” দলে ভাগ করেছে। এই পর্বে symmetric-এর জায়গায় উল্টো ধর্মটি বসবে, আর তাতে পাওয়া যাবে “আগে-পরে” বা “ছোট-বড়”-র গণিত।
বাজারঘরে একটি অর্ডার এলে কয়েকটি কাজ হয়: অর্ডার গ্রহণ, পেমেন্ট যাচাই, স্টক যাচাই, ইনভয়েস, প্যাকিং আর ডেলিভারি। প্যাকিংয়ের আগে পেমেন্ট আর স্টক দুটিই যাচাই হতে হবে, কিন্তু পেমেন্ট আগে না স্টক আগে, তাতে কিছু আসে যায় না। কাজগুলোর মধ্যে একটি ক্রম আছে, কিন্তু তা “পূর্ণ” নয়: কিছু জোড়া তুলনীয় নয়। রান্নাঘরেও একই ছবি: ভাত চড়ানো আর পেঁয়াজ কাটা যেকোনো ক্রমে হয়, কিন্তু মশলা কষানোর আগে পেঁয়াজ কাটতেই হবে।
সেট S-এর ওপর একটি relation R-কে partial order বলে, যদি এটি একসঙ্গে
- reflexive: প্রতিটি a ∈ S-এর জন্য (a, a) ∈ R;
- antisymmetric: (a, b) ∈ R আর (b, a) ∈ R হলে a = b;
- transitive: (a, b) ∈ R আর (b, c) ∈ R হলে (a, c) ∈ R.
জোড়া (S, R)-কে বলে poset (partially ordered set). সাধারণ চিহ্ন: (a, b) ∈ R লিখি a ≼ b, পড়ি “a আগে বা a সমান b”; আর a ≼ b কিন্তু a ≠ b হলে লিখি a ≺ b.
খেয়াল করুন, antisymmetric মানে “symmetric নয়” নয়। Antisymmetric বলে দুটি আলাদা উপাদান একে অন্যের দিকে দুই দিক থেকে যুক্ত হতে পারে না; কোনো relation একসঙ্গে symmetric আর antisymmetric দুটিই হতে পারে (যেমন শুধু সমতা, {(a, a)}), আবার দুটির কোনোটিই না-ও হতে পারে। তিনটি মূল উদাহরণ:
- (ℤ, ≤): সাধারণ ছোট-বড়। একমাত্র “পূর্ণ” উদাহরণ এই তালিকায়: যেকোনো দুটি সংখ্যা তুলনীয়।
- (ℤ+, ∣): a ∣ b মানে a, b-কে ভাগ করে। 2 ∣ 6, কিন্তু 4 আর 6-এর কেউ কাউকে ভাগ করে না।
- (P(S), ⊆): একটি সেটের power set, subset সম্পর্ক নিয়ে। {a} আর {b} তুলনীয় নয়।
ধনাত্মক পূর্ণসংখ্যার সেট ℤ+-এ ∣ একটি partial order.
- Reflexive: a = 1 · a, তাই a ∣ a. — বিভাজ্যতার সংজ্ঞা
- Antisymmetric: a ∣ b আর b ∣ a হলে b = ka, a = lb কোনো ধনাত্মক পূর্ণসংখ্যা k, l-এর জন্য। তাই a = lka, অর্থাৎ lk = 1, আর ধনাত্মক পূর্ণসংখ্যায় তা কেবল l = k = 1-এ হয়; তাই a = b. — a > 0 দিয়ে ভাগ
- Transitive: b = ka আর c = lb হলে c = (lk)a, তাই a ∣ c. ∎ — গুণের সংযোজন
ধাপ ২-এ “ধনাত্মক” শর্তটি জরুরি। পুরো ℤ-এ 2 ∣ −2 আর −2 ∣ 2, অথচ 2 ≠ −2; তাই ℤ-এ ∣ antisymmetric নয়, partial order-ও নয়। একটি উপপাদ্যের শর্ত বাদ দিলে কী হয়, তার এটি ছোট কিন্তু সুন্দর উদাহরণ।
আরেকটি প্রশ্ন: ≤-এর বদলে < নিলে কী হয়? < reflexive নয় (3 < 3 মিথ্যা), তাই partial order নয়। এমন irreflexive, transitive relation-কে বলে strict order, আর দুটি ধারণা পরস্পরে বদলানো যায়: a ≺ b মানে a ≼ b আর a ≠ b, উল্টো দিকে a ≼ b মানে a ≺ b বা a = b. এই পর্বে ≼ বলতে সবসময় reflexive রূপটি বোঝাবে।
২ · তুলনীয়তা, total order আর lexicographic order
Poset (S, ≼)-এ a আর b comparable (তুলনীয়), যদি a ≼ b বা b ≼ a. যে poset-এ প্রতিটি জোড়া তুলনীয়, তাকে বলে total order (বা linear order).
(ℤ, ≤) total; (ℤ+, ∣) আর (P(S), ⊆) total নয় (|S| ≥ 2 হলে)। কয়েকটি ছোট সেটে কতগুলো partial order আর কতগুলো total order আছে, scratch-এ সব relation পরীক্ষা করে গোনা হয়েছে: n = 1, 2, 3, 4 উপাদানে partial order যথাক্রমে 1, 3, 19, 219টি, আর total order 1, 2, 6, 24টি, অর্থাৎ n!. Total order মানে একটি সারি, আর n-টি উপাদানের সারি n!টি।
Total order বানানোর একটি স্বাভাবিক উপায় অভিধানের ক্রম। পর্ব ৩৬ “Permutation আর combination তৈরি — lexicographic order আর backtracking”-এ এই ক্রমে permutation তৈরি করেছেন; এখানে তার গাণিতিক ভিত।
(A, ≼1) আর (B, ≼2) দুটি poset. A × B-এ সংজ্ঞায়িত করুন: (a, b) ≼ (a′, b′) যদি a ≺1 a′, অথবা a = a′ আর b ≼2 b′. তাহলে ≼ একটি partial order; আর ≼1, ≼2 দুটিই total হলে ≼-ও total.
- Reflexive: a = a আর b ≼2 b, তাই (a, b) ≼ (a, b). — দ্বিতীয় শর্ত
- Antisymmetric: ধরুন (a, b) ≼ (a′, b′) আর (a′, b′) ≼ (a, b). যদি a ≠ a′ হতো, তাহলে দুই দিক থেকে a ≺1 a′ আর a′ ≺1 a, আর transitivity দিয়ে a ≺1 a, যা অসম্ভব। তাই a = a′, আর তখন b ≼2 b′, b′ ≼2 b থেকে b = b′. — ≼1, ≼2-এর antisymmetry
- Transitive: (a, b) ≼ (a′, b′) ≼ (a″, b″). প্রথম স্থানাঙ্কে a ≼1 a′ ≼1 a″. কোথাও কঠোরভাবে ছোট হলে a ≺1 a″; দুই জায়গাতেই সমান হলে a = a″ আর b ≼2 b′ ≼2 b″. — ঘটনা ভাগ, পর্ব ৯
- Total: দুই জোড়ার প্রথম স্থানাঙ্ক আলাদা হলে ≼1 total বলে একটি ছোট; সমান হলে ≼2 total বলে দ্বিতীয় স্থানাঙ্ক তুলনীয়। ∎ — total-এর সংজ্ঞা
উদাহরণ: ℤ × ℤ-এ (3, 9) ≺ (4, 1), কারণ প্রথম স্থানাঙ্কে 3 < 4, দ্বিতীয়টি দেখাই লাগে না; আর (4, 1) ≺ (4, 7). String-এ একই নিয়ম অক্ষর ধরে ধরে চলে, আর একটি string অন্যটির শুরুর অংশ হলে ছোটটি আগে: “bat” ≺ “bath” ≺ “bed”. বাজারঘরের অর্ডার-তালিকায় (তারিখ, অর্ডার নম্বর) জোড়া এই ক্রমে সাজালে আগে তারিখ, একই তারিখে অর্ডার নম্বর অনুযায়ী সারি হয়।
৩ · Hasse diagram — শুধু “ঠিক ওপরের” সম্পর্ক
একটি poset-কে পর্ব ১৯-এর zero-one matrix বা একটি directed graph হিসেবে আঁকা যায়, কিন্তু তাতে অনেক অপ্রয়োজনীয় রেখা থাকে। ৬০-এর উৎপাদকে ১২টি উপাদান, আর a ∣ b এমন জোড়া ৫৪টি, যার ১২টি loop (a ∣ a). বাকি ৪২টির বেশিরভাগ transitivity থেকে আপনিই বোঝা যায়: 2 ∣ 4 আর 4 ∣ 12 জানলে 2 ∣ 12 আঁকার দরকার নেই।
সসীম poset-এ b, a-কে cover করে, যদি a ≺ b আর এমন কোনো c নেই যাতে a ≺ c ≺ b. Hasse diagram-এ প্রতিটি উপাদান একটি বিন্দু, প্রতিটি cover জোড়া একটি রেখা, আর b যদি a-কে cover করে তবে b-কে a-র ওপরে আঁকা হয়; তাই তীর লাগে না।
Hasse diagram থেকে পুরো order ফিরে পাওয়া যায়: a ≼ b ঠিক তখন, যখন a থেকে রেখা ধরে শুধু ওপরের দিকে উঠে b-তে পৌঁছানো যায় (শূন্য ধাপও চলে)। এর কারণ, সসীম poset-এ a ≺ b হলে a আর b-এর মাঝে একটি দীর্ঘতম chain নিলে তার পাশাপাশি প্রতিটি জোড়া একটি cover. অর্থাৎ ≼ হলো cover relation-এর reflexive-transitive closure, যা পর্ব ৫৪ “Relation-এর closure আর Warshall-এর algorithm”-এর ভাষা।
৬০-এর ১২টি উৎপাদকের Hasse diagram (ভাগ করা সম্পর্ক)
প্রতিটি রেখা একটি cover: ওপরের সংখ্যা = নিচের সংখ্যা × একটি মৌলিক। একই সারির সংখ্যায় মৌলিক উৎপাদক (গুণিতকসহ) সমান সংখ্যক; সারিগুলোই §৭-এর antichain.
Hasse diagram বানানোর হাতের নিয়ম তিন ধাপের: সব জোড়া লিখুন, loop মুছুন, তারপর যে জোড়া মাঝের কোনো উপাদান দিয়ে “ঘুরে” পাওয়া যায় তা মুছুন। ১২-র উৎপাদকে ধাপগুলো দেখুন।
1S = {1, 2, 3, 4, 6, 12}2সব জোড়া a ∣ b3loop মোছা41-এর ঘুরপথ মোছা5বাকি ঘুরপথ মোছা6সারিতে সাজানো
| জোড়া | |
| মোছা হলো | |
| রেখা |
- উপাদান। 12 = 22 · 3, তাই উৎপাদক 1, 2, 3, 4, 6, 12, মোট (2 + 1)(1 + 1) = 6টি।
- সব জোড়া। a ∣ b এমন (a, b) গুনলে ১৮টি: 1 সবাইকে ভাগ করে (৬টি), 2 ভাগ করে 2, 4, 6, 12 (৪টি), 3 ভাগ করে 3, 6, 12 (৩টি), 4 ভাগ করে 4, 12, 6 ভাগ করে 6, 12 (২টি করে), আর 12 শুধু নিজেকে (১টি)।
- Loop মোছা। Reflexive জোড়া (a, a) ৬টি; Hasse diagram-এ এগুলো আঁকা হয় না। বাকি ১২টি কঠোর জোড়া a ≺ b.
- 1-এর ঘুরপথ। 1 ∣ 4 আসে 1 ∣ 2 ∣ 4 দিয়ে, 1 ∣ 6 আসে 1 ∣ 2 ∣ 6 দিয়ে, আর 1 ∣ 12-ও মাঝের উপাদান দিয়ে আসে। এই ৩টি মুছলে ৯টি থাকে; 1–2 আর 1–3 থাকে, কারণ মাঝে কেউ নেই।
- বাকি ঘুরপথ। 2 ∣ 12 আসে 2 ∣ 4 ∣ 12 দিয়ে; 3 ∣ 12 আসে 3 ∣ 6 ∣ 12 দিয়ে। এ দুটি মুছলে আর কোনো জোড়ার মাঝে উপাদান নেই: ৭টি cover রেখা।
- আঁকা। মৌলিক উৎপাদকের সংখ্যা অনুযায়ী সারি: 1; তারপর 2, 3; তারপর 4, 6; সবার ওপরে 12. প্রতিটি রেখা নিচ থেকে ওপরে একটি মৌলিক দিয়ে গুণ।
নিচের ব্লক এই কাজটি যেকোনো সসীম poset-এ করে: প্রথমে তিনটি ধর্ম সব জোড়া আর ত্রয়ীতে পরীক্ষা করে, তারপর cover জোড়া বের করে। প্রথমবার চালালে ব্রাউজারে Python (Pyodide) নামতে কয়েক সেকেন্ড লাগে; পরের ব্লকগুলো দ্রুত চলে।
from itertools import combinations
def divisors(n):
return [d for d in range(1, n + 1) if n % d == 0]
def is_partial_order(X, le):
refl = all(le(x, x) for x in X)
anti = all(not (le(a, b) and le(b, a)) for a, b in combinations(X, 2))
trans = all(le(a, c) for a in X for b in X for c in X
if le(a, b) and le(b, c))
return refl, anti, trans
def covers(X, le): # b covers a: a < b, nothing strictly between
return [(a, b) for a in X for b in X
if a != b and le(a, b)
and not any(c != a and c != b and le(a, c) and le(c, b)
for c in X)]
divides = lambda a, b: b % a == 0
for n in (12, 60):
X = divisors(n)
pairs = sum(divides(a, b) for a in X for b in X)
E = covers(X, divides)
print(f"n={n}: {len(X)} divisors, {pairs} pairs, "
f"{len(E)} Hasse edges, PO={is_partial_order(X, divides)}")
print("D12 Hasse edges:", covers(divisors(12), divides))
S = [frozenset(c) for r in range(4) for c in combinations("abc", r)]
subset = lambda A, B: A <= B
print("P({a,b,c}):", len(S), "sets,", len(covers(S, subset)),
"Hasse edges, PO =", is_partial_order(S, subset))
print("< on 1..4:", is_partial_order(range(1, 5), lambda a, b: a < b))আসল আউটপুট (ব্রাউজারের Python):
n=12: 6 divisors, 18 pairs, 7 Hasse edges, PO=(True, True, True)
n=60: 12 divisors, 54 pairs, 20 Hasse edges, PO=(True, True, True)
D12 Hasse edges: [(1, 2), (1, 3), (2, 4), (2, 6), (3, 6), (4, 12), (6, 12)]
P({a,b,c}): 8 sets, 12 Hasse edges, PO = (True, True, True)
< on 1..4: (False, True, True)
PO-র তিনটি মান যথাক্রমে reflexive, antisymmetric আর transitive. ১২-র ১৮টি জোড়া থেকে ৭টি রেখা, stepper-এর সঙ্গে হুবহু মেলে; ৬০-এর ৫৪টি জোড়া থেকে ২০টি, ওপরের ছবির রেখার সংখ্যা। P({a, b, c})-এর Hasse diagram একটি ঘনক (cube): ৮টি কোণ, ১২টি ধার, প্রতিটি ধারে একটি অক্ষর যোগ হয়। শেষ লাইন দেখায় < শুধু reflexive-এ ব্যর্থ, তাই এটি strict order. Cover খুঁজতে এখানে প্রতিটি জোড়ার জন্য সব c দেখা হয়েছে, অর্থাৎ O(n3) কাজ; ছোট poset-এ তা যথেষ্ট।
৪ · Maximal, minimal, greatest আর least
ক্রিকেট দলের নির্বাচনে ভাবুন: “এমন কোনো খেলোয়াড় নেই যে তার চেয়ে সব দিক থেকে ভালো” আর “সে সবার চেয়ে সব দিক থেকে ভালো” দুটি আলাদা কথা। প্রথমটি অনেকের জন্য সত্য হতে পারে, দ্বিতীয়টি বড়জোর একজনের জন্য। Poset-এ এই পার্থক্যটিই maximal আর greatest-এর পার্থক্য।
Poset (S, ≼)-এ একটি উপাদান a
- maximal, যদি এমন কোনো b ∈ S নেই যাতে a ≺ b; minimal, যদি এমন কোনো b নেই যাতে b ≺ a;
- greatest, যদি প্রতিটি b ∈ S-এর জন্য b ≼ a; least, যদি প্রতিটি b-এর জন্য a ≼ b.
উদাহরণ: S = {2, 3, 4, 6, 9, 12}, ∣ নিয়ে। Minimal: 2 আর 3 (এদের কোনো উৎপাদক S-এ নেই)। Maximal: 9 আর 12 (এদের কোনো গুণিতক S-এ নেই)। Greatest নেই, কারণ 9 ∤ 12 আর 12 ∤ 9; least-ও নেই। কিন্তু ৬০-এর উৎপাদকে 1 least আর 60 greatest. (ℤ, ≤)-এ কোনোটিই নেই: সেট অসীম, আর প্রতিটি সংখ্যার চেয়ে বড় ও ছোট সংখ্যা আছে।
Poset-এ greatest উপাদান থাকলে তা অনন্য, আর তা একমাত্র maximal উপাদান। Least-এর জন্যও একই কথা।
- ধরুন g আর g′ দুটিই greatest. g greatest বলে g′ ≼ g; g′ greatest বলে g ≼ g′. — সংজ্ঞা ৪.১
- Antisymmetry থেকে g = g′; তাই greatest অনন্য। — partial order-এর ধর্ম
- g maximal: g ≺ b হলে b ≼ g-ও সত্য (g greatest), তাই antisymmetry দিয়ে b = g, যা g ≺ b-এর বিরোধী। — contradiction, পর্ব ৮
- অন্য কোনো maximal m থাকলে m ≼ g; m maximal বলে m ≺ g হতে পারে না, তাই m = g. ∎ — maximal-এর সংজ্ঞা
প্রতিটি অশূন্য সসীম poset-এ অন্তত একটি minimal (আর একইভাবে একটি maximal) উপাদান আছে।
- যেকোনো a1 ∈ S নিন। a1 minimal হলে শেষ; না হলে কোনো a2 ≺ a1 আছে। — minimal-এর সংজ্ঞার নেতিবাচক রূপ
- এভাবে চালালে … ≺ a3 ≺ a2 ≺ a1 পাওয়া যায়। Transitivity দিয়ে i > j হলে ai ≺ aj, তাই সব ai আলাদা (সমান হলে a ≺ a, যা antisymmetry আর ≠-এর বিরোধী)। — transitivity
- S-এ মাত্র |S|-টি উপাদান, তাই এই শিকল |S| ধাপের মধ্যে থামে, আর যেখানে থামে সেটি minimal. ∎ — pigeonhole, পর্ব ৩২
“সসীম” শর্তটি বাদ দেওয়া যায় না: (ℤ, ≤)-এ কোনো minimal নেই। আর আরেকটি সূক্ষ্ম কথা: সসীম poset-এ maximal উপাদান একটিই থাকলে তা greatest (প্রমাণ: যেকোনো b থেকে ওপরে উঠতে থাকলে উপপাদ্য ৪.৩-এর মতো কোনো maximal-এ থামে, আর সেটি একমাত্রটি)। অসীম poset-এ এই শেষ কথাটি মিথ্যা হতে পারে, যা §৯-এর ভুল-ধরা প্রশ্নের বিষয়।
৫ · Well-ordered সেট — অসীম নিচে নামা যায় না
একটি total order (S, ≼)-কে well-ordered বলে, যদি S-এর প্রতিটি অশূন্য subset-এর একটি least উপাদান থাকে।
(ℕ, ≤) well-ordered, আর এটিই পর্ব ১১ “Strong induction আর well-ordering”-এর well-ordering principle. (ℤ, ≤) নয় (পুরো ℤ-এর least নেই), আর ধনাত্মক মূলদ সংখ্যাও নয় ({1/n}-এর least নেই)। একটি সমতুল্য রূপ: well-ordered সেটে কোনো অসীম কঠোরভাবে নামতে থাকা ধারা x1 ≻ x2 ≻ x3 ≻ ⋯ নেই, কারণ এমন ধারার মানগুলোর সেটের least থাকত না।
এই কারণেই well-ordering প্রোগ্রাম থামার প্রমাণে কাজে লাগে। পর্ব ১২-এর Ackermann ফাংশনের প্রতিটি recursive call-এ যুক্তির জোড়া (m, n) ℕ × ℕ-এর lexicographic order-এ কমে। ℕ × ℕ lexicographic order-এ well-ordered: একটি অশূন্য subset T-এ প্রথম স্থানাঙ্কের least m0 নিন (ℕ well-ordered), তারপর m0 দিয়ে শুরু হওয়া জোড়াগুলোর দ্বিতীয় স্থানাঙ্কের least n0; (m0, n0) T-এর least. তাই কমতে থাকা call-ধারা অসীম হতে পারে না, আর ফাংশনটি সবসময় থামে।
সাধারণ ভুল: “অভিধানের ক্রম সবসময় well-ordered”. {a, b} অক্ষরের সব string-এ অভিধানের ক্রম total, কিন্তু well-ordered নয়: b ≻ ab ≻ aab ≻ aaab ≻ ⋯ একটি অসীম নামতে থাকা ধারা, তাই এই সেটের কোনো least নেই। সমাধান হলো আগে দৈর্ঘ্য, তারপর অভিধান (shortlex): এতে প্রতিটি দৈর্ঘ্যে সসীম সংখ্যক string, আর ক্রমটি well-ordered.
৬ · Topological sort — প্রতিটি সসীম poset-কে একটি সারিতে সাজানো
বাজারঘরের ছয়টি কাজে ফিরি: A অর্ডার গ্রহণ, B পেমেন্ট যাচাই, C স্টক যাচাই, D ইনভয়েস, E প্যাকিং, F ডেলিভারি। নির্ভরতা: A → B, A → C, B → D, B → E, C → E, D → F, E → F, যেখানে u → v মানে “v-র আগে u”. একজন কর্মী একবারে একটি কাজ করেন; তাকে এমন একটি সারি দিতে হবে যা সব নির্ভরতা মানে। এই নির্ভরতার reflexive-transitive closure একটি partial order, আর প্রশ্নটি হলো এটিকে বাড়িয়ে একটি total order বানানো।
(S, ≼)-এর একটি linear extension (বা topological sort) হলো S-এর ওপর একটি total order ≤t, যাতে a ≼ b হলে a ≤t b. প্রতিটি সসীম poset-এর অন্তত একটি linear extension আছে।
- |S|-এর ওপর induction. |S| = 1 হলে একমাত্র উপাদানটিই সারি। — basis, পর্ব ১০
- |S| = n + 1 হলে উপপাদ্য ৪.৩ দিয়ে একটি minimal উপাদান m নিন, আর তাকে সারির প্রথমে বসান। — সসীম poset-এ minimal আছে
- S − {m}, একই ≼ নিয়ে, একটি n-উপাদানের poset (তিনটি ধর্ম subset-এ বজায় থাকে)। Induction hypothesis দিয়ে এর একটি linear extension b1, …, bn আছে; সারি m, b1, …, bn. — inductive hypothesis
- এই সারি ≼ মানে কি? bi ≼ bj জোড়াগুলো hypothesis-এ মানা হয়েছে। m-যুক্ত জোড়ায় b ≼ m হতে পারে শুধু b = m হলে, কারণ m minimal; তাই m-এর আগে কারও আসার দরকার নেই, আর m ≼ b-গুলো m প্রথমে বলে মানা হয়। ∎ — minimal-এর সংজ্ঞা
এই প্রমাণই একটি algorithm: বারবার একটি minimal উপাদান তুলে নিন। Graph-এর ভাষায় নির্ভরতার রেখাগুলো একটি DAG (directed acyclic graph), minimal উপাদান মানে যে vertex-এ কোনো রেখা ঢোকে না (in-degree 0). A. B. Kahn ১৯৬২ সালে এই পদ্ধতি প্রকাশ করেন বলে সাধারণত উল্লেখ করা হয়; তাই এর নাম Kahn-এর algorithm. প্রতিটি vertex-এর in-degree গুনে রাখুন; in-degree 0 এমনগুলো একটি “প্রস্তুত” তালিকায়; প্রতিবার একটি বের করে সারিতে লিখুন আর তার পরের vertex-গুলোর in-degree এক কমান। এখানে প্রস্তুত তালিকা থেকে বর্ণক্রমে সবচেয়ে ছোটটি নেওয়া হলো।
1in-degree গোনা2A নেওয়া3B নেওয়া4C নেওয়া5D নেওয়া6E নেওয়া7F নেওয়া
| in-degree | |
| প্রস্তুত | |
| সারি |
- শুরু। ঢোকা রেখা গুনে in-degree: A 0, B 1, C 1, D 1, E 2 (B আর C থেকে), F 2 (D আর E থেকে)। প্রস্তুত তালিকায় শুধু A.
- A. A সারিতে; A → B আর A → C সরে যায়, তাই B আর C-এর in-degree 0. প্রস্তুত: B, C.
- B. বর্ণক্রমে B আগে। B → D আর B → E সরে: D 0, E 1. প্রস্তুত: C, D.
- C. C → E সরে, E 0. প্রস্তুত: D, E. প্যাকিং (E) এখন মুক্ত, কারণ পেমেন্ট আর স্টক দুটিই হয়ে গেছে।
- D. D → F সরে, F 1. প্রস্তুত: শুধু E.
- E. E → F সরে, F 0. প্রস্তুত: F.
- F. সারি A B C D E F; ছয়টি কাজই বেরিয়েছে, তাই নির্ভরতায় কোনো cycle নেই। প্রস্তুত তালিকা থেকে অন্য ক্রমে নিলে অন্য বৈধ সারি আসত।
নির্ভরতার graph G-তে n-টি vertex থাকলে Kahn-এর algorithm n-টি vertex-ই বের করে যদি এবং কেবল যদি G-তে কোনো directed cycle নেই; আর তখন বের হওয়ার ক্রমটি একটি topological sort.
- Invariant: যেকোনো মুহূর্তে একটি vertex-এর রাখা in-degree = এখনো বের না হওয়া vertex থেকে তাতে ঢোকা রেখার সংখ্যা। শুরুতে সত্য, আর প্রতিবার x বের হলে x থেকে বের হওয়া রেখার শেষ vertex-গুলোতে ঠিক এক করে কমে। — loop invariant, পর্ব ১৩
- তাই x বের হওয়ার সময় তার in-degree 0, অর্থাৎ x-এ ঢোকা প্রতিটি রেখা u → x-এর u আগেই বেরিয়েছে: ক্রমটি প্রতিটি নির্ভরতা মানে। — invariant থেকে
- Cycle থাকলে তার কোনো vertex প্রথম বের হতে পারে না: cycle-এ তার আগের vertex তখনো ভেতরে, তাই in-degree অন্তত 1. তাই cycle-এর কোনো vertex বের হয় না, আর মোট বের হয় n-এর কম। — contradiction
- Cycle না থাকলে, ধরুন algorithm কিছু vertex বাকি রেখে থামল। বাকিগুলো একটি সসীম poset (cycle নেই বলে closure antisymmetric), তাই উপপাদ্য ৪.৩ দিয়ে একটি minimal আছে, যার বাকিদের মধ্যে কোনো পূর্বসূরি নেই, অর্থাৎ in-degree 0, তাই প্রস্তুত তালিকা খালি ছিল না, বিরোধ। ∎ — উপপাদ্য ৪.৩
প্রতিটি রেখা একবার আর প্রতিটি vertex একবার ধরা হয়, তাই adjacency list দিয়ে লিখলে কাজ O(V + E). Queue, adjacency list আর DFS-ভিত্তিক বিকল্প পদ্ধতির কোড DSA কোর্সের পর্ব ৪২ “Topological sort আর DAG”-এ আছে; এখানে আমাদের লক্ষ্য প্রমাণ। নিচের ব্লক Kahn চালায়, তারপর ৬! = 720টি সারির প্রতিটি পরীক্ষা করে মোট কয়টি বৈধ সারি আছে তা গোনে, আর একটি cycle যোগ করে দেখে algorithm তা ধরে কি না।
from itertools import permutations
tasks = {"A": "order received", "B": "payment check",
"C": "stock check", "D": "invoice",
"E": "packing", "F": "delivery"}
deps = [("A", "B"), ("A", "C"), ("B", "D"), ("B", "E"),
("C", "E"), ("D", "F"), ("E", "F")]
def kahn(V, E):
indeg = {v: 0 for v in V}
for a, b in E:
indeg[b] += 1
ready = sorted(v for v in V if indeg[v] == 0)
order = []
while ready:
x = ready.pop(0) # smallest label first
order.append(x)
for a, b in E:
if a == x:
indeg[b] -= 1
if indeg[b] == 0:
ready = sorted(ready + [b])
return order if len(order) == len(V) else None # None = cycle
order = kahn(tasks, deps)
print("Kahn order:", " -> ".join(order))
print(" ", " -> ".join(tasks[t] for t in order))
ok = [p for p in permutations(tasks)
if all(p.index(a) < p.index(b) for a, b in deps)]
print("all 720 orders checked, valid:", len(ok))
for p in ok:
print(" ", "".join(p))
print("with E -> A added:", kahn(tasks, deps + [("E", "A")]))আসল আউটপুট (ব্রাউজারের Python):
Kahn order: A -> B -> C -> D -> E -> F
order received -> payment check -> stock check -> invoice -> packing -> delivery
all 720 orders checked, valid: 5
ABCDEF
ABCEDF
ABDCEF
ACBDEF
ACBEDF
with E -> A added: None
Kahn-এর সারি stepper-এর সঙ্গে মেলে। Brute force দেখায় মোট ৫টি linear extension: A সবসময় প্রথমে আর F শেষে; মাঝে B আর C-এর ক্রম, আর D কোথায় বসবে, তাতেই পার্থক্য। তবে D কখনো B-এর আগে নয়, আর E কখনো C-এর আগে নয়। শেষ লাইনে E → A যোগ করায় A → B → E → A একটি cycle, কোনো কাজের in-degree শুরুতে 0 নয়, তাই algorithm কিছুই বের করতে পারেনি আর None দিয়েছে, যেমন উপপাদ্য ৬.২-এর ধাপ ৩ বলে। সব সারি পরীক্ষা করা n! কাজ, তাই এটি শুধু ছোট n-এ চলে; linear extension গোনা সাধারণভাবে কঠিন সমস্যা, ভাবনার প্রশ্ন ৩-এ এ নিয়ে আরও।
৭ · Chain, antichain — Mirsky আর Dilworth
Poset-এর একটি subset যদি পরস্পর তুলনীয় উপাদানে গঠিত হয়, তবে তা একটি chain; আর যদি এর কোনো দুটি আলাদা উপাদান তুলনীয় না হয়, তবে তা একটি antichain. দীর্ঘতম chain-এর আকারকে poset-এর height, আর বৃহত্তম antichain-এর আকারকে width বলে।
কাজের ভাষায়: chain হলো এমন কাজের দল যেগুলো একটির পর একটি করতেই হবে, আর antichain হলো এমন কাজের দল যেগুলো একসঙ্গে, আলাদা কর্মী দিয়ে করা যায়। বাজারঘরের ছয় কাজে A, B, E, F একটি chain (height ৪), আর {B, C} বা {D, E} একটি antichain. একটি chain আর একটি antichain-এর সাধারণ উপাদান বড়জোর একটি, কারণ দুটি সাধারণ উপাদান হলে তারা একসঙ্গে তুলনীয় আর অতুলনীয় হতো। এই সরল পর্যবেক্ষণ থেকেই দুটি সুন্দর উপপাদ্য আসে।
সসীম poset-এর height h হলে S-কে ঠিক h-টি antichain-এ ভাগ করা যায়, আর h-এর কম antichain-এ ভাগ করা যায় না।
- h-এর কম অসম্ভব: h আকারের একটি chain-এর প্রতিটি উপাদান আলাদা antichain-এ পড়তে হবে, কারণ একটি antichain chain-এর বড়জোর একটি উপাদান নেয়। — pigeonhole
- প্রতিটি x-এর জন্য level(x) = x-এ শেষ হওয়া দীর্ঘতম chain-এর আকার। 1 ≤ level(x) ≤ h. — সংজ্ঞা
- Ak = {x : level(x) = k} নিন। x ≺ y হলে x-এ শেষ হওয়া দীর্ঘতম chain-এর পরে y যোগ করা যায়, তাই level(y) ≥ level(x) + 1 > level(x). — chain বাড়ানো
- তাই একই level-এর দুটি উপাদান তুলনীয় হতে পারে না: প্রতিটি Ak একটি antichain, আর A1, …, Ah মিলে S-এর একটি partition. ∎ — ধাপ ১ আর ৪ মিলিয়ে সমতা
সসীম poset-এর width w হলে S-কে ঠিক w-টি chain-এ ভাগ করা যায়, আর এর কম chain-এ ভাগ করা যায় না।
“কম হয় না” অংশটি আগের মতোই সহজ: w আকারের antichain-এর প্রতিটি উপাদান আলাদা chain-এ পড়ে। “ঠিক w-টি chain যথেষ্ট” অংশটি কঠিনতর; Robert P. Dilworth ১৯৫০ সালে এটি প্রকাশ করেন বলে উল্লেখ করা হয়, আর Leon Mirsky ১৯৭১ সালে তার “dual” হিসেবে ওপরের সহজ উপপাদ্যটি দেন। Dilworth-এর একটি পরিচিত প্রমাণ bipartite matching দিয়ে চলে, যা পর্ব ৬৪ “Matching — bipartite graph, Hall-এর উপপাদ্য আর stable matching”-এর বিষয়; সেখানে §৫-এ König-এর উপপাদ্য থেকে পুরো প্রমাণটি দেওয়া আছে।
একটি প্রয়োগ: পর্ব ৩২-এর Erdős–Szekeres উপপাদ্য (n2 + 1টি আলাদা সংখ্যার যেকোনো ধারায় দৈর্ঘ্য n + 1-এর একটি বাড়তে থাকা বা কমতে থাকা subsequence আছে) Mirsky দিয়ে দুই লাইনে আসে। অবস্থান i-তে মান xi হলে i ≼ j বলুন যদি i ≤ j আর xi ≤ xj. এখানে chain মানে বাড়তে থাকা subsequence, আর antichain মানে কমতে থাকা। সবচেয়ে লম্বা বাড়তি অংশ n বা কম হলে Mirsky অনুযায়ী n2 + 1টি উপাদান বড়জোর n-টি antichain-এ ভাগ হয়, তাই pigeonhole দিয়ে একটি antichain-এ অন্তত n + 1টি: দৈর্ঘ্য n + 1-এর কমতে থাকা subsequence.
নিচের ব্লক ৬০-এর উৎপাদকে Mirsky-এর level হিসাব করে, ৪০৯৬টি subset পরীক্ষা করে width বের করে, ৪টি chain-এর একটি ভাগ যাচাই করে (Dilworth-এর সংখ্যা), আর linear extension গোনে।
from itertools import combinations
from functools import lru_cache
X = [d for d in range(1, 61) if 60 % d == 0]
le = lambda a, b: b % a == 0
level = {} # Mirsky: longest chain ending at x
for x in X: # X is increasing, so smaller divisors come first
level[x] = 1 + max((level[y] for y in level if le(y, x)), default=0)
h = max(level.values())
print("height (longest chain):", h)
for k in range(1, h + 1):
print(f" level {k}: {[x for x in X if level[x] == k]}")
def antichain(c):
return all(not le(a, b) and not le(b, a) for a, b in combinations(c, 2))
w = max(len(c) for r in range(1, len(X) + 1)
for c in combinations(X, r) if antichain(c))
print("width (largest antichain), brute force over 4096 subsets:", w)
chains = [[1, 2, 4, 12, 60], [3, 6, 30], [5, 10, 20], [15]]
print("4 chains cover all:", sorted(sum(chains, [])) == X,
"each a chain:", all(le(a, b) for c in chains for a, b in zip(c, c[1:])))
@lru_cache(None)
def linear_extensions(rest):
if not rest:
return 1
return sum(linear_extensions(rest - {x}) for x in rest
if not any(y != x and le(y, x) for y in rest))
print("linear extensions of D60:", linear_extensions(frozenset(X)))
print("linear extensions of D12:",
linear_extensions(frozenset(d for d in X if 12 % d == 0)))আসল আউটপুট (ব্রাউজারের Python):
height (longest chain): 5
level 1: [1]
level 2: [2, 3, 5]
level 3: [4, 6, 10, 15]
level 4: [12, 20, 30]
level 5: [60]
width (largest antichain), brute force over 4096 subsets: 4
4 chains cover all: True each a chain: True
linear extensions of D60: 2452
linear extensions of D12: 5
Height ৫ (যেমন 1 ∣ 2 ∣ 4 ∣ 12 ∣ 60), আর level-গুলো ঠিক Hasse diagram-এর পাঁচটি সারি: Mirsky-এর ৫টি antichain. বৃহত্তম antichain {4, 6, 10, 15}, আকার ৪, আর ৪টি chain-এ ভাগটি পাওয়া গেছে, তাই এই poset-এ Dilworth-এর সংখ্যা ৪ সত্যিই অর্জিত। Linear extension গোনায় প্রতিবার একটি minimal উপাদান প্রথমে বসিয়ে বাকিটা গোনা হয়েছে, অর্থাৎ উপপাদ্য ৬.১-এর প্রমাণটিই গণনায় রূপ নিয়েছে; memoization (lru_cache) একই বাকি-সেট দুবার গোনা এড়ায়। ৬০-এর উৎপাদক ২৪৫২ ভাবে সারিতে বসানো যায়, আর ১২-র উৎপাদক ৫ ভাবে।
৮ · Upper bound, lub, glb আর lattice
Poset (S, ≼)-এ A ⊆ S. u ∈ S হলো A-র একটি upper bound, যদি A-র প্রতিটি a-র জন্য a ≼ u; একইভাবে lower bound. সব upper bound-এর least উপাদান থাকলে তা A-র least upper bound (lub, supremum); সব lower bound-এর greatest থাকলে তা greatest lower bound (glb, infimum). উপপাদ্য ৪.২ অনুযায়ী lub আর glb থাকলে অনন্য।
ভাগ করা সম্পর্কে a আর b-এর upper bound মানে উভয়ের সাধারণ গুণিতক, আর lub মানে সেই সাধারণ গুণিতক যা অন্য সব সাধারণ গুণিতককে ভাগ করে। এটিই পর্ব ২১-এর lcm; একইভাবে glb হলো gcd. খেয়াল করুন, এখানে “ছোট” মানে ≤ নয়, ∣. ৬০-এর উৎপাদকে কয়েকটি জোড়া দেখুন।
14 আর 6: upper bound24 আর 6: lower bound310 আর 1244 আর 5520 আর 306সাধারণ নিয়ম
| জোড়া | |
| upper bound | |
| lower bound | |
| lub, glb |
- Upper bound. 4 আর 6 দুটিই ভাগ করে এমন উৎপাদক: 12 আর 60. এদের মধ্যে 12 ∣ 60, তাই 12 least: lub(4, 6) = 12 = lcm(4, 6).
- Lower bound. 4 আর 6-এর সাধারণ উৎপাদক: 1 আর 2. 1 ∣ 2, তাই 2 greatest: glb(4, 6) = 2 = gcd(4, 6).
- 10 আর 12. সাধারণ গুণিতক S-এ শুধু 60, তাই lub 60; সাধারণ উৎপাদক 1, 2, তাই glb 2. lcm(10, 12) = 60 আর gcd = 2.
- 4 আর 5. Upper bound 20, 60; lub 20. Lower bound শুধু 1, তাই glb 1: 4 আর 5 সহমৌলিক।
- 20 আর 30. Upper bound শুধু 60; lower bound 1, 2, 5, 10, যাদের প্রত্যেকে 10-কে ভাগ করে, তাই glb 10. খেয়াল করুন, “greatest” মানে এখানে সংখ্যায় বড় নয়, বাকি সবাই যাকে ভাগ করে।
- নিয়ম। n-এর উৎপাদকে a আর b দুটিই n-কে ভাগ করে, তাই lcm(a, b) আর gcd(a, b)-ও n-এর উৎপাদক, আর এরাই lub আর glb. তাই প্রতিটি জোড়ার lub আর glb আছে।
যে poset-এ প্রতিটি জোড়া a, b-এর lub (লেখা হয় a ∨ b, “join”) আর glb (a ∧ b, “meet”) আছে, তাকে lattice বলে। প্রতিটি n ≥ 1-এর জন্য n-এর উৎপাদকের সেট Dn, ∣ নিয়ে, একটি lattice, যেখানে a ∨ b = lcm(a, b) আর a ∧ b = gcd(a, b).
- a, b ∈ Dn হলে a ∣ n আর b ∣ n, তাই n একটি সাধারণ গুণিতক, আর lcm(a, b) ∣ n; অর্থাৎ lcm(a, b) ∈ Dn. — lcm প্রতিটি সাধারণ গুণিতককে ভাগ করে, পর্ব ২১
- lcm(a, b) একটি upper bound, আর যেকোনো upper bound u (a ∣ u, b ∣ u) হলে lcm(a, b) ∣ u. তাই এটি upper bound-গুলোর least. — lub-এর সংজ্ঞা
- gcd(a, b) ∣ a ∣ n, তাই gcd ∈ Dn; আর যেকোনো সাধারণ উৎপাদক c-এর জন্য c ∣ gcd(a, b). তাই gcd হলো glb. ∎ — Bézout-ভিত্তিক gcd-এর ধর্ম, পর্ব ২১
আরেকটি মৌলিক উদাহরণ (P(S), ⊆): A ∨ B = A ∪ B আর A ∧ B = A ∩ B, কারণ A আর B দুটিকেই ধারণ করে এমন সবচেয়ে ছোট সেট A ∪ B (পর্ব ১৫)। (ℤ, ≤)-ও lattice, max আর min নিয়ে; প্রতিটি total order-ই lattice.
Lattice নয় এমন উদাহরণ: S = {1, 2, 3, 12, 18, 36}, ∣ নিয়ে। 2 আর 3-এর upper bound 12, 18, 36; কিন্তু 12 আর 18 কেউ কাউকে ভাগ করে না, তাই upper bound-গুলোর least নেই, অর্থাৎ lub(2, 3) নেই। (S-এ 6 থাকলে তা-ই হতো lub.) একইভাবে 12 আর 18-এর lower bound 1, 2, 3, যাদের greatest নেই। নিচের ব্লক সব জোড়া পরীক্ষা করে এটি নিশ্চিত করে, আর Dn-এ lub আর glb যে সত্যিই lcm আর gcd, তা-ও মেলায়।
from math import gcd
def least(cands, le): # the element below all others, or None
best = [c for c in cands if all(le(c, d) for d in cands)]
return best[0] if best else None
def lattice_report(X, name):
le = lambda a, b: b % a == 0
ge = lambda a, b: a % b == 0
bad = []
for i, a in enumerate(X):
for b in X[i + 1:]:
ub = [c for c in X if le(a, c) and le(b, c)]
lb = [c for c in X if le(c, a) and le(c, b)]
lub, glb = least(ub, le), least(lb, ge)
if lub is None or glb is None:
bad.append((a, b, ub, lb))
elif lub != a * b // gcd(a, b) or glb != gcd(a, b):
bad.append((a, b, "differs from lcm/gcd"))
print(f"{name}: {len(X)} elements, lattice = {not bad}")
for row in bad[:3]:
print(" no lub or glb:", row)
D60 = [d for d in range(1, 61) if 60 % d == 0]
lattice_report(D60, "D60")
lattice_report([1, 2, 3, 12, 18, 36], "S")
for n in (12, 36, 210):
lattice_report([d for d in range(1, n + 1) if n % d == 0], f"D{n}")আসল আউটপুট (ব্রাউজারের Python):
D60: 12 elements, lattice = True
S: 6 elements, lattice = False
no lub or glb: (2, 3, [12, 18, 36], [1])
no lub or glb: (12, 18, [36], [1, 2, 3])
D12: 6 elements, lattice = True
D36: 9 elements, lattice = True
D210: 16 elements, lattice = True
প্রতিটি ব্যর্থ সারিতে আছে জোড়ার দুটি উপাদান, upper bound-এর তালিকা আর lower bound-এর তালিকা। S-এ ঠিক দুটি জোড়া ব্যর্থ: (2, 3)-এর upper bound তিনটি কিন্তু least নেই (glb 1 আছে), আর (12, 18)-এর lower bound তিনটি কিন্তু greatest নেই (lub 36 আছে)। এই একটি ব্যর্থতাই lattice না হওয়ার জন্য যথেষ্ট। সব Dn-এ lub = lcm আর glb = gcd মিলেছে। D210 (210 = 2 · 3 · 5 · 7) আসলে ৪টি মৌলিকের subset-গুলোর lattice-এর মতো: প্রতিটি উৎপাদক কোন মৌলিকগুলো নেয় তা দিয়ে চেনা যায়, তাই ১৬ = 24টি উপাদান।
শেষ পর্যবেক্ষণটি একটি বড় ধারণার দরজা। n squarefree হলে (কোনো মৌলিকের বর্গ n-কে ভাগ করে না) Dn আর P(মৌলিক উৎপাদকের সেট) একই গঠনের: D30-এর Hasse diagram P({a, b, c})-এর মতো একটি ঘনক, আর দুটিরই linear extension ৪৮টি (scratch-এ গোনা)। এমন lattice-এ প্রতিটি উপাদানের একটি “পরিপূরক” আছে (30-এ 2-এর পরিপূরক 15), আর এই গঠনই Boolean algebra. পর্ব ৬৯ “Boolean algebra-র গণিত — function, identity আর minimization”-এ এই গঠন বীজগণিত হিসেবে আসবে।
৯ · পরীক্ষার অঙ্ক আর একটি ভুল প্রমাণ
অঙ্ক ১. S = {1, 2, 3, 4, 5, 6, 8, 12}, ∣ নিয়ে। Maximal, minimal, greatest, least বের করুন, আর {2, 3}-এর lub খুঁজুন। সমাধান: minimal শুধু 1, আর 1 সবাইকে ভাগ করে, তাই least 1. Maximal: 5, 8, 12 (এদের কোনো গুণিতক S-এ নেই)। তিনটি maximal, তাই greatest নেই (উপপাদ্য ৪.২)। {2, 3}-এর upper bound 6, 12; 6 ∣ 12, তাই lub 6.
অঙ্ক ২. P({a, b, c})-এর Hasse diagram-এ কয়টি রেখা, height আর width কত? সমাধান: প্রতিটি সেট থেকে একটি অনুপস্থিত অক্ষর যোগ করলে cover; ৮টি সেটে মোট অনুপস্থিত অক্ষর 3 · 4 = 12 (প্রতিটি অক্ষর ৪টি সেটে নেই), তাই ১২টি রেখা। Height ৪ (∅ ⊂ {a} ⊂ {a, b} ⊂ {a, b, c}); width ৩ ({a}, {b}, {c}), আর Mirsky-এর ৪টি antichain হলো আকার অনুযায়ী সারি: ১, ৩, ৩, ১।
অঙ্ক ৩. ℤ × ℤ-এর lexicographic order-এ (2, 5), (1, 9) আর (2, −1)-কে ছোট থেকে বড় সাজান। সমাধান: (1, 9) ≺ (2, −1) ≺ (2, 5); প্রথম স্থানাঙ্ক আগে দেখা হয়, তাই 9 বড় হলেও (1, 9) সবার আগে।
ভুল প্রমাণ ধরুন। দাবি: “যে poset-এ ঠিক একটি maximal উপাদান m, সেখানে m greatest.” প্রমাণ: “যেকোনো b নিন। b = m হলে শেষ। না হলে b maximal নয় (maximal একটিই), তাই b ≺ b1 কোনো b1-এর জন্য। b1 = m হলে শেষ, না হলে b1 ≺ b2, এভাবে চলতে থাকে, আর শেষে m-এ পৌঁছায়। তাই b ≼ m.”
ভুল কোথায়: “শেষে m-এ পৌঁছায়” কথাটির কোনো যুক্তি নেই; শিকলটি অসীম হতে পারে। Counterexample: S = ℕ ∪ {m}, যেখানে ℕ-এ সাধারণ ≤ আর m কোনো সংখ্যার সঙ্গে তুলনীয় নয়। ℕ-এ কোনো maximal নেই (প্রতিটির পরে বড় সংখ্যা), তাই m একমাত্র maximal; কিন্তু 0 ⋠ m, তাই m greatest নয়। প্রমাণটি সঠিক হয় S সসীম হলে, কারণ তখন উপপাদ্য ৪.৩-এর মতো শিকল |S| ধাপের মধ্যে থামে। এটি একটি পরিচিত ধাঁচ: অসীম সেটে “এভাবে চলতে থাকলে শেষে” কথাটি well-ordering বা finiteness ছাড়া অর্থহীন।
আরও গভীরে: অসীম poset-এও linear extension থাকে, এটি Edward Szpilrajn-এর ১৯৩০ সালের উপপাদ্য বলে উল্লেখ করা হয়, তবে প্রমাণে axiom of choice-এর একটি রূপ লাগে। Lattice-এর তত্ত্ব Dedekind-এর উনিশ শতকের শেষের কাজ থেকে শুরু বলে ধরা হয়, আর Garrett Birkhoff-এর ১৯৪০ সালের বই Lattice Theory একে একটি স্বতন্ত্র শাখা বানায়। কম্পিউটার বিজ্ঞানে lattice আসে program analysis-এ (dataflow analysis-এর মান একটি lattice-এ থাকে, আর fixed point খোঁজা হয়), distributed system-এর vector clock-এ (ঘটনাগুলোর “আগে ঘটেছে” সম্পর্ক একটি partial order), আর CRDT-এর মতো data structure-এ, যেখানে দুই কপির join নিয়ে মেলানো হয়।
পরীক্ষা ও ইন্টারভিউতে: বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন প্রায়ই আসে:
- Partial order-এর তিনটি শর্ত? Reflexive, antisymmetric, transitive.
- ১২-র উৎপাদকের Hasse diagram-এ কয়টি রেখা? ৭টি।
- Maximal আর greatest-এর পার্থক্য? Maximal-এর ওপরে কেউ নেই; greatest-এর নিচে সবাই। Greatest থাকলে তা অনন্য।
- Topological sort কখন অসম্ভব? নির্ভরতার graph-এ directed cycle থাকলে; Kahn তখন সব vertex বের করতে পারে না।
- Dn-এ join আর meet? lcm আর gcd.
১০ · AI-এর যুগে — ক্রম আর lattice-এর উত্তর যাচাই
Partial order-এর প্রশ্নে AI সহকারী প্রায়ই সংজ্ঞা ঠিক বলে, কিন্তু উদাহরণে ভুল করে, আর তা আত্মবিশ্বাসী ভাষায় আসে। কয়েকটি নিয়মিত ভুল:
| AI-এর ভুল | কীভাবে ধরবেন |
|---|---|
| Maximal আর greatest গুলিয়ে ফেলা, যেমন “maximal 8 আর 12, তাই greatest 12” | Greatest দাবি করলে প্রতিটি উপাদান তার নিচে কি না একে একে দেখুন |
| Antisymmetric-কে “symmetric নয়” ধরা | সংজ্ঞা মিলিয়ে একটি জোড়া (a, b), (b, a), a ≠ b খুঁজুন |
| Hasse diagram-এ transitivity-র রেখা রেখে দেওয়া (যেমন 1–12) | প্রতিটি রেখার মাঝে কোনো উপাদান আছে কি না দেখুন; রেখার সংখ্যা Python-এ গুনুন |
| “সংখ্যায় বড়” আর “ক্রমে বড়” মেশানো, যেমন ∣-এ glb(20, 30) = 5 বলা | সব lower bound তালিকা করে দেখুন কোনটিকে বাকিরা ভাগ করে |
| সসীম না হলেও “maximal আছে” বা “একটি maximal হলে greatest” বলা | উপপাদ্যের শর্ত (সসীম, total, well-ordered) জিজ্ঞেস করুন; অসীম counterexample খুঁজুন |
| Linear extension-এর সংখ্যা আন্দাজে বলা | ছোট poset-এ সব permutation পরীক্ষা করে গুনুন |
AI-এর কাছে poset-এর কোনো সমাধান চাইলে এমন কাঠামো দিন, যাতে প্রতিটি দাবি আলাদা করে যাচাই করা যায়:
AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট
Poset-এর প্রায় প্রতিটি দাবি ছোট উদাহরণে যন্ত্রের মতো যাচাই করা যায়: সব জোড়া, সব ত্রয়ী, সব subset, সব permutation. এই পর্বের চারটি ছোট Python ব্লকে প্রায় সব সংজ্ঞা এভাবেই পরীক্ষা হয়েছে। AI-এর উত্তরকে তালিকায় ভেঙে নিন, আর একটি স্বাধীন brute force চালিয়ে মিলিয়ে তবেই ভরসা করুন।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।
প্র ০১Build system, spreadsheet আর package manager কীভাবে topological sort ব্যবহার করে? Cycle থাকলে তারা কী করে?
একটি বড় software-এ শত শত ফাইল, আর একটি ফাইল compile করতে আগে অন্য কিছু ফাইল তৈরি থাকতে হয়। Make-এর মতো build tool ১৯৭০-এর দশকের শেষ থেকে এই নির্ভরতাগুলো একটি DAG হিসেবে পড়ে, আর এমন ক্রমে কাজ চালায় যাতে প্রতিটি লক্ষ্য তার নির্ভরতার পরে তৈরি হয়; অর্থাৎ একটি linear extension. Spreadsheet-এ একটি ঘরের সূত্র অন্য ঘরের ওপর নির্ভর করে; একটি ঘর বদলালে কোন ঘরগুলো আবার হিসাব করতে হবে আর কোন ক্রমে, তা নির্ভরতার graph থেকে আসে। Package manager একটি library install করার আগে তার নির্ভর library-গুলো install করে, একই নীতিতে।
Cycle থাকলে কোনো linear extension নেই, কারণ cycle-এর closure antisymmetric নয়: a আগে b আর b আগে a, অথচ a ≠ b. উপপাদ্য ৬.২-এর ধাপ ৩ ঠিক এটি বলে, আর এই কারণেই tool-গুলো cycle পেলে থেমে যায়। Spreadsheet-এ এটিকে সাধারণত circular reference বলা হয়, আর build tool cycle-এর কথা জানিয়ে থামে। ব্যবহারিক দিক থেকে এখানে একটি শিক্ষা আছে: Kahn-এর algorithm শুধু সারি দেয় না, বরং “সারি পাওয়া গেল কি না” দিয়েই cycle-এর উপস্থিতি জানায়, আর বাকি থাকা vertex-গুলো দেখে cycle কোথায় তা-ও খোঁজা যায়।
আরেকটি দিক সমান্তরাল কাজ। অনেক build tool একসঙ্গে কয়েকটি কাজ চালায়। কোন কাজগুলো একসঙ্গে চলতে পারে? যেগুলো পরস্পর অতুলনীয়, অর্থাৎ একটি antichain. Mirsky-এর level-গুলো এখানে স্বাভাবিক পরিকল্পনা দেয়: level 1-এর সব কাজ একসঙ্গে, তারপর level 2-এর সব, এভাবে। মোট ধাপের সংখ্যা height, অর্থাৎ দীর্ঘতম নির্ভরতা-শিকল; যত কর্মীই থাকুক, এর কম ধাপে কাজ শেষ হয় না। বাজারঘরের ছয় কাজে height ৪ (A, B, E, F), তাই অন্তত ৪টি ধাপ লাগবে, যদিও কাজ ৬টি। Project management-এ এই দীর্ঘতম শিকলকেই critical path বলা হয়।
অবশ্য বাস্তবে সব কাজের সময় সমান নয়, আর কর্মীর সংখ্যা সীমিত। তখন প্রশ্নটি একটি কঠিন scheduling সমস্যা হয়ে যায়, যার অনেক রূপ NP-hard বলে জানা; সেখানে নির্ভুল সমাধানের বদলে ভালো আনুমানিক নিয়ম ব্যবহার হয়।
মূল উপলব্ধি: নির্ভরতা মানে একটি partial order; একটি বৈধ কাজের সারি মানে linear extension, cycle মানে কোনো বৈধ সারি নেই, আর একসঙ্গে করা যায় এমন কাজ মানে antichain.
প্র ০২Distributed system-এ “আগে ঘটেছে” সম্পর্কটি কেন একটি partial order, total order নয়? Lamport-এর ধারণা কী বলে?
ধরুন বাজারঘরের তিনটি server আলাদা শহরে, প্রত্যেকে নিজের ঘড়িতে চলে, আর তারা বার্তা পাঠিয়ে যোগাযোগ করে। ঘড়িগুলো কখনো পুরোপুরি মেলে না, তাই “কোনটি আগে ঘটেছে” প্রশ্নের উত্তর ঘড়ি দেখে নিশ্চিতভাবে দেওয়া যায় না। Leslie Lamport ১৯৭৮ সালের একটি বিখ্যাত প্রবন্ধে এর একটি গাণিতিক উত্তর দেন: একটি ঘটনা a অন্য ঘটনা b-এর “আগে ঘটেছে” (happened-before) যদি a আর b একই server-এ পরপর ঘটে, বা a একটি বার্তা পাঠানো আর b সেই বার্তা পাওয়া, বা এদের transitive closure-এ যুক্ত।
এই সম্পর্ক strict partial order: কোনো ঘটনা নিজের আগে ঘটে না, আর transitive. কিন্তু total নয়: দুটি ভিন্ন server-এ একই সময়ে, কোনো বার্তার যোগাযোগ ছাড়া ঘটা দুটি ঘটনা অতুলনীয়, আর এদের বলা হয় concurrent. এটিই এই পর্বের ভাষায় antichain. কোনটি “আসলে” আগে, সেই প্রশ্নের উত্তর system-এর ভেতর থেকে জানার উপায় নেই, তাই partial order-ই সৎ বর্ণনা।
Lamport-এর logical clock প্রতিটি ঘটনাকে একটি সংখ্যা দেয়, যাতে a আগে b হলে সংখ্যায়ও a ছোট। সমান সংখ্যার ক্ষেত্রে server-এর নম্বর দিয়ে ভাঙলে একটি total order আসে, যা happened-before-এর একটি linear extension: ঠিক উপপাদ্য ৬.১-এর গঠন। পরে প্রস্তাবিত vector clock আরও সূক্ষ্ম: প্রতিটি ঘটনায় প্রতিটি server-এর একটি গণনা রাখে, আর দুটি vector-এর উপাদান-ধরে-ধরে তুলনা (component-wise ≤) একটি partial order, যা ℕk-এর product order. এই order-এ দুটি vector-এর join হলো উপাদান-ধরে max, তাই vector-গুলো একটি lattice গঠন করে; বার্তা পেলে server নিজের vector আর আগত vector-এর join নেয়।
এই ধারণাই আধুনিক replicated database আর collaborative editing-এর CRDT-এর ভিত্তি: অবস্থাগুলো একটি lattice-এ থাকে, আর দুই কপি মেলানো মানে join নেওয়া, যা ক্রম যাই হোক একই ফল দেয় (join commutative, associative আর idempotent).
মূল উপলব্ধি: বিতরিত ব্যবস্থায় ঘটনার ক্রম স্বভাবতই partial; logical clock তার একটি linear extension দেয়, আর vector clock একটি lattice-এর join দিয়ে কপিগুলো মেলায়।
প্র ০৩Linear extension খোঁজা O(V + E)-এ হয়, অথচ সেগুলো গোনা কঠিন বলা হয় কেন? এর ব্যবহার কোথায়?
একটি linear extension খোঁজা আর সবগুলো গোনা দুটি আলাদা প্রশ্ন, আর এদের কঠিনতাও আলাদা। Kahn-এর algorithm একটি সারি দেয় রৈখিক সময়ে। কিন্তু মোট কয়টি সারি আছে? এই পর্বের brute force n!টি permutation দেখে, আর memoization-যুক্ত পদ্ধতি সম্ভাব্য সব “বাকি সেট” দেখে, যা সবচেয়ে খারাপ ক্ষেত্রে 2n-এর কাছাকাছি। কোনোটিই বড় n-এ চলে না।
Graham Brightwell আর Peter Winkler ১৯৯১ সালে প্রমাণ করেন বলে জানা যায় যে linear extension গোনা #P-complete. #P হলো গণনার সমস্যার একটি শ্রেণি, যেখানে “সমাধান আছে কি না” না জিজ্ঞেস করে “সমাধান কয়টি” জিজ্ঞেস করা হয়; #P-complete সমস্যার জন্য polynomial সময়ের algorithm থাকলে জটিলতা-তত্ত্বের বড় বড় অনুমান ভেঙে পড়বে বলে মনে করা হয়। এটি একটি সাধারণ ধাঁচ: perfect matching খোঁজা polynomial, কিন্তু গোনা #P-complete (Valiant, ১৯৭৯)। P বনাম NP-এর পটভূমি DSA কোর্সের পর্ব ৬৪-এ আছে।
তবু আনুমানিক গণনা সম্ভব। ১৯৯০-এর দশকের শুরুর কিছু কাজ থেকে (Dyer, Frieze আর Kannan-এর volume-গণনা, Karzanov আর Khachiyan-এর random walk) একটি ধারা আছে, যেখানে randomized পদ্ধতি দিয়ে linear extension-এর সংখ্যা যেকোনো নির্দিষ্ট আপেক্ষিক ভুলের মধ্যে polynomial সময়ে আন্দাজ করা যায় বলে জানা যায়; মূল কৌশল হলো একটি random walk, যা প্রতিবার পাশাপাশি দুটি অতুলনীয় উপাদান অদলবদল করে।
কেন এই সংখ্যা জরুরি? একটি প্রয়োগ sorting: যদি কিছু তুলনার ফল আগেই জানা থাকে (একটি partial order), তাহলে বাকি সারিটি বের করতে অন্তত log2 e(P)টি তুলনা লাগে, যেখানে e(P) linear extension-এর সংখ্যা, কারণ প্রতিটি তুলনা সম্ভাবনাগুলোকে বড়জোর অর্ধেক করে। কোনো কিছু জানা না থাকলে e = n!, আর সেখান থেকে আসে সুপরিচিত log2 n! সীমা। ৬০-এর উৎপাদকের জন্য e = 2452, তাই অন্তত ১২টি তুলনা লাগবে (211 = 2048 < 2452). আরেকটি প্রয়োগ ranking: একটি দলের কিছু জোড়ার ফল জানা থাকলে প্রতিটি সম্ভাব্য পূর্ণ র্যাংকিং সমান সম্ভাব্য ধরে কোনো দলের গড় অবস্থান অনুমান করা।
মূল উপলব্ধি: একটি সমাধান খোঁজা আর সব সমাধান গোনা আলাদা কঠিনতার প্রশ্ন; linear extension একটি পাওয়া সহজ, গোনা #P-complete, আর তার লগারিদম sorting-এর তুলনার নিম্নসীমা দেয়।
প্র ০৪সব lattice কি একই রকম? Distributive lattice কী, আর কোন দুটি ছোট lattice তা নয়?
সেটের lattice-এ ∪ আর ∩ পরস্পরের ওপর ছড়ায় (distributive law): A ∩ (B ∪ C) = (A ∩ B) ∪ (A ∩ C). Dn-এও একই নিয়ম খাটে: gcd(a, lcm(b, c)) = lcm(gcd(a, b), gcd(a, c)), কারণ প্রতিটি মৌলিকের ঘাতে এটি min আর max-এর নিয়মে নেমে আসে, আর min(x, max(y, z)) = max(min(x, y), min(x, z)) সব সংখ্যায় সত্য। যে lattice-এ এই নিয়ম সব উপাদানে খাটে, তাকে distributive lattice বলে।
কিন্তু সব lattice distributive নয়। দুটি পাঁচ-উপাদানের উদাহরণ মূল: “diamond” M3, যেখানে একটি নিচের আর একটি ওপরের উপাদানের মাঝে তিনটি পরস্পর অতুলনীয় উপাদান a, b, c; আর “pentagon” N5, যেখানে নিচ থেকে ওপরে একদিকে একটি দুই-ধাপের পথ আর অন্যদিকে একটি এক-ধাপের পথ। M3-এ a ∧ (b ∨ c) = a ∧ 1 = a, কিন্তু (a ∧ b) ∨ (a ∧ c) = 0 ∨ 0 = 0. Dedekind আর পরে Birkhoff-এর কাজের সঙ্গে যুক্ত একটি উপপাদ্য বলে, একটি lattice distributive যদি এবং কেবল যদি এর ভেতরে M3 বা N5 sublattice হিসেবে না থাকে।
আরও গভীর একটি ফল Birkhoff-এর representation theorem (১৯৩০-এর দশক): প্রতিটি সসীম distributive lattice কোনো একটি সসীম poset-এর “নিচে বন্ধ” subset-গুলোর (down-set) lattice-এর মতো, যেখানে join মানে union আর meet মানে intersection. অর্থাৎ সসীম distributive lattice মানেই আসলে সেটের lattice, একটু ছদ্মবেশে। D60-এর ক্ষেত্রে সেই poset হলো 60-এর মৌলিক-ঘাতগুলোর chain: {2, 4}, {3}, {5}.
Lattice কেন কম্পিউটার বিজ্ঞানে আসে, তার একটি উদাহরণ program analysis. একটি variable-এর সম্ভাব্য মান সম্পর্কে compiler যা জানে (যেমন “ধনাত্মক”, “শূন্য”, “অজানা”) তা একটি lattice-এ সাজানো থাকে, আর দুটি পথ এক জায়গায় মিললে তথ্যগুলোর join নেওয়া হয়। Lattice সসীম উচ্চতার হলে এই হিসাব একটি fixed point-এ থামে; এর পেছনে আছে Knaster–Tarski ধরনের fixed point উপপাদ্য। পর্ব ৬৯-এ Boolean algebra হিসেবে আপনি একটি বিশেষ distributive lattice দেখবেন, যেখানে প্রতিটি উপাদানের পরিপূরক আছে।
মূল উপলব্ধি: সেটের lattice আর উৎপাদকের lattice distributive; M3 আর N5 হলো distributivity ভাঙার দুটি মৌলিক নকশা, আর সসীম distributive lattice মূলত সেটের lattice.
প্র ০৫“Hasse diagram” নামটি কোথা থেকে এল, আর Dilworth-এর উপপাদ্য কেন matching আর network flow-এর আত্মীয়?
Helmut Hasse ছিলেন বিশ শতকের একজন জার্মান সংখ্যাতত্ত্ববিদ, যিনি algebraic number theory-তে field-এর extension-গুলোর সম্পর্ক বোঝাতে এমন চিত্র ব্যবহার করতেন। তাই নামটি তাঁর নামে, যদিও ইতিহাসবিদেরা বলেন এই ধরনের চিত্র আগেও, যেমন উনিশ শতকের শেষে Henri Gustav Vogt-এর কাজে, দেখা যায়। আবারও সেই পরিচিত ঘটনা: একটি ধারণার নাম সবসময় তার প্রথম ব্যবহারকারীর নামে হয় না। নাম মুখস্থের চেয়ে জরুরি হলো চিত্রটির নিয়ম: শুধু cover রেখা, আর বড় উপাদান ওপরে।
Dilworth-এর উপপাদ্য (width = ন্যূনতম chain-সংখ্যা) প্রথম দেখায় একটি নিছক poset-এর কথা মনে হয়, কিন্তু এটি combinatorics-এর একগুচ্ছ “min = max” উপপাদ্যের একটি। Poset-এর প্রতিটি উপাদানের দুটি কপি নিয়ে একটি bipartite graph বানান: বাঁ দিকের x থেকে ডান দিকের y-তে রেখা, যদি x ≺ y. এই graph-এর প্রতিটি matching একটি chain-ভাগ দেয় (matched রেখাগুলো chain-গুলোকে জোড়া দেয়), আর chain-এর সংখ্যা = n − matching-এর আকার। তাই ন্যূনতম chain-সংখ্যা = n − সর্বোচ্চ matching. König-এর উপপাদ্য (bipartite graph-এ সর্বোচ্চ matching = ন্যূনতম vertex cover) থেকে তারপর একটি antichain বের করা যায়, যার আকার ঠিক সেই সংখ্যা। এই কারণে Dilworth, König, Hall-এর বিবাহ উপপাদ্য আর network flow-এর max-flow min-cut উপপাদ্য একে অন্যকে প্রমাণ করে বলে পরিচিত।
এর একটি ব্যবহারিক রূপ: বাজারঘরের দিনের ডেলিভারির একটি তালিকা আছে, আর একটি ডেলিভারি শেষ করে একই রাইডার আরেকটিতে সময়মতো পৌঁছাতে পারলে বলুন প্রথমটি ≺ দ্বিতীয়টি। এই সম্পর্ক transitive হলে ন্যূনতম কয়জন রাইডার লাগবে? প্রতিজন রাইডার একটি chain, তাই উত্তর Dilworth-এর width, অর্থাৎ এমন ডেলিভারির সবচেয়ে বড় দল যাদের কোনো দুটি একজন রাইডার করতে পারে না। আর তা matching দিয়ে polynomial সময়ে বের হয়। এই পর্বের ব্লকে width বের করা হয়েছিল 212টি subset দেখে; matching-পদ্ধতি বড় poset-এও চলে। Matching-এর প্রমাণগুলো পর্ব ৬৪-এ আছে, Dilworth-এর পূর্ণ প্রমাণসহ।
মূল উপলব্ধি: Hasse diagram নামটি একটি পরিচিত চিত্রের পরের দিকের নামকরণ; আর Dilworth-এর উপপাদ্য matching-এর min-max উপপাদ্যগুলোর আত্মীয়, যা ন্যূনতম রাইডার বা কর্মীর মতো প্রশ্নের দক্ষ সমাধান দেয়।
অনুশীলন
আগে খাতায় করুন, তারপর উত্তর খুলে মেলান।
-
প্রমাণ: (S, ≼) একটি poset আর T ⊆ S. প্রমাণ করুন, ≼-কে T-তে সীমিত করলে তা-ও একটি partial order; আর দেখান, (S, ≼)-এর dual (a ≼* b যদি b ≼ a) একটি partial order, যেখানে maximal আর minimal জায়গা বদলায়।
- T-তে সীমিত ≼ মানে R ∩ (T × T). তিনটি শর্তই “সব a, b, c-এর জন্য” ধরনের; S-এর সব উপাদানে সত্য হলে T-এর উপাদানে সত্য, আর transitivity-তে (a, c) T × T-তেই থাকে কারণ a, c ∈ T. — universal শর্ত subset-এ বজায় থাকে
- Dual reflexive: a ≼ a, তাই a ≼* a. — সংজ্ঞা
- Dual antisymmetric: a ≼* b আর b ≼* a মানে b ≼ a আর a ≼ b, তাই a = b. — ≼-এর antisymmetry
- Dual transitive: a ≼* b ≼* c মানে c ≼ b ≼ a, তাই c ≼ a, অর্থাৎ a ≼* c. — ≼-এর transitivity
- a, ≼-এ maximal মানে কোনো b নেই যাতে a ≺ b; অর্থাৎ ≼*-এ কোনো b নেই যাতে b ≺* a: a, ≼*-এ minimal. ∎ — সংজ্ঞা উল্টানো
এই কারণেই §৪-এ minimal-এর প্রমাণ দিয়ে maximal-এর অস্তিত্বও এসেছে, আর Hasse diagram উল্টে দিলে dual-এর diagram পাওয়া যায়।
-
হিসাব: D36 (36-এর উৎপাদক, ∣ নিয়ে)-এর জন্য বের করুন: (ক) উপাদানের সংখ্যা আর Hasse diagram-এর রেখার সংখ্যা, (খ) height আর width, (গ) lub(4, 9), glb(12, 18), lub(6, 4).
(ক) 36 = 22 · 32, তাই উৎপাদক (2 + 1)(2 + 1) = 9টি: 1, 2, 3, 4, 6, 9, 12, 18, 36. প্রতিটি উৎপাদক 2i3j একটি 3 × 3 জালের বিন্দু, আর রেখা হলো i বা j এক বাড়ানো: প্রতিটি দিকে 3 · 2 = 6, মোট 12টি রেখা।
(খ) দীর্ঘতম chain 1 ∣ 2 ∣ 4 ∣ 12 ∣ 36 (বা অন্য কোনো পথ), height 5. Level অনুযায়ী সারি: {1}, {2, 3}, {4, 6, 9}, {12, 18}, {36}; বৃহত্তম antichain {4, 6, 9}, width 3.
(গ) lub(4, 9) = lcm = 36; glb(12, 18) = gcd = 6; lub(6, 4) = 12. সব মান scratch-এ brute force দিয়ে মেলানো (১২টি রেখা, height ৫, width ৩)।
-
আউটপুট অনুমান: কোড না চালিয়ে বলুন কী ছাপা হবে, আর প্রতিটি লাইন কী গোনে। তারপর যেকোনো Python-এ চালিয়ে মেলান।
X = [1, 2, 3, 4, 6, 8, 12] le = lambda a, b: b % a == 0 print([x for x in X if not any(x != y and le(x, y) for y in X)]) print([x for x in X if all(le(x, y) for y in X)]) print(sorted(X, key=lambda x: sum(le(y, x) for y in X)))[8, 12] [1] [1, 2, 3, 4, 6, 8, 12]প্রথম লাইন maximal উপাদান: যাদের কোনো আলাদা গুণিতক X-এ নেই, অর্থাৎ 8 আর 12. দুটি maximal, তাই greatest নেই। দ্বিতীয় লাইন least: যে সবাইকে ভাগ করে, শুধু 1. তৃতীয় লাইন প্রতিটি x-কে তার উৎপাদকের সংখ্যা (X-এর ভেতরে, নিজেসহ) দিয়ে সাজায়: 1, 2, 2, 3, 4, 4, 6. a ≺ b হলে a-র প্রতিটি উৎপাদক b-এরও উৎপাদক আর b নিজে অতিরিক্ত, তাই এই সংখ্যা কঠোরভাবে বাড়ে; সুতরাং এটি একটি linear extension (সমান মানে Python-এর sort আগের ক্রম রাখে)। আউটপুট CPython-এ চালিয়ে মেলানো।
-
প্রমাণের ভুল ধরুন: একজন লিখলেন: “দাবি: প্রতিটি poset-এ, a আর b তুলনীয় না হলে তাদের কোনো upper bound নেই। প্রমাণ: ধরুন u একটি upper bound, অর্থাৎ a ≼ u আর b ≼ u. Transitivity দিয়ে a ≼ u আর u ≽ b থেকে a ≼ b, যা ধরে নেওয়ার বিরোধী।” ভুল কোথায়? একটি counterexample দিন।
- ভুল ধাপ: transitivity খাটে a ≼ u আর u ≼ b হলে; এখানে আছে a ≼ u আর b ≼ u, অর্থাৎ দুটি তীর একই দিকে u-তে ঢুকছে। এ থেকে a আর b সম্পর্কে কিছুই আসে না। প্রমাণটি “u ≽ b”-কে চুপিচুপি “u ≼ b” হিসেবে ব্যবহার করেছে।
- Counterexample: D12-এ 4 আর 6 অতুলনীয়, অথচ 12 দুটিরই upper bound (lub(4, 6) = 12). P(S)-এ {a} আর {b} অতুলনীয়, কিন্তু {a, b} upper bound.
- শিক্ষা: transitivity প্রয়োগের আগে দুটি তীরের দিক মিলিয়ে নিন; একটি ছোট উদাহরণে দাবি পরীক্ষা করলে ভুলটি এক মুহূর্তে ধরা পড়ে।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমKahn-এর algorithm দিয়ে একটি নির্ভরতা-তালিকার topological sort করার ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- প্রতিটি কাজে কয়টি নির্ভরতা ঢোকে (in-degree) গোনা
- In-degree শূন্য এমন কাজগুলো প্রস্তুত তালিকায় রাখা
- প্রস্তুত তালিকা থেকে একটি কাজ বের করে সারিতে লেখা
- সেই কাজের ওপর নির্ভর কাজগুলোর in-degree এক কমানো, শূন্য হলে প্রস্তুত তালিকায় যোগ
- তালিকা খালি হলে দেখা, সব কাজ সারিতে এসেছে কি না (না এলে cycle আছে)
নিচের কোন relation একটি partial order?
- পূর্ণসংখ্যায় <
- পুরো ℤ-এ ভাগ করা (∣)
- একটি সেটের power set-এ ⊆
- বাজারঘরের ক্রেতাদের মধ্যে “একই জেলায় থাকে”
১২-র উৎপাদক {1, 2, 3, 4, 6, 12}, ভাগ করা সম্পর্ক নিয়ে। এর Hasse diagram-এ কয়টি রেখা?
- 18
- 7
- 12
- 6
S = {2, 3, 4, 6, 9, 12}, ভাগ করা সম্পর্ক নিয়ে। কোন কথাটি সত্য?
- 12 greatest উপাদান
- 2 least উপাদান
- শুধু 12 maximal
- Maximal 9 আর 12; greatest বা least কোনোটিই নেই
কাজ A, B, C, D, E, F-এর নির্ভরতা A → B, A → C, B → D, B → E, C → E, D → F, E → F (u → v মানে v-র আগে u). সব নির্ভরতা মানে এমন সারি মোট কয়টি?
- 5
- 1
- 720
- 2
৬০-এর উৎপাদক, ভাগ করা সম্পর্ক নিয়ে। 20 আর 30-এর greatest lower bound কত?
- 5
- 60
- 10
- 2
একটি সসীম poset-এর দীর্ঘতম chain-এ ৫টি উপাদান। Poset-টিকে antichain-এ ভাগ করতে ন্যূনতম কয়টি antichain লাগবে?
- 4
- 5
- Width-এর সমান
- উপাদানের সংখ্যার সমান
S = {1, 2, 3, 12, 18, 36}, ভাগ করা সম্পর্ক নিয়ে। S কেন lattice নয়?
- S-এ greatest উপাদান নেই
- ভাগ করা এখানে partial order নয়
- 2 আর 3-এর কোনো lower bound নেই
- 2 আর 3-এর least upper bound নেই
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Partial order: reflexive + antisymmetric + transitive; সব জোড়া তুলনীয় হলে total order. Lexicographic order দুটি total order থেকে একটি total order বানায়।
- Hasse diagram: শুধু cover রেখা, বড় উপাদান ওপরে; পুরো order হলো cover-এর reflexive-transitive closure.
- Maximal ≠ greatest: greatest থাকলে অনন্য; সসীম poset-এ minimal আর maximal থাকে, অসীমে না-ও থাকতে পারে।
- Topological sort: প্রতিটি সসীম poset-এর linear extension আছে (বারবার minimal তুলে নিয়ে); Kahn O(V + E)-এ একটি দেয় আর cycle ধরে। দীর্ঘতম chain = ন্যূনতম antichain-ভাগ (Mirsky); width = ন্যূনতম chain-ভাগ (Dilworth).
- Lattice: প্রতিটি জোড়ার lub আর glb আছে; Dn-এ lcm আর gcd, P(S)-এ ∪ আর ∩.
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৫৭ · গ্রাফ — সংজ্ঞা, degree আর handshake theoremপরবর্তী পর্বনতুন মডিউল: graph-এর সংজ্ঞা আর প্রথম উপপাদ্য।
- পর্ব ২১ · GCD আর Euclid-এর algorithm — Bézout আর extended Euclidপুনরালোচনাউৎপাদকের lattice-এর join আর meet.
- পর্ব ১১ · Strong induction আর well-orderingপুনরালোচনাWell-ordering principle আর ℕ-এর least উপাদান।
- পর্ব ৩২ · Pigeonhole principle — সহজ থেকে generalizedপুনরালোচনাErdős–Szekeres, যা Mirsky দিয়েও প্রমাণ হয়।
- ডিসক্রিট ম্যাথমেটিক্স · কোর্স হোম৮৩টি পর্বপুরো কোর্সের মানচিত্র আর ১৪টি মডিউল।
- DSA · পর্ব ৪২ · Topological sort আর DAGকোডে প্রয়োগKahn আর DFS-ভিত্তিক topological sort-এর কোড।