সরাসরি পর্বে যান
পর্ব ৬০ · ৮৩-এর মধ্যে · মডিউল ১০

Euler আর Hamilton path — Königsberg থেকে NP-কঠিনতা

Euler and Hamilton Paths — Königsberg, Euler's Theorem with Proof, Hierholzer, de Bruijn Sequences, Route Inspection, Dirac and Ore, and NP-Completeness

Taught in Bangla, this lesson proves Euler's theorem for circuits and trails, explains the Königsberg bridges, and builds circuits with Hierholzer's and Fleury's methods. It extends the idea to directed graphs and de Bruijn sequences and solves a route inspection (Chinese postman) problem. For Hamilton cycles it gives Dirac's and Ore's sufficient conditions with proof, non-existence arguments such as the 3 × 3 grid, and why the problem is NP-complete. In-page Python builds circuits and tests Ore on small graphs.

এই পর্বে যা শিখবেন

  • Euler circuit আর trail-এর উপপাদ্য, দুই দিকের সম্পূর্ণ প্রমাণসহ, আর directed graph-এ তার রূপ
  • Hierholzer আর Fleury-র পদ্ধতি, Hierholzer কেন সঠিক, আর Python-এ circuit বানিয়ে যাচাই
  • de Bruijn sequence আর route inspection: Euler-এর তত্ত্বের দুটি ব্যবহারিক প্রয়োগ
  • Hamilton cycle না-থাকার প্রমাণ, আর Ore-এর উপপাদ্যের পূর্ণ প্রমাণ (তা থেকে Dirac)
  • কেন Euler সহজ আর Hamilton কঠিন: NP-completeness-এর ধারণা আর TSP-এর সঙ্গে যোগ

১ · Königsberg-এর সাত সেতু — একটি ধাঁধা থেকে graph theory

ধরুন বাজারঘরের একজন ডেলিভারি রাইডার সকালে গুদাম থেকে বের হন। তাঁর কাজ প্রতিটি গলিতে লিফলেট দেওয়া: এমন রুট কি আছে, যাতে প্রতিটি গলি ঠিক একবার ঘোরা হয় আর শেষে তিনি গুদামে ফেরেন? আরেকজন রাইডারের কাজ প্রতিটি মোড়ে একবার একটি পার্সেল দেওয়া। প্রথম প্রশ্নটি edge নিয়ে, দ্বিতীয়টি vertex নিয়ে। শুনতে প্রায় একই, কিন্তু প্রথমটির উত্তর এক লাইনে দেওয়া যায়, আর দ্বিতীয়টির জন্য আজও কোনো দ্রুত পদ্ধতি জানা নেই।

প্রুশিয়ার Königsberg শহরে (আজকের রাশিয়ার Kaliningrad) Pregel নদী একটি দ্বীপকে ঘিরে দুই শাখায় বয়ে যেত, আর শহরের চারটি ভূখণ্ড সাতটি সেতু দিয়ে যুক্ত ছিল। ধাঁধাটি ছিল: প্রতিটি সেতু ঠিক একবার পার হয়ে কি পুরো শহর ঘোরা যায়? Leonhard Euler এই প্রশ্নের উত্তর দিয়ে একটি প্রবন্ধ লেখেন, যা সাধারণত ১৭৩৬ সালের বলে উল্লেখ করা হয় (St. Petersburg-এর একাডেমিতে উপস্থাপন আর প্রকাশের সাল নিয়ে সূত্রভেদে সামান্য পার্থক্য আছে)। প্রবন্ধটিকে graph theory-র সূচনা ধরা হয়। Euler দেখান যে উত্তর “না”, আর কোন শর্তে এমন হাঁটা সম্ভব তাও বলেন; তবে শর্তটি যে যথেষ্টও, তার পূর্ণ প্রমাণ পরে Carl Hierholzer দেন, যা ১৮৭৩ সালে তাঁর মৃত্যুর পর প্রকাশিত হয় বলে জানা যায়।

Euler-এর মূল অন্তর্দৃষ্টি ছিল বিমূর্ত করা: গুরুত্বপূর্ণ শুধু কোন ভূখণ্ড কোনটির সঙ্গে কয়টি সেতু দিয়ে যুক্ত। প্রতিটি ভূখণ্ডকে একটি vertex আর প্রতিটি সেতুকে একটি edge ধরলে পাওয়া যায় একটি multigraph, কারণ একই দুই ভূখণ্ডের মধ্যে দুটি সেতু আছে।

Königsberg: সরলীকৃত নকশা থেকে multigraph

ওপরে নদী (নীল), চারটি ভূখণ্ড A, B, C, D আর সাতটি সেতু (বাদামি)। নিচে একই তথ্য একটি multigraph হিসেবে, প্রতিটি vertex-এর পাশে তার degree.

The seven bridges of Königsberg as a simplified map and as a multigraph with degrees 5, 3, 3, 3 A দ্বীপ B · উত্তর পাড় C · দক্ষিণ পাড় D ভূখণ্ড → vertex, সেতু → edge AB CD deg 5 deg 3 deg 3 deg 3

এই পর্ব পর্ব ৫৭ “গ্রাফ — সংজ্ঞা, degree আর handshake theorem” আর পর্ব ৫৯ “Connectivity — path, component, cut vertex আর Menger-এর ধারণা”-এর ভাষা ব্যবহার করে। দরকারি সংজ্ঞাগুলো এক জায়গায়:

সংজ্ঞা ১.১ (কোন graph, কোন হাঁটা)
  • এই পর্বের Euler-অংশ multigraph নিয়ে: একই দুই vertex-এর মধ্যে একাধিক edge চলবে, আর loop (একই vertex-এ শুরু-শেষ edge) থাকলে তা degree-তে ২ যোগ করে। Hamilton-অংশ simple graph নিয়ে (loop বা parallel edge নেই), কারণ সেখানে ওগুলো কোনো কাজে লাগে না।
  • একটি vertex v-এর degree deg(v) = v-কে ছোঁয়া edge-এর সংখ্যা। Handshake lemma: সব degree-র যোগফল = 2m, যেখানে m edge-এর সংখ্যা; তাই বিজোড় degree-র vertex সবসময় জোড় সংখ্যক।
  • Walk: v0, e1, v1, …, ek, vk, যেখানে ei হলো vi−1 আর vi-এর মধ্যে একটি edge. Trail: কোনো edge পুনরাবৃত্ত হয় না। Circuit: শুরু আর শেষ একই vertex-এ, এমন trail. Path: কোনো vertex পুনরাবৃত্ত হয় না। Cycle: শুধু শুরু = শেষ ছাড়া কোনো vertex পুনরাবৃত্ত হয় না, এমন circuit.
  • Euler circuit: graph-এর প্রতিটি edge ঠিক একবার ব্যবহার করে এমন circuit. Euler trail (Euler path): প্রতিটি edge ঠিক একবার ব্যবহার করে এমন trail, শুরু-শেষ আলাদা হতে পারে।
  • Hamilton path: প্রতিটি vertex ঠিক একবার ছোঁয় এমন path. Hamilton cycle: প্রতিটি vertex ঠিক একবার ছুঁয়ে শুরুতে ফেরে এমন cycle (n ≥ 3).

Königsberg-এ ফিরি। যাত্রার মাঝখানের প্রতিটি ভূখণ্ডে যতবার ঢোকা হয়, ততবারই বের হওয়া হয়, তাই সেখানে সেতুর সংখ্যা জোড় হতে হবে; বিজোড় degree-র ভূখণ্ড কেবল শুরু বা শেষ হতে পারে। কিন্তু চারটিরই degree বিজোড় (5, 3, 3, 3), আর শুরু-শেষ মিলে মাত্র দুটি জায়গা। তাই হাঁটা অসম্ভব। এই যুক্তিটিই পরের উপপাদ্যের অর্ধেক।

২ · Euler-এর উপপাদ্য — কখন প্রতিটি edge ঠিক একবার

“Connected” কথাটি এখানে একটু সাবধানে বলতে হয়: কোনো edge-ই নেই এমন বিচ্ছিন্ন vertex (isolated vertex) থাকলেও Euler circuit-এর কোনো ক্ষতি নেই, কারণ circuit-কে তাদের ছুঁতে হয় না। তাই নিচে “connected” মানে: অন্তত একটি edge-যুক্ত সব vertex একই component-এ।

উপপাদ্য ২.১ (Euler circuit)

অন্তত একটি edge আছে এমন একটি multigraph G (loop থাকতে পারে), যার সব edge একই component-এ, তাতে Euler circuit আছে যদি এবং কেবল যদি G-এর প্রতিটি vertex-এর degree জোড়।

প্রমাণের আগে একটি lemma লাগবে, যা Hierholzer-এর পদ্ধতিরও মূল।

Lemma ২.২ (আটকে যাওয়া শুধু শুরুতে)

প্রতিটি degree জোড় এমন একটি multigraph-এ যেকোনো edge-যুক্ত vertex s থেকে শুরু করে ব্যবহার-না-করা edge ধরে যেভাবেই হাঁটা হোক, হাঁটা শুধু s-এ গিয়ে আটকায়। ফলে প্রতিটি edge-যুক্ত vertex দিয়ে যায় এমন একটি circuit সবসময় আছে।

  1. হাঁটা একটি trail, কারণ কোনো edge দুবার নেওয়া হয় না; edge সসীম, তাই হাঁটা কোথাও থামে। — সসীমতা
  2. ধরুন হাঁটা এখন w ≠ s-এ। w-তে প্রতিবার ঢোকা আর বের হওয়া মিলে ২টি করে edge খরচ হয়েছে, আর এইমাত্র ঢোকার জন্য আরও ১টি; মোট বিজোড় সংখ্যক। — গোনা
  3. deg(w) জোড়, তাই w-তে অন্তত একটি edge এখনো অব্যবহৃত, আর হাঁটা চলতে পারে। অর্থাৎ w ≠ s-এ হাঁটা কখনো আটকায় না। — জোড় − বিজোড় ≥ 1
  4. তাই হাঁটা থামে কেবল s-এ, আর তৈরি হয় s থেকে s-এ একটি circuit. ∎ — ধাপ ১ আর ৩

লক্ষ করুন lemma কী বলে না: আটকানোর সময় সব edge ব্যবহার হয়ে গেছে, এমন কোনো দাবি নেই। শুধু s-এর edge-গুলো শেষ। এই পার্থক্যটি অনুশীলন ৪-এর ভুল প্রমাণের মূলে।

উপপাদ্য ২.১-এর প্রমাণ, “কেবল যদি” দিক (circuit থাকলে সব degree জোড়)।

  1. Euler circuit-টি v0, e1, v1, …, em, vm = v0 লিখুন। প্রতিটি edge এখানে ঠিক একবার আছে। — সংজ্ঞা
  2. circuit-টি একটি vertex-এর মধ্য দিয়ে প্রতিবার যাওয়ায় দুটি edge খরচ করে: একটি দিয়ে ঢোকে, একটি দিয়ে বের হয় (একটি loop একবারেই ২ গোনে)। শুরুর v0-এ প্রথমবার বের হওয়া আর শেষবার ঢোকা মিলেও একটি জোড়া। — জোড়ায় গোনা
  3. প্রতিটি edge ঠিক একবার আছে বলে প্রতিটি vertex-এর degree = এই জোড়াগুলোর মোট edge, অর্থাৎ জোড়। ∎ — ধাপ ১, ২

