পাঠ ৪২ · ৫৬-এর মধ্যে · মডিউল ৯
Home / Courses / Formal Language & Automata Theory / Theory of Computation / পোস্ট করেসপন্ডেন্স প্রবলেম

পোস্ট করেসপন্ডেন্স প্রবলেম

The Post Correspondence Problem
৭ মিনিট পড়া উচ্চ · Advanced Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • PCP-এর ফরমাল স্টেটমেন্ট — ডোমিনো, সিকোয়েন্স, ও ম্যাচিং কন্ডিশন
  • PCP কেন আনডিসাইডেবল — প্রমাণের কৌশলের সংক্ষিপ্ত রূপরেখা (টুরিং মেশিন অ্যাকসেপ্টেন্স থেকে রিডাকশন)
  • একটি সত্যিকারের সমাধানযোগ্য উদাহরণ হাতে-কলমে ও কোডে সমাধান করা
  • "bounded সার্চে সমাধান না পাওয়া" এবং "সমস্যাটি আনডিসাইডেবল" — এই দুটোর মধ্যে সঠিক পার্থক্য বোঝা

১ · PCP কী — ডোমিনো ও ফরমাল স্টেটমেন্ট

কল্পনা করুন আপনার কাছে কিছু ডোমিনোপ্রতিটি টাইলের উপরে একটি টপ-স্ট্রিং, নিচে একটি বটম-স্ট্রিং লেখা — সাধারণ ডোমিনো খেলার টাইলের মতোই একটি রূপক টাইল আছে, প্রতিটির উপরে একটি স্ট্রিং (টপ) আর নিচে একটি স্ট্রিং (বটম) লেখা। আপনি এই টাইলগুলো (পুনরাবৃত্তি সহ, যত খুশি বার একই টাইল ব্যবহার করা যায়) পাশাপাশি সাজাবেন — প্রশ্ন হলো: এমনভাবে সাজানো কি সম্ভব যাতে সব টাইলের উপরের স্ট্রিংগুলো পাশাপাশি জোড়া লাগিয়ে যে স্ট্রিং হয়, সেটা ঠিক নিচের স্ট্রিংগুলো জোড়া লাগিয়ে যে স্ট্রিং হয়, তার সাথে অক্ষরে-অক্ষরে মিলে যায়?

ফরমালি (KaTeX-এ): একটি আলফাবেট Σ-এর উপর ডোমিনোর একটি সসীম সংগ্রহ $(t_1,b_1), (t_2,b_2), \ldots, (t_k,b_k)$ দেওয়া হলে ($t_i, b_i \in \Sigma^*$ প্রতিটি জোড়ার টপ ও বটম স্ট্রিং), PCP জিজ্ঞাসা করে — এমন কোনো $n \geq 1$ ও সূচক (index) সিকোয়েন্স $i_1, i_2, \ldots, i_n \in \{1,\ldots,k\}$ (একই সূচক বারবার ব্যবহার করা যাবে) কি বিদ্যমান, যাতে —

$$t_{i_1}t_{i_2}\cdots t_{i_n} = b_{i_1}b_{i_2}\cdots b_{i_n}$$

লক্ষ্য করুন এই সংজ্ঞায় কোনো "মেশিন," "প্রোগ্রাম," বা "গণনা" নেই — শুধু স্ট্রিং জোড়া লাগানো ও তুলনা করা। তবুও, পরের সেকশনে দেখবেন, এই নিরীহ-দেখতে সমস্যাটি সাধারণভাবে সমাধানযোগ্য নয়।

a aa ডোমিনো ১ ab b ডোমিনো ২ ba a ডোমিনো ৩ সিকোয়েন্স: ডোমিনো ১, তারপর ডোমিনো ২ টপ: a + ab = aab বটম: aa + b = aab aab = aab — মিলে গেছে!
তিনটি ডোমিনো {(a,aa), (ab,b), (ba,a)} — শুধু প্রথম দুটি ডোমিনো (১, ২) ব্যবহার করলেই টপ ও বটম স্ট্রিং হুবহু মিলে যায়।

