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

Error-correcting code — parity, Hamming code আর Hamming distance

Error-Correcting Codes — Parity, Hamming Distance, Hamming Bound, Linear Codes and the Hamming(7,4) Code

Taught in Bangla, this lesson adds deliberate redundancy to detect and correct bit errors. It analyses repetition and parity codes, proves that minimum distance d detects d − 1 errors and corrects ⌊(d − 1)/2⌋, and derives the Hamming bound, perfect codes, Singleton and Gilbert–Varshamov. Linear codes use generator and parity-check matrices, Hamming(7,4) is encoded and syndrome-decoded, and SECDED and Shannon's theorem follow. In-page Python checks the bounds and runs Hamming(7,4) and SECDED.

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

  • Binary symmetric channel, code, rate, repetition code আর parity code, আর তাদের error-সম্ভাবনার নির্ভুল হিসাব
  • Hamming distance কেন একটি metric, আর minimum distance থেকে error ধরা ও শোধরানোর ক্ষমতার দুই দিকের প্রমাণ
  • Hamming (sphere-packing) bound, perfect code, Singleton bound-এর প্রমাণ আর Gilbert–Varshamov-এর নিশ্চয়তা
  • GF(2)-এর ওপর linear code: generator matrix, parity-check matrix, syndrome decoding
  • Hamming(7,4) হাতে encode আর decode, তার d = 3 আর perfect হওয়ার প্রমাণ, SECDED আর বাস্তবের ব্যবহার

১ · Channel আর error — বিট কেন উল্টে যায়

দুর্বল নেটওয়ার্কে মোবাইলে কাউকে একটি অর্ডার নম্বর বলছেন। ওপাশ থেকে শোনা গেল “সাত না এক?” তাই আপনি নম্বরটি দুবার বলেন, বা প্রতিটি অঙ্কের সঙ্গে একটি শব্দ জুড়ে দেন। যোগাযোগে বাড়তি অংশ যোগ করে ভুল ধরা আর শোধরানো, এটাই coding theory-র মূল কথা। প্রশ্ন হলো, সবচেয়ে কম বাড়তি অংশে সবচেয়ে বেশি সুরক্ষা কীভাবে পাওয়া যায়।

বাজারঘরের জেলা-গুদাম থেকে প্রধান সার্ভারে প্রতি মিনিটে অর্ডারের ডেটা যায়: অর্ডার নম্বর, পণ্যের কোড, পরিমাণ, টাকার অঙ্ক। পথে বৈদ্যুতিক গোলমাল, দুর্বল বেতার সংকেত বা মেমরির একটি কোষের সমস্যায় কোনো বিট 0 থেকে 1 বা 1 থেকে 0 হয়ে যেতে পারে। পরিমাণ “2”-এর বদলে “3” হলে ভুল পণ্য যায়। গণিতে এই পথের সবচেয়ে সরল মডেল নিচেরটি।

সংজ্ঞা ১.১ (binary symmetric channel)

Binary symmetric channel (BSC) প্রতিটি পাঠানো বিটকে অন্য সব বিট থেকে স্বাধীনভাবে, একই সম্ভাবনা p-তে উল্টে দেয় (0 < p < 1/2), আর 1 − p সম্ভাবনায় অবিকৃত রাখে। p-কে crossover probability বা bit-error rate বলে। “Symmetric” মানে 0 → 1 আর 1 → 0 উল্টানোর সম্ভাবনা সমান।

n-বিটের একটি block-এ কয়টি বিট উল্টায়, তা একটি binomial distribution মানে (পর্ব ৪০): ঠিক k-টি উল্টানোর সম্ভাবনা C(n, k) pk(1 − p)n−k. উদাহরণের জন্য ধরি p = 0.01 (কাল্পনিক মান; বাস্তব তার, বেতার বা মেমরিতে এটি অনেক ছোট থেকে বেশ বড় পর্যন্ত হয়)। তাহলে একটি ৮-বিটের byte:

ঘটনাসূত্রমান (p = 0.01)
কোনো বিট উল্টায়নি(1 − p)80.9227
ঠিক একটি উল্টেছে8p(1 − p)70.0746
দুই বা তার বেশিবাকি অংশ0.0027

প্রায় ৮% byte নষ্ট হয়, কিন্তু নষ্টগুলোর বেশিরভাগে মাত্র একটি বিট উল্টেছে। তাই “একটি error শোধরানো” code-ই বিরাট লাভ দেয়। এখন code-এর ভাষা ঠিক করি।

সংজ্ঞা ১.২ (block code, codeword, rate)

দৈর্ঘ্য n-এর একটি binary block code হলো C ⊆ {0, 1}n; এর উপাদানগুলো codeword, আর M = C-এর উপাদান-সংখ্যা। M = 2k হলে প্রতিটি codeword k বিট তথ্য বহন করে, আর rate R = k/n: প্রতি পাঠানো বিটে কতটুকু আসল তথ্য। বাকি n − k বিট হলো redundancy.

পর্ব ৬৮ “Prefix code আর Huffman coding”-এ উল্টো কাজ করেছিলাম: উৎসের redundancy ছেঁটে বিট কমানো। বাস্তবে দুটোই চলে: আগে সংকোচন, তারপর channel-এর জন্য হিসাব করা redundancy যোগ। Shannon দেখান এই দুই কাজ আলাদা করে সর্বোত্তমভাবে করা যায় (§৭)।

২ · সবচেয়ে সরল দুটি code — repetition আর parity

Repetition code আর majority

Repetition code Rn (n বিজোড়) প্রতিটি বিট n বার পাঠায়: 0 → 00…0, 1 → 11…1. গ্রাহক majority vote নেয়: বেশিরভাগ বিট যা, সেটাই। R3-এ 1 পাঠালে 111; একটি বিট উল্টে 101 এলেও majority 1.

উপপাদ্য ২.১ (repetition code-এর ব্যর্থতা)

BSC(p)-তে Rn-এর majority decoding ঠিক তখনই ভুল করে, যখন (n − 1)/2-এর বেশি বিট উল্টায়, তাই

Pfail(Rn) = ∑k=(n+1)/2..n C(n, k) pk(1 − p)n−k.

প্রমাণ: majority ভুল বিট বেছে নেয় ⇔ উল্টানো বিট অক্ষত বিটের চেয়ে বেশি ⇔ k > n − k ⇔ k ≥ (n + 1)/2 (n বিজোড়)। আলাদা k-এর ঘটনা disjoint, তাই সম্ভাবনা যোগ হয়। ∎ R3-এ এটি 3p2(1 − p) + p3 = 3p2 − 2p3; p = 0.1 হলে 0.028, অর্থাৎ error প্রায় সাড়ে তিন গুণ কমল। দাম: rate 1/3, তিন গুণ বিট পাঠাতে হয়।

n বাড়ালে ব্যর্থতা দ্রুত শূন্যের দিকে যায়। কতটা দ্রুত? উল্টানো বিটের সংখ্যার গড় np < n/2, আর গড় থেকে n/2 পর্যন্ত সরে যাওয়ার সম্ভাবনা n-এর সঙ্গে ঘাতের হারে কমে: এটাই পর্ব ৪১-এর Chernoff bound-এর বক্তব্য। কিন্তু rate 1/n শূন্যে নামে। “কম error আর ভালো rate একসঙ্গে পাওয়া যায় কি?” এই প্রশ্নই পুরো পর্বকে চালায়।

Parity code — শুধু ধরা

Parity check code k বিটের শেষে একটি parity bit বসায়, যাতে মোট 1-এর সংখ্যা জোড় হয় (even parity). যেমন 1011001-এর চারটি 1, তাই parity বিট 0, পাঠানো হয় 10110010. Rate k/(k + 1), খুবই ভালো। “জোড় না বিজোড়” প্রশ্নটি XOR দিয়ে লেখা যায়: parity বিট = সব data বিটের XOR (পর্ব ৬৯-এর Boolean function).

উপপাদ্য ২.২ (parity code কী ধরে)

Even-parity code-এ বিজোড় সংখ্যক বিট উল্টালে গ্রাহক সবসময় error ধরে, আর জোড় সংখ্যক (শূন্য নয়) উল্টালে কখনো ধরে না। কোনো error-এর অবস্থান সে জানে না।

  1. একটি বিট উল্টালে 1-এর সংখ্যা ঠিক এক বাড়ে বা কমে, তাই তার জোড়-বিজোড় অবস্থা বদলায়। — ±1-এ parity বদলায়
  2. e-টি আলাদা বিট উল্টালে এই বদল e বার ঘটে; শুরুতে সংখ্যা জোড়, তাই শেষে জোড় ⇔ e জোড়। — e বার বদল, induction
  3. গ্রাহক শুধু মোট parity দেখে, তাই e বিজোড় হলে “error”, e জোড় হলে “ঠিক আছে” বলে। আর অবস্থান 1-এ একটি error আর অবস্থান 5-এ একটি error একই বিজোড় parity দেখায়, তাই অবস্থান বলা যায় না। ∎

এর সঙ্গে আছে পর্ব ২৬-এর check digit (ISBN, ব্যাংক কার্ড) আর CRC, যারা আরও বেশি ধরনের error ধরে, কিন্তু শোধরায় না। ধরা পড়লে নেটওয়ার্ক সাধারণত আবার পাঠাতে বলে।

নিচের ব্লক BSC-তে p = 0.1 নিয়ে R1, R3, R5, R7-এর ব্যর্থতা সূত্রে আর ২০,০০০টি করে seed-বাঁধা simulation-এ মেলায়, তারপর ৮-বিটের parity code-এর ধরা-না-ধরার সম্ভাবনা গোনে। প্রথমবার চালালে ব্রাউজারে Python (Pyodide) নামতে কয়েক সেকেন্ড লাগে।