“যদি” দিক (সব degree জোড় হলে circuit আছে), m-এর ওপর strong induction (পর্ব ১১)।

  1. দাবি: শর্ত মানে এমন প্রতিটি multigraph-এ, যার edge সংখ্যা m ≥ 1, Euler circuit আছে। ধরুন m-এর চেয়ে কম edge-এর সব ক্ষেত্রে দাবিটি সত্য। — induction hypothesis
  2. lemma ২.২ থেকে একটি circuit C পাওয়া যায়। C যদি সব edge ব্যবহার করে, তবে C-ই Euler circuit, কাজ শেষ। — lemma ২.২
  3. না হলে C-এর edge-গুলো মুছে বাকি graph H নিন। C প্রতিটি vertex-এ জোড় সংখ্যক edge খরচ করে (“কেবল যদি” দিকের ধাপ ২), তাই H-এর প্রতিটি degree এখনো জোড়। — জোড় − জোড় = জোড়
  4. H-এর যেকোনো edge-যুক্ত component K নিন। K-এর edge m-এর চেয়ে কম আর সব degree জোড়, তাই hypothesis অনুযায়ী K-এর একটি Euler circuit CK আছে। — induction hypothesis
  5. G connected বলে K-এর কোনো vertex x অবশ্যই C-এর ওপর আছে: না হলে K-এর edge আর C-এর edge-এর মধ্যে G-তে কোনো পথ থাকত না। — connectedness
  6. C ধরে হাঁটতে হাঁটতে x-এ পৌঁছে প্রথমে পুরো CK ঘুরে x-এ ফিরুন, তারপর C-এর বাকি অংশ চালিয়ে যান। প্রতিটি component-এর জন্য এভাবে “জোড়া” (splice) দিলে প্রতিটি edge ঠিক একবার ব্যবহার হয়। ∎ — splicing
উপপাদ্য ২.৩ (Euler trail)

উপপাদ্য ২.১-এর মতো একটি connected multigraph-এ Euler trail আছে যদি এবং কেবল যদি বিজোড় degree-র vertex ঠিক ০টি বা ২টি। ২টি হলে প্রতিটি Euler trail ওই দুটির একটিতে শুরু হয়ে অন্যটিতে শেষ হয়।

  1. “কেবল যদি”: u থেকে v-তে একটি Euler trail-এ মাঝের প্রতিটি vertex-এ ঢোকা-বের হওয়া জোড়ায় আসে, তাই তাদের degree জোড়। u = v হলে এটি একটি circuit, বিজোড় vertex ০টি; u ≠ v হলে শুধু u আর v-এ একটি করে বাড়তি edge, তাই ঠিক এরা দুটি বিজোড়। — উপপাদ্য ২.১-এর একই গোনা
  2. “যদি”, ০টি বিজোড় হলে উপপাদ্য ২.১ নিজেই একটি circuit দেয়। — উপপাদ্য ২.১
  3. ঠিক ২টি বিজোড় u, v হলে একটি নতুন edge u–v যোগ করুন (parallel হলেও চলবে)। এখন সব degree জোড়, তাই একটি Euler circuit আছে, যা নতুন edge-টি একবার ব্যবহার করে। — উপপাদ্য ২.১
  4. circuit-টিকে নতুন edge-এর জায়গায় কেটে দিলে বাকি অংশ u থেকে v-তে একটি trail, যা G-এর প্রতিটি edge ঠিক একবার নেয়। ∎ — circuit থেকে একটি edge বাদ

বিজোড় vertex ১টি বা ৩টি হওয়া অসম্ভব, handshake lemma অনুযায়ী। আর কোনো connected graph-এ বিজোড় vertex 2k-টি (k ≥ 1) হলে তার edge-গুলো ঠিক k-টি trail-এ ভাগ করা যায়, কমে নয়: k-টি কাল্পনিক edge দিয়ে বিজোড়দের জোড়ায় জুড়ে circuit বানিয়ে কাল্পনিক edge-গুলো কেটে দিলেই হয়। “কলম না তুলে ছবি আঁকা” ধাঁধার এটিই উত্তর।

৩ · Hierholzer আর Fleury — circuit বানানোর দুই পদ্ধতি

উপরের প্রমাণটি নিজেই একটি algorithm: একটি circuit বানানো, বাকি edge-এ আরেকটি circuit বানানো, তারপর দুটি জুড়ে দেওয়া। একে বলে Hierholzer-এর algorithm. নিচের stepper বাজারঘরের পাঁচটি হাব A, B, C, D, E-এর একটি multigraph-এ কাজটি দেখায়; B আর D-এর মধ্যে দুটি আলাদা রাস্তা আছে।

Hierholzer's algorithm on a five-vertex multigraph: three sub-circuits spliced together ABC DE
৫টি হাব, ৮টি রাস্তা
circuit
নতুন চক্র
বাকি edge
  1. শর্ত যাচাই। deg(A) = 2, deg(B) = 4, deg(C) = 4, deg(D) = 4, deg(E) = 2: সব জোড়, আর graph connected. উপপাদ্য ২.১ অনুযায়ী Euler circuit আছে।
  2. প্রথম circuit. A থেকে শুরু: A → B → C → A. A-এর দুটি edge-ই শেষ, তাই হাঁটা A-তে আটকাল, ঠিক lemma ২.২ যেমন বলে। বাকি ৫টি edge.
  3. প্রথম জোড়া। circuit-এর ওপর B-এর এখনো দুটি অব্যবহৃত edge আছে (দুটি B–D রাস্তা)। B থেকে নতুন হাঁটা: B → D → B. এটিকে প্রথম circuit-এর B-এর জায়গায় বসালে A B D B C A. বাকি ৩টি।
  4. দ্বিতীয় জোড়া। এবার C-তে অব্যবহৃত edge আছে: C → D → E → C. C-এর জায়গায় বসালে A B D B C D E C A. বাকি ০টি।
  5. যাচাই। চূড়ান্ত circuit-এ ৮টি পদক্ষেপ, আর প্রতিটি রাস্তা ঠিক একবার এসেছে (B–D দুটি আলাদা রাস্তা বলে দুবার)। শুরু আর শেষ A. প্রতিটি splice একটি “বন্ধ ঘুরপথ” ঢোকায়, তাই circuit কখনো ভাঙে না।

Hierholzer কেন সঠিক। দুটি invariant: (১) হাতের ক্রমটি সবসময় একটি বৈধ circuit, কারণ বন্ধ ঘুরপথ ঢোকালে ক্রম বন্ধই থাকে; (২) বাকি edge-এর graph-এ সব degree জোড়, তাই lemma ২.২ অনুযায়ী নতুন হাঁটা শুরুতেই ফেরে। edge বাকি থাকলে connectedness অনুযায়ী circuit-এর ওপর এমন vertex আছে যার edge বাকি; প্রতিবার edge কমে, তাই কাজ শেষ হয়, আর তখন সব edge ব্যবহৃত।

প্রোগ্রামে splice আলাদা করে লাগে না: stack-এ বর্তমান হাঁটা রাখুন; অব্যবহৃত edge থাকলে এগোন, না থাকলে vertex-টিকে stack থেকে তুলে ফলাফলে যোগ করুন। প্রতিটি edge একবার দেখা হয়: O(n + m). DSA কোর্সের পর্ব ৩৯ “গ্রাফ — উপস্থাপন আর পরিভাষা”-এ এর প্রোগ্রামিং দিক আছে।

Fleury-র পদ্ধতি (১৮৮৩ সালের বলে উল্লেখ করা হয়) একটিই হাঁটা চালায়, কিন্তু নিয়ম মেনে: বর্তমান vertex থেকে একটি bridge (যে edge মুছলে বাকি অব্যবহৃত graph দুই ভাগ হয়) নেবেন না, যদি অন্য কোনো উপায় থাকে। তাহলে কোনো edge “ওপারে” আটকে থাকে না। পদ্ধতিটি সঠিক (প্রমাণ এখানে বাদ; বেশির ভাগ discrete math পাঠ্যবইয়ে আছে), কিন্তু প্রতি ধাপে bridge পরীক্ষায় সরল রূপে প্রায় O(m2) কাজ লাগে। তাই হাতে Fleury, প্রোগ্রামে Hierholzer.

নিচের ব্লক degree পরীক্ষা করে, stack-ভিত্তিক Hierholzer চালায়, আর ফলাফলটি সত্যিই প্রতিটি edge ঠিক একবার নেয় কি না যাচাই করে। প্রথমবার চালালে ব্রাউজারে Python (Pyodide) নামতে কয়েক সেকেন্ড লাগে; পরের ব্লকগুলো দ্রুত চলে।

from collections import Counter, defaultdict
def odd_vertices(edges):              # loops count 2, parallel edges each 1
    deg = Counter(v for e in edges for v in e)
    return deg, sorted(v for v in deg if deg[v] % 2)
def hierholzer(edges, start):
    adj = defaultdict(list)           # vertex -> [(neighbour, edge id)]
    for i, (u, v) in enumerate(edges):
        adj[u].append((v, i)); adj[v].append((u, i))
    used = [False] * len(edges)
    stack, circuit = [start], []
    while stack:
        v = stack[-1]
        while adj[v] and used[adj[v][-1][1]]:
            adj[v].pop()              # skip edges walked from the other end
        if adj[v]:
            w, i = adj[v].pop(); used[i] = True
            stack.append(w)           # extend the current trail
        else:
            circuit.append(stack.pop())   # stuck: v is finished
    return circuit[::-1]
def uses_each_edge_once(seq, edges):
    return Counter(frozenset(p) for p in zip(seq, seq[1:])) == \
           Counter(frozenset(e) for e in edges)
konig = [("A","B"), ("A","B"), ("A","C"), ("A","C"), ("A","D"), ("B","D"), ("C","D")]
deg, odd = odd_vertices(konig)
print("Konigsberg:", dict(deg), "odd:", odd)
hubs = [("A","B"), ("B","C"), ("C","A"), ("C","D"), ("D","E"), ("E","C"), ("B","D"), ("D","B")]
deg, odd = odd_vertices(hubs)
c = hierholzer(hubs, "A")
print("hubs odd:", odd, "circuit:", "-".join(c), uses_each_edge_once(c, hubs))
konig8 = konig + [("B","C")]          # an 8th bridge between the banks
deg, odd = odd_vertices(konig8)
t = hierholzer(konig8, odd[0])
print("8 bridges odd:", odd, "trail:", "-".join(t), uses_each_edge_once(t, konig8))

আসল আউটপুট (ব্রাউজারের Python):

Konigsberg: {'A': 5, 'B': 3, 'C': 3, 'D': 3} odd: ['A', 'B', 'C', 'D']
hubs odd: [] circuit: A-C-E-D-B-D-C-B-A True
8 bridges odd: ['A', 'D'] trail: A-D-C-B-A-C-A-B-D True

প্রথম লাইনে Königsberg-এর চারটি বিজোড় vertex: কোনো Euler trail নেই। দ্বিতীয় লাইনের circuit stepper-এর A B D B C D E C A থেকে আলাদা, কারণ stack-ভিত্তিক রূপ edge-গুলো অন্য ক্রমে নেয়; কিন্তু শেষ True বলছে এটিও প্রতিটি রাস্তা ঠিক একবার নেয়। একটি graph-এ সাধারণত অনেক Euler circuit থাকে। তৃতীয় লাইন একটি “যদি” পরীক্ষা: B আর C-এর মধ্যে অষ্টম একটি সেতু বানালে B আর C জোড় হয়ে যায়, বিজোড় থাকে শুধু A আর D, আর উপপাদ্য ২.৩ অনুযায়ী A থেকে D-তে একটি Euler trail পাওয়া যায়। প্রোগ্রামটি বিজোড় vertex থেকে শুরু করেছে বলেই trail পেয়েছে। frozenset-এর তুলনায় edge-এর দিক গোনা হয়নি, আর Counter parallel edge আলাদা করে গুনেছে।

৪ · দিকযুক্ত graph আর de Bruijn sequence