২ · PCP কেন আনডিসাইডেবল

থিওরেম: PCP আনডিসাইডেবল — অর্থাৎ কোনো অ্যালগরিদম নেই যা প্রতিটি সম্ভাব্য ডোমিনো-সংগ্রহের জন্য সঠিকভাবে "সমাধান আছে" বা "সমাধান নেই" বলতে পারে। প্রমাণের কৌশলটি (M9/L40-এর রিডাকশন-স্টাইলের সরাসরি সম্প্রসারণ) হলো — একটি নির্বিচারে বেছে নেওয়া টুরিং মেশিন $M$ ও ইনপুট $w$ থেকে একটি ডোমিনো-সংগ্রহ নির্মাণ করা, যেভাবে যে $M$ যদি $w$-তে accept করে, তাহলে এবং শুধুমাত্র তাহলেই সেই ডোমিনো-সংগ্রহের একটি সমাধান-সিকোয়েন্স থাকবে — প্রতিটি ডোমিনো $M$-এর কম্পিউটেশনের এক-একটি "স্ন্যাপশট"কে টপ থেকে বটমে এগিয়ে নিয়ে যাওয়ার প্রতিনিধিত্ব করে, এবং একটি বৈধ সমাধান-সিকোয়েন্স ঠিক $M$-এর $w$-এর উপর সম্পূর্ণ, সঠিক কম্পিউটেশন হিস্টোরি এনকোড করে। এই নির্মাণ নিজেই বেশ জটিল (সম্পূর্ণ বিস্তারিত এখানে প্রয়োজন নেই) — মূল কথা হলো, যদি PCP ডিসাইডেবল হতো, তাহলে এই রিডাকশন ব্যবহার করে হল্টিং প্রবলেমও (M9/L39) ডিসাইডেবল হয়ে যেত — একটি সরাসরি contradiction, তাই PCP আনডিসাইডেবল।

PCP-এর এই আনডিসাইডেবিলিটি একটি গুরুত্বপূর্ণ ব্যবহারিক ভূমিকাও পালন করে — যেহেতু এটি টুরিং মেশিন থেকে সম্পূর্ণ স্বাধীনভাবে বর্ণনা করা যায়, PCP প্রায়ই অন্যান্য আনডিসাইডেবিলিটি প্রমাণের জন্য একটি সুবিধাজনক "রিডাকশন সোর্স" হিসেবে ব্যবহৃত হয় — যেমন ../programming-languages-compilers/-ঘেঁষা কিছু গ্রামার-অ্যাম্বিগুইটি-স্টাইল প্রশ্নের আনডিসাইডেবিলিটি প্রমাণেও PCP থেকে সরাসরি রিডাকশন ব্যবহৃত হয়।

৩ · Worked example — হাতে-কলমে সমাধান খোঁজা

উপরের ফ্লো-ডায়াগ্রামে দেখানো ডোমিনো-সংগ্রহ {(a, aa), (ab, b), (ba, a)} বিবেচনা করুন — একে ডোমিনো ১, ২, ৩ হিসেবে সূচিত করি। সিকোয়েন্স "১, ২" চেষ্টা করে দেখা যাক —

  • টপ: $t_1 t_2 = \texttt{a} + \texttt{ab} = \texttt{aab}$
  • বটম: $b_1 b_2 = \texttt{aa} + \texttt{b} = \texttt{aab}$

দুটোই aab — হুবহু মিলে গেছে! সুতরাং সিকোয়েন্স $(1, 2)$ এই PCP ইনস্ট্যান্সের একটি বৈধ সমাধান। এটিই এই কোর্সের একটি সাধারণ থিম — একটি সমস্যা সাধারণভাবে আনডিসাইডেবল হলেও, নির্দিষ্ট ছোট ইনস্ট্যান্সে হাতে-কলমে (বা bounded সার্চে) সমাধান খুঁজে পাওয়া সম্পূর্ণ সম্ভব।

