একটি ল্যাঙ্গুয়েজ রেগুলার নয় তা প্রমাণ করা
এই পাঠে যা শিখবেন
- প্রুফ-বাই-কন্ট্রাডিকশন টেমপ্লেট — assume regular → choose s → show every split fails → contradiction
- $L=\{0^n1^n\}$-এর সম্পূর্ণ, নিখুঁত প্রমাণ, ধাপে ধাপে
- কেন "একটি split হাতে বেছে দেখানো" যথেষ্ট নয় — সব বৈধ split-ই ভাঙতে হবে
- Python-এ real
check_pumping_violation— প্রতিটি বৈধ $(x,y,z)$ split এক্সহস্টিভলি জেনারেট ও যাচাই - একাধিক $p$-এর মান নিয়ে কোড চালিয়ে প্রমাণ পুনরায় নিশ্চিত করা
১ · প্রুফ-বাই-কন্ট্রাডিকশন টেমপ্লেট
L13-এর পাম্পিং লেমাকে কনট্রাপজিটিভেContrapositive"$P \Rightarrow Q$" সত্য হলে "$\neg Q \Rightarrow \neg P$"-ও সত্য — যুক্তিগতভাবে সমতুল্য একটি ভিন্ন রূপ, প্রায়ই প্রমাণে বেশি ব্যবহারযোগ্য (Discrete Mathematics কোর্সে ফরমালি আলোচিত)। ব্যবহার করলে দাঁড়ায় — "যদি একটি ল্যাঙ্গুয়েজ পাম্পিং প্রপার্টি না মানে, তাহলে সেটি রেগুলার নয়।" ব্যবহারিকভাবে এটি একটি স্ট্যান্ডার্ড প্রুফ-বাই-কন্ট্রাডিকশন টেমপ্লেটে পরিণত হয় —
- ধরে নিন $L$ রেগুলার — তাহলে L13 অনুযায়ী একটি পাম্পিং লেংথ $p$ থাকতেই হবে।
- বেছে নিন একটি নির্দিষ্ট স্ট্রিং $s \in L$ যেখানে $|s| \geq p$ (এই বাছাইটাই প্রমাণের "শিল্প" — যুক্তিটা কাজ করার মতো করে বেছে নিতে হয়)।
- দেখান যে $s=xyz$-এর প্রতিটি সম্ভাব্য বৈধ ভাগ (শর্ত (১) $|y|>0$ ও শর্ত (২) $|xy|\leq p$ মেনে) নিয়ে, কোনো না কোনো $i$-এর জন্য $xy^iz \notin L$ — এটি শর্ত (৩)-এর সাথে সরাসরি বিরোধ।
- সিদ্ধান্ত নিন — যেহেতু ধরে নেওয়া অনুমান থেকে বিরোধ এসেছে, তাই মূল অনুমান ("$L$ রেগুলার") ভুল — $L$ রেগুলার নয়।
২ · ক্লাসিক উদাহরণ — $L = \{0^n1^n : n \geq 0\}$
এটিই সবচেয়ে বেশি উদ্ধৃত নন-রেগুলারিটি প্রমাণ — সমান সংখ্যক 0 তারপর সমান সংখ্যক 1 (যেমন "0011", "000111", খালি স্ট্রিং)। এই ভাষাকে রেগুলার হওয়ার জন্য অসীম "গণনা" মনে রাখতে হবে (কতগুলো 0 পড়া হয়েছে), যা একটি ফাইনাইট-স্টেট DFA-র পক্ষে অসম্ভব — নিচের প্রমাণ এটিই নিখুঁতভাবে দেখায়।
ধরুন $L$ রেগুলার, তাহলে একটি পাম্পিং লেংথ $p$ থাকে। বেছে নিন $s = 0^p1^p \in L$ (এবং $|s|=2p \geq p$)। এখন যেকোনো বৈধ split $s = xyz$ যেখানে $|xy| \leq p$, খেয়াল করুন — $s$-এর প্রথম $p$টি ক্যারেক্টারই সব "0"। যেহেতু $xy$ প্রথম $p$ ক্যারেক্টারের মধ্যেই সীমাবদ্ধ, তাই $xy$ (এবং তাই $y$-ও) সম্পূর্ণভাবে 0 দিয়ে গঠিত — $y = 0^k$ কোনো $k \geq 1$-এর জন্য। এখন $i=0$ নিলে (পাম্প ডাউন, $y$ সম্পূর্ণ বাদ) — $xy^0z = xz$-এ 0-এর সংখ্যা $k$ কমে গেছে কিন্তু 1-এর সংখ্যা অপরিবর্তিত — ফলে 0 আর 1-এর সংখ্যা আর সমান নেই, তাই $xz \notin L$। এটি শর্ত (৩)-এর সরাসরি বিরোধ — অতএব $L$ রেগুলার নয়। $\blacksquare$
৩ · কোডে এক্সহস্টিভ ভেরিফিকেশন
নিচের কোড সেলে check_pumping_violation(s, p, in_L) ফাংশনটি $|xy|\leq p$ ও $|y|>0$ মেনে
সম্ভাব্য সবগুলো $(x,y,z)$ split জেনারেট করে, এবং প্রতিটির জন্য $i \in \{0,2,3\}$ টেস্ট
করে দেখে কোনো একটি ভায়োলেশন খুঁজে পাওয়া যায় কি না। এটি $s=0^p1^p$-এর জন্য $p=1,2,3,4$ — প্রতিটির জন্য
চালিয়ে নিশ্চিত করা হয়েছে যে সবগুলো বৈধ split-ই ভায়োলেশন ঘটায়, উপরের হাতে-লেখা প্রমাণকে
একটি concrete, code-verified চেকে রূপান্তর করে।
def in_zero_n_one_n(s):
# সত্যিকারের মেম্বারশিপ চেকার (কোনো re মডিউল ব্যবহার ছাড়াই) -- L = { 0^n 1^n : n >= 0 }
i = 0
n = 0
while i < len(s) and s[i] == '0':
n += 1
i += 1
m = 0
while i < len(s) and s[i] == '1':
m += 1
i += 1
return i == len(s) and n == m # পুরো স্ট্রিং শেষ হয়ে গেছে এবং 0/1-এর সংখ্যা সমান
def all_valid_splits(s, p):
# |xy| <= p এবং |y| > 0 মেনে s = xyz-এর সম্ভাব্য সবগুলো ভাগ জেনারেট করে
splits = []
for xy_len in range(1, p + 1): # শর্ত (২): |xy| <= p
for y_start in range(0, xy_len): # শর্ত (১): |y| > 0
x = s[:y_start]
y = s[y_start:xy_len]
z = s[xy_len:]
splits.append((x, y, z))
return splits
def check_pumping_violation(s, p, in_L):
assert len(s) >= p and in_L(s)
results = []
all_splits_violate = True
for (x, y, z) in all_valid_splits(s, p):
violated_by = None
for i in (0, 2, 3): # পাম্প ডাউন এবং পাম্প আপ, দুই দিকেই টেস্ট
pumped = x + y * i + z
if not in_L(pumped):
violated_by = (i, pumped)
break
results.append((x, y, z, violated_by))
if violated_by is None:
all_splits_violate = False # এই split-এ কোনো ভায়োলেশন পাওয়া যায়নি -- প্রমাণ ভেঙে যেত
return results, all_splits_violate
for p in (1, 2, 3, 4):
s = "0" * p + "1" * p
results, all_violate = check_pumping_violation(s, p, in_zero_n_one_n)
print(f"p={p}, s={s!r}: {len(results)}টি বৈধ (x,y,z) split চেক করা হলো")
for (x, y, z, v) in results:
i, pumped = v
print(f" x={x!r:6s} y={y!r:6s} z={z!r:6s} -> i={i}: xy^{i}z = {pumped!r} (in L: {in_zero_n_one_n(pumped)})")
print(f" => প্রতিটি split-এই ভায়োলেশন পাওয়া গেছে (all_splits_violate): {all_violate}")
print()
প্রতিটি বৈধ split আলাদাভাবে জেনারেট ও যাচাই — কোনো একটি হাতে-বাছাই নয়।
$0^n1^n$-এ সবসময় নির্ণায়ক — 0-এর সংখ্যা কমে যায়, 1-এর সংখ্যা স্থির থাকে।
ধর্ম ভাঙলে নন-রেগুলার — এটিই এই টেমপ্লেটের মূল লজিক্যাল কাঠামো।
নন-রেগুলারিটি প্রমাণের কেন্দ্রীয় টেমপ্লেট — assume regular, choose a clever $s$, show every valid split fails, contradiction। "প্রতিটি split" শব্দটাই সবচেয়ে গুরুত্বপূর্ণ — একটি নয়, সব। $0^n1^n$-এর প্রমাণ এই টেমপ্লেটের সবচেয়ে ক্লাসিক প্রয়োগ, এবং এখানে দেখানো এক্সহস্টিভ কোড-ভেরিফিকেশন কৌশলটি প্রায় যেকোনো নন-রেগুলারিটি প্রমাণেই পুনর্ব্যবহারযোগ্য।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ $s=0^p1^p$-এর বদলে যদি $s=1^p0^p$ বেছে নেওয়া হতো, প্রমাণটি কি একইভাবে কাজ করত?
না, সরাসরি নয় — এবং এটি বাছাইয়ের গুরুত্ব দেখায়। $1^p0^p \notin L$ (যেহেতু $L$-এর সংজ্ঞা 0 আগে, তারপর 1), তাই প্রমাণের ধাপ (২)-এই ("বেছে নিন $s \in L$") এটি ব্যর্থ হবে — $s$ আদৌ $L$-এর সদস্যই নয়। এই কারণেই প্রমাণের "বাছাই" ধাপকে "শিল্প" বলা হয় — $s$-কে অবশ্যই $L$-এর সদস্য হতে হবে, এবং এমনভাবে গঠিত হতে হবে যাতে শর্ত (২) ($|xy|\leq p$) বাধ্য করে $y$ একটি নির্দিষ্ট, ভবিষ্যদ্বাণীযোগ্য আকারে থাকুক — এখানে "সব 0"।
প্র ০২ যদি কেউ শুধু $p=2$-এর একটিমাত্র split (যেমন $x{=}\varepsilon, y{=}00, z{=}11$) দেখিয়ে "প্রমাণ শেষ" বলে, এই প্রমাণে কী সমস্যা?
এটি একটি অসম্পূর্ণ প্রমাণ। পাম্পিং লেমার শর্ত (৩) বলে — যদি $L$ রেগুলার হতো, তাহলে প্রতিটি বৈধ split-এর জন্যই সব $xy^iz \in L$ হতো। তাই বিরোধ প্রতিষ্ঠা করতে দেখাতে হবে সবগুলো বৈধ split ($p=2$-এ মোট ৩টি — উপরের কোড আউটপুট দেখুন) কোনো না কোনো $i$-তে ভাঙে। শুধু একটি split ভাঙলে সেটি বিরোধের একটি প্রয়োজনীয় অংশ দেখায়, কিন্তু বাকি split-গুলো (যেগুলো হয়তো না-ও ভাঙতে পারত, অন্য কোনো ভাষায়) যাচাই না করলে প্রমাণটি যুক্তিগতভাবে অসম্পূর্ণ থেকে যায় — এই কারণেই উপরের কোড সবগুলো split এক্সহস্টিভলি চেক করে।
প্র ০৩ $L = \{ww^R : w \in \{0,1\}^*\}$ (প্যালিনড্রোম) নন-রেগুলার প্রমাণেও কি একই টেমপ্লেট প্রযোজ্য?
হ্যাঁ, একদম একই চার-ধাপের টেমপ্লেট প্রযোজ্য — শুধু $s$-এর বাছাই ভিন্ন হবে। উদাহরণস্বরূপ $s = 0^p110^p$ (একটি প্যালিনড্রোম) বেছে নিলে, শর্ত (২) আবারও $y$-কে প্রথম $p$ ক্যারেক্টারের মধ্যে (সব 0) বাধ্য করবে — পাম্প ডাউন করলে বাম দিকের 0-এর সংখ্যা কমে যাবে কিন্তু ডান দিকের 0-এর সংখ্যা অপরিবর্তিত থাকবে, ফলে প্যালিনড্রোম-ধর্ম ভেঙে যাবে। এই টেমপ্লেটের সাধারণতা (generality) — যেকোনো ভাষায় প্রযোজ্য যেখানে একটি "সুষম গণনা" বা "মিলে যাওয়া অংশ" আছে যা ফাইনাইট স্টেট দিয়ে মনে রাখা যায় না — এটিই এই কৌশলটিকে এত শক্তিশালী করে তোলে।
অনুশীলন
-
চিন্তা করুন: $L = \{0^i1^j : i > j\}$ নন-রেগুলার প্রমাণে $s = 0^{p+1}1^p$ কেন একটি
ভালো বাছাই হবে? শর্ত (২) কীভাবে $y$-কে বাধ্য করবে চিন্তা করুন।
$s=0^{p+1}1^p \in L$ (যেহেতু $p+1 > p$), এবং $|s| = 2p+1 \geq p$। শর্ত (২) ($|xy|\leq p$) আবারও $y$-কে প্রথম $p$ ক্যারেক্টারের মধ্যে বাধ্য করবে — যেহেতু প্রথম $p+1$টি ক্যারেক্টারই "0" (স্ট্রিং-এ মোট $p+1$টি 0 আছে), তাই $y$ নিশ্চিতভাবে শুধু 0 দিয়ে গঠিত ($y=0^k$)। পাম্প আপ করলে ($i=2$) 0-এর সংখ্যা বেড়ে যাবে (আরও বেশি $i>j$ হবে, তাই সেটি এখনও $L$-এই থাকবে!) — কিন্তু পাম্প ডাউন করলে ($i=0$) 0-এর সংখ্যা $k$ কমে যাবে; যদি $k \geq (p+1)-p = 1$... আসলে এখানে সাবধানে দেখতে হবে — যেহেতু $k \geq 1$ এবং মোট 0 ছিল $p+1$, পাম্প-ডাউনের পর 0-এর সংখ্যা হয় $p+1-k \leq p$, যা 1-এর সংখ্যা $p$-এর চেয়ে বড় নাও হতে পারে — এই সূক্ষ্ম বিশ্লেষণটাই দেখায় কেন $s$ সাবধানে বেছে নেওয়া এবং প্রতিটি সম্ভাব্য $k$ (অর্থাৎ প্রতিটি বৈধ split) আলাদাভাবে যাচাই করা জরুরি — ঠিক যেমন উপরের কোড করে।
-
পরীক্ষা করুন: উপরের কোড সেলে
for p in (1, 2, 3, 4):-এর রেঞ্জ বাড়িয়েrange(1, 7)করে Run চাপুন — বড় $p$-এর জন্যও কি সবগুলো split-এ ভায়োলেশন পাওয়া যায় (all_violate সবসময় True)?হ্যাঁ, $p$ যত বড়ই হোক না কেন
all_violateসবসময়Trueথাকবে, কারণ হাতে-লেখা প্রমাণের যুক্তি ($s=0^p1^p$-এর প্রথম $p$ ক্যারেক্টার সবসময়ই সব 0, শর্ত (২) দিয়ে) $p$-এর নির্দিষ্ট মানের উপর নির্ভর করে না — এটি সাধারণভাবে সত্য যেকোনো $p \geq 1$-এর জন্য। কোডে বড় $p$ টেস্ট করলে split-সংখ্যা বাড়বে ($p=6$-এ ২১টি split) কিন্তু প্রতিটিই একই কারণে ($i=0$-এ 0-এর সংখ্যা কমে যাওয়া) ভাঙবে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৬টি পাঠ পরবর্তী পাঠ — মাইহিল-নেরোড থিওরেম — নন-রেগুলারিটি প্রমাণের একটি সম্পূর্ণ বিকল্প, শক্তিশালী কৌশল দেখাবে।
- L13 · পাম্পিং লেমা পূর্ববর্তী ভিত্তি এই পাঠের কনট্রাপজিটিভ প্রমাণ-টেমপ্লেট সরাসরি সেই পাঠের ফরমাল স্টেটমেন্টের উপর ভিত্তি করে তৈরি।
- Discrete Mathematics কোর্স সহোদর কোর্স প্রুফ-বাই-কন্ট্রাডিকশন ও কনট্রাপজিটিভ যুক্তির ফরমাল ভিত্তি সেই কোর্সেই তৈরি হয়েছে।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git ও Theory of Computation — সব এক জায়গায়।