import random
from math import comb
def rep_fail_exact(n, p):              # majority wrong: more than n//2 flips
    return sum(comb(n, k) * p**k * (1 - p)**(n - k) for k in range(n // 2 + 1, n + 1))
def rep_fail_sim(n, p, trials):
    bad = 0
    for _ in range(trials):
        flips = sum(random.random() < p for _ in range(n))
        bad += flips > n // 2           # majority decoding picks the wrong bit
    return bad / trials
random.seed(72); p = 0.1; T = 20000
print(f"BSC p = {p}, {T} simulated blocks each")
for n in (1, 3, 5, 7):
    print(f"R{n}: rate 1/{n}  exact {rep_fail_exact(n, p):.5f}  sim {rep_fail_sim(n, p, T):.5f}")
# even-parity code on 8 bits: an error slips through iff an even number (>= 2) flip
undetected = sum(comb(8, k) * p**k * (1 - p)**(8 - k) for k in range(2, 9, 2))
detected = sum(comb(8, k) * p**k * (1 - p)**(8 - k) for k in range(1, 9, 2))
print(f"parity-8: detected {detected:.4f}  undetected {undetected:.4f}")
word = [1, 0, 1, 1, 0, 0, 1]
sent = word + [sum(word) % 2]          # parity bit makes the weight even
for flips in ([2], [2, 5], [0, 3, 6]):
    r = sent[:]
    for i in flips:
        r[i] ^= 1
    print(len(flips), "flip(s): parity check says", "error" if sum(r) % 2 else "OK")

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

BSC p = 0.1, 20000 simulated blocks each
R1: rate 1/1  exact 0.10000  sim 0.10170
R3: rate 1/3  exact 0.02800  sim 0.02880
R5: rate 1/5  exact 0.00856  sim 0.00915
R7: rate 1/7  exact 0.00273  sim 0.00260
parity-8: detected 0.4161  undetected 0.1534
1 flip(s): parity check says error
2 flip(s): parity check says OK
3 flip(s): parity check says error

সূত্রের মান আর simulation কাছাকাছি, তবে হুবহু নয়: ২০,০০০টি নমুনায় এলোমেলো ওঠানামা থাকে (R5-এ 0.00856 বনাম 0.00915). R3-এর 0.028 ঠিক 3p2 − 2p3. প্রতি ধাপে n দুই বাড়ালে ব্যর্থতা মোটামুটি তিন ভাগের এক ভাগ হচ্ছে, কিন্তু rate 1, 1/3, 1/5, 1/7 হয়ে নামছে। Parity অংশে: p = 0.1-এ ৮ বিটের প্রায় ৪২% block-এ বিজোড় error ধরা পড়ে, আর প্রায় ১৫%-এ জোড় error লুকিয়ে যায়; বিট-error এত বেশি হলে শুধু parity যথেষ্ট নয়। শেষ তিন লাইন উপপাদ্য ২.২ হাতে-কলমে: ১ আর ৩টি উল্টানো ধরা পড়ল, ২টি পড়ল না।

৩ · Hamming distance আর minimum distance

সংজ্ঞা ৩.১ (দূরত্ব আর weight)

x, y ∈ {0, 1}n-এর Hamming distance d(x, y) = যে কয়টি অবস্থানে xi ≠ yi. x-এর Hamming weight w(x) = x-এ 1-এর সংখ্যা। যেহেতু xi ⊕ yi = 1 ঠিক তখন, যখন দুটি আলাদা, তাই d(x, y) = w(x ⊕ y). Code C-এর minimum distance d(C) = আলাদা দুটি codeword-এর মধ্যে সবচেয়ে ছোট দূরত্ব।

যেমন d(1011, 1001) = 1, d(0000, 1111) = 4. পর্ব ৩৬-এ Gray code-এ পরপর দুটি শব্দের Hamming distance 1 দেখেছেন, আর পর্ব ৫৭-এর hypercube Qn-এ d(x, y) ঠিক x থেকে y-তে সবচেয়ে ছোট পথের edge-সংখ্যা। “দূরত্ব” নামটি যথার্থ কি না, তা প্রমাণ করা দরকার।

উপপাদ্য ৩.২ (Hamming distance একটি metric)

সব x, y, z ∈ {0, 1}n-এর জন্য: (ক) d(x, y) ≥ 0, আর d(x, y) = 0 ⇔ x = y; (খ) d(x, y) = d(y, x); (গ) triangle inequality d(x, z) ≤ d(x, y) + d(y, z). এই তিন ধর্মের দূরত্বকে metric বলে।

  1. (ক) আর (খ) সংজ্ঞা থেকে সরাসরি: সংখ্যাটি গণনা, তাই অঋণাত্মক; শূন্য মানে কোথাও অমিল নেই; “xi ≠ yi” আর “yi ≠ xi” একই শর্ত। — সংজ্ঞা
  2. (গ) এমন একটি অবস্থান i নিন, যেখানে xi ≠ zi. বিট মাত্র দুটি মান নেয়, তাই yi হয় xi-এর সমান, নয় zi-এর সমান, দুটোর সমান হতে পারে না। ফলে xi ≠ yi অথবা yi ≠ zi. — দুই মানের ক্ষেত্র ভাগ
  3. অর্থাৎ d(x, z)-তে গোনা প্রতিটি অবস্থান d(x, y) বা d(y, z)-এর অন্তত একটিতে গোনা হয়। সব অবস্থানে যোগ করলে d(x, z) ≤ d(x, y) + d(y, z). ∎ — গণনা

এখন মূল দুটি উপপাদ্য। গ্রাহক শব্দ r পায়; পাঠানো হয়েছিল codeword c, আর error-pattern e = r ⊕ c, যার weight হলো উল্টানো বিটের সংখ্যা। Nearest-codeword decoding মানে r-এর সবচেয়ে কাছের codeword বেছে নেওয়া। p < 1/2 হলে কম বিট উল্টানো বেশি সম্ভাব্য, তাই এটিই সবচেয়ে সম্ভাব্য পাঠানো শব্দ বেছে নেয়।

উপপাদ্য ৩.৩ (ধরা আর শোধরানোর ক্ষমতা)

(ক) C প্রতিটি 1 থেকে s-টি error ধরতে পারে ⇔ d(C) ≥ s + 1. (খ) Nearest-codeword decoding প্রতিটি সর্বোচ্চ t-টি error শোধরায় ⇔ d(C) ≥ 2t + 1. তাই d-দূরত্বের code d − 1টি পর্যন্ত error ধরে, আর t = ⌊(d − 1)/2⌋টি পর্যন্ত শোধরায়।

  1. (ক, ⇐) 1 ≤ w(e) ≤ s হলে 1 ≤ d(r, c) ≤ s < d(C), তাই r অন্য কোনো codeword হতে পারে না, আবার c-ও নয়; গ্রাহক দেখে r ∉ C, অর্থাৎ error ধরা পড়ে। — দূরত্ব d-এর কম
  2. (ক, ⇒) d(C) ≤ s হলে দুটি codeword c, c′ আছে, d(c, c′) ≤ s. c পাঠালে e = c ⊕ c′ error (weight ≤ s) ঘটলে গ্রাহক পায় c′, একটি বৈধ codeword; error ধরা পড়ে না। — পাল্টা-উদাহরণ
  3. (খ, ⇐) ধরুন d(r, c) ≤ t, আর কোনো c′ ≠ c-এর জন্য d(r, c′) ≤ d(r, c). তাহলে triangle inequality অনুযায়ী d(c, c′) ≤ d(c, r) + d(r, c′) ≤ 2t < d(C), বিরোধ। তাই c-ই একমাত্র সবচেয়ে কাছের। — উপপাদ্য ৩.২
  4. (খ, ⇒) d(C) = d ≤ 2t হলে c, c′ নিন, d(c, c′) = d. যে d অবস্থানে তারা আলাদা, তার ⌈d/2⌉টিতে c-কে উল্টে r বানান। তাহলে d(r, c) = ⌈d/2⌉ ≤ t, অথচ d(r, c′) = ⌊d/2⌋ ≤ d(r, c): c′ অন্তত সমান কাছে, তাই decoder c পাবে এমন নিশ্চয়তা নেই। ∎ — মাঝের শব্দ

সাবধান: d − 1টি ধরা অথবা t-টি শোধরানো, একসঙ্গে দুটো নয়। d = 3-এর code দুটি error ধরতে পারে, কিন্তু তখন তাকে শোধরানোর চেষ্টা বাদ দিতে হয়; শোধরানোর মোডে দুটি error তাকে ভুল codeword-এ নিয়ে যায় (§৬)। সাধারণ রূপ: একসঙ্গে t-টি শোধরানো আর মোট s-টি (s ≥ t) পর্যন্ত ধরা যায় ⇔ d ≥ t + s + 1; প্রমাণ একই ধাঁচের। R3 = {000, 111}-এ d = 3, তাই একটি শোধরায়। নিচের ছবিতে Q3-এর ঘনকে এর জ্যামিতি দেখুন।

ঘনক Q3-এ repetition code {000, 111}

প্রতিটি কোণ একটি ৩-বিটের শব্দ; edge মানে ঠিক এক বিটের পার্থক্য। মোটা দাগের বাক্স দুটি codeword. সবুজ কোণগুলো 000-এর ব্যাসার্ধ-1 বল, কমলা কোণগুলো 111-এর। দুই বল আলাদা, আর মিলে আটটি কোণই ঢেকে ফেলে।

Hypercube Q3 with codewords 000 and 111 and their radius-1 Hamming balls 000100010001 110101011111 codewordcodeword

৪ · Hamming bound, perfect code আর অন্য সীমা

ছবির বলগুলো একটি গণনার জন্ম দেয়। কেন্দ্র x আর ব্যাসার্ধ t-এর Hamming ball B(x, t) = {y : d(x, y) ≤ t}. x থেকে ঠিক i দূরত্বের শব্দ পেতে n অবস্থান থেকে i-টি উল্টানোর জায়গা বাছতে হয়, তাই (পর্ব ৩৪)

V(n, t) = |B(x, t)| = C(n, 0) + C(n, 1) + ⋯ + C(n, t),

যা কেন্দ্রের ওপর নির্ভর করে না।

উপপাদ্য ৪.১ (Hamming bound, sphere-packing bound)

দৈর্ঘ্য n, M-টি codeword আর d(C) ≥ 2t + 1 হলে M · V(n, t) ≤ 2n.

  1. দুটি আলাদা codeword c, c′-এর বল B(c, t) আর B(c′, t) disjoint: কোনো y দুটিতেই থাকলে d(c, c′) ≤ d(c, y) + d(y, c′) ≤ 2t < d(C), বিরোধ। — triangle inequality
  2. M-টি disjoint বল, প্রতিটিতে V(n, t)টি শব্দ, সবই {0, 1}n-এর ভেতরে, যেখানে মোট 2nটি শব্দ। তাই M · V(n, t) ≤ 2n. ∎ — disjoint সেটের যোগ
সংজ্ঞা ৪.২ (perfect code)

যে t-error শোধরানো code-এ Hamming bound-এ সমতা, M · V(n, t) = 2n: ব্যাসার্ধ t-এর বলগুলো পুরো space ফাঁক ছাড়া ঢেকে ফেলে। প্রতিটি সম্ভাব্য প্রাপ্ত শব্দ ঠিক একটি codeword-এর t-দূরত্বের মধ্যে।

ছবির R3 perfect: 2 · (1 + 3) = 8 = 23. যেকোনো বিজোড় n-এ Rn-ও perfect (প্রমাণ: C(n, i) = C(n, n − i) দিয়ে V(n, (n − 1)/2) = 2n−1). এগুলো “তুচ্ছ” perfect code. অতুচ্ছ উদাহরণ দুটি পরিবার: §৬-এর Hamming code আর Golay-এর (23, 12) code, যাতে t = 3: 212(1 + 23 + 253 + 1771) = 212 · 2048 = 223. নিচের stepper n = 7, t = 1-এর গণনাটি ধাপে ধাপে দেখায়।

1space: 2^7 = 128 words2V(7,1) = 1 + C(7,1) = 83d = 3 ≥ 2·1+1: disjoint4M ≤ 128 / 8 = 165Hamming(7,4): 16 × 8 = 1286t = 2: V = 29, M ≤ 4
বলের আকার আর সীমা
V(7, t)
M-এর সীমা
ঢাকা শব্দ
  1. পুরো space. দৈর্ঘ্য 7-এর binary শব্দ 27 = 128টি। প্রাপ্ত শব্দ এদের যেকোনোটি হতে পারে।
  2. একটি বল। একটি codeword c-এর ব্যাসার্ধ-1 বলে c নিজে (দূরত্ব 0, C(7, 0) = 1টি) আর ঠিক এক বিট উল্টানো 7টি শব্দ (C(7, 1) = 7). মোট V(7, 1) = 8.
  3. বলগুলো আলাদা। একটি error শোধরাতে d ≥ 3 লাগে (উপপাদ্য ৩.৩)। তখন উপপাদ্য ৪.১-এর ধাপ ১ অনুযায়ী দুটি বল কোনো শব্দ ভাগ করে না।
  4. সীমা। M-টি disjoint বলে 8M-টি আলাদা শব্দ, যা 128-এর বেশি হতে পারে না: M ≤ 16. তাই দৈর্ঘ্য 7-এর single-error-correcting code-এ বড়জোর 16টি codeword, অর্থাৎ বড়জোর 4 বিট তথ্য।
  5. সমতা। §৬-এর Hamming(7,4) code-এ ঠিক 16টি codeword আর d = 3: 16 × 8 = 128 = 27. বলগুলো পুরো space ভরে দেয়, তাই code-টি perfect, আর এই দৈর্ঘ্যে এর চেয়ে বেশি তথ্য বহন করা অসম্ভব।
  6. দুটি error. t = 2 চাইলে V(7, 2) = 1 + 7 + 21 = 29, আর M ≤ 128/29 ≈ 4.41, অর্থাৎ বড়জোর 4টি codeword. শোধরানোর ক্ষমতা বাড়ালে তথ্যের জায়গা দ্রুত কমে।

আরেকটি ওপরের সীমা আরও সরল যুক্তিতে আসে।

উপপাদ্য ৪.৩ (Singleton bound)

দৈর্ঘ্য n আর minimum distance d-এর যেকোনো binary code-এ M ≤ 2n−d+1. M = 2k হলে k ≤ n − d + 1.

  1. প্রতিটি codeword থেকে প্রথম d − 1টি বিট মুছে দৈর্ঘ্য n − d + 1-এর শব্দ বানান। — puncturing
  2. দুটি আলাদা codeword অন্তত d অবস্থানে আলাদা; মোছা হয়েছে মাত্র d − 1টি অবস্থান, তাই ছাঁটা শব্দ দুটিও অন্তত একটি অবস্থানে আলাদা। — minimum distance
  3. অতএব ছাঁটার ফাংশনটি one-to-one, আর দৈর্ঘ্য n − d + 1-এর শব্দ মাত্র 2n−d+1টি; পর্ব ৩২-এর pigeonhole অনুযায়ী M ≤ 2n−d+1. ∎

Repetition code (k = 1, d = n) ঠিক এই সীমায় বসে। Hamming(7,4)-এ 4 < 7 − 3 + 1 = 5, তাই binary-তে Hamming bound বেশি কড়া। বড় alphabet-এ (যেমন GF(28)-এর উপাদানকে চিহ্ন ধরলে) Reed–Solomon code Singleton-এ সমতা দেয়; এমন code-কে MDS বলে (§৭)।

ওপরের সীমা বলে “এর বেশি অসম্ভব”; নিচের সীমা বলে “অন্তত এতটুকু সম্ভব”।

উপপাদ্য ৪.৪ (Gilbert–Varshamov bound)

যেকোনো n আর d-এর জন্য দৈর্ঘ্য n, minimum distance অন্তত d-এর এমন code আছে, যাতে M ≥ 2n / V(n, d − 1).

প্রমাণ (greedy): একটি একটি করে শব্দ নিন, যা আগে নেওয়া সবার থেকে অন্তত d দূরে। যখন আর নেওয়া যায় না, তখন প্রতিটি শব্দ কোনো নেওয়া শব্দের d − 1 দূরত্বের মধ্যে, অর্থাৎ M-টি বল B(c, d − 1) মিলে পুরো space ঢাকে: M · V(n, d − 1) ≥ 2n. ∎ n = 7, d = 3-এ নিশ্চয়তা M ≥ 128/29 ≈ 4.41, অর্থাৎ অন্তত 5টি codeword; Hamming bound বলে বড়জোর 16, আর Hamming code 16-ই দেয়। দুই সীমার মাঝখানে সবচেয়ে ভালো code কোথায়, বড় n-এ তা আজও পুরোপুরি জানা নেই।

নিচের ব্লক ছোট কয়েকটি code-এর minimum distance brute force-এ গোনে আর Hamming ও Singleton সীমা মেলায়; Golay-এর সমতা আর GV-র সংখ্যাও দেখায়।

from itertools import combinations, product
from math import comb
def dist(x, y):
    return sum(a != b for a, b in zip(x, y))
def span(rows):                        # all XOR-combinations of the rows
    out = set()
    for bits in product((0, 1), repeat=len(rows)):
        c = 0
        for r, b in zip(rows, bits):
            if b:
                c ^= int(r, 2)
        out.add(format(c, f"0{len(rows[0])}b"))
    return out
def report(name, C):
    n, M = len(next(iter(C))), len(C)
    d = min(dist(x, y) for x, y in combinations(C, 2))
    t = (d - 1) // 2
    ball = sum(comb(n, i) for i in range(t + 1))
    tag = " PERFECT" if M * ball == 2**n else ""
    print(f"{name}: n={n} M={M} d={d}, detect {d-1}, correct {t}")
    print(f"   M*V={M * ball} vs 2^n={2**n}{tag}; Singleton M <= {2**(n-d+1)}")
report("R3", {"000", "111"})
report("R5", {"00000", "11111"})
report("parity-4", {"".join(w) for w in product("01", repeat=4) if w.count("1") % 2 == 0})
report("Ham(7,4)", span(["1110000", "1001100", "0101010", "1101001"]))
report("exam C", {"00000", "01011", "10101", "11110"})
print("Golay(23,12), t=3:", 2**12 * sum(comb(23, i) for i in range(4)) == 2**23)
print("GV n=7 d=3: some code has M >=", 2**7 / sum(comb(7, i) for i in range(3)))

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

R3: n=3 M=2 d=3, detect 2, correct 1
   M*V=8 vs 2^n=8 PERFECT; Singleton M <= 2
R5: n=5 M=2 d=5, detect 4, correct 2
   M*V=32 vs 2^n=32 PERFECT; Singleton M <= 2
parity-4: n=4 M=8 d=2, detect 1, correct 0
   M*V=8 vs 2^n=16; Singleton M <= 8
Ham(7,4): n=7 M=16 d=3, detect 2, correct 1
   M*V=128 vs 2^n=128 PERFECT; Singleton M <= 32
exam C: n=5 M=4 d=3, detect 2, correct 1
   M*V=24 vs 2^n=32; Singleton M <= 8
Golay(23,12), t=3: True
GV n=7 d=3: some code has M >= 4.413793103448276

“detect” আর “correct” দুটি আলাদা মোডের ক্ষমতা (উপপাদ্য ৩.৩)। R3, R5 আর Hamming(7,4)-এ M·V = 2n, তাই তিনটিই perfect. parity-4-এ d = 2: একটি error ধরে, কিছুই শোধরায় না (t = 0, বল মানে শুধু কেন্দ্র)। এটি Singleton-এ ঠিক সমতায় (M = 8), কিন্তু Hamming bound-এ অনেক ফাঁক। “exam C” §৮-এর অঙ্ক ১-এর code: 24 < 32, perfect নয়। span ফাংশন generator matrix-এর সারিগুলোর সব XOR-যোগ বানায়, অর্থাৎ §৫-এর linear code. Golay-এর সমতা পূর্ণসংখ্যায় হুবহু মিলেছে। GV-র 4.41 মানে নিশ্চিতভাবে অন্তত 5টি codeword-এর code আছে।

৫ · Linear code — matrix দিয়ে code

এলোমেলো code-এ M-টি codeword-এর তালিকা রাখতে আর প্রতিটি প্রাপ্ত শব্দকে সবার সঙ্গে মেলাতে হয়; k = 50 হলে তালিকায় 250টি শব্দ, অচল। বীজগণিত এখানে বাঁচায়। {0, 1}-এ ⊕ (XOR, অর্থাৎ যোগ mod 2) আর AND (গুণ) নিয়ে GF(2), সবচেয়ে ছোট finite field (পর্ব ৩০; ring আর field-এর গভীর কাঠামো পর্ব ৭১ “Ring আর field — modular ring, polynomial আর GF(2ⁿ)”-এ)। তাহলে {0, 1}n একটি vector space: শব্দ যোগ হয় ঘরে ঘরে XOR দিয়ে।

সংজ্ঞা ৫.১ (linear code)

C ⊆ {0, 1}n linear, যদি যেকোনো দুটি codeword-এর XOR-ও codeword হয় (তাহলে c ⊕ c = 0 থেকে শূন্য শব্দও codeword). অর্থাৎ C একটি subspace; তার dimension k হলে M = 2k, আর code-টিকে [n, k, d] code লেখা হয়।

উপপাদ্য ৫.২ (linear code-এ d = সর্বনিম্ন weight)

Linear code C-এ d(C) = শূন্য নয় এমন codeword-এর সবচেয়ে ছোট weight.

  1. আলাদা c, c′ ∈ C-এর জন্য d(c, c′) = w(c ⊕ c′), আর c ⊕ c′ একটি শূন্য-নয় codeword (linear). তাই প্রতিটি দূরত্ব কোনো শূন্য-নয় codeword-এর weight. — সংজ্ঞা ৩.১
  2. উল্টো দিকে, শূন্য-নয় c-এর weight w(c) = d(c, 0), আর 0 ∈ C, তাই প্রতিটি weight কোনো দুই codeword-এর দূরত্ব। দুই সেট সমান, তাই সর্বনিম্নও সমান। ∎ — উভয় দিক

লাভ: d বের করতে M(M − 1)/2টি জোড়ার বদলে M − 1টি weight দেখলেই চলে।

সংজ্ঞা ৫.৩ (generator আর parity-check matrix)

C-এর একটি basis-কে সারি করে বানানো k × n matrix G হলো generator matrix: data u ∈ {0, 1}k-এর codeword c = uG (সব হিসাব mod 2). (n − k) × n matrix H হলো parity-check matrix, যদি c ∈ C ⇔ HcT = 0. প্রাপ্ত শব্দ r-এর syndrome s = HrT.

uG মানে u-তে যেসব অবস্থানে 1, G-এর সেই সারিগুলোর XOR (পর্ব ১৯-এর matrix গুণ, যোগটা শুধু mod 2). Syndrome-এর জাদু এক লাইনে: r = c ⊕ e হলে s = HcT ⊕ HeT = HeT. Syndrome শুধু error-এর ওপর নির্ভর করে, কোন codeword পাঠানো হয়েছিল তার ওপর নয়। তাই decoder একটি ছোট table রাখে: প্রতিটি syndrome-এর জন্য সবচেয়ে কম weight-এর error. একে syndrome decoding বলে। (Group-এর ভাষায় C হলো ({0, 1}n, ⊕)-এর একটি subgroup, আর একই syndrome-এর শব্দগুলো C-এর একটি coset; coset যে space-কে ভাগ করে, তা পর্ব ৫৫-এর partition, আর পর্ব ৭০ “Group — symmetry, cyclic group আর Lagrange-এর উপপাদ্য”-এ এর সাধারণ রূপ।)

উপপাদ্য ৫.৪ (H-এর column থেকে d)

d(C) = H-এর সবচেয়ে কম সংখ্যক column, যাদের যোগফল (mod 2) শূন্য।

প্রমাণ: c-এর যেসব অবস্থানে 1, HcT ঠিক H-এর সেই column-গুলোর যোগ। তাই weight w-এর codeword আছে ⇔ H-এর কোনো w-টি column-এর যোগ শূন্য। উপপাদ্য ৫.২ বাকিটা দেয়। ∎

৬ · Hamming(7,4) — syndrome বলে দেয় কোন বিট ভুল

উপপাদ্য ৫.৪ একটি নকশার নির্দেশ দেয়: d ≥ 3 চাইলে H-এর কোনো column শূন্য হবে না (নইলে weight 1-এর codeword) আর কোনো দুটি column সমান হবে না (নইলে তাদের যোগ শূন্য, weight 2). ৩ সারির column শূন্য-নয় এমন মাত্র 23 − 1 = 7টি। সবকটি নিন, আর j-তম column-এ j-এর binary রূপ বসান:

H1234567
s4 (৪-এর বিট)0001111
s2 (২-এর বিট)0110011
s1 (১-এর বিট)1010101

অবস্থান 1, 2, 4 (২-এর ঘাত) parity বিট p1, p2, p4; অবস্থান 3, 5, 6, 7-এ data বিট d1, d2, d3, d4. H-এর প্রতিটি সারি বলে কোন অবস্থানগুলোর XOR শূন্য হতে হবে: p1 দেখে অবস্থান 1, 3, 5, 7 (যাদের binary রূপে ১-এর বিট 1); p2 দেখে 2, 3, 6, 7; p4 দেখে 4, 5, 6, 7. Richard Hamming-এর ১৯৫০ সালের প্রবন্ধে বর্ণিত বিন্যাস এটাই। Data-র চারটি একক শব্দ encode করলে G-এর সারি: d1 → 1110000, d2 → 1001100, d3 → 0101010, d4 → 1101001.

উপপাদ্য ৬.১ (Hamming(7,4)-এর ধর্ম)

এটি একটি [7, 4, 3] linear code; এটি perfect; আর অবস্থান j-তে একটিমাত্র error হলে syndrome (s4s2s1) হলো j-এর binary রূপ।

  1. কোনো column শূন্য নয়, তাই weight 1-এর codeword নেই; সব column আলাদা, তাই দুটির যোগ শূন্য নয়, weight 2-এর codeword নেই। — উপপাদ্য ৫.৪
  2. Column 1, 2, 3 = 001, 010, 011, যোগ 000; তাই 1110000 একটি weight-3 codeword (এটি G-এর প্রথম সারি)। অতএব d = 3. — উপপাদ্য ৫.৪
  3. H-এর তিনটি সারি স্বাধীন (column 1, 2, 4 একক ভেক্টর), তাই parity শর্ত তিনটি আর dimension k = 7 − 3 = 4, M = 16. 16 · V(7, 1) = 16 · 8 = 128 = 27: perfect. — উপপাদ্য ৪.১-এ সমতা
  4. e = অবস্থান j-তে একটি 1 হলে syndrome HeT = H-এর j-তম column = j-এর binary রূপ। ∎ — syndrome-এর সূত্র

বাজারঘরের একটি অর্ডারের পরিমাণ-কোড 1011 পাঠানো যাক।

1data d1 d2 d3 d4 = 10112pos 3,5,6,7 ← 1,0,1,13p1 = c3 ⊕ c5 ⊕ c74p2 = c3 ⊕ c6 ⊕ c75p4 = c5 ⊕ c6 ⊕ c76codeword = 0110011
অবস্থান 1 থেকে 7
শব্দ
হিসাব
  1. ঘর সাজানো। সাতটি অবস্থান; 1, 2, 4-এ parity বিট বসবে, 3, 5, 6, 7-এ data. Data 1011, অর্থাৎ d1 = 1, d2 = 0, d3 = 1, d4 = 1.
  2. Data বসানো। অবস্থান 3-এ 1, 5-এ 0, 6-এ 1, 7-এ 1. Parity-র ঘর এখনো ফাঁকা।
  3. p1. অবস্থান 1, 3, 5, 7-এর XOR শূন্য হতে হবে, তাই p1 = c3 ⊕ c5 ⊕ c7 = 1 ⊕ 0 ⊕ 1 = 0.
  4. p2. অবস্থান 2, 3, 6, 7: p2 = 1 ⊕ 1 ⊕ 1 = 1.
  5. p4. অবস্থান 4, 5, 6, 7: p4 = 0 ⊕ 1 ⊕ 1 = 0.
  6. Codeword. 0110011. যাচাই: G-এর সারি 1, 3, 4 (d1, d3, d4 = 1) XOR করলে 1110000 ⊕ 0101010 ⊕ 1101001 = 0110011, একই। Weight 4, শূন্য-নয় codeword-এর weight 3, 4 বা 7 হয় (নিচের কোডে)।

পথে অবস্থান 5-এর বিটটি উল্টে গেল। গ্রাহক কী করে?

1r = 01101112s1 = r1 ⊕ r3 ⊕ r5 ⊕ r73s2 = r2 ⊕ r3 ⊕ r6 ⊕ r74s4 = r4 ⊕ r5 ⊕ r6 ⊕ r75s = 101 → flip bit 56data = r3 r5 r6 r7
Decoder-এর অবস্থা
শব্দ
s4 s2 s1
হিসাব
  1. প্রাপ্ত শব্দ। পাঠানো হয়েছিল 0110011, এসেছে 0110111: অবস্থান 5-এর 0 হয়ে গেছে 1. গ্রাহক তা জানে না।
  2. প্রথম parity পরীক্ষা। অবস্থান 1, 3, 5, 7: 0 ⊕ 1 ⊕ 1 ⊕ 1 = 1. শূন্য হওয়ার কথা ছিল, তাই s1 = 1.
  3. দ্বিতীয়। অবস্থান 2, 3, 6, 7: 1 ⊕ 1 ⊕ 1 ⊕ 1 = 0, তাই s2 = 0; এই দলের সব বিট ঠিক আছে।
  4. তৃতীয়। অবস্থান 4, 5, 6, 7: 0 ⊕ 1 ⊕ 1 ⊕ 1 = 1, তাই s4 = 1.
  5. অবস্থান পড়া। s4s2s1 = 101, binary-তে 5 (উপপাদ্য ৬.১). অবস্থান 5 উল্টে পাই 0110011, আসল codeword. Syndrome 000 হলে কোনো বিট বদলানো হতো না।
  6. Data বের করা। অবস্থান 3, 5, 6, 7 থেকে 1, 0, 1, 1: data 1011 ফেরত এল। গ্রাহক তিনটি XOR গুনেই কাজ সারল, কোনো তালিকা খুঁজতে হয়নি।

নিচের ব্লক একই encoder আর decoder লেখে, তারপর সব 16 × 7 = 112টি একক error আর সব 16 × 21 = 336টি দ্বৈত error পরীক্ষা করে।

from itertools import product, combinations
G = ["1110000", "1001100", "0101010", "1101001"]   # rows for data bits d1..d4
def encode(data):                      # XOR of the rows picked by the data bits
    c = 0
    for bit, row in zip(data, G):
        if bit == "1":
            c ^= int(row, 2)
    return format(c, "07b")
def syndrome(r):                       # XOR of the positions (1..7) holding a 1
    s = 0
    for pos, bit in enumerate(r, start=1):
        if bit == "1":
            s ^= pos
    return s
def flip(w, i):
    return w[:i] + ("1" if w[i] == "0" else "0") + w[i + 1:]
def decode(r):
    s = syndrome(r)
    if s:
        r = flip(r, s - 1)             # syndrome = position of the error
    return r[2] + r[4] + r[5] + r[6]   # data sits at positions 3, 5, 6, 7
c = encode("1011"); r = flip(c, 4)
print("1011 ->", c, "| received", r, "syndrome", format(syndrome(r), "03b"), "->", decode(r))
code = {encode("".join(d)): "".join(d) for d in product("01", repeat=4)}
print("codewords:", len(code), "weights:", sorted({w.count("1") for w in code}))
ok1 = all(decode(flip(c, i)) == d for c, d in code.items() for i in range(7))
print("all 16 x 7 single errors corrected:", ok1)
bad2 = sum(decode(flip(flip(c, i), j)) != d
           for c, d in code.items() for i, j in combinations(range(7), 2))
print("double errors decoded wrongly:", bad2, "of", 16 * 21)

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

1011 -> 0110011 | received 0110111 syndrome 101 -> 1011
codewords: 16 weights: [0, 3, 4, 7]
all 16 x 7 single errors corrected: True
double errors decoded wrongly: 336 of 336

প্রথম লাইন দুই stepper হুবহু: 1011 থেকে 0110011, বিট 5 উল্টালে syndrome 101, আর data 1011 ফেরত। শূন্য-নয় codeword-এর weight 3, 4 বা 7, সবচেয়ে ছোট 3: উপপাদ্য ৫.২ অনুযায়ী d = 3. ১১২টি একক error-এর প্রতিটি শুধরেছে। কিন্তু ৩৩৬টি দ্বৈত error-এর প্রতিটিতে ভুল data বেরিয়েছে। কারণ code-টি perfect: প্রতিটি শব্দ ঠিক একটি codeword-এর ব্যাসার্ধ-1 বলে, তাই দুই-error-এর শব্দও কোনো (ভুল) codeword-এর বলে পড়ে, আর decoder আত্মবিশ্বাসের সঙ্গে আরেকটি বিট উল্টে তৃতীয় error যোগ করে। দুটি error-এর সম্ভাবনা কম হলেও এটি বাস্তবে বিপজ্জনক; §৭ এর প্রতিকার দেখায়।

সাধারণভাবে r-টি parity বিটে H-এর column হিসেবে 2r − 1টি শূন্য-নয় ভেক্টর বসানো যায়, তাই Hamming code-এর দৈর্ঘ্য n = 2r − 1 আর k = n − r: (7, 4), (15, 11), (31, 26), … প্রতিটিই perfect, কারণ 2k(1 + n) = 2n−r · 2r = 2n. k-বিট data-র জন্য একটি error শোধরাতে কয়টি parity বিট লাগে? সব একক error আর “error নেই” আলাদা করতে 2r ≥ k + r + 1 লাগে, আর Hamming-এর নির্মাণ দেখায় সেটাই যথেষ্ট।

৭ · SECDED, বাস্তবের code আর Shannon-এর সীমা

একটি বিট বেশি, অনেক নিরাপত্তা বেশি

Hamming(7,4)-এর শেষে পুরো শব্দের একটি parity বিট যোগ করলে extended Hamming code (8,4) পাওয়া যায়। weight 3-এর codeword weight 4 হয়, weight 4 আর 0 যেমন ছিল থাকে, আর 7 হয় 8; তাই সব codeword-এর weight জোড় আর d = 4 (প্রমাণ অনুশীলন ১-এ)। উপপাদ্য ৩.৩-এর সাধারণ রূপে t = 1, s = 2: d ≥ 1 + 2 + 1 = 4. তাই code-টি একসঙ্গে একটি error শোধরায় আর দুটি error ধরে, এর নাম SECDED (single error correction, double error detection). Decoder-এর নিয়ম:

Syndrome s (প্রথম ৭ বিট)মোট parityসিদ্ধান্ত
0জোড়error নেই
যেকোনোবিজোড়একটি error: s ≠ 0 হলে অবস্থান s, s = 0 হলে শেষের parity বিট উল্টে শোধরানো হয়
≠ 0জোড়দুটি error: ধরা পড়ল, শোধরানো হয় না
from itertools import product, combinations
G = ["1110000", "1001100", "0101010", "1101001"]
def encode8(data):                     # Hamming(7,4) word + overall parity bit
    c = 0
    for bit, row in zip(data, G):
        if bit == "1":
            c ^= int(row, 2)
    w = format(c, "07b")
    return w + str(w.count("1") % 2)
def secded(r):                         # returns (verdict, corrected word)
    s = 0
    for pos, bit in enumerate(r[:7], start=1):
        if bit == "1":
            s ^= pos
    odd = r.count("1") % 2             # overall parity of all 8 bits
    if s == 0 and not odd:
        return "ok", r
    if odd:                            # odd number of flips: assume one, fix it
        i = s - 1 if s else 7          # s = 0 means the parity bit itself
        return "fixed", r[:i] + str(1 - int(r[i])) + r[i + 1:]
    return "double", r                 # even flips, s != 0: detect, do not fix
def flips(w, idx):
    return "".join(str(1 - int(b)) if i in idx else b for i, b in enumerate(w))
code = [encode8("".join(d)) for d in product("01", repeat=4)]
print("weights:", sorted({c.count("1") for c in code}), "| 1011 ->", encode8("1011"))
for k in (1, 2, 3):
    tally = {}
    for c in code:
        for idx in combinations(range(8), k):
            v, out = secded(flips(c, idx))
            key = v + ("" if v != "fixed" else (" right" if out == c else " wrong"))
            tally[key] = tally.get(key, 0) + 1
    print(k, "error(s):", dict(sorted(tally.items())))

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

weights: [0, 4, 8] | 1011 -> 01100110
1 error(s): {'fixed right': 128}
2 error(s): {'double': 448}
3 error(s): {'fixed wrong': 896}

Weight শুধু 0, 4, 8: d = 4. ১২৮টি একক error (16 × 8) সবই ঠিকভাবে শুধরেছে; ৪৪৮টি দ্বৈত error (16 × 28) সবই “double” বলে ধরা পড়েছে, একটিকেও ভুল শোধরানো হয়নি, যেখানে Hamming(7,4) ৩৩৬টির সবকটিতে ভুল করেছিল। তিনটি error-এ (16 × 56 = 896) decoder প্রতিবার বিজোড় parity দেখে একটি বিট “শোধরায়”, আর ভুল করে: d = 4-এর code তিন error থেকে রক্ষা দেয় না, যা উপপাদ্য ৩.৩-এর সঙ্গে মেলে।

বাস্তবে কোথায়

সার্ভারের ECC memory-তে প্রতি 64 data বিটে 8টি check বিটের (72, 64) SECDED বিন্যাস বহুল প্রচলিত বলে বর্ণিত; 27 = 128 ≥ 64 + 7 + 1, তাই একক error-এর জন্য 7টি, আর দ্বৈত error ধরতে আরও 1টি। হার্ডওয়্যারের দিক Computer Architecture কোর্সের পর্ব ৪৯-এ। নেটওয়ার্কে সাধারণত CRC দিয়ে error ধরে আবার পাঠানো হয়; parity, checksum, CRC আর Hamming-এর ব্যবহারিক দিক Computer Networks কোর্সের পর্ব ৯-এ, আর ASCII-র সঙ্গে parity বিট Computer Fundamentals কোর্সের পর্ব ১৮-এ। CD, DVD আর QR code-এ Reed–Solomon code ব্যবহৃত হয় বলে বহুল নথিভুক্ত: তার চিহ্ন বিট নয়, GF(28)-এর উপাদান (একটি byte), তাই একটি আঁচড়ে পরপর অনেক বিট নষ্ট হলেও তা অল্প কয়েকটি চিহ্নের error, আর code Singleton bound-এ সমতা দেয়। QR code-এ L, M, Q, H নামের চারটি সুরক্ষা-স্তর আছে, যা মোটামুটি ৭% থেকে ৩০% পর্যন্ত চিহ্ন-ক্ষতি সামলাতে পারে বলে মানদণ্ডে বর্ণিত।

Shannon-এর channel coding উপপাদ্য

Repetition code-এ error কমাতে rate শূন্যে নামাতে হয়েছিল। এটা কি অনিবার্য? Claude Shannon-এর ১৯৪৮ সালের প্রবন্ধ “A Mathematical Theory of Communication” বলে, না। BSC(p)-র channel capacity

C = 1 − H2(p), যেখানে H2(p) = −p log2 p − (1 − p) log2(1 − p),

আর H2 হলো পর্ব ৬৮-এর entropy, দুই ফলের জন্য। উপপাদ্য (এখানে প্রমাণ নয়, শুধু বক্তব্য): যেকোনো rate R < C-এ এমন code আছে, যার decoding-ভুলের সম্ভাবনা n বাড়ালে যত খুশি ছোট হয়; R > C-এ তা অসম্ভব। p = 0.01-এ C ≈ 0.919, p = 0.1-এ C ≈ 0.531 (scratch-এ গোনা)। মজার তুলনা: Hamming(7,4)-এর rate 4/7 ≈ 0.571, যা p = 0.1-এর capacity-র চেয়ে বেশি; সেই channel-এ এই rate-এ কোনো code দিয়েই error যত খুশি কমানো যাবে না। Shannon-এর প্রমাণ এলোমেলো code বেছে গড় নেয় (পর্ব ৪৩-এর probabilistic method-এর ধাঁচ), তাই এটি অস্তিত্ব দেখায়, কোনো নির্দিষ্ট code নয়।

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

অঙ্ক ১: একটি code বিশ্লেষণ

C = {00000, 01011, 10101, 11110}. (ক) d(C) কত? (খ) কয়টি error ধরে, কয়টি শোধরায়? (গ) C কি linear? (ঘ) Perfect কি না।

  1. (ক) ছয়টি জোড়ার দূরত্ব: 3, 3, 4, 4, 3, 3. তাই d = 3.
  2. (খ) d − 1 = 2টি ধরে, অথবা ⌊(3 − 1)/2⌋ = 1টি শোধরায়।
  3. (গ) 01011 ⊕ 10101 = 11110, আর যেকোনো শব্দ নিজের সঙ্গে XOR করলে 00000; চারটি শব্দ XOR-এ বদ্ধ, তাই linear, k = 2. শূন্য-নয় weight 3, 3, 4: সর্বনিম্ন 3, (ক)-এর সঙ্গে মেলে (উপপাদ্য ৫.২)।
  4. (ঘ) M · V(5, 1) = 4 × 6 = 24 < 32: perfect নয়; Hamming bound বলে দৈর্ঘ্য 5-এ single-error-correcting code-এ বড়জোর ⌊32/6⌋ = 5টি codeword. (§৪-এর কোডে মেলানো।)

অঙ্ক ২: কয়টি parity বিট

k = 8, 11, 32, 64 data বিটে একক error শোধরাতে সর্বনিম্ন কয়টি parity বিট r লাগে? SECDED-এ কয়টি?

  1. শর্ত 2r ≥ k + r + 1. k = 8: r = 3-এ 8 < 12, r = 4-এ 16 ≥ 13, তাই 4. k = 11: 16 ≥ 16, 4 (সমতা, তাই (15, 11) perfect).
  2. k = 32: r = 5-এ 32 < 38, r = 6-এ 64 ≥ 39, তাই 6. k = 64: r = 6-এ 64 < 71, r = 7-এ 128 ≥ 72, তাই 7.
  3. SECDED-এ একটি করে বেশি: 5, 5, 7, 8. শেষেরটিই (72, 64). (scratch-এ লুপ দিয়ে মেলানো।)

অঙ্ক ৩: repetition-এর হিসাব আর Hamming decode

(ক) p = 0.1-এ R5-এর ব্যর্থতা: 3, 4 বা 5টি উল্টাতে হবে: 10p3(1 − p)2 + 5p4(1 − p) + p5 = 0.0081 + 0.00045 + 0.00001 = 0.00856 (§২-এর কোডে একই)। (খ) Hamming(7,4)-এ প্রাপ্ত 1011011. 1-ওয়ালা অবস্থান 1, 3, 4, 6, 7; তাদের XOR 1 ⊕ 3 ⊕ 4 ⊕ 6 ⊕ 7 = 7, তাই অবস্থান 7 উল্টে 1011010, data (অবস্থান 3, 5, 6, 7) = 1010. যাচাই: 1010-এর encoding G-এর সারি 1 ⊕ সারি 3 = 1011010.

প্রমাণের ভুল ধরুন: “Hamming bound মানলেই code আছে”

একজন লিখলেন: “দৈর্ঘ্য 4, d = 3, M = 3 চাই। t = 1, V(4, 1) = 5, আর 3 × 5 = 15 ≤ 16. Hamming bound মানে, তাই এমন code আছে।”

ভুল কোথায়: উপপাদ্য ৪.১ একটি প্রয়োজনীয় শর্ত: code থাকলে অসমতা সত্য। উল্টো দিক (“অসমতা সত্য হলে code আছে”) কোথাও প্রমাণ হয়নি; এটি converse গুলিয়ে ফেলা। সত্যিই এমন code নেই: 0000 নিলে অন্য দুটি codeword-এর weight অন্তত 3, অর্থাৎ 0000 থেকে দূরত্ব ≥ 3, তাই তারা 1110, 1101, 1011, 0111, 1111-এর মধ্যে; এদের যেকোনো দুটির দূরত্ব বড়জোর 2. সব 4-বিট শব্দের brute force-এও সর্বোচ্চ M = 2 আসে (scratch-এ মেলানো)। অস্তিত্বের নিশ্চয়তা চাইলে Gilbert–Varshamov লাগে, আর এখানে তা দেয় 16/V(4, 2) = 16/11, অর্থাৎ M ≥ 2.

(যুক্তিতে “শূন্য শব্দ নিলে” বলা চলে, কারণ যেকোনো code-এর সব শব্দে একই শব্দ x XOR করলে দূরত্ব বদলায় না, আর একটি codeword শূন্য হয়ে যায়।)

আরও গভীরে: অতুচ্ছ binary perfect code-এর প্রাচল কেবল Hamming code আর (23, 12) Golay code-এর মতো হতে পারে; ১৯৭০-এর দশকে Tietäväinen আর van Lint-এর কাজে (স্বাধীনভাবে Zinoviev আর Leontiev-ও) এই শ্রেণিবিভাগ সম্পূর্ণ হয় বলে উল্লেখ করা হয়। Shannon-এর capacity-র কাছে পৌঁছানো বাস্তব code এসেছে অনেক পরে: ১৯৯৩ সালের turbo code, Gallager-এর ১৯৬০-এর দশকের LDPC code-এর পুনরাবিষ্কার, আর Arıkan-এর ২০০৯ সালের polar code, যার শেষ দুটি আধুনিক মোবাইল নেটওয়ার্কের মানদণ্ডে জায়গা পেয়েছে বলে বর্ণিত। Cyclic code (যেমন CRC আর Reed–Solomon) code-কে polynomial ring-এর ideal হিসেবে দেখে, যা পর্ব ৭১-এর বীজগণিতের সরাসরি প্রয়োগ।

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

  • Minimum distance 5-এর code কয়টি error শোধরায়? ⌊(5 − 1)/2⌋ = 2; শুধু ধরলে 4.
  • Hamming(7,4)-এ syndrome 110 মানে? অবস্থান 6-এর বিট উল্টেছে; সেটি উল্টে দিন।
  • ৮টি data বিটে কয়টি Hamming parity বিট? 4, কারণ 24 = 16 ≥ 8 + 4 + 1.
  • Perfect code কী? ব্যাসার্ধ t-এর বলগুলো পুরো space ঠিক একবার ঢাকে: M · V(n, t) = 2n.
  • Linear code-এ d দ্রুত কীভাবে? শূন্য-নয় codeword-এর সর্বনিম্ন weight, বা H-এর সর্বনিম্ন সংখ্যক column যাদের যোগ শূন্য।

৯ · AI-এর যুগে — code-এর হিসাব যাচাই

AI সহকারী Hamming code-এর ধারণা ঠিকঠাক বোঝায়, কিন্তু অবস্থান-গণনা, শর্ত আর সীমার দিকনির্ণয়ে নিয়মিত ভুল করে। কয়েকটি পরিচিত ভুল আর ধরার উপায়:

AI-এর ভুলকীভাবে ধরবেন
অবস্থান 0 থেকে গুনে syndrome-কে এক ঘর সরিয়ে পড়া, বা parity বিট কোন অবস্থানগুলো দেখে তা গুলিয়ে ফেলাএকটি codeword-এ প্রতিটি অবস্থান একবার করে উল্টে syndrome মেলান; ৭টিই আলাদা আর সঠিক হওয়া চাই
“d = 4, তাই দুটি error শোধরায়” বা ধরা আর শোধরানো একসঙ্গে যোগ করা⌊(d − 1)/2⌋ গুনুন; দূরত্ব d-এর দুটি codeword-এর মাঝের শব্দ বানিয়ে দেখুন
Hamming bound-কে অস্তিত্বের প্রমাণ ধরাn = 4, d = 3, M = 3-এর মতো ছোট ক্ষেত্রে brute force চালান
Binomial যোগে সীমা ভুল (k ≥ n/2 বনাম k > n/2), বা p আর 1 − p অদলবদলR3-এ 3p2 − 2p3 আসে কি না, আর seed-বাঁধা simulation কাছাকাছি কি না দেখুন
বাস্তব মানদণ্ডের সংখ্যা (QR-এর স্তর, ECC-এর বিন্যাস) বা সাল আত্মবিশ্বাসের সঙ্গে বানানোমূল মানদণ্ড বা বিশ্বস্ত পাঠ্যবইয়ে মেলান; না পেলে “অনিশ্চিত” লিখুন

AI-এর কাছে coding theory-র প্রশ্ন করলে এমন কাঠামো দিন, যাতে প্রতিটি দাবি আলাদা করে যাচাই করা যায়:

নিচের coding theory-র প্রশ্নের উত্তর ধাপে ধাপে দাও: প্রশ্ন: [যেমন "Hamming(7,4)-এ প্রাপ্ত 1101101 decode করো"] ১. অবস্থান 1 থেকে গোনো, আর কোন parity বিট কোন অবস্থানগুলো দেখে তা আগে তালিকা করো। ২. প্রতিটি syndrome বিটের XOR আলাদা লাইনে লেখো, তারপর পুরো syndrome আর তার দশমিক মান। ৩. কোনো উপপাদ্য (Hamming bound, Singleton, d ও t-এর সম্পর্ক) ব্যবহার করলে তার শর্ত লেখো, আর সেটি প্রয়োজনীয় না যথেষ্ট শর্ত তা বলো। ৪. "ধরা" আর "শোধরানো" মোড আলাদা রাখো; একসঙ্গে দুটো দাবি করলে d ≥ t + s + 1 দেখাও। ৫. শুধু itertools আর math দিয়ে সব একক error পরীক্ষা করার একটি ছোট Python কোড দাও, যাতে আমি নিজে চালাতে পারি। ৬. কোনো মানদণ্ড, সাল বা নামের তথ্য নিয়ে নিশ্চিত না হলে স্পষ্ট বলো।

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

Code-এর হিসাব যাচাই সহজ, কারণ space ছোট হলে সব error-pattern গুনে ফেলা যায়: ৭ বিটে মাত্র 128টি শব্দ। দাবি যত বড়ই হোক, ছোট ক্ষেত্রে পূর্ণ গণনা তাকে পরীক্ষা করতে পারে।

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

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

প্র ০১সপ্তাহান্তে বারবার থেমে যাওয়া একটি যন্ত্র কীভাবে Hamming code-এর জন্ম দিল?

১৯৪০-এর দশকের শেষে Richard Hamming Bell Telephone Laboratories-এ কাজ করতেন। তখনকার relay-ভিত্তিক কম্পিউটার punched card থেকে ইনপুট পড়ত, আর কিছু parity-ধাঁচের পরীক্ষা দিয়ে error ধরতে পারত। প্রচলিত বিবরণ অনুযায়ী, কর্মদিবসে error ধরা পড়লে অপারেটর এসে সমস্যা ঠিক করতেন; কিন্তু সপ্তাহান্তে যন্ত্র একা চলত, আর error ধরা পড়লে সে কাজটি বাদ দিয়ে পরেরটিতে চলে যেত। Hamming-এর দীর্ঘ হিসাব বারবার এভাবে নষ্ট হয়। তাঁর বলে উদ্ধৃত বিরক্ত প্রশ্নটি অনেকে উল্লেখ করেন: যন্ত্র যদি error আছে বলে বুঝতে পারে, তবে কোথায় আছে বুঝে ঠিক করতে পারবে না কেন?

এই প্রশ্নের উত্তরই §৬-এর নির্মাণ। একটি parity বিট শুধু বলে “কিছু ভুল আছে”। কয়েকটি parity বিট যদি অবস্থানের আলাদা আলাদা দল দেখে, আর দলগুলো এমনভাবে সাজানো হয় যে প্রতিটি অবস্থান একটি অনন্য দল-সমষ্টিতে পড়ে, তবে কোন পরীক্ষাগুলো ব্যর্থ হলো, সেই প্যাটার্নই অবস্থানের binary নাম। H-এর j-তম column-এ j-এর binary রূপ বসানো ঠিক এই ধারণার গাণিতিক রূপ।

Hamming-এর প্রবন্ধ “Error Detecting and Error Correcting Codes” ১৯৫০ সালে Bell System Technical Journal-এ প্রকাশিত হয়। একই সময়ে Marcel Golay ১৯৪৯ সালে একটি ছোট নোটে Hamming code-এর সাধারণীকরণ আর বিখ্যাত (23, 12) code প্রকাশ করেন; কে কোন ধারণা আগে পেয়েছিলেন, সে বিষয়ে ইতিহাসবিদরা সাবধানে লেখেন, কারণ Shannon-এর ১৯৪৮ সালের প্রবন্ধেও Hamming-এর (7, 4) উদাহরণের উল্লেখ আছে বলে জানা যায়।

গল্পটির একটি গভীর শিক্ষা আছে: সীমাবদ্ধতা থেকে প্রশ্ন, আর প্রশ্ন থেকে তত্ত্ব। Hamming পরে “The Art of Doing Science and Engineering” নামের বক্তৃতামালায় গবেষণার পদ্ধতি নিয়ে লিখেছেন; তাঁর পরামর্শ ছিল গুরুত্বপূর্ণ সমস্যা খোঁজা আর বিরক্তিকর অভিজ্ঞতাকে প্রশ্নে বদলানো।

মূল উপলব্ধি: ধরা থেকে শোধরানোয় যাওয়ার চাবি হলো কয়েকটি parity পরীক্ষাকে এমনভাবে সাজানো যাতে ব্যর্থতার প্যাটার্ন নিজেই error-এর অবস্থান হয়; Hamming(7,4) তার সবচেয়ে ছোট আর পরিপাটি রূপ।

প্র ০২Shannon দেখালেন ভালো code আছে, কিন্তু বানালেন না। প্রায় পঞ্চাশ বছর লাগল কেন?

১৯৪৮ সালে Claude Shannon প্রমাণ করেন, capacity C-এর নিচের যেকোনো rate-এ error যত খুশি কমানো যায়। প্রমাণের কৌশল চমকপ্রদ: তিনি কোনো নির্দিষ্ট code বানাননি, বরং 2nRটি codeword এলোমেলোভাবে বেছে নেন আর দেখান যে গড়ে এমন code-এর ভুলের সম্ভাবনা ছোট। গড় ছোট হলে অন্তত একটি code-এর ভুলও ছোট; এটি পর্ব ৪৩-এর probabilistic method-এর একটি প্রাথমিক ও বিখ্যাত ব্যবহার। কিন্তু অস্তিত্ব জানা আর ব্যবহারযোগ্য code পাওয়া এক কথা নয়।

এলোমেলো code-এ দুটি বাধা। প্রথমত, সংরক্ষণ: 2nRটি এলোমেলো শব্দের তালিকা n = 1000-এ অকল্পনীয় বড়। Linear code এই সমস্যা মেটায়, কারণ k × n matrix G-ই পুরো code; আর জানা যায় এলোমেলো linear code-ও গড়ে capacity-র কাছে যায়। দ্বিতীয় বাধা কঠিনতর: decoding. সাধারণ linear code-এ “সবচেয়ে কাছের codeword খোঁজা” সমস্যাটি NP-কঠিন বলে প্রমাণিত (Berlekamp, McEliece আর van Tilborg, ১৯৭৮)। তাই এমন কাঠামো লাগে, যা decoding-কে দ্রুত করে।

পরের কয়েক দশক বীজগাণিতিক কাঠামোর যুগ: Reed–Muller, BCH (১৯৫৯–৬০), Reed–Solomon (১৯৬০), আর convolutional code ও Viterbi-র decoding (১৯৬৭)। এগুলো ভালো ও কার্যকর, কিন্তু capacity থেকে বেশ দূরে থাকত। ১৯৯৩ সালে Berrou, Glavieux আর Thitimajshima-র turbo code দেখায় যে পুনরাবৃত্ত, সম্ভাবনাভিত্তিক decoding দিয়ে capacity-র খুব কাছে যাওয়া যায়। এর পর পরই দেখা গেল Robert Gallager তাঁর ১৯৬০-এর দশকের গোড়ার গবেষণায় LDPC code-এ প্রায় একই রকম ধারণা দিয়েছিলেন, যা তখনকার কম্পিউটারের জন্য বেশি ভারী ছিল বলে চাপা পড়ে যায়। ২০০৯ সালে Erdal Arıkan-এর polar code প্রথম এমন নির্মাণ, যা BSC-এর মতো channel-এ capacity অর্জন করে বলে প্রমাণিত।

এই ইতিহাস বিচ্ছিন্ন গণিতের একটি সাধারণ সত্যও দেখায়: অস্তিত্বের প্রমাণ প্রায়ই সহজ, নির্মাণ কঠিন, আর দক্ষ নির্মাণ আরও কঠিন।

মূল উপলব্ধি: Shannon-এর এলোমেলো code-এর যুক্তি দেখায় ভালো code প্রচুর, কিন্তু সংরক্ষণ আর বিশেষ করে decoding-এর জটিলতা ভাঙতে বীজগাণিতিক ও সম্ভাবনাভিত্তিক কাঠামো লেগেছে, আর তাতে প্রায় অর্ধশতাব্দী।

প্র ০৩Perfect code এত বিরল কেন? Golay-এর (23, 12) code-এ এমন কী বিশেষ?

Perfect code-এর শর্ত একটি সংখ্যাতাত্ত্বিক সমীকরণ: M · V(n, t) = 2n. অর্থাৎ V(n, t) = C(n, 0) + ⋯ + C(n, t)-কে 2-এর একটি ঘাত হতে হবে। t = 1-এ 1 + n = 2r, তাই n = 2r − 1, ঠিক Hamming code-এর দৈর্ঘ্য। t = 3-এ শর্ত 1 + n + C(n, 2) + C(n, 3) = 2r; n = 23-এ এটি 2048 = 211, এক অবাক করা সংখ্যাতাত্ত্বিক কাকতালীয় মিল। Marcel Golay ১৯৪৯ সালে এই সংখ্যাটি দেখে একটি (23, 12) code বানান, যার d = 7, আর বলগুলো {0, 1}23 ফাঁক ছাড়া ঢাকে।

কিন্তু সমীকরণের সমাধান থাকলেই code থাকে না, যেমন §৮-এর ভুল প্রমাণে দেখেছেন। গবেষকরা প্রশ্ন করলেন: Hamming আর Golay-এর বাইরে কোনো অতুচ্ছ perfect code আছে কি? ১৯৭০-এর দশকে Aimo Tietäväinen আর Jacobus van Lint-এর কাজে, আর স্বাধীনভাবে Zinoviev ও Leontiev-এর কাজে, উত্তর আসে বলে উল্লেখ করা হয়: prime-power আকারের alphabet-এ অতুচ্ছ perfect code-এর প্রাচল কেবল Hamming code আর দুটি Golay code-এর মতো (binary (23, 12) আর ternary (11, 6)). ঠিক একই প্রাচলের কিন্তু linear নয় এমন perfect code-ও আছে, তাই শ্রেণিবিভাগটি প্রাচলের, প্রতিটি code-এর নয়।

Golay code-এর সৌন্দর্য সংখ্যার বাইরেও। এর বর্ধিত রূপ (24, 12, 8)-এর symmetry group হলো Mathieu group M24, যা বিচ্ছিন্ন sporadic simple group-গুলোর একটি; আর এই code থেকে ২৪ মাত্রার Leech lattice তৈরি হয়, যা সেই মাত্রায় সবচেয়ে ঘন গোলক-সাজানো বলে ২০১৬ সালে প্রমাণিত হয় বলে জানা যায়। Hamming bound-এর “গোলক সাজানো” রূপক এখানে আক্ষরিক জ্যামিতিতে পরিণত হয়।

ব্যবহারিক দিক: perfect হওয়া সবসময় সুবিধা নয়। §৬-এ দেখেছেন, Hamming(7,4) দুই error-এ সবসময় ভুল শোধরায়, কারণ space-এ কোনো “ফাঁকা” শব্দ নেই যেখানে decoder বলতে পারে “নিশ্চিত নই”। বাড়তি একটি বিটে SECDED এই ফাঁক তৈরি করে।

মূল উপলব্ধি: Perfect code-এর শর্ত বলের আয়তনকে 2-এর ঘাত হতে বাধ্য করে, যা খুব কম n আর t-তে ঘটে; তার ওপর code-এর অস্তিত্বও লাগে, তাই অতুচ্ছ binary perfect code-এর প্রাচল কেবল Hamming আর Golay পরিবারের।

প্র ০৪CD-তে আঁচড় বা QR code-এর একটি কোণ ছিঁড়ে গেলেও কেন তথ্য ফেরত আসে?

Hamming code ধরে নেয় error গুলো এলোমেলোভাবে ছড়ানো, প্রতিটি বিট স্বাধীন। কিন্তু বাস্তবের অনেক error burst error: CD-র একটি আঁচড় পরপর শত শত বিট নষ্ট করে, QR code-এর একটি দাগ পাশাপাশি অনেকগুলো মডিউল ঢেকে দেয়। এক block-এ দশটি বিট নষ্ট হলে single-error-correcting code অসহায়।

Irving Reed আর Gustave Solomon ১৯৬০ সালে “Polynomial Codes over Certain Finite Fields” প্রবন্ধে একটি ভিন্ন পথ দেখান। চিহ্ন হিসেবে বিট না নিয়ে একটি finite field-এর উপাদান নিন, যেমন GF(28), যার প্রতিটি উপাদান একটি byte (পর্ব ৩০)। k-টি data চিহ্নকে degree k − 1-এর একটি polynomial-এর সহগ ধরুন, আর n-টি আলাদা বিন্দুতে তার মান পাঠান। Degree k − 1-এর দুটি আলাদা polynomial বড়জোর k − 1টি বিন্দুতে মেলে, কারণ তাদের পার্থক্যের বড়জোর k − 1টি মূল থাকে (field-এ এই নিয়মটি পর্ব ৭১-এর বিষয়)। তাই দুটি codeword অন্তত n − k + 1টি অবস্থানে আলাদা: d = n − k + 1, ঠিক Singleton সীমা। এমন code-কে MDS (maximum distance separable) বলে।

Burst-এর সুবিধাটা এখানে: আটটি পরপর নষ্ট বিট একটি বা দুটি byte-চিহ্নের ক্ষতি মাত্র। তার ওপর interleaving, অর্থাৎ কয়েকটি codeword-এর চিহ্ন মিশিয়ে লেখা, একটি লম্বা আঁচড়কে অনেক codeword-এ ছড়িয়ে দেয়, যাতে প্রত্যেকে অল্প কিছু চিহ্ন হারায়। Audio CD-তে দুই স্তরের Reed–Solomon আর interleaving মেশানো CIRC পদ্ধতি ব্যবহৃত হয় বলে ব্যাপকভাবে নথিভুক্ত। QR code-এর মানদণ্ডে Reed–Solomon-এর চারটি স্তর আছে, সর্বোচ্চ স্তরে প্রায় ৩০% চিহ্ন নষ্ট হলেও পড়া যায় বলে বর্ণিত; এজন্য কিছু QR code-এর মাঝে ছোট লোগো বসালেও তা কাজ করে।

মহাকাশযানের যোগাযোগেও Reed–Solomon আর convolutional code-এর সমন্বয় ব্যবহারের কথা Voyager অভিযানসহ নানা প্রসঙ্গে উল্লেখ করা হয়; নির্দিষ্ট বিবরণ অভিযানভেদে আলাদা।

মূল উপলব্ধি: বিটের বদলে byte-চিহ্নে কাজ করা, polynomial-এর মূলের সীমা দিয়ে Singleton-এ পৌঁছানো, আর interleaving দিয়ে burst ছড়িয়ে দেওয়া, এই তিনে মিলে Reed–Solomon বাস্তবের আঁচড় আর দাগ সামলায়।

প্র ০৫কখন error শুধু ধরে আবার পাঠানো ভালো, আর কখন পাঠানোর আগেই শোধরানোর ক্ষমতা যোগ করা দরকার?

দুটি কৌশল আছে। ARQ (automatic repeat request): শুধু ধরার code (যেমন CRC) পাঠান; গ্রাহক error দেখলে আবার চায়। FEC (forward error correction): এমন code পাঠান যা গ্রাহক নিজেই শোধরাতে পারে। পছন্দটি গাণিতিক আর ব্যবহারিক দুই হিসাবেই নির্ভর করে।

গাণিতিক দিক: উপপাদ্য ৩.৩ বলে একই minimum distance d-তে ধরা যায় d − 1টি, অথচ শোধরানো যায় মাত্র ⌊(d − 1)/2⌋টি। অর্থাৎ ধরা প্রায় দ্বিগুণ “সস্তা”। CRC-এর মতো code অল্প কিছু বাড়তি বিটে প্রায় সব error ধরে। তাই যেখানে ফিরতি পথ আছে আর দেরি সহনীয়, যেমন ইন্টারনেটে একটি ফাইল নামানো, সেখানে ARQ কার্যকর: ভালো অবস্থায় প্রায় কোনো বাড়তি খরচ নেই, খারাপ অবস্থায় শুধু নষ্ট অংশ আবার আসে। Computer Networks কোর্সের পর্ব ১০-এ stop-and-wait আর Go-Back-N এর বাস্তব রূপ।

কিন্তু অনেক ক্ষেত্রে আবার চাওয়া অসম্ভব বা খুব ব্যয়বহুল। মহাকাশযানের সংকেত পৃথিবীতে পৌঁছাতে ঘণ্টা লাগে; সরাসরি সম্প্রচার (টিভি, রেডিও) একসঙ্গে লাখো গ্রাহকের, কে কী হারাল তা শোনার উপায় নেই; CD বা হার্ডডিস্কে লেখা তথ্যের “প্রেরক” হয়তো বছর আগের নিজেই। মেমরিতে প্রতিটি পড়ার সময় অপেক্ষা করার সুযোগ নেই, তাই ECC memory-তে SECDED সঙ্গে সঙ্গে একটি error শোধরায়, আর দুটি হলে অন্তত সতর্ক করে, যাতে ভুল ডেটা নীরবে ব্যবহৃত না হয়।

বাস্তব ব্যবস্থা প্রায়ই দুটি মেশায়: hybrid ARQ-তে প্রথমে FEC দিয়ে সাধারণ error শোধরানো হয়, আর না পারলে বাড়তি redundancy চাওয়া হয়। বাজারঘরের জেলা-গুদাম থেকে সার্ভারে ডেটা পাঠাতে CRC আর পুনঃপ্রেরণ যথেষ্ট; কিন্তু গুদামের যে সার্ভার রাতভর হিসাব চালায়, তার মেমরিতে ECC থাকলে একটি উল্টে যাওয়া বিট পুরো হিসাব নষ্ট করে না।

মূল উপলব্ধি: একই দূরত্বে ধরা শোধরানোর চেয়ে প্রায় দ্বিগুণ শক্তিশালী, তাই ফিরতি পথ আর সময় থাকলে ধরে আবার পাঠানো সাশ্রয়ী; ফিরতি পথ না থাকলে বা দেরি অসহনীয় হলে আগেই শোধরানোর ক্ষমতা যোগ করতে হয়।

অনুশীলন

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

  1. প্রমাণ: C একটি binary code, d(C) = d বিজোড়। প্রতিটি codeword-এর শেষে একটি parity বিট বসিয়ে (যাতে weight জোড় হয়) C′ বানানো হলো। প্রমাণ করুন d(C′) = d + 1.
    1. যেকোনো a, b-এর জন্য w(a ⊕ b) = w(a) + w(b) − 2w(a ∧ b), যেখানে a ∧ b হলো যেসব অবস্থানে দুটিতেই 1. দুটিতেই 1 থাকা অবস্থান a ⊕ b-তে 0 হয়, আর w(a) + w(b)-তে দুবার গোনা। — গণনা
    2. C′-এর সব শব্দের weight জোড়, তাই ধাপ ১ থেকে যেকোনো দুটির দূরত্ব জোড়। — parity
    3. c1′, c2′-এর দূরত্ব ≥ d(c1, c2) ≥ d, কারণ শেষ বিট বাদে শব্দ অপরিবর্তিত। জোড় আর ≥ d (d বিজোড়) মানে ≥ d + 1. — জোড় সংখ্যা
    4. উল্টো দিকে, d(c1, c2) = d এমন জোড়া নিন। d বিজোড়, তাই c1 আর c2-এর weight-এর জোড়-বিজোড় আলাদা, ফলে তাদের parity বিটও আলাদা; দূরত্ব ঠিক d + 1. তাই d(C′) = d + 1. ∎

    Hamming(7,4)-এ প্রয়োগ করলে (8,4) code-এর d = 4, যা §৭-এর কোডে weight 0, 4, 8 দেখে মিলিয়েছেন।

  2. গণনা: Hamming(15,11) code-এর জন্য (ক) codeword-সংখ্যা, (খ) rate, (গ) Hamming bound-এ সমতা যাচাই, (ঘ) কয়টি আলাদা শূন্য-নয় syndrome, আর (ঙ) ২৬টি data বিটের জন্য একক error শোধরাতে সর্বনিম্ন parity বিট বের করুন।

    (ক) 211 = 2048. (খ) R = 11/15 ≈ 0.733, Hamming(7,4)-এর 4/7 ≈ 0.571-এর চেয়ে ভালো। (গ) V(15, 1) = 16, আর 2048 × 16 = 32768 = 215: perfect. (ঘ) 4টি syndrome বিট, তাই 24 − 1 = 15টি শূন্য-নয় syndrome, ঠিক 15টি সম্ভাব্য একক error-অবস্থানের সমান। (ঙ) 2r ≥ 26 + r + 1: r = 4-এ 16 < 31, r = 5-এ 32 ≥ 32, তাই 5, আর code-টি Hamming(31, 26). সব সংখ্যা scratch-এ মেলানো।

  3. আউটপুট অনুমান: কোড না চালিয়ে বলুন কী ছাপা হবে, আর প্রতিটি শব্দ সম্পর্কে Hamming(7,4)-এর decoder কী সিদ্ধান্ত নেবে। তারপর যেকোনো Python-এ চালিয়ে মেলান।
    for r in ("1100110", "1100100"):
        s = 0
        for pos, bit in enumerate(r, start=1):
            if bit == "1":
                s ^= pos
        print(r, s, format(s, "03b"))
    1100110 0 000
    1100100 6 110

    প্রথম শব্দে 1 আছে অবস্থান 1, 2, 5, 6-এ: 1 ⊕ 2 ⊕ 5 ⊕ 6 = 0, তাই এটি একটি codeword (data 0110). দ্বিতীয়টিতে অবস্থান 1, 2, 5: 1 ⊕ 2 ⊕ 5 = 6, তাই decoder অবস্থান 6 উল্টে 1100110 বানায়, অর্থাৎ প্রথম শব্দটি। সত্যিই দুটি শব্দ শুধু অবস্থান 6-এ আলাদা (CPython 3.14-এ চালিয়ে মেলানো)।

  4. প্রমাণের ভুল ধরুন: দাবি: “Extended Hamming (8,4) code-এর d = 4, তাই এটি যেকোনো দুটি error শোধরাতে পারে।” যুক্তি: “d = 4 মানে তিনটি পর্যন্ত error ধরা পড়ে। ধরা পড়লে সব ১৬টি codeword-এর সঙ্গে দূরত্ব মেপে সবচেয়ে কাছেরটি নিলেই হলো। ∎” ভুল কোথায়? একটি পাল্টা-উদাহরণ দিন।
    • ভুল ধাপ: “ধরা পড়ে” থেকে “শোধরানো যায়” আসে না। শোধরানোর শর্ত d ≥ 2t + 1 (উপপাদ্য ৩.৩-খ); t = 2-এ লাগে d ≥ 5. সবচেয়ে কাছের codeword অনন্য হওয়ার নিশ্চয়তা নেই।
    • পাল্টা-উদাহরণ: 00000000 আর 11100001 দুটিই (8,4) codeword (দ্বিতীয়টি data 1000-এর encoding 1110000-এর সঙ্গে parity বিট 1), দূরত্ব 4. প্রাপ্ত শব্দ 11000000 দুটি থেকেই ঠিক 2 দূরে। প্রথমটি পাঠিয়ে দুটি error, নাকি দ্বিতীয়টি পাঠিয়ে দুটি error, বলা অসম্ভব।
    • সঠিক কথা: d = 4-এ একসঙ্গে একটি শোধরানো আর দুটি ধরা (SECDED), অথবা শুধু তিনটি পর্যন্ত ধরা; দুটি শোধরানো নয়।

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

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

ক্রম“d(C) ≥ 2t + 1 হলে nearest-codeword decoding t-টি পর্যন্ত error শোধরায়”, এই প্রমাণের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. Codeword c পাঠানো হলো, আর প্রাপ্ত শব্দ r-এ d(r, c) ≤ t
  2. বিরোধের জন্য ধরুন অন্য একটি codeword c′-এর জন্য d(r, c′) ≤ d(r, c)
  3. Triangle inequality: d(c, c′) ≤ d(c, r) + d(r, c′)
  4. দুই পদই বড়জোর t, তাই d(c, c′) ≤ 2t
  5. এটি d(C) ≥ 2t + 1-এর বিরোধী, তাই c-ই অনন্য সবচেয়ে কাছের codeword

একটি code-এর minimum distance 5. শুধু শোধরানোর মোডে আর শুধু ধরার মোডে এটি যথাক্রমে কয়টি error সামলায়?

  • শোধরায় 2, ধরে 3
  • শোধরায় 2, ধরে 4
  • শোধরায় 3, ধরে 4
  • শোধরায় 2, ধরে 5

দৈর্ঘ্য 7-এর যে binary code প্রতিটি একক error শোধরায়, তাতে সর্বোচ্চ কয়টি codeword থাকতে পারে?

  • 8
  • 128
  • 16
  • 32

Hamming(7,4)-এ (অবস্থান 1, 2, 4-এ parity বিট; syndrome = 1-ওয়ালা অবস্থানগুলোর XOR) প্রাপ্ত শব্দ 0110111. Decoder কোন অবস্থানের বিট উল্টাবে?

  • অবস্থান 5
  • কোনোটি নয়, শব্দটি codeword
  • অবস্থান 4
  • অবস্থান 3

BSC-তে প্রতিটি বিট স্বাধীনভাবে 0.1 সম্ভাবনায় উল্টায়। Repetition code R3 (প্রতিটি বিট তিনবার, majority vote)-এ একটি data বিট ভুল decode হওয়ার সম্ভাবনা কত?

  • 0.1
  • 0.001
  • 0.03
  • 0.028

একটি binary linear code-এর শূন্য-নয় codeword-গুলোর weight 3, 4, 4, 5, 6, 7, 8. Minimum distance কত?

  • 0
  • 3
  • 4
  • জোড়ায় জোড়ায় দূরত্ব না মাপলে বলা যায় না

Extended Hamming (8,4) code (d = 4) দিয়ে পাঠানো একটি শব্দে ঠিক দুটি বিট উল্টে গেল। SECDED decoder কী করে?

  • দুটি বিটই শোধরায়
  • কিছুই টের পায় না
  • দ্বৈত error ধরে, কিন্তু শোধরায় না
  • একটি বিট উল্টে ভুল codeword-এ পৌঁছায়

শব্দকোষ

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

মনে রাখুন

  1. দূরত্ব: d(x, y) = w(x ⊕ y), একটি metric; d(C) থেকে ধরা d − 1, শোধরানো ⌊(d − 1)/2⌋, একসঙ্গে t আর s-এ d ≥ t + s + 1.
  2. সরল code: Rn-এ error দ্রুত কমে কিন্তু rate 1/n; parity বিট বিজোড় error ধরে, জোড় error নয়।
  3. সীমা: Hamming M · V(n, t) ≤ 2n (সমতায় perfect), Singleton M ≤ 2n−d+1, GV বলে M ≥ 2n/V(n, d − 1)-এর code আছে।
  4. Linear code: c = uG, HcT = 0, syndrome = HeT; d = সর্বনিম্ন শূন্য-নয় weight.
  5. Hamming(7,4): H-এর column = 1 থেকে 7-এর binary, d = 3, perfect, syndrome = error-অবস্থান; একটি parity বিট বেশি দিলে SECDED.

পরের পর্বে: মডিউল ১৩ শুরু, পর্ব ৭৩ “Grammar আর formal language — BNF থেকে Chomsky-র শ্রেণি”: সসীম নিয়ম দিয়ে কীভাবে অসীম ভাষা লেখা যায়, programming language-এর syntax কীভাবে BNF-এ বাঁধা হয়, আর grammar-এর শ্রেণিগুলো কীভাবে সাজানো।

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

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