Python
# PCP-এর জন্য একটি সত্যিকারের bounded BFS সার্চ -- একটি সাধারণ ডিসিশন প্রসিডিউর নয়!
# (PCP আনডিসাইডেবল -- এই ফাংশনটি শুধু "length বাউন্ডের মধ্যে" সমাধান খোঁজে, বাউন্ডের বাইরে
#  সমাধান থাকলেও এটি "নেই" বলে ভুল সিদ্ধান্তে আসতে পারে -- এটিই আনডিসাইডেবিলিটির সাথে সামঞ্জস্যপূর্ণ)

from collections import deque

def solve_pcp_bounded(dominoes, max_sequence_length):
    # state = (top_so_far, bottom_so_far, sequence_of_indices)
    start = ("", "", [])
    queue = deque([start])
    visited = set()
    while queue:
        top_so_far, bottom_so_far, seq = queue.popleft()
        if len(seq) > 0 and top_so_far == bottom_so_far:
            return seq   # সমাধান পাওয়া গেছে
        if len(seq) >= max_sequence_length:
            continue     # length বাউন্ড ছাড়িয়ে গেছে, এই শাখা বাদ
        for idx, (t, b) in enumerate(dominoes):
            new_top = top_so_far + t
            new_bottom = bottom_so_far + b
            # prefix pruning: একটি অবশ্যই অন্যটির প্রিফিক্স হতে হবে, নাহলে এই শাখা কখনোই মিলবে না
            if new_top.startswith(new_bottom) or new_bottom.startswith(new_top):
                seq2 = seq + [idx]
                key = (new_top, new_bottom, len(seq2))
                if key not in visited:
                    visited.add(key)
                    queue.append((new_top, new_bottom, seq2))
    return None   # বাউন্ডের মধ্যে কোনো সমাধান পাওয়া যায়নি

# ---- সমাধানযোগ্য ইনস্ট্যান্স ----
dominoes = [("a", "aa"), ("ab", "b"), ("ba", "a")]
solution = solve_pcp_bounded(dominoes, max_sequence_length=6)
print("ডোমিনো সংগ্রহ:", dominoes)
print("পাওয়া সিকোয়েন্স (0-indexed):", solution)

if solution is not None:
    top_concat = "".join(dominoes[i][0] for i in solution)
    bottom_concat = "".join(dominoes[i][1] for i in solution)
    print(f"টপ concatenation    = {top_concat!r}")
    print(f"বটম concatenation   = {bottom_concat!r}")
    print("সমাধান বৈধ (টপ == বটম)?", top_concat == bottom_concat)

# ---- ডেলিবারেটলি আনসলভেবল ইনস্ট্যান্স ----
# প্রতিটি ডোমিনোর টপ ও বটমের প্রথম অক্ষর ভিন্ন -- তাই কোনো ডোমিনোই সিকোয়েন্স শুরু করতে পারে না
unsolvable_dominoes = [("ab", "ba"), ("ca", "ac")]
unsolvable_result = solve_pcp_bounded(unsolvable_dominoes, max_sequence_length=6)
print()
print("আনসলভেবল ডোমিনো সংগ্রহ:", unsolvable_dominoes)
print("bounded সার্চের ফলাফল:", unsolvable_result, "(কোনো সমাধান নেই, প্রত্যাশিতভাবেই)")

    
লক্ষ্য করুন unsolvable_dominoes-এর প্রতিটি ডোমিনোর টপ ও বটম স্ট্রিং ভিন্ন অক্ষর দিয়ে শুরু — যেহেতু সিকোয়েন্সের প্রথম ডোমিনো ব্যবহারের পরই টপ ও বটমের একটিকে অন্যটির প্রিফিক্স হতে হবে (নাহলে কখনোই মিলবে না), আর প্রথম অক্ষরই যদি ভিন্ন হয়, কোনো ডোমিনোই বৈধভাবে সিকোয়েন্স শুরু করতে পারে না — তাই এই ইনস্ট্যান্সের আসলে কোনো length-এই সমাধান নেই, শুধু এই bounded সার্চের মধ্যেই নয়।
মূল কথা · Key takeaway