শহরের সব রাস্তা দুই দিকে চলে না। একমুখী রাস্তার জন্য directed graph লাগে, যেখানে প্রতিটি edge u থেকে v-তে একটি তীর। একটি vertex-এ ঢোকা তীরের সংখ্যা তার in-degree deg−(v), আর বেরোনো তীরের সংখ্যা out-degree deg+(v). Euler-এর যুক্তি এখানে আরও সরল: প্রতিবার ঢুকলে একবার বেরোতে হয়।

উপপাদ্য ৪.১ (directed Euler circuit)

একটি directed multigraph-এ, যার সব edge তীরের দিক উপেক্ষা করলে একই component-এ, directed Euler circuit আছে যদি এবং কেবল যদি প্রতিটি vertex-এ deg−(v) = deg+(v). Directed Euler trail (circuit নয়) আছে যদি এবং কেবল যদি একটি vertex-এ deg+ − deg− = 1 (শুরু), একটিতে deg− − deg+ = 1 (শেষ), আর বাকি সবখানে সমান।

প্রমাণ উপপাদ্য ২.১-এর হুবহু অনুবাদ। “কেবল যদি”: circuit প্রতিবার একটি vertex-এ ঢুকে বের হয়, তাই ঢোকা = বেরোনো। “যদি”: lemma ২.২-এর directed রূপ সত্য, কারণ w ≠ s-এ এইমাত্র ঢুকলে ব্যবহৃত বেরোনো তীর ব্যবহৃত ঢোকা তীরের চেয়ে একটি কম, আর deg+(w) = deg−(w) বলে একটি বেরোনো তীর বাকি থাকে। তারপর একই induction আর splice. শর্ত পূরণ হলে তীর-যুক্ত সব vertex আসলে strongly connected, কারণ Euler circuit সবাইকে একটি বন্ধ পথে বাঁধে। ∎

de Bruijn sequence: একটি তালার সব কোড একটানা

বাজারঘরের গুদামের একটি পুরোনো তালায় ৩-বিটের কোড, আর তালাটি শুধু শেষ তিনটি চাপা বিট দেখে। প্রতিটি কোড আলাদা চাপলে 8 × 3 = 24 চাপ লাগে, কিন্তু কোডগুলো একে অন্যের ওপর চাপানো যায়: 0001011100 চাপলে পরপর তিনটি করে বিট 000, 001, 010, 101, 011, 111, 110, 100, অর্থাৎ ৮টি কোডই আসে, মাত্র ১০ চাপে। চক্রাকারে লিখলে এমন একটি string-কে বলে de Bruijn sequence B(2, n): দৈর্ঘ্য 2n-এর একটি চক্রাকার bit string, যাতে প্রতিটি n-বিট শব্দ ঠিক একবার আসে। পর্ব ৫১-এর necklace আলোচনায় এদের দেখা পেয়েছিলেন।

উপপাদ্য ৪.২ (de Bruijn sequence সবসময় আছে)

প্রতিটি n ≥ 2-এর জন্য B(2, n) আছে। প্রমাণ: (n − 1)-বিট শব্দগুলোকে vertex ধরুন (2n−1টি), আর প্রতিটি n-বিট শব্দ b1b2…bn-কে b1…bn−1 থেকে b2…bn-এ একটি তীর (2nটি তীর, loop-সহ)।

  1. প্রতিটি vertex x-এর পরে 0 বা 1 বসিয়ে দুটি বেরোনো তীর, আর সামনে 0 বা 1 বসিয়ে দুটি ঢোকা তীর: deg+ = deg− = 2. — গোনা
  2. যেকোনো x থেকে যেকোনো y-তে যাওয়া যায়: y-এর n − 1টি বিট একে একে পেছনে জুড়ে দিলে n − 1 ধাপে x “সরে গিয়ে” y হয়ে যায়। তাই graph connected. — shift
  3. উপপাদ্য ৪.১ অনুযায়ী একটি directed Euler circuit আছে, যা প্রতিটি তীর, অর্থাৎ প্রতিটি n-বিট শব্দ, ঠিক একবার নেয়। — উপপাদ্য ৪.১
  4. circuit-এর প্রতিটি তীর থেকে তার নতুন (শেষ) বিটটি পরপর লিখলে 2n দৈর্ঘ্যের একটি চক্রাকার string পাওয়া যায়, যার প্রতিটি n-বিট জানালা ঠিক একটি তীর। ∎ — নির্মাণ
from itertools import product
def de_bruijn(n):                     # Euler circuit in the de Bruijn digraph
    out = {"".join(p): ["1", "0"] for p in product("01", repeat=n - 1)}
    start = "0" * (n - 1)
    stack, circuit = [start], []
    while stack:                      # Hierholzer, directed version
        v = stack[-1]
        if out[v]:
            b = out[v].pop()          # unused edge v -> v[1:] + b
            stack.append(v[1:] + b)
        else:
            circuit.append(stack.pop())
    circuit.reverse()
    return "".join(v[-1] for v in circuit[1:])   # new bit of each edge
def is_de_bruijn(s, n):
    t = s + s[:n - 1]                 # read the string as a circle
    return len(s) == 2 ** n and len({t[i:i + n] for i in range(len(s))}) == len(s)
for n in (3, 4):
    s = de_bruijn(n)
    print(f"n={n}: {s}  every {n}-bit word once: {is_de_bruijn(s, n)}")
for n in (3, 4):                      # brute force over all 2^(2^n) strings
    L = 2 ** n
    hits = sum(is_de_bruijn("".join(p), n) for p in product("01", repeat=L))
    print(f"n={n}: {hits:3} strings, {hits // L:2} circles,"
          f" formula 2^(2^(n-1)-n) = {2 ** (2 ** (n - 1) - n)}")

আসল আউটপুট (ব্রাউজারের Python):

n=3: 01011100  every 3-bit word once: True
n=4: 0100110101111000  every 4-bit word once: True
n=3:  16 strings,  2 circles, formula 2^(2^(n-1)-n) = 2
n=4: 256 strings, 16 circles, formula 2^(2^(n-1)-n) = 16

প্রথম দুই লাইনে Euler circuit থেকে পাওয়া B(2, 3) আর B(2, 4): 01011100-কে চক্র হিসেবে পড়লে জানালাগুলো 010, 101, 011, 111, 110, 100, 000, 001, আটটিই আলাদা। পরের দুই লাইন brute force: n = 4-এ সব 216 = 65536টি string পরীক্ষা করে ২৫৬টি de Bruijn string পাওয়া গেছে। একটি de Bruijn string-এর সব জানালা আলাদা বলে তার কোনো rotation নিজের সমান নয়, তাই প্রতিটি চক্র ঠিক L = 2nটি string দেয়, আর চক্রের সংখ্যা 256/16 = 16. এটি binary de Bruijn চক্র গোনার সূত্র 22n−1−n-এর সঙ্গে মেলে, যা Euler circuit গোনার BEST উপপাদ্য থেকে আসে (নামটি de Bruijn, van Aardenne-Ehrenfest, Smith আর Tutte-এর আদ্যক্ষরে)। n = 5-এ brute force-কে 232টি string দেখতে হতো; Euler circuit সেখানেও এক মুহূর্তে উত্তর দেয়।

৫ · বাজারঘরের রাইডার — route inspection (Chinese postman)

বাস্তবের রাস্তার জাল প্রায় কখনো সব-জোড় degree-র নয়, তবু রাইডারকে প্রতিটি রাস্তায় অন্তত একবার গিয়ে গুদামে ফিরতে হয়; কিছু রাস্তা দুবার যেতেই হবে। মোট সময় সবচেয়ে কম কীভাবে? একে বলে route inspection বা Chinese postman সমস্যা; চীনা গণিতবিদ Kwan Mei-Ko (Guan Meigu) ১৯৬০-এর দশকের শুরুতে ডাকপিয়নের রুট নিয়ে এটি তোলেন বলে নামটি এসেছে।

উপপাদ্য ৫.১ (route inspection, undirected)

প্রতিটি রাস্তার দৈর্ঘ্য w(e) ≥ 0, graph connected. বিজোড় vertex-গুলোর সেট O (|O| = 2k). তাহলে প্রতিটি edge অন্তত একবার নিয়ে শুরুতে ফেরা সবচেয়ে ছোট রুটের দৈর্ঘ্য

∑e w(e) + minO-এর জোড়ায় ভাগ ∑{x, y} d(x, y)

যেখানে d(x, y) হলো x থেকে y-এর সবচেয়ে ছোট দূরত্ব, আর minimum নেওয়া হয় O-কে k-টি জোড়ায় ভাগ করার সব উপায়ের ওপর।

  1. যেকোনো এমন রুট একটি closed walk. প্রতিটি edge যতবার নেওয়া হয়েছে ততটি কপি বসালে একটি multigraph G′ হয়, যার Euler circuit-ই রুটটি; তাই G′-এর সব degree জোড়। — উপপাদ্য ২.১
  2. বাড়তি কপিগুলো দিয়ে একটি graph D বানান, যাতে G′ = G + D. G′-এর সব degree জোড়, তাই D-তে একটি vertex-এর degree বিজোড় ঠিক তখন, যখন G-তে তার degree বিজোড়: D-এর বিজোড় vertex-এর সেট ঠিক O. — parity
  3. উপপাদ্য ২.৩-এর পরের মন্তব্যটি D-এর প্রতিটি component-এ প্রয়োগ করলে D-এর ভেতরে k-টি edge-বিচ্ছিন্ন trail পাওয়া যায়, যারা O-এর বিন্দুগুলোকে জোড়ায় জোড়ে; প্রতিটি trail-এর দৈর্ঘ্য অন্তত তার দুই প্রান্তের d. তাই বাড়তি ≥ কোনো একটি জোড়ভাগের ∑d ≥ minimum. — নিম্নসীমা
  4. উল্টো দিকে, সবচেয়ে ভালো জোড়ভাগের প্রতিটি জোড়ার সবচেয়ে ছোট পথ দ্বিতীয়বার যোগ করলে সব degree জোড় হয়, আর Euler circuit ঠিক ওই দৈর্ঘ্যের রুট দেয়। ∎ — নির্মাণ

উদাহরণ: ঢাকার ছয়টি এলাকা মিরপুর (M), ফার্মগেট (F), ধানমন্ডি (D), গুলশান (G), মতিঝিল (T) আর উত্তরা (U)-এর মধ্যে ৯টি রাস্তা, মিনিটে সময় দেওয়া (সংখ্যাগুলো কাল্পনিক, শুধু উদাহরণের জন্য)। নিচের ব্লক বিজোড় vertex খোঁজে, পর্ব ৫৪-এর Warshall-এর মতো একটি লুপে (Floyd–Warshall) সব জোড়ার সবচেয়ে ছোট দূরত্ব বের করে, আর সব জোড়ভাগ পরীক্ষা করে।

from collections import Counter
roads = {("M","F"): 10, ("M","D"): 12, ("F","D"): 7, ("F","G"): 9, ("F","T"): 11,
         ("G","T"): 8, ("D","T"): 14, ("G","U"): 15, ("M","U"): 20}   # minutes
V = sorted({v for e in roads for v in e})
d = {(a, b): 0 if a == b else float("inf") for a in V for b in V}
for (a, b), w in roads.items():
    d[a, b] = d[b, a] = w
for k in V:                           # Floyd-Warshall: all shortest distances
    for a in V:
        for b in V:
            d[a, b] = min(d[a, b], d[a, k] + d[k, b])
deg = Counter(v for e in roads for v in e)
odd = [v for v in V if deg[v] % 2]
print("degrees:", dict(sorted(deg.items())), " odd:", odd)
def pairings(xs):                     # every way to split xs into pairs
    if not xs:
        yield []
        return
    for i in range(1, len(xs)):
        for rest in pairings(xs[1:i] + xs[i + 1:]):
            yield [(xs[0], xs[i])] + rest
