সমস্যাকে ল্যাঙ্গুয়েজ হিসেবে দেখা — ডিসিশন প্রবলেম
এই পাঠে যা শিখবেন
- ডিসিশন প্রবলেমের সংজ্ঞা
- যেকোনো ডিসিশন প্রবলেমকে ল্যাঙ্গুয়েজ হিসেবে এনকোড করার মূল কৌশল
- Worked example — বাইনারি সংখ্যার ৩-বিভাজ্যতা একটি ল্যাঙ্গুয়েজ হিসেবে
- জটিল বস্তু (গ্রাফ) স্ট্রিং-এ এনকোড করার মূলনীতি — M9-এর প্রস্তুতি
- Python দিয়ে একটি real, verified বিভাজ্যতা-চেকার এবং একটি গ্রাফ-এনকোডার
১ · ডিসিশন প্রবলেম কী
একটি ডিসিশন প্রবলেমDecision Problemএমন একটি প্রশ্ন যার উত্তর প্রতিটি সম্ভাব্য ইনপুট ইনস্ট্যান্সের জন্য YES বা NO। হলো এমন একটি প্রশ্ন যার উত্তর প্রতিটি সম্ভাব্য ইনপুট ইনস্ট্যান্স-এর জন্য YES অথবা NO — যেমন "এই গ্রাফ কি connected?" বা "এই সংখ্যা কি ৩ দ্বারা বিভাজ্য?" প্রতিটি ইনপুটের জন্য একটি নির্দিষ্ট, দ্ব্যর্থহীন উত্তর থাকে — "মাঝামাঝি" কোনো উত্তর নেই।
২ · সমস্যা থেকে ল্যাঙ্গুয়েজ — মূল রিফ্রেমিং
এই কোর্সের সবচেয়ে গুরুত্বপূর্ণ প্রাথমিক ট্রিকগুলোর একটি — যেকোনো ডিসিশন প্রবলেম একটি ল্যাঙ্গুয়েজ হিসেবে এনকোড করা যায়। কীভাবে? প্রতিটি সম্ভাব্য ইনপুটকে একটি স্ট্রিং হিসেবে এনকোড করে, ল্যাঙ্গুয়েজ $L$ সংজ্ঞায়িত করা হয় — ঠিক সেই সব ইনপুট-এনকোডিং-এর সেট যাদের উত্তর YES:
$$L = \{w \in \Sigma^* : w\text{-এর এনকোড করা ইনপুটের উত্তর YES}\}$$
এই সংজ্ঞা অনুযায়ী, "সমস্যা সমাধান করা" এখন হুবহু "ল্যাঙ্গুয়েজ membership যাচাই করা"-এর সমতুল্য — একটি নির্দিষ্ট $w$ ইনপুটের জন্য উত্তর YES কি না, তা জানতে শুধু জিজ্ঞাসা করতে হয়: $w \in L$ কি না? এই একটিমাত্র, একীভূত গাণিতিক কাঠামো (ল্যাঙ্গুয়েজ ও অটোমাটা) দিয়েই তাই সব ডিসিশন প্রবলেম পড়ানো সম্ভব — এটিই এই কোর্স কেন M2 থেকে M9 পর্যন্ত ক্রমাগত "ল্যাঙ্গুয়েজ" নিয়ে কথা বলবে, "সমস্যা" নয়, তার সরাসরি, স্পষ্ট প্রেরণা।
ডিসিশন প্রবলেম: "একটি বাইনারি সংখ্যা কি ৩ দ্বারা বিভাজ্য?" এই প্রশ্নটি ল্যাঙ্গুয়েজ হিসেবে —
$$L = \{w \in \{0,1\}^* : w\text{-কে বাইনারি সংখ্যা হিসেবে পড়লে তা ৩ দ্বারা বিভাজ্য}\}$$
উদাহরণ — "110" (দশমিকে ৬) $\in L$, কারণ ৬ ÷ ৩ = ২ (বিভাজ্য)। "101" (দশমিকে ৫) $\notin L$, কারণ ৫ ৩ দ্বারা বিভাজ্য নয়। এখন "এই সংখ্যা ৩ দিয়ে বিভাজ্য কি না" জানতে চাওয়া, এবং "$w \in L$ কি না" জিজ্ঞাসা করা — সম্পূর্ণ একই প্রশ্ন। M2-এ (L06) এই একই $L$-এর জন্য একটি বাস্তব DFA বানানো হবে — নিচের কোড সেলের অ্যালগরিদমটিই সেই DFA-এর ভিত্তি।
৩ · এনকোডিং — জটিল বস্তুও স্ট্রিং হতে পারে
সংখ্যার মতো "স্বাভাবিকভাবে স্ট্রিং-আকৃতির" ইনপুট ছাড়াও, আরও জটিল বস্তু — গ্রাফ, এমনকি (M9-এ দেখা যাবে) অন্য একটি টুরিং মেশিনের সম্পূর্ণ বর্ণনা — সবই একটি ফিক্সড আলফাবেটের উপর স্ট্রিং হিসেবে এনকোড করা যায়। যেমন একটি গ্রাফকে তার adjacency matrix-কে সারি-বাই-সারি একটি ফ্ল্যাট স্ট্রিং-এ রূপান্তর করে এনকোড করা যায়। এই এনকোডিং-ক্ষমতাই নিশ্চিত করে যে "ল্যাঙ্গুয়েজ" ফ্রেমওয়ার্কটি সত্যিই সাধারণ (general) — শুধু সংখ্যা/টেক্সট-জাতীয় সমস্যায় সীমাবদ্ধ নয়।
৪ · Python-এ ডিসিশন প্রবলেম ও এনকোডিং
নিচের কোড সেলে দুটি জিনিস দেখা যাচ্ছে — প্রথমত, "বাইনারি সংখ্যা ৩ দ্বারা বিভাজ্য কি না" প্রশ্নের একটি real, DFA-স্টাইল অ্যালগরিদম (প্রতিটি বিট প্রসেস করে remainder ট্র্যাক করা — M2-এর DFA formalism-এর সরাসরি পূর্বাভাস), Python-এর নেটিভ int(w,2)%3-এর বিপরীতে ক্রস-চেক করা; দ্বিতীয়ত, একটি গ্রাফকে (adjacency matrix হিসেবে) স্ট্রিং-এ এনকোড করার একটি সাধারণ ফাংশন।
def is_divisible_by_3(w):
"""w ekti binary string -- w-ke binary shonkha hisebe porle ta 3 dara bivajjo kina, ekti real
bit-by-bit remainder-tracking algorithm diye (M2-er DFA-r purbabhash)"""
remainder = 0
for bit in w:
remainder = (remainder * 2 + int(bit)) % 3
return remainder == 0
test_strings = ["0", "11", "110", "1001", "1100", "111111", "101"]
print(f"{'w':10s} | {'int(w,2)':10s} | remainder-ট্রেস | int(w,2)%3==0 | মিলছে?")
print("-" * 65)
for w in test_strings:
value = int(w, 2)
trace_result = is_divisible_by_3(w)
native_result = (value % 3 == 0)
match = trace_result == native_result
print(f"{w:10s} | {value:10d} | {str(trace_result):15s} | {str(native_result):13s} | {'হ্যাঁ' if match else 'না'}")
def encode_graph_as_string(adjacency_matrix):
"""n x n adjacency matrix (0/1 entry) -ke ekti flat string-e encode kore --
protita sari ekshathe jora, sarir majhe '|' diye alada"""
rows = []
for row in adjacency_matrix:
rows.append(''.join(str(bit) for bit in row))
return '|'.join(rows)
triangle_graph = [
[0, 1, 1],
[1, 0, 1],
[1, 1, 0],
]
print()
print("গ্রাফ (adjacency matrix, ৩টি vertex, প্রতিটি জোড়ার মধ্যে edge):")
for row in triangle_graph:
print(" ", row)
encoded = encode_graph_as_string(triangle_graph)
print("এনকোড করা স্ট্রিং:", encoded)
print("এই এনকোডিং একটি ফিক্সড আলফাবেট {0,1,|} -এর উপর একটি স্ট্রিং -- L(graph-properties)-এর মতো ল্যাঙ্গুয়েজে সরাসরি ব্যবহারযোগ্য")
is_divisible_by_3 কোনো int(w,2) কনভার্সন ব্যবহার করছে না — এটি বিট-বাই-বিট, একটি ফাইনাইট remainder (০, ১, বা ২) ট্র্যাক করে, ঠিক যেভাবে একটি DFA কাজ করবে (M2/L06)। তবুও এটি Python-এর নেটিভ modulo-এর সাথে হুবহু মিলছে — এটিই দেখায় একটি ফাইনাইট-মেমরি অ্যালগরিদম দিয়েও এই ডিসিশন প্রবলেমটি সম্পূর্ণ সঠিকভাবে সমাধানযোগ্য।
"ল্যাঙ্গুয়েজ = ডিসিশন প্রবলেম" এই সমতুল্যতাই M1-এর চূড়ান্ত পাঠ, এবং পুরো কোর্সের একীভূত থিম। M2 থেকে শুরু হয়ে, আমরা এখন নির্দিষ্ট অটোমাটা ক্লাস (DFA, NFA, PDA, টুরিং মেশিন) দিয়ে কোন ল্যাঙ্গুয়েজ/সমস্যা শ্রেণী সমাধানযোগ্য তা ধাপে ধাপে অন্বেষণ করব।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ "সমস্যা সমাধান করা" এবং "ল্যাঙ্গুয়েজ membership যাচাই করা" — এই দুটো কেন সত্যিই একই জিনিস, শুধু শব্দের খেলা নয়?
কারণ ল্যাঙ্গুয়েজ $L$-এর সংজ্ঞাটাই ("YES-উত্তরের সব ইনপুট-এনকোডিং") নির্মিত হয় সমস্যাটি থেকে সরাসরি, এক-থেকে-এক ম্যাপিং-এ। একটি ইনপুট $w$-এর জন্য সমস্যার উত্তর YES $\iff$ $w \in L$ — এটি একটি সংজ্ঞাগত সমতা (definitional equivalence), কোনো আনুমানিক সাদৃশ্য নয়। তাই "$L$-এর জন্য একটি DFA বানানো" আক্ষরিক অর্থেই "সেই ডিসিশন প্রবলেমটি সমাধান করা" — এই কারণেই M2 থেকে M9 পর্যন্ত অটোমাটা ও ভাষা নিয়ে যা শেখানো হবে, তার প্রতিটি সরাসরি বাস্তব ডিসিশন প্রবলেমের সাথে প্রযোজ্য।
প্র ০২ গ্রাফের মতো একটি বস্তু স্ট্রিং-এ এনকোড করার সময়, একই গ্রাফের বিভিন্ন এনকোডিং (যেমন vertex-এর ভিন্ন ক্রম) কি সমস্যা তৈরি করে?
এটি একটি গুরুত্বপূর্ণ সূক্ষ্ম বিষয় — এনকোডিং স্কিম নিজেই নির্দিষ্ট (fixed) ও সুসংজ্ঞায়িত (well-defined) হতে হবে, যাতে একই বস্তুর জন্য দ্ব্যর্থহীনভাবে একটি স্ট্রিং পাওয়া যায়। ভিন্ন vertex-অর্ডারিং সত্যিই ভিন্ন স্ট্রিং তৈরি করতে পারে (যদিও গ্রাফটি "একই"), কিন্তু এটি সমস্যা নয় যতক্ষণ ল্যাঙ্গুয়েজের সংজ্ঞা এই সব বৈধ এনকোডিং-কেই অন্তর্ভুক্ত করে (যেমন "connected গ্রাফের সব এনকোডিং"-এর ল্যাঙ্গুয়েজ, vertex-অর্ডার নির্বিশেষে)। M9-এ যখন টুরিং মেশিন এনকোডিং নিয়ে কাজ করা হবে, তখন এই একই সতর্কতা আরও গুরুত্বপূর্ণ হয়ে উঠবে।
প্র ০৩
উপরের কোড সেলে is_divisible_by_3-এর remainder সবসময় {0, 1, 2}-এর মধ্যে সীমাবদ্ধ থাকে কেন — এবং এই "ফাইনাইট মেমরি" বৈশিষ্ট্যটি M2-এর সাথে কীভাবে সরাসরি সম্পর্কিত?
কারণ প্রতিটি ধাপে remainder = (remainder * 2 + bit) % 3 — মডুলো-৩ অপারেশনটি ফলাফলকে সবসময় {0,1,2}-এ "ক্ল্যাম্প" করে রাখে, ইনপুট স্ট্রিং যত লম্বাই হোক না কেন। এই তিনটি সম্ভাব্য remainder-ই আসলে M2/L06-এ যে DFA বানানো হবে তার তিনটি স্টেট ($q_0, q_1, q_2$) — remainder ট্র্যাক করা মানে ফাইনাইট সংখ্যক অবস্থার মধ্যে ঘোরাফেরা করা, যা ঠিক একটি DFA-এর সংজ্ঞাগত বৈশিষ্ট্য (ফাইনাইট স্টেট, ফাইনাইট মেমরি)।
অনুশীলন
-
ডিসিশন প্রবলেম লিখুন: "একটি বাইনারি স্ট্রিং-এ 1-এর সংখ্যা কি জোড় (even)?" — এই ডিসিশন প্রবলেমটিকে L01/L02-এর মতো একটি ল্যাঙ্গুয়েজ $L$ হিসেবে ফরমালি লিখুন (সেট-বিল্ডার নোটেশনে)।
$$L = \{w \in \{0,1\}^* : w\text{-তে '1'-এর সংখ্যা জোড়}\}$$ এটি হুবহু L01-এর প্রিভিউ DFA-এর ভাষা — এখন আমরা দেখলাম এটি আসলে একটি ডিসিশন প্রবলেমের ফরমাল এনকোডিং, শুধু একটি "উদাহরণ ভাষা" নয়।
-
পরীক্ষা করুন: উপরের কোড সেলে
test_strings-এ "1000000" (দশমিকে ৬৪) যোগ করে চালান — হাতে হিসাব করুন ৬৪ ৩ দ্বারা বিভাজ্য কি না, তারপর কোডের ফলাফলের সাথে মেলান।৬৪ ÷ ৩ = ২১.৩৩... — বিভাজ্য নয় (৬৪ = ৩×২১+১)। কোড সেলেও
is_divisible_by_3("1000000")এবং64 % 3 == 0দুটোইFalseদেখানোর কথা — remainder ট্রেস করলে: প্রতিটি '0'-এ remainder দ্বিগুণ হয় (mod 3), '1'-এ দ্বিগুণ+১; "1000000"-এ একটি ১ এবং ছয়টি ০ — r=1, তারপর ছয়বার r=(r*2)%3, যা শেষে r=1 দেয়, তাই বিভাজ্য নয় — গণনা মেলে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৬টি পাঠ পরবর্তী পাঠ (মডিউল ২-এর শুরু) — DFA: ফরমাল ডেফিনিশন ও ল্যাঙ্গুয়েজ অ্যাকসেপ্টেন্স — এখনই পড়া যাবে।
- Discrete Mathematics কোর্স সহোদর কোর্স সেট-বিল্ডার নোটেশন ও লজিক্যাল স্টেটমেন্টের ফরমাল ভিত্তি (YES/NO প্রেডিকেট) সেই কোর্সেই তৈরি হয়েছে।
- সব 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 — সব এক জায়গায়।