PCP দেখায় আনডিসাইডেবিলিটি শুধু "প্রোগ্রাম সম্পর্কে প্রশ্ন" (হল্টিং প্রবলেম, রাইসের থিওরেম)-এ সীমাবদ্ধ নয় — নিরীহ-দেখতে স্ট্রিং-ম্যাচিং সমস্যাতেও এটি ঘটে। তবুও, নির্দিষ্ট ছোট ইনস্ট্যান্সে সমাধান খোঁজা (bounded সার্চ দিয়ে) সম্পূর্ণ সম্ভব — আনডিসাইডেবিলিটি মানে "কখনো সমাধান করা যায় না," বরং মানে "সব ইনস্ট্যান্সের জন্য কাজ করা একটিমাত্র সাধারণ অ্যালগরিদম নেই।" M9-এর এটিই শেষ পাঠ — এরপর M10 থেকে "কতটা কার্যকরভাবে গণনাযোগ্য" প্রশ্নে যাওয়া হবে।

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

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

প্র ০১ PCP-এর সংজ্ঞায় কোনো টুরিং মেশিন বা প্রোগ্রামের উল্লেখ নেই, তবুও এটি আনডিসাইডেবল কেন এত গুরুত্বপূর্ণ একটি আবিষ্কার?

কারণ এটি দেখায় আনডিসাইডেবিলিটি কোনো "প্রোগ্রাম-নির্দিষ্ট" বৈশিষ্ট্য নয় — এটি এমনকি বিশুদ্ধ স্ট্রিং-ম্যাচিং সমস্যাতেও ঘটতে পারে, যার সংজ্ঞায় কম্পিউটেশনের কোনো ধারণাই স্পষ্টভাবে নেই। এটি আনডিসাইডেবিলিটিকে একটি আরও গভীর, সাধারণ ঘটনা হিসেবে প্রতিষ্ঠিত করে — এবং ঠিক এই কারণেই PCP পরবর্তীতে অন্যান্য (এমনকি computation-অসম্পর্কিত দেখতে) সমস্যার আনডিসাইডেবিলিটি প্রমাণের জন্য একটি জনপ্রিয় "রিডাকশন সোর্স" হয়ে ওঠে।

প্র ০২ solve_pcp_bounded যদি একটি নির্দিষ্ট length বাউন্ডের মধ্যে কোনো সমাধান খুঁজে না পায়, তাহলে কি আমরা নিশ্চিতভাবে বলতে পারি সেই PCP ইনস্ট্যান্সের কোনো সমাধান নেই?

না — এটিই আনডিসাইডেবিলিটির সাথে সামঞ্জস্যপূর্ণ গুরুত্বপূর্ণ সীমাবদ্ধতা। bounded সার্চ শুধু নির্দিষ্ট length পর্যন্ত সিকোয়েন্স যাচাই করে — সমাধান থাকলেও সেটি হয়তো বাউন্ডের চেয়ে দীর্ঘ হতে পারে। "বাউন্ডের মধ্যে না পাওয়া" মানে "বাউন্ডের মধ্যে নেই," কখনোই সাধারণভাবে "কোনো length-এই নেই" নয় — যদি একটি সাধারণ (unbounded) অ্যালগরিদম থাকত যা সব ইনস্ট্যান্সের জন্য নির্ভুলভাবে এই প্রশ্নের উত্তর দিতে পারত, PCP তাহলে ডিসাইডেবল হয়ে যেত — যা থিওরেম অনুযায়ী অসম্ভব। (তবে ব্যতিক্রম: যদি প্রথম ডোমিনো নির্বাচনের সময়ই কোনো ডোমিনোর টপ-বটম প্রথম অক্ষরে মেলে না, তাহলে সেটি প্রমাণযোগ্যভাবেই কখনো সমাধান হতে পারবে না, যেমন এই পাঠের দ্বিতীয় উদাহরণে।)