best = None
for p in pairings(odd):
    extra = sum(d[pair] for pair in p)
    print("pair", p, "extra", extra)
    if best is None or extra < best[0]:
        best = (extra, p)
total = sum(roads.values())
print("all roads once:", total, "min extra:", best[0], "tour:", total + best[0])

আসল আউটপুট (ব্রাউজারের Python):

degrees: {'D': 3, 'F': 4, 'G': 3, 'M': 3, 'T': 3, 'U': 2}  odd: ['D', 'G', 'M', 'T']
pair [('D', 'G'), ('M', 'T')] extra 37
pair [('D', 'M'), ('G', 'T')] extra 20
pair [('D', 'T'), ('G', 'M')] extra 33
all roads once: 106 min extra: 20 tour: 126

৪টি বিজোড় vertex জোড়ায় ভাগের ৩টি উপায় (2k-টির জন্য 1 · 3 · 5 ⋯ (2k − 1)টি)। D–G-এর সবচেয়ে ছোট পথ D → F → G = 16, M–T-এর M → F → T = 21. সবচেয়ে ভালো জোড়ভাগ {D, M} আর {G, T}: ধানমন্ডি–মিরপুর (12) আর গুলশান–মতিঝিল (8) রাস্তা দুটি দুবার নিলে সব degree জোড় হয়। তাই রাইডারের সবচেয়ে ছোট রুট 106 + 20 = 126 মিনিট, আর তার একটি Euler circuit Hierholzer দিয়ে বানানো যায়। বিজোড় vertex বেশি হলে সব জোড়ভাগ দেখা অসম্ভব হয়ে পড়ে (২০টি বিজোড়ে প্রায় ৬৫ কোটি জোড়ভাগ); তখন minimum-weight perfect matching-এর polynomial algorithm লাগে, যার মূল ভাবনা পর্ব ৬৪ “Matching — bipartite graph, Hall-এর উপপাদ্য আর stable matching”-এ আসবে।

৬ · Hamilton path আর cycle — কেন কোনো সহজ শর্ত নেই

এবার দ্বিতীয় রাইডার: প্রতিটি মোড়ে ঠিক একবার, রাস্তা যতবার লাগুক তাতে আপত্তি নেই, শুধু কোনো মোড়ে দ্বিতীয়বার নয়। নামটি এসেছে William Rowan Hamilton-এর ১৮৫৭ সালের দিকের “Icosian game” থেকে: একটি dodecahedron-এর ২০টি কোণ ঠিক একবার ছুঁয়ে ফিরে আসা। Thomas Kirkman প্রায় একই সময়ে এমন cycle নিয়ে লিখেছিলেন বলেও উল্লেখ পাওয়া যায়।

Euler-এর শর্তটি স্থানীয়: প্রতিটি vertex আলাদা করে পরীক্ষা করা যায়। Hamilton-এর জন্য এমন শর্ত জানা নেই। আমরা জানি কিছু আবশ্যিক শর্ত (ভাঙলে cycle নেই) আর কিছু যথেষ্ট শর্ত (থাকলে cycle আছে); মাঝখানের বিরাট অঞ্চলে খুঁজতেই হয়।

উপপাদ্য ৬.১ (আবশ্যিক শর্ত)

G একটি simple graph, n ≥ 3, আর G-তে একটি Hamilton cycle আছে। তাহলে:
(ক) G connected, আর প্রতিটি vertex-এর degree ≥ 2.
(খ) যেকোনো k ≥ 1টি vertex মুছলে বাকি graph-এ component সর্বোচ্চ kটি। বিশেষত G-তে কোনো cut vertex নেই।
(গ) G bipartite হলে, দুই দিক X আর Y-এর আকার সমান: |X| = |Y|.

  1. (ক) cycle সব vertex-কে একটি বন্ধ পথে বাঁধে, তাই যেকোনো দুটি যুক্ত; আর cycle-এ প্রতিটি vertex-এর দুটি প্রতিবেশী। — সংজ্ঞা
  2. (খ) একটি cycle থেকে k-টি vertex মুছলে cycle-টি সর্বোচ্চ k-টি টুকরো path-এ ভাঙে (বৃত্তকে k জায়গায় কাটলে সর্বোচ্চ k টুকরো)। প্রতিটি টুকরো connected, আর graph-এর বাকি edge শুধু টুকরোগুলোকে আরও জুড়তে পারে। তাই component ≤ k. k = 1-এ: একটি vertex মুছলে graph connected থাকে। — টুকরো গোনা
  3. (গ) bipartite graph-এর প্রতিটি edge X আর Y-এর মধ্যে, তাই cycle ধরে হাঁটলে X, Y, X, Y, … পালাক্রমে আসে, আর শুরুতে ফিরতে হলে দৈর্ঘ্য জোড়, X আর Y থেকে সমান সংখ্যক vertex. Hamilton cycle সব vertex নেয়, তাই |X| = |Y|. ∎ — পালাক্রম

(গ)-এর একই যুক্তিতে Hamilton path-এর জন্য ||X| − |Y|| ≤ 1 লাগে, কারণ path-এ X আর Y পালাক্রমে আসে কিন্তু শুরু-শেষ মিলতে হয় না। নিচের stepper এই যুক্তিটি বাজারঘরের ৩ × ৩ গুদাম-গ্রিডে চালায়।

The 3 by 3 grid graph with a bipartite colouring: five blue and four white vertices, so no Hamilton cycle, but a snake-shaped Hamilton path 012 345 678
৯টি গুদাম, ১২টি পথ
নীল X
সাদা Y
দাবি
  1. প্রশ্ন। ৩ × ৩ গ্রিডের ৯টি গুদাম, পাশাপাশি দুটির মধ্যে পথ (মোট ১২টি)। একজন পরিদর্শক কি প্রতিটি গুদামে ঠিক একবার গিয়ে শুরুর গুদামে ফিরতে পারেন?
  2. দুই রঙে ভাগ। দাবার বোর্ডের মতো রং করুন: সারি + কলাম জোড় হলে নীল (0, 2, 4, 6, 8), বিজোড় হলে সাদা (1, 3, 5, 7). প্রতিটি পথ পাশাপাশি দুটি ঘর জোড়ে, যাদের রং আলাদা: graph-টি bipartite.
  3. পালাক্রম। যেকোনো cycle-এ রং পালাক্রমে আসে: নীল, সাদা, নীল, সাদা, …. শুরুর রঙে ফিরতে হলে cycle-এ নীল আর সাদা সমান সংখ্যক।
  4. বিরোধ। Hamilton cycle সব ৯টি vertex নেবে: ৫টি নীল আর ৪টি সাদা। সমান নয় (আর ৯ বিজোড়), তাই কোনো Hamilton cycle নেই। উপপাদ্য ৬.১(গ) কাজ করল, একটি cycle-ও না খুঁজে।
  5. Path-এর প্রশ্ন। path-এ শুরু-শেষ মিলতে হয় না, তাই রঙের পার্থক্য ১ চলে: নীল দিয়ে শুরু আর নীল দিয়ে শেষ হলে ৫ নীল, ৪ সাদা। তাই রঙের যুক্তি path-কে নিষেধ করে না।
  6. Path আছে। সাপের মতো পথ 0 1 2 5 4 3 6 7 8 প্রতিটি গুদাম একবার ছোঁয়, নীলে শুরু, নীলে শেষ। scratch-এ সব ক্রম পরীক্ষা করে এমন path মোট ২০টি পাওয়া গেছে (দুই দিক একই ধরে), আর cycle ০টি।

Petersen graph. ১০টি vertex, ১৫টি edge: বাইরের একটি পাঁচভুজ, ভেতরের একটি পাঁচকোণা তারা, আর বাইরের প্রতিটি কোণ থেকে ভেতরের একটি কোণে একটি করে “স্পোক”। প্রতিটি vertex-এর degree 3, কোনো cut vertex নেই, bipartite-ও নয়, তবু এতে কোনো Hamilton cycle নেই; অথচ যেকোনো একটি vertex মুছলে বাকিটায় Hamilton cycle আছে। এটি একটি সুপরিচিত ফল, যার হাতে-লেখা প্রমাণ কয়েকটি ক্ষেত্রে ভাগ করে করা হয়; এখানে আমরা নিচের ব্লকে সব সম্ভাবনা খুঁজে যাচাই করব। Julius Petersen ১৮৯৮ সালে এটি একটি পাল্টা-উদাহরণ হিসেবে ব্যবহার করেন বলে জানা যায়। Petersen graph গ্রাফ তত্ত্বের অনেক অনুমানের পাল্টা-উদাহরণ; পর্ব ৫৮ “গ্রাফের representation আর isomorphism”-এও এটি আসবে।

Gray code আর hypercube. Hypercube Qn-এর vertex সব n-বিট string, আর এক বিটে আলাদা দুটি string-এর মধ্যে edge. পর্ব ৩৬-এর চক্রাকার Gray code ঠিক Qn-এর একটি Hamilton cycle (n ≥ 2): 000, 001, 011, 010, 110, 111, 101, 100, আবার 000. Reflected নির্মাণটিই induction-এ প্রমাণ যে প্রতিটি Qn (n ≥ 2) Hamiltonian. অন্যদিকে Qn-এর প্রতিটি degree n, তাই Qn-এ Euler circuit আছে ঠিক তখন, যখন n জোড়।

দাবার ঘোড়া। Knight's tour মানে ঘোড়ার চাল দিয়ে বোর্ডের প্রতিটি ঘরে ঠিক একবার যাওয়া: ঘর = vertex, ঘোড়ার চাল = edge ধরলে এটি একটি Hamilton path (শুরুতে ফিরলে cycle); 8 × 8 বোর্ডে বন্ধ tour আছে। ঘোড়া প্রতিবার রং বদলায় বলে graph-টি bipartite, তাই উপপাদ্য ৬.১(গ) অনুযায়ী বিজোড় সংখ্যক ঘরের বোর্ডে (যেমন 5 × 5) বন্ধ tour অসম্ভব।

৭ · Dirac আর Ore-এর উপপাদ্য — যথেষ্ট শর্ত

শুধু “মোট edge বেশি” যথেষ্ট নয়: Kn−1-এর সঙ্গে একটি ঝুলন্ত vertex জুড়লে প্রায় সব edge আছে, তবু degree 1-এর vertex-এর জন্য cycle নেই। প্রতিটি vertex-এর নিজের degree বড় হওয়া চাই।

উপপাদ্য ৭.১ (Ore, ১৯৬০) আর অনুসিদ্ধান্ত ৭.২ (Dirac, ১৯৫২)

Ore: G একটি simple graph, n ≥ 3, আর প্রতিটি অসংলগ্ন জোড়া u, v-এর জন্য deg(u) + deg(v) ≥ n. তাহলে G-তে Hamilton cycle আছে।

Dirac: G simple, n ≥ 3, আর সবচেয়ে ছোট degree δ(G) ≥ n/2. তাহলে G-তে Hamilton cycle আছে।

Dirac সরাসরি Ore থেকে আসে: δ ≥ n/2 হলে যেকোনো দুটি vertex-এর degree-র যোগফল ≥ n/2 + n/2 = n. তাই শুধু Ore প্রমাণ করলেই হয়। প্রমাণের হৃদয় একটি “ক্রসিং edge” যুক্তি, যা আগে নিচের stepper-এ একটি ৮-vertex উদাহরণে দেখুন।

Ore's crossing-edge argument on an eight-vertex Hamilton path from u to v 1234 5678 uv
n = 8, path v1 … v8, u = v1, v = v8
S
T
গোনা
  1. অবস্থা। ধরুন একটি Hamilton path আছে v1 → v2 → ⋯ → v8, কিন্তু দুই প্রান্ত u = v1 আর v = v8 সংলগ্ন নয়, তাই path-টি সরাসরি বন্ধ করা যায় না। লক্ষ্য: path-টি ঘুরিয়ে একটি cycle বানানো।
  2. u-এর প্রতিবেশী। u-এর প্রতিবেশী v2, v4, v6, v7 (deg u = 4). প্রতিটি প্রতিবেশী v(i+1)-এর জন্য সূচক i লিখুন: S = {1, 3, 5, 6}. S-এর সব সংখ্যা 1 থেকে 7-এর মধ্যে।
  3. v-এর প্রতিবেশী। v-এর প্রতিবেশী v2, v3, v5, v7 (deg v = 4). প্রতিটি প্রতিবেশী v(i)-এর সূচক লিখুন: T = {2, 3, 5, 7}. T-ও 1 থেকে 7-এর মধ্যে।
  4. Pigeonhole. |S| + |T| = 4 + 4 = 8 = n, কিন্তু সম্ভাব্য সূচক মাত্র ৭টি (1 থেকে 7). তাই অন্তত একটি সূচক দুটিতেই আছে (পর্ব ৩২): S ∩ T = {3, 5}.
  5. ক্রসিং edge. i = 3 নিন: u ~ v4 (কারণ 3 ∈ S) আর v ~ v3 (কারণ 3 ∈ T). path-এর v3–v4 edge-টি বাদ দিয়ে এই দুটি edge যোগ করুন। ছবিতে সবুজ দুটি বাঁকা রেখা একে অন্যকে “ক্রস” করে।
  6. Cycle. নতুন ক্রম: v1 → v4 → v5 → v6 → v7 → v8 → v3 → v2 → v1. প্রতিটি vertex একবার, সব edge graph-এ আছে: একটি Hamilton cycle. i = 5 নিলেও একটি cycle আসে: 1 6 7 8 5 4 3 2 1 (দুটিই scratch-এ যাচাই করা)।

Ore-এর উপপাদ্য ৭.১-এর প্রমাণ। বিরোধ দিয়ে (proof by contradiction).

  1. ধরুন এমন একটি G আছে যা শর্ত মানে, কিন্তু Hamiltonian নয়। G-তে নতুন edge একটি একটি করে যোগ করুন, যতক্ষণ graph Hamiltonian না হয়। শেষে পাওয়া যায় একটি H ⊇ G, যা Hamiltonian নয়, কিন্তু যেকোনো একটি নতুন edge যোগ করলেই Hamiltonian হয়। — Kn Hamiltonian বলে প্রক্রিয়াটি Kn-এর আগে থামে
  2. edge যোগ করলে degree কমে না, আর অসংলগ্ন জোড়া কমে; তাই H-ও Ore-এর শর্ত মানে। H ≠ Kn, তাই H-এ অসংলগ্ন u, v আছে। — degree একঘেয়েভাবে বাড়ে
  3. H + uv Hamiltonian, আর তার যেকোনো Hamilton cycle অবশ্যই uv ব্যবহার করে (না হলে H নিজেই Hamiltonian হতো)। cycle থেকে uv বাদ দিলে H-এ একটি Hamilton path u = v1, v2, …, vn = v. — H-এর গঠন
  4. S = {i : 1 ≤ i ≤ n − 1, u ~ vi+1} আর T = {i : 1 ≤ i ≤ n − 1, v ~ vi} নিন। u-এর প্রতিটি প্রতিবেশী v2, …, vn−1-এর মধ্যে (vn = v নয়), তাই |S| = deg(u); একইভাবে |T| = deg(v). — সংজ্ঞা
  5. |S| + |T| = deg(u) + deg(v) ≥ n, কিন্তু S ∪ T ⊆ {1, …, n − 1}, যেখানে মাত্র n − 1টি সংখ্যা। তাই কোনো i ∈ S ∩ T আছে। — pigeonhole
  6. এই i-তে u ~ vi+1 আর v ~ vi. তাহলে v1, vi+1, vi+2, …, vn, vi, vi−1, …, v2, v1 একটি Hamilton cycle, যা H-এর edge দিয়েই তৈরি। কিন্তু H Hamiltonian নয়: বিরোধ। তাই G Hamiltonian. ∎ — stepper-এর ধাপ ৬

শর্তগুলো প্রায় নিখুঁত। Dirac-এর n/2-কে কমানো যায় না: Kk,k+1-এ n = 2k + 1, δ = k = (n − 1)/2, কিন্তু দুই দিক অসমান বলে উপপাদ্য ৬.১(গ) অনুযায়ী Hamilton cycle নেই। আবার শর্তগুলো শুধু যথেষ্ট, আবশ্যিক নয়: C6 নিজেই একটি Hamilton cycle, অথচ এর প্রতিটি degree 2 < 3 = n/2. নিচের ব্লক একটি backtracking অনুসন্ধানে (backtracking, DSA কোর্সের পর্ব ৫৬) এসব দাবি পরীক্ষা করে।

import random
from itertools import combinations
def ham_cycle(adj):                   # backtracking from vertex 0
    n, path, seen = len(adj), [0], {0}
    def extend():
        if len(path) == n:
            return path[0] in adj[path[-1]]
        for w in sorted(adj[path[-1]] - seen):
            path.append(w); seen.add(w)
            if extend(): return True
            path.pop(); seen.discard(w)
        return False
    return path + [0] if extend() else None
def ore(adj):                         # deg u + deg v >= n for non-adjacent u, v
    return all(len(adj[u]) + len(adj[v]) >= len(adj)
               for u, v in combinations(adj, 2) if v not in adj[u])
petersen = {i: set() for i in range(10)}
for i in range(5):                    # outer 5-cycle, spokes, inner star
    for u, v in ((i, (i + 1) % 5), (i, i + 5), (i + 5, (i + 2) % 5 + 5)):
        petersen[u].add(v); petersen[v].add(u)