প্র ০৩ {(a, aa), (ab, b), (ba, a)} উদাহরণে সিকোয়েন্স "১, ২" কেন কাজ করে, ধাপে ধাপে ব্যাখ্যা করুন।

ডোমিনো ১ = (a, aa) এবং ডোমিনো ২ = (ab, b)। সিকোয়েন্স "১, ২" ব্যবহার করলে — টপ স্ট্রিং হয় $t_1 + t_2 = \texttt{a} + \texttt{ab} = \texttt{aab}$, আর বটম স্ট্রিং হয় $b_1 + b_2 = \texttt{aa} + \texttt{b} = \texttt{aab}$। দুটোই ঠিক aab — তাই এই সিকোয়েন্স মিলে যায়। লক্ষ্য করুন ডোমিনো ১ একাই কাজ করত না (a ≠ aa) — কিন্তু ডোমিনো ১-এর পর ডোমিনো ২ যোগ করায় টপ-বটমের দৈর্ঘ্যের পার্থক্য ঠিক পূরণ হয়ে যায়, এটিই bounded সার্চের prefix-pruning ধাপে ধাপে খুঁজে বের করে।

অনুশীলন

  1. পরীক্ষা করুন: উপরের কোড সেলে dominoes-এ ডোমিনো ৩ = (ba, a)ও ব্যবহার করে একটি ভিন্ন, দীর্ঘ সমাধান-সিকোয়েন্স আছে কি না খুঁজে দেখুন (হিন্ট: max_sequence_length বাড়িয়ে দিন এবং solve_pcp_bounded কি প্রথম পাওয়া সমাধানটিই ফেরত দেয়, নাকি অন্য কিছু, তা লক্ষ করুন)।

    যেহেতু solve_pcp_bounded BFS ব্যবহার করে (queue-ভিত্তিক, প্রতিটি length স্তর ধাপে ধাপে অন্বেষণ করে), এটি সবসময় সবচেয়ে সংক্ষিপ্ততম বৈধ সমাধান-সিকোয়েন্স খুঁজে ফেরত দেয় — এই উদাহরণে সেটি "১, ২" (length ২)। max_sequence_length বাড়ালেও একই সংক্ষিপ্ততম উত্তর পাবেন, কারণ BFS length অনুযায়ী স্তরে-স্তরে খোঁজে, আর সংক্ষিপ্ততম সমাধান প্রথমেই পাওয়া যায়।

  2. চিন্তা করুন: কিছু সংজ্ঞায় PCP-তে $n \geq 1$ শর্ত (অন্তত একটি ডোমিনো ব্যবহার করতেই হবে) রাখা হয়, খালি সিকোয়েন্স ($n = 0$) অনুমোদিত নয়। কেন এই শর্তটি প্রয়োজনীয়?

    যদি $n = 0$ অনুমোদিত হতো, তাহলে খালি সিকোয়েন্সের টপ concatenation ও বটম concatenation দুটোই খালি স্ট্রিং ($\varepsilon$) হয়ে যেত — যা সবসময় স্বয়ংক্রিয়ভাবে সমান, মানে প্রতিটি PCP ইনস্ট্যান্স (এমনকি সম্পূর্ণ অসামঞ্জস্যপূর্ণ ডোমিনো নিয়েও) trivially "সমাধানযোগ্য" হয়ে যেত — এটি সমস্যাটিকে অর্থহীন করে ফেলত। $n \geq 1$ শর্তটি নিশ্চিত করে সমাধান খোঁজাটা সত্যিকারের, non-trivial একটি প্রশ্ন থাকে।

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

আগের পাঠ
L41 · রাইসের থিওরেম