grid = {i: {j for j in range(9) if abs(i // 3 - j // 3) + abs(i % 3 - j % 3) == 1}
        for i in range(9)}            # 3x3 grid, vertex 3*row + col
cube = {i: {i ^ 1, i ^ 2, i ^ 4} for i in range(8)}
for name, g in (("Petersen", petersen), ("3x3 grid", grid), ("Q3", cube)):
    print(f"{name}: Ore {ore(g)}, Hamilton cycle {ham_cycle(g)}")
random.seed(60); n_ore = n_ham = ham_not_ore = 0
for _ in range(2000):
    n, p = random.randint(5, 8), random.choice((0.4, 0.6, 0.8))
    g = {i: set() for i in range(n)}
    for u, v in combinations(range(n), 2):
        if random.random() < p: g[u].add(v); g[v].add(u)
    h, o = ham_cycle(g) is not None, ore(g)
    assert h or not o                 # Ore's theorem: Ore => Hamiltonian
    n_ore += o; n_ham += h; ham_not_ore += h and not o
print("Ore:", n_ore, " Hamiltonian:", n_ham, " Hamiltonian, not Ore:", ham_not_ore)

আসল আউটপুট (ব্রাউজারের Python):

Petersen: Ore False, Hamilton cycle None
3x3 grid: Ore False, Hamilton cycle None
Q3: Ore False, Hamilton cycle [0, 1, 3, 2, 6, 7, 5, 4, 0]
Ore: 667  Hamiltonian: 1165  Hamiltonian, not Ore: 498

Petersen graph-এ backtracking সব সম্ভাবনা শেষ করে কোনো cycle পায়নি, আর গ্রিড stepper-এর সিদ্ধান্ত মেলে। Q3-এর cycle 0, 1, 3, 2, 6, 7, 5, 4 binary-তে 000, 001, 011, 010, 110, 111, 101, 100: ঠিক reflected Gray code. তিনটি graph-ই Ore-এর শর্ত মানে না (Petersen আর Q3-এ degree 3 কিন্তু n = 10 আর 8; গ্রিডে দুই বিপরীত কোণের degree 2 + 2 < 9), অথচ Q3 Hamiltonian: শর্তটি আবশ্যিক নয়। শেষ লাইনে ২০০০টি এলোমেলো graph: ৬৬৭টি Ore মেনেছে, আর assert কখনো ব্যর্থ হয়নি, অর্থাৎ প্রতিটি Ore-graph Hamiltonian ছিল। কিন্তু ৪৯৮টি graph Ore না মেনেও Hamiltonian; শর্তটি অনেক Hamiltonian graph ধরতে পারে না।

৮ · NP-completeness — Euler সহজ, Hamilton কঠিন

“Euler circuit আছে?” — degree আর connectedness দেখুন, O(n + m) সময়ে উত্তর। “Hamilton cycle আছে?” — সব graph-এ polynomial সময়ে উত্তর দেয় এমন কোনো algorithm জানা নেই। এটি শুধু আমাদের অজ্ঞতা কি না, সেটিই P বনাম NP প্রশ্ন।

তথ্য ৮.১ (প্রমাণ এই কোর্সে নয়)

HAMILTON CYCLE (একটি simple graph-এ Hamilton cycle আছে কি না) সমস্যাটি NP-complete. Richard Karp ১৯৭২ সালের প্রবন্ধে ২১টি সমস্যাকে NP-complete দেখান, আর directed ও undirected Hamilton cycle সেই তালিকায় ছিল বলে জানা যায়। এর মানে: (১) একটি প্রস্তাবিত cycle দ্রুত যাচাই করা যায় (NP-তে আছে); (২) NP-এর যেকোনো সমস্যা polynomial সময়ে এই সমস্যায় রূপান্তর করা যায় (polynomial-time reduction দিয়ে)। তাই HAMILTON CYCLE-এর polynomial algorithm পেলে P = NP হয়ে যেত।

যাচাই আর খোঁজার এই পার্থক্যই মূল কথা। কেউ একটি ক্রম দিলে আপনি n ধাপে দেখে নিতে পারেন প্রতিটি vertex একবার এসেছে কি না, আর পরপর দুটি সংলগ্ন কি না। কিন্তু নিজে খুঁজতে গেলে সম্ভাব্য ক্রম Kn-এ (n − 1)!/2টি (পর্ব ৩৩-এর circular permutation): n = 20-এ প্রায় ৬ × ১০16. Backtracking শাখা কাটে, কিন্তু খারাপ ক্ষেত্রে তাও exponential; সবচেয়ে ভালো জানা সঠিক algorithm-ও exponential, যেমন dynamic programming-এ O(n2 2n) (Bellman, Held–Karp, ১৯৬২-এর দিকে)। NP-completeness-এর পূর্ণ তত্ত্ব DSA কোর্সের পর্ব ৬৪ “P বনাম NP — NP-complete আর reduction”-এ আছে, আর এমন সমস্যা বাস্তবে কীভাবে সামলানো হয় তা পর্ব ৬৫-এ।

Euler সহজ কেন? Lemma ২.২ নিশ্চয়তা দেয় যে ভুল পথে গেলেও কিছু হারায় না, পরে splice করে ঠিক করা যায়। Hamilton-এ একটি ভুল সিদ্ধান্ত পরে শোধরানো যায় না, কারণ ছোঁয়া vertex-এ আর ফেরা নিষেধ।

Traveling salesperson-এর পূর্বাভাস। Hamilton cycle-এর ওজনযুক্ত রূপ: প্রতিটি শহর জোড়ার দূরত্ব দেওয়া, সবচেয়ে ছোট Hamilton cycle (tour) কোনটি? এটিই traveling salesperson problem (TSP), আর এটি অন্তত HAMILTON CYCLE-এর সমান কঠিন (NP-hard): একটি graph G থেকে Kn বানান যেখানে G-এর edge-এর দৈর্ঘ্য 1 আর বাকিগুলোর 2; G Hamiltonian ⇔ দৈর্ঘ্য n-এর একটি tour আছে। পর্ব ৬১ “Shortest path-এর গণিত — Dijkstra-র প্রমাণ আর traveling salesperson”-এ TSP-এর brute force আর heuristic আসবে। Route inspection (§৫) সব edge ঢাকে আর polynomial; TSP সব vertex ঢাকে আর NP-hard: Euler বনাম Hamilton-এর একই বিভাজন।

৯ · পরীক্ষার অঙ্ক আর একটি ভুল প্রমাণ

অঙ্ক ১: কোন পরিচিত graph-এ Euler circuit বা trail

  • Kn (n ≥ 3): প্রতিটি degree n − 1. Euler circuit ⇔ n বিজোড়। K4-এ চারটি vertex-ই বিজোড় (degree 3), তাই trail-ও নেই।
  • Km,n: একদিকের degree n, অন্যদিকের m. Euler circuit ⇔ m আর n দুটিই জোড়। K2,3-এ ২-দিকের দুটি vertex-এর degree 3, বাকি তিনটির 2: ঠিক দুটি বিজোড়, তাই Euler trail আছে, circuit নেই।
  • Qn: প্রতিটি degree n, connected: Euler circuit ⇔ n জোড়। Q4-এ আছে, Q3-এ নেই (৮টি বিজোড় vertex, তাই অন্তত ৪টি trail লাগে)।

অঙ্ক ২: Hamilton cycle গোনা

K6-এ কয়টি আলাদা Hamilton cycle? আর K3,3-এ? (cycle-কে edge-এর সেট হিসেবে ধরুন, তাই শুরু আর দিক গুরুত্বহীন।)

  1. Kn: vertex 1 থেকে শুরু ধরে বাকি n − 1টির যেকোনো ক্রম একটি cycle, (n − 1)!টি; প্রতিটি cycle দুই দিকে পড়া যায়, তাই (n − 1)!/2. n = 6-এ 120/2 = 60.
  2. Kn,n: X-এর একটি নির্দিষ্ট vertex থেকে শুরু; X-এর বাকি n − 1টি (n − 1)! ক্রমে, Y-এর n-টি n! ক্রমে পালাক্রমে বসে; দিকের জন্য ২ দিয়ে ভাগ: n!(n − 1)!/2. n = 3-এ 6 · 2/2 = 6; n = 4-এ 72 (তিনটিই scratch-এ সব ক্রম গুনে মেলানো)।

অঙ্ক ৩: গ্রিডে Hamilton cycle

m × n গ্রিড graph (m, n ≥ 2)-এ Hamilton cycle কখন আছে? উত্তর: ঠিক তখন, যখন mn জোড়। mn বিজোড় হলে রঙের দুই দলের আকার (mn + 1)/2 আর (mn − 1)/2, অসমান: উপপাদ্য ৬.১(গ)। mn জোড় হলে (ধরুন m জোড়) প্রথম কলাম বাদ রেখে সারিগুলো সাপের মতো ঘুরে প্রথম কলাম ধরে শুরুতে ফেরা যায়। scratch-এর backtracking 3 × 4-এ একটি cycle পেয়েছে, 3 × 3, 3 × 5, 5 × 5-এ কোনোটি নয়।

প্রমাণের ভুল ধরুন: “degree ≥ 2 হলেই Hamiltonian”

একজন লিখলেন: “দাবি: n ≥ 3 vertex-এর প্রতিটি connected simple graph, যার প্রতিটি degree ≥ 2, Hamiltonian. প্রমাণ n-এর ওপর induction. n = 3: একমাত্র এমন graph হলো ত্রিভুজ, যা নিজেই Hamilton cycle. ধাপ: n vertex-এর এমন একটি graph-এর Hamilton cycle v1, …, vn নিন, আর একটি নতুন vertex w যোগ করুন যা cycle-এর পাশাপাশি দুটি vertex vi, vi+1-এর সঙ্গে যুক্ত। তাহলে vi, w, vi+1 ঢুকিয়ে n + 1 vertex-এর cycle পাওয়া যায়। ∎”

ভুল কোথায়: ধাপটি একটি নির্দিষ্ট ধরনের (n + 1)-vertex graph বানায়, কিন্তু দাবিটি সব (n + 1)-vertex graph নিয়ে, আর সবাইকে এভাবে বানানো যায় না। সঠিক ধাপ শুরু হয় যেকোনো (n + 1)-vertex graph থেকে, তারপর একটি vertex সরিয়ে hypothesis প্রয়োগ (“build-up” ভুল)। পাল্টা-উদাহরণ: দুটি ত্রিভুজ একটি vertex-এ জোড়া (“bow-tie”, ৫টি vertex নিয়ে)। connected, প্রতিটি degree ≥ 2, কিন্তু মাঝের vertex একটি cut vertex, তাই উপপাদ্য ৬.১(খ) অনুযায়ী Hamilton cycle নেই (scratch-এর backtracking-ও কিছু পায়নি)। ভুল প্রমাণ এমন graph কখনো “বানায়” না, তাই এটিকে ছুঁয়েও দেখেনি।

আরও গভীরে: Ore-এর প্রমাণের ভাবনা থেকে Bondy আর Chvátal ১৯৭৬ সালের দিকে “closure”-এর ধারণা দেন: deg(u) + deg(v) ≥ n এমন প্রতিটি অসংলগ্ন জোড়ায় বারবার edge যোগ করুন; মূল graph Hamiltonian যদি এবং কেবল যদি closure Hamiltonian. Chvátal–Erdős শর্ত (connectivity ≥ independence number) আরেকটি শক্তিশালী যথেষ্ট শর্ত। খোলা প্রশ্নও আছে: Lovász-এর একটি অনুমান (১৯৬৯-এর দিকে) বলে প্রতিটি connected vertex-transitive graph-এ Hamilton path আছে, যা এখনো প্রমাণ বা খণ্ডন হয়নি বলে জানা যায়; Petersen graph দেখায় যে “path”-এর জায়গায় “cycle” বললে তা মিথ্যা।

পরীক্ষা ও ইন্টারভিউতে: বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন প্রায়ই আসে:

  • কোনো ছবি কলম না তুলে আঁকা যায় কি না কীভাবে বুঝবেন? connected আর বিজোড় বিন্দু ০টি বা ২টি হলে যায়; ২টি হলে একটি থেকে শুরু, অন্যটিতে শেষ।
  • Kn-এ Euler circuit কখন? n বিজোড় হলে, কারণ degree n − 1 জোড় হতে হয়।
  • K3,4-এ Hamilton cycle আছে? না; bipartite graph-এর দুই দিক অসমান।
  • Dirac আর Ore-এর শর্ত কি আবশ্যিক? না, শুধু যথেষ্ট; Cn (n ≥ 5) Hamiltonian কিন্তু শর্ত মানে না।
  • Euler circuit আর Hamilton cycle খোঁজার জটিলতা? প্রথমটি O(n + m); দ্বিতীয়টির সিদ্ধান্ত-সমস্যা NP-complete.

১০ · AI-এর যুগে — Euler আর Hamilton-এর দাবি যাচাই

Graph-এর প্রশ্নে AI সহকারী প্রায়ই Euler আর Hamilton গুলিয়ে ফেলে। নিয়মিত ভুল আর ধরার উপায়:

AI-এর ভুলকীভাবে ধরবেন
“সব degree জোড়, তাই Hamilton cycle আছে” ধরনের মিশ্রণপ্রশ্নটি edge নিয়ে না vertex নিয়ে, আলাদা করে লিখুন; bow-tie দিয়ে পরীক্ষা করুন
উপপাদ্য ২.১ বলার সময় “connected” শর্ত বাদ দেওয়াদুটি আলাদা ত্রিভুজ: সব degree জোড়, কিন্তু circuit নেই
Dirac বা Ore-কে “যদি এবং কেবল যদি” হিসেবে বলাC6 বা Q3-এ শর্ত ভাঙে, অথচ cycle আছে
“আটকে গেলে সব edge শেষ” বলে Euler-এর প্রমাণ শেষ করাশুরুর vertex-এর edge শেষ মানেই সব শেষ নয়: অনুশীলন ৪
Hamilton cycle গুনতে n! বা (n − 1)! বলাK4-এ হাতে গুনুন: ৩টি, যা (4 − 1)!/2

AI-এর কাছে graph-এর প্রমাণ বা উত্তর চাইলে এমন কাঠামো দিন, যাতে প্রতিটি দাবি যাচাই করা যায়:

নিচের graph-টি নিয়ে ধাপে ধাপে উত্তর দাও: Graph: [যেমন edge-এর তালিকা: (A,B), (B,C), (C,A), (C,D), (D,E), (E,C)] ১. প্রথমে বলো graph-টি simple, multigraph না directed; loop থাকলে degree-তে কত গুনেছ। ২. প্রতিটি vertex-এর degree-র একটি সারণি দাও, আর যোগফল 2m কি না মিলিয়ে দেখাও। ৩. Euler circuit/trail-এর প্রশ্নে যে উপপাদ্য ব্যবহার করছ তার সব শর্ত (connected সহ) লেখো, তারপর একটি সত্যিকারের circuit বা trail ক্রম হিসেবে দাও। ৪. Hamilton cycle দাবি করলে পুরো ক্রমটি দাও; না থাকলে কোন আবশ্যিক শর্ত ভাঙে (cut vertex, bipartite অসমতা) তা প্রমাণসহ বলো, শুধু "খুঁজে পাইনি" নয়। ৫. আমি নিজে চালাতে পারি এমন একটি ছোট Python কোড দাও (শুধু standard library), যা তোমার দেওয়া ক্রমটি যাচাই করে।

AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট

যেকোনো দাবি করা circuit বা cycle এক লাইনের কোডে যাচাই হয়, আর ছোট graph-এ “নেই” দাবিও backtracking দিয়ে মেলানো যায়; ভুল প্রমাণ সাধারণত bow-tie, Petersen বা দুটি আলাদা ত্রিভুজেই ধরা পড়ে।

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

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।

প্র ০১Euler-এর Königsberg প্রবন্ধে আসলে কী ছিল, আর একটি শহরের ধাঁধা কীভাবে একটি নতুন গণিতের সূচনা হলো?

Euler তাঁর প্রবন্ধে প্রশ্নটিকে “অবস্থানের জ্যামিতি” (geometria situs) নামে একটি বিষয়ের উদাহরণ হিসেবে দেখেন বলে জানা যায়, যে নাম Leibniz আগে ব্যবহার করেছিলেন: দূরত্ব বা কোণ নয়, শুধু কোন জিনিস কোনটির সঙ্গে যুক্ত। আজ একে graph theory আর topology-র পূর্বসূরি বলা হয়। মজার ব্যাপার, প্রবন্ধে কোনো আঁকা graph ছিল না বলে উল্লেখ করা হয়; Euler ভূখণ্ডগুলোকে অক্ষর দিয়ে চিহ্নিত করে সেতু পার হওয়ার ক্রমকে অক্ষরের ক্রম হিসেবে লেখেন। বিন্দু আর রেখার ছবি পরে প্রচলিত হয়।

Euler স্পষ্টভাবে আবশ্যিক শর্তটি দেন: বিজোড় সংখ্যক সেতুর ভূখণ্ড দুটির বেশি হলে হাঁটা অসম্ভব। বিজোড় ভূখণ্ড ০টি বা ২টি হলে হাঁটা সম্ভব, এটিও তিনি বলেন, কিন্তু ইতিহাসবিদদের সাধারণ মত হলো এই দিকের পূর্ণ প্রমাণ তাঁর লেখায় ছিল না। প্রথম প্রকাশিত পূর্ণ প্রমাণ Carl Hierholzer-এর, ১৮৭৩ সালে, তাঁর মৃত্যুর পর প্রকাশিত। §২-এর induction আর §৩-এর algorithm মূলত তাঁরই ভাবনা।

দ্বিতীয় বিশ্বযুদ্ধে Königsberg-এর বড় অংশ ধ্বংস হয়, পরে শহরটি Kaliningrad নাম পায়, আর পুরোনো সেতুর কয়েকটি আর নেই বলে বিভিন্ন সূত্রে উল্লেখ আছে; সেতুর বিন্যাস বদলালে প্রশ্নের উত্তরও বদলায়। আসল শিক্ষা বিমূর্তকরণ: প্রশ্নটি একটি শহরের, কিন্তু উত্তরটি প্রতিটি নেটওয়ার্কের, যেমন বাজারঘরের ডেলিভারি রুট বা রাস্তা ঝাড়ু দেওয়ার গাড়ি। একটি ভালো মডেল অপ্রাসঙ্গিক সব বাদ দিয়ে শুধু গঠনটুকু রাখে, আর তখন একটি সমস্যার উত্তর হাজার সমস্যার উত্তর হয়ে যায়।

মূল উপলব্ধি: Königsberg-এর উত্তর একটি parity যুক্তি, কিন্তু আসল অবদান বিমূর্তকরণ; আর Euler-এর “যথেষ্ট” দিকের পূর্ণ প্রমাণ এসেছিল প্রায় দেড়শো বছর পরে।

প্র ০২Euler circuit-এর জন্য সহজ শর্ত আছে, Hamilton cycle-এর জন্য নেই। এই পার্থক্যকে কীভাবে নির্ভুলভাবে বলা যায়, আর এতে P বনাম NP কোথা থেকে আসে?

“সহজ শর্ত নেই” কথাটির একটি নির্ভুল রূপ আছে: certificate. Euler-এর ক্ষেত্রে দুই দিকেরই ছোট প্রমাণ আছে: circuit থাকলে circuit-টি নিজেই প্রমাণ; না থাকলে একটি বিজোড় vertex বা একটি বিচ্ছিন্ন অংশ। দুটিই দ্রুত যাচাই হয়। Hamilton-এ “আছে” দিকের certificate সহজ (cycle-টি দেখান), কিন্তু “নেই” দিকের জন্য সাধারণভাবে ছোট, দ্রুত যাচাইযোগ্য প্রমাণ আছে কি না জানা নেই। থাকলে NP = co-NP হতো, যা বেশির ভাগ বিশেষজ্ঞ সত্য মনে করেন না।

Stephen Cook ১৯৭১ সালে প্রথম একটি সমস্যাকে (SAT) NP-complete প্রমাণ করেন, আর Leonid Levin প্রায় একই সময়ে স্বাধীনভাবে একই ধরনের ফল পান বলে জানা যায়। পরের বছর Richard Karp reduction দিয়ে দেখান যে Hamilton cycle, clique আর graph coloring-এর মতো graph-এর অনেক স্বাভাবিক প্রশ্ন একই রকম কঠিন।

ব্যবহারিক অর্থ কৌশল বদলানো। ছোট n-এ backtracking বা O(n22n) dynamic programming চলে; বিশেষ শ্রেণির graph-এ নিশ্চিত উত্তর আছে, আর Ore-এর প্রমাণ আসলে একটি polynomial algorithm দেয়, যা Hamilton path থেকে ক্রসিং edge দিয়ে cycle বানায়; বড় বাস্তব সমস্যায় heuristic আর SAT solver ব্যবহার হয়। মনে রাখুন, “polynomial algorithm জানা নেই” আর “নেই” এক নয়: P ≠ NP আজও অপ্রমাণিত, আর Clay Mathematics Institute এটিকে সাতটি Millennium সমস্যার একটি হিসেবে ঘোষণা করেছে।

মূল উপলব্ধি: Euler-এর প্রশ্নে “আছে” আর “নেই” দুই দিকেরই ছোট, দ্রুত যাচাইযোগ্য প্রমাণ আছে; Hamilton-এর “নেই” দিকে তা জানা নেই, আর সেখানেই NP-completeness-এর কঠিনতা লুকিয়ে।

প্র ০৩de Bruijn sequence আর de Bruijn graph বাস্তবে কোথায় কাজে লাগে? DNA পড়ার সঙ্গে Euler path-এর কী সম্পর্ক?

Nicolaas Govert de Bruijn ১৯৪৬ সালে এই sequence গোনার ওপর একটি প্রবন্ধ প্রকাশ করেন, কিন্তু পরে জানা যায় C. Flye Sainte-Marie ১৮৯৪ সালেই binary ক্ষেত্রের সংখ্যা 22n−1−n বের করেছিলেন। সূত্রটি directed graph-এর Euler circuit গোনার BEST উপপাদ্যের একটি বিশেষ ক্ষেত্র।

প্রয়োগগুলো সরল কিন্তু চতুর। একটি ঘূর্ণায়মান চাকার গায়ে de Bruijn sequence খোদাই করলে মাত্র n-টি সেন্সর পরপর n-টি বিট পড়ে চাকার অবস্থান বলতে পারে, কারণ প্রতিটি n-বিট জানালা একবারই আসে। কিছু structured-light 3D scanner প্রক্ষিপ্ত রঙিন ডোরায় এমন ধারা ব্যবহার করে, যাতে ক্যামেরা প্রতিটি ডোরা চিনতে পারে।

সবচেয়ে বড় প্রয়োগ সম্ভবত জীববিজ্ঞানে। DNA sequencing যন্ত্র দীর্ঘ genome সরাসরি পড়ে না, পড়ে লাখ লাখ ছোট টুকরো (read). এগুলো জোড়া দেওয়া (genome assembly) প্রথমে Hamilton path হিসেবে ভাবা হয়েছিল: প্রতিটি read একটি vertex, ওভারল্যাপ একটি edge; কিন্তু Hamilton path NP-complete. ২০০১ সালের দিকে Pavel Pevzner ও সহকর্মীরা read-গুলোকে k দৈর্ঘ্যের টুকরো (k-mer) করে de Bruijn graph বানানোর পদ্ধতি জনপ্রিয় করেন বলে জানা যায়, যেখানে প্রতিটি k-mer একটি edge; তখন সমস্যাটি Euler path খোঁজায় পরিণত হয়। ভুল-পড়া আর পুনরাবৃত্ত অংশের জন্য বাস্তব কাজটি জটিল, তবু এই রূপান্তর আধুনিক short-read assembler-এর ভিত্তি বলে ধরা হয়।

মূল উপলব্ধি: প্রতিটি শব্দকে vertex নয়, edge বানানোর কৌশল একটি Hamilton সমস্যাকে Euler সমস্যায় বদলে দেয়; সঠিক মডেল বাছাই অনেক সময় কঠিন সমস্যাকে সহজ করে।

প্র ০৪বাস্তবের route inspection (ডাক বিলি, ময়লার গাড়ি, রাস্তা পরিদর্শন) §৫-এর উপপাদ্যের চেয়ে কঠিন কেন? কোন রূপগুলো এখনো কঠিন?

§৫-এর undirected রূপের জন্য Jack Edmonds আর Ellis Johnson ১৯৭৩ সালের একটি প্রবন্ধে polynomial algorithm দেন বলে জানা যায়: বিজোড় vertex-গুলোর মধ্যে একটি minimum-weight perfect matching, যার জন্য Edmonds-এর “blossom” algorithm (১৯৬৫) কাজে লাগে। সব রাস্তা একমুখী হলে সমস্যাটি network flow দিয়ে polynomial সময়ে সমাধান হয়: যেসব vertex-এ ঢোকা আর বেরোনো তীর অসমান, তাদের মধ্যে সবচেয়ে সস্তায় বাড়তি পথ পাঠাতে হয়।

কিন্তু বাস্তব শহর মিশ্র: কিছু রাস্তা একমুখী, কিছু দ্বিমুখী। এই “mixed” রূপ NP-hard, যা Christos Papadimitriou ১৯৭৬ সালের দিকে দেখান বলে উল্লেখ পাওয়া যায়। শুধু কিছু নির্দিষ্ট রাস্তা ঢাকতে হলে (যেমন যেসব রাস্তায় অর্ডার আছে) সমস্যাটির নাম rural postman, আর সেটিও সাধারণভাবে NP-hard. সঙ্গে যোগ হয় গাড়ির ধারণক্ষমতা, সময়-জানালা, U-turn নিষেধ, একাধিক গাড়ি; এদের একসঙ্গে arc routing সমস্যা বলা হয়।

তাই রুট-পরিকল্পনার সফটওয়্যার সাধারণত গাণিতিক কাঠামো (Euler-এর শর্ত, matching, flow) থেকে একটি ভালো প্রাথমিক রুট বানিয়ে heuristic বা integer programming দিয়ে উন্নত করে। উপপাদ্য ৫.১-এর নিম্নসীমাও কাজে লাগে: কোনো রুট ∑w(e) + min-matching-এর চেয়ে ছোট হতে পারে না, তাই একটি heuristic রুট এই সীমার কত কাছে, তা দেখে তার মান বিচার করা যায়। লক্ষ করুন, Euler থেকে আসা polynomial সমস্যার সীমানা খুব সরু: দিকের সামান্য মিশ্রণেই সমস্যা NP-hard হয়ে যায়।

মূল উপলব্ধি: সব-দ্বিমুখী বা সব-একমুখী রাস্তায় route inspection polynomial, কিন্তু মিশ্র রাস্তা বা আংশিক ঢাকার শর্তে তা NP-hard; বাস্তব রুটিংয়ে Euler-এর তত্ত্ব ভিত্তি আর নিম্নসীমা দেয়।

প্র ০৫Knight's tour, Gray code আর বড় TSP সমাধান: Hamilton cycle-এর কঠিনতা সত্ত্বেও বাস্তবে এত বড় উদাহরণ কীভাবে সমাধান হয়?

দাবার ঘোড়ার tour বহু শতাব্দীর পুরোনো ধাঁধা, আর Euler ১৭৫৯ সালের দিকে এর গণিত নিয়ে লেখেন বলে জানা যায়। H. C. von Warnsdorff ১৮২৩ সালে একটি সহজ নিয়ম প্রস্তাব করেন: সবসময় এমন ঘরে যান, যেখান থেকে পরের চালের সুযোগ সবচেয়ে কম। এটি একটি heuristic, প্রমাণিত algorithm নয়, কিন্তু সাধারণ বোর্ডে প্রায় সবসময় কাজ করে। কোন আয়তাকার বোর্ডে বন্ধ tour আছে, তার পূর্ণ শ্রেণিবিভাগ Allen Schwenk ১৯৯১ সালে দেন বলে জানা যায়।

Gray code দেখায় যে বিশেষ গঠনের graph-এ Hamilton cycle একটি সূত্রেও লেখা যায়: k-তম শব্দ k ⊕ (k ≫ 1). NP-completeness একটি “সবচেয়ে খারাপ ক্ষেত্রের” বিবৃতি: সব graph-এ দ্রুত কাজ করবে এমন algorithm জানা নেই, কিন্তু অনেক graph-এ দ্রুত উত্তর মেলে।

TSP-এ এর সবচেয়ে নাটকীয় প্রমাণ মেলে। David Applegate, Robert Bixby, Vašek Chvátal আর William Cook-এর Concorde প্রোগ্রাম linear programming, cutting plane আর branch-and-bound মিলিয়ে বহু হাজার শহরের উদাহরণ প্রমাণসহ সর্বোত্তমভাবে সমাধান করেছে; প্রায় ৮৬ হাজার বিন্দুর একটি উদাহরণ ২০০০-এর দশকের মাঝামাঝি সমাধান হয়েছিল বলে জানা যায়। কৌশলটি নিম্নসীমা: একটি tour পাওয়া সহজ, আর যদি প্রমাণ করা যায় যে কোনো tour একটি নির্দিষ্ট দৈর্ঘ্যের চেয়ে ছোট হতে পারে না, আর পাওয়া tour ঠিক সেই দৈর্ঘ্যের, তাহলে সর্বোত্তমতা প্রমাণিত। তবু কিছু কৃত্রিম উদাহরণ ছোট আকারেও এই পদ্ধতিগুলোকে আটকে দেয়।

মূল উপলব্ধি: NP-completeness সবচেয়ে খারাপ ক্ষেত্রের কথা বলে; বিশেষ গঠন (Gray code), ভালো heuristic (Warnsdorff) আর শক্ত নিম্নসীমা (Concorde) মিলে বাস্তবের অনেক বড় উদাহরণ সমাধানযোগ্য।

অনুশীলন

আগে খাতায় করুন, তারপর উত্তর খুলে মেলান।

  1. প্রমাণ: m, n ≥ 2 হলে প্রমাণ করুন: (ক) Km,n-এ Hamilton cycle আছে যদি এবং কেবল যদি m = n; (খ) Km,n-এ Euler circuit আছে যদি এবং কেবল যদি m আর n দুটিই জোড়।
    1. (ক) “কেবল যদি”: Km,n bipartite, দুই দিক m আর n. উপপাদ্য ৬.১(গ) অনুযায়ী Hamilton cycle থাকলে m = n. — পালাক্রম
    2. (ক) “যদি”: m = n হলে X = {x1, …, xn}, Y = {y1, …, yn}. x1 y1 x2 y2 ⋯ xn yn x1 একটি cycle: প্রতিটি পরপর জোড়া X–Y, আর Kn,n-এ X–Y-এর সব edge আছে; n ≥ 2 বলে দৈর্ঘ্য 2n ≥ 4 আর প্রতিটি vertex একবার। — নির্মাণ
    3. (খ) X-এর প্রতিটি vertex-এর degree n, Y-এর প্রতিটির m; graph connected (যেকোনো দুটি vertex সর্বোচ্চ দুই ধাপে যুক্ত)। উপপাদ্য ২.১ অনুযায়ী Euler circuit ⇔ n আর m দুটিই জোড়। ∎ — উপপাদ্য ২.১

    যেমন K2,4-এ Euler circuit আছে কিন্তু Hamilton cycle নেই; K3,3-এ উল্টো। দুটি ধারণা স্বাধীন।

  2. হিসাব: বাজারঘরের চারটি পিকআপ পয়েন্ট A, B, C, D. রাস্তা (মিনিটে, কাল্পনিক): A–B 5, B–C 4, C–D 5, D–A 4, আর A–C 6. (ক) রাইডার প্রতিটি রাস্তা অন্তত একবার নিয়ে A-তে ফিরলে সবচেয়ে কম কত মিনিট? (খ) A-তে ফেরার দরকার না থাকলে? (গ) এই graph-এ Hamilton cycle আছে কি?

    degree: A 3 (B, D, C), B 2, C 3, D 2. বিজোড় শুধু A আর C. সব রাস্তার যোগফল 5 + 4 + 5 + 4 + 6 = 24.

    (ক) একটিই জোড়ভাগ {A, C}; d(A, C) = min(6, A–B–C 9, A–D–C 9) = 6. উপপাদ্য ৫.১: 24 + 6 = 30 মিনিট, A–C রাস্তাটি দুবার। একটি রুট: A B C A C D A (5 + 4 + 6 + 6 + 5 + 4 = 30).

    (খ) উপপাদ্য ২.৩ অনুযায়ী A থেকে C-তে একটি Euler trail আছে, তাই বাড়তি কিছু লাগে না: 24 মিনিট, যেমন A B C A D C.

    (গ) আছে: A B C D A. graph-টিতে Euler circuit নেই কিন্তু Hamilton cycle আছে (সব সংখ্যা scratch-এ মেলানো)।

  3. আউটপুট অনুমান: কোড না চালিয়ে বলুন কী ছাপা হবে। তারপর যেকোনো Python-এ চালিয়ে মেলান।
    from collections import Counter
    edges = [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5), (5, 3), (1, 5), (2, 2)]
    deg = Counter(v for e in edges for v in e)
    odd = [v for v in sorted(deg) if deg[v] % 2]
    print(dict(sorted(deg.items())))
    print(odd, "trail" if len(odd) in (0, 2) else "none", sum(deg.values()) == 2 * len(edges))
    {1: 3, 2: 4, 3: 4, 4: 2, 5: 3}
    [1, 5] trail True

    মূল কথা loop (2, 2): generator প্রতিটি tuple-এর দুটি প্রান্তই গোনে, তাই loop vertex 2-এর degree-তে ২ যোগ করে, ঠিক সংজ্ঞা ১.১-এর মতো। deg(2) = 1 (থেকে 1) + 1 (থেকে 3) + 2 = 4. বিজোড় শুধু 1 আর 5, তাই উপপাদ্য ২.৩ অনুযায়ী 1 থেকে 5-এ একটি Euler trail আছে, কারণ graph-টি যুক্ত। শেষ True হলো handshake lemma: degree-র যোগফল 16 = 2 × 8. আউটপুট CPython 3.14-এ চালিয়ে মেলানো।

  4. প্রমাণের ভুল ধরুন: একজন লিখলেন: “দাবি: connected graph-এ সব degree জোড় হলে, যেকোনো vertex s থেকে অব্যবহৃত edge ধরে যেভাবে খুশি হাঁটলেই একটি Euler circuit পাওয়া যায়। প্রমাণ: lemma ২.২ অনুযায়ী হাঁটা শুধু s-এ আটকায়। s-এ আটকানো মানে s-এর সব edge ব্যবহৃত। তাই সব edge ব্যবহৃত, আর আমরা একটি Euler circuit পেয়েছি। ∎” ভুলটি কোথায়? একটি পাল্টা-উদাহরণ দিন, আর দাবিটি কীভাবে সংশোধন করা যায় বলুন।
    • ভুল ধাপ: “s-এর সব edge ব্যবহৃত” থেকে “graph-এর সব edge ব্যবহৃত” লাফটি অবৈধ। আটকানোর শর্ত শুধু s-এর স্থানীয় অবস্থা বলে; অন্য vertex-এ অব্যবহৃত edge থাকতেই পারে।
    • পাল্টা-উদাহরণ: দুটি ত্রিভুজ A-B-C আর C-D-E, C-তে যুক্ত (bow-tie). সব degree জোড় (C-এর 4, বাকিদের 2), graph connected. A থেকে হাঁটা A → B → C → A: A-এর দুটি edge শেষ, হাঁটা আটকাল, অথচ C–D, D–E, E–C অব্যবহৃত।
    • সংশোধন: এখানেই splice লাগে (Hierholzer): circuit-এর ওপর অব্যবহৃত edge-যুক্ত vertex (এখানে C) থেকে আবার হাঁটুন আর জুড়ে দিন: A B C D E C A. অথবা Fleury-র নিয়ম মানুন: C-তে পৌঁছে C–A নেবেন না, কারণ তখন C–A বাকি অব্যবহৃত graph-এর bridge (নিলে C–D–E অংশ আলাদা হয়ে যায়), আর অন্য উপায় আছে।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রম“সব degree জোড় এমন connected multigraph-এ Euler circuit আছে” প্রমাণের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. অব্যবহৃত edge ধরে হাঁটলে জোড় degree-র কারণে হাঁটা শুধু শুরুর vertex-এ আটকায়, তাই একটি circuit C পাওয়া যায়
  2. C-এর edge মুছলে বাকি graph-এ প্রতিটি degree তখনো জোড় থাকে
  3. বাকি graph-এর প্রতিটি component-এ কম edge, তাই induction অনুযায়ী তার একটি Euler circuit আছে
  4. connectedness-এর কারণে প্রতিটি component C-এর কোনো vertex ছোঁয়
  5. সেই vertex-এ component-এর circuit C-এর ভেতরে জুড়ে দিলে সব edge ঠিক একবার নেওয়া একটি circuit হয়

Königsberg-এর চারটি ভূখণ্ড আর সাতটি সেতুর multigraph-এ degree 5, 3, 3, 3. প্রতিটি সেতু ঠিক একবার পার হওয়া হাঁটা কেন অসম্ভব?

  • সেতুর মোট সংখ্যা ৭, যা বিজোড়
  • দুই ভূখণ্ডের মধ্যে দুটি সেতু থাকায় graph-টি simple নয়
  • বিজোড় degree-র vertex ৪টি, কিন্তু Euler trail-এ সর্বোচ্চ ২টি থাকতে পারে
  • graph-টি connected নয়

নিচের কোন graph-এ Euler circuit আছে?

  • K4
  • K5
  • K2,3
  • Q3 (৩-মাত্রার hypercube)

নিচের কোন graph-এ কোনো Hamilton cycle নেই?

  • K3,4
  • K4,4
  • Q3
  • C7

৬টি vertex-এর cycle graph C6-এ প্রতিটি degree 2. Ore-এর শর্ত (অসংলগ্ন প্রতিটি u, v-তে deg u + deg v ≥ n) সম্পর্কে কোনটি সত্য?

  • শর্ত ভাঙে, তাই C6-এ Hamilton cycle নেই
  • C6 Ore-এর শর্ত মানে
  • Ore-এর শর্ত আবশ্যিক, তাই C6 একটি ব্যতিক্রমী ভুল উদাহরণ
  • শর্ত ভাঙে, তবু Hamilton cycle আছে; শর্তটি শুধু যথেষ্ট

৫টি শহরের সম্পূর্ণ graph K5-এ কয়টি আলাদা Hamilton cycle আছে (শুরুর শহর আর দিক গুরুত্বহীন)?

  • 120
  • 12
  • 24
  • 10

একটি সড়ক-জালের সব রাস্তার দৈর্ঘ্যের যোগফল 40. বিজোড় degree-র vertex P, Q, R, S, আর তাদের সবচেয়ে ছোট দূরত্ব: d(P,Q) = 3, d(R,S) = 4, d(P,R) = 2, d(Q,S) = 2, d(P,S) = 6, d(Q,R) = 5. প্রতিটি রাস্তা অন্তত একবার নিয়ে শুরুতে ফেরার সবচেয়ে ছোট রুটের দৈর্ঘ্য কত?

  • 40
  • 47
  • 44
  • 51

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Euler: connected multigraph-এ Euler circuit ⇔ সব degree জোড়; Euler trail ⇔ বিজোড় vertex ০টি বা ২টি; 2k-টি বিজোড় হলে k-টি trail লাগে।
  2. প্রমাণের মূল: জোড় degree-তে হাঁটা শুধু শুরুতে আটকায়; তারপর বাকি edge-এর circuit জুড়ে দেওয়া (Hierholzer, O(n + m)). Directed graph-এ শর্ত in-degree = out-degree.
  3. প্রয়োগ: de Bruijn sequence = de Bruijn digraph-এর Euler circuit; route inspection = সব রাস্তা + বিজোড় vertex-এর সবচেয়ে সস্তা জোড়ভাগ।
  4. Hamilton: “নেই” প্রমাণ: cut vertex, অসমান bipartite দুই দিক, k-টি vertex মুছলে k-এর বেশি component. “আছে” নিশ্চয়তা: Ore (অসংলগ্নে deg u + deg v ≥ n) আর Dirac (δ ≥ n/2), শুধু যথেষ্ট।
  5. কঠিনতা: Euler polynomial, Hamilton cycle NP-complete; TSP তার ওজনযুক্ত রূপ আর NP-hard.

পরের পর্বে: পর্ব ৬১ “Shortest path-এর গণিত — Dijkstra-র প্রমাণ আর traveling salesperson”: edge-এ দৈর্ঘ্য বসিয়ে সবচেয়ে ছোট পথের গণিত, Dijkstra কেন সঠিক তার প্রমাণ, আর এই পর্বের Hamilton cycle থেকে আসা traveling salesperson সমস্যার প্রথম পরিচয়।

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

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান