ইটারেটিভ মেথড — জ্যাকোবি ও গস-সেইডেল
এই পাঠে যা শিখবেন
- ডাইরেক্ট বনাম ইটারেটিভ মেথডের পার্থক্য এবং কখন প্রতিটি পছন্দনীয়
- জ্যাকোবি ও গস-সেইডেল ইটারেশনের আপডেট নিয়ম এবং তাদের মূল পার্থক্য
- ডায়াগোনাল ডমিন্যান্স কী এবং কেন এটি কনভারজেন্সের জন্য গুরুত্বপূর্ণ
- একটি সত্যিকারের, চলমান Python ডেমো — কনভার্জিং ও ডাইভার্জিং উভয় ক্ষেত্রে প্রকৃত ইটারেশন টেবিল
১ · ডাইরেক্ট বনাম ইটারেটিভ মেথড
L10-L11-এর গসিয়ান এলিমিনেশন ও LU ডিকম্পোজিশন হলো ডাইরেক্ট মেথড — একটি সীমিত-সংখ্যক
ধাপে (কার্যত) সঠিক সমাধান দেয়। কিন্তু বড় স্পার্স সিস্টেমে (হাজার হাজার সারি, বেশিরভাগ শূন্য — L15-এ
বিস্তারিত) ডাইরেক্ট মেথডের O(n³) খরচ অসম্ভব হয়ে যায়। ইটারেটিভ মেথড একটি
ভিন্ন কৌশল নেয়: একটি প্রাথমিক অনুমান (সাধারণত x = 0) থেকে শুরু করে, প্রতিটি ধাপে সমাধানের
কাছাকাছি একটি নতুন অনুমান তৈরি করে — যতক্ষণ না পরিবর্তন যথেষ্ট ছোট হয়ে যায়।
২ · জ্যাকোবি ইটারেশন
Ax = b সিস্টেমের i-তম সমীকরণ থেকে x_i আলাদা করে লেখা যায়:
জ্যাকোবি ইটারেশনে পুরনো ইটারেশনের সব x_j ব্যবহার করে নতুন
x^{(k+1)}-এর প্রতিটি উপাদান একসাথে গণনা করা হয় — নতুন মান পুরো ধাপ শেষ না হওয়া পর্যন্ত
ব্যবহার করা হয় না।
৩ · গস-সেইডেল ইটারেশন
গস-সেইডেল একটি সহজ কিন্তু কার্যকর পরিবর্তন করে: প্রতিটি x_i আপডেট করার সময়, যেসব
x_j (j < i) ইতিমধ্যে এই একই ধাপে আপডেট হয়ে গেছে, সেগুলোর
নতুন মান ব্যবহার করা হয় — পুরনো মান নয়। এতে তথ্য দ্রুত সিস্টেমের মধ্যে ছড়িয়ে পড়ে, এবং সাধারণত জ্যাকোবির
চেয়ে দ্রুত কনভার্জ করে (নিচের ডেমোতেই দেখা যাবে)।
একটি সিস্টেম "ডায়াগোনালি-ডমিন্যান্ট" যদি প্রতিটি সারিতে
|a_ii| > সাম(|a_ij|, j≠i) হয় — এই শর্ত জ্যাকোবি ও গস-সেইডেল উভয়ের কনভারজেন্সের জন্য যথেষ্ট (যদিও সবসময় প্রয়োজনীয় নয়)।প্রতিটি ইটারেশনের খরচ মাত্র
O(n²) (dense সিস্টেমে) বা তারও কম (স্পার্স সিস্টেমে) — বড় সিস্টেমে ডাইরেক্ট মেথডের O(n³)-এর চেয়ে অনেক সস্তা।ডায়াগোনাল ডমিন্যান্স না থাকলে এই মেথডগুলো কনভার্জ নাও করতে পারে — নিচের ডেমোর দ্বিতীয় অংশে এটি সত্যিই ঘটতে দেখা যাবে।
৪ · একটি সত্যিকারের ডেমো — কনভার্জিং বনাম ডাইভার্জিং
প্রথমে একটি ডায়াগোনালি-ডমিন্যান্ট 3x3 সিস্টেমে জ্যাকোবি ও গস-সেইডেল উভয়ই চালানো হয়েছে, এবং L10-এর গসিয়ান এলিমিনেশন থেকে পাওয়া রেফারেন্স সমাধানের সাথে তুলনা করা হয়েছে। তারপর একটি non-diagonally-dominant 2x2 সিস্টেমে জ্যাকোবি চালিয়ে দেখানো হয়েছে এটি সত্যিই ব্যর্থ হয় (মান বাড়তে থাকে, কমতে নয়)।
def jacobi_step(A, b, x_old):
n = len(A)
x_new = [0.0] * n
for i in range(n):
s = sum(A[i][j] * x_old[j] for j in range(n) if j != i)
x_new[i] = (b[i] - s) / A[i][i]
return x_new
def gauss_seidel_step(A, b, x):
n = len(A)
x_new = x[:]
for i in range(n):
s = sum(A[i][j] * x_new[j] for j in range(n) if j != i)
x_new[i] = (b[i] - s) / A[i][i]
return x_new
def run(A, b, method, n_iter, cap=1e12):
n = len(A)
x = [0.0] * n
history = [x[:]]
for k in range(n_iter):
x = jacobi_step(A, b, x) if method == "jacobi" else gauss_seidel_step(A, b, x)
history.append(x[:])
if any(abs(v) > cap for v in x):
break # ব্লো-আপ থামিয়ে দেওয়া
return history
# --- ডায়াগোনালি-ডমিন্যান্ট সিস্টেম (কনভার্জ করবে) ---
A_conv = [
[10.0, -1.0, 2.0],
[ 1.0, 11.0, -1.0],
[ 2.0, -1.0, 10.0],
]
b_conv = [6.0, 25.0, -11.0]
hist_j = run(A_conv, b_conv, "jacobi", 10)
hist_g = run(A_conv, b_conv, "gauss_seidel", 10)
print("Jacobi ইটারেশন টেবিল:")
print(f"{'k':>2} | {'x1':>10} {'x2':>10} {'x3':>10}")
for k, xk in enumerate(hist_j):
print(f"{k:>2} | {xk[0]:>10.6f} {xk[1]:>10.6f} {xk[2]:>10.6f}")
print()
print("Gauss-Seidel ইটারেশন টেবিল:")
print(f"{'k':>2} | {'x1':>10} {'x2':>10} {'x3':>10}")
for k, xk in enumerate(hist_g):
print(f"{k:>2} | {xk[0]:>10.6f} {xk[1]:>10.6f} {xk[2]:>10.6f}")
# L10-এর গসিয়ান এলিমিনেশন দিয়ে রেফারেন্স সমাধান
def gaussian_solve(A, b):
n = len(A)
M = [row[:] + [b[i]] for i, row in enumerate(A)]
for k in range(n - 1):
for i in range(k + 1, n):
f = M[i][k] / M[k][k]
for j in range(k, n + 1):
M[i][j] -= f * M[k][j]
x = [0.0] * n
for i in range(n - 1, -1, -1):
s = M[i][n]
for j in range(i + 1, n):
s -= M[i][j] * x[j]
x[i] = s / M[i][i]
return x
x_ref = gaussian_solve(A_conv, b_conv)
print()
print("রেফারেন্স সমাধান (Gaussian elimination):", [round(v, 6) for v in x_ref])
err_j = max(abs(hist_j[-1][i] - x_ref[i]) for i in range(3))
err_g = max(abs(hist_g[-1][i] - x_ref[i]) for i in range(3))
print(f"১০ ইটারেশন পর Jacobi সর্বোচ্চ ভুল: {err_j:.2e}")
print(f"১০ ইটারেশন পর Gauss-Seidel সর্বোচ্চ ভুল: {err_g:.2e}")
# --- ডায়াগোনালি-ডমিন্যান্ট নয় এমন সিস্টেম (ডাইভার্জ করবে) ---
print()
print("=== ডায়াগোনালি-ডমিন্যান্ট নয় এমন সিস্টেম ===")
A_div = [[1.0, 2.0], [3.0, 1.0]]
b_div = [5.0, 10.0]
hist_jd = run(A_div, b_div, "jacobi", 10)
print("Jacobi ইটারেশন টেবিল (ডাইভার্জিং):")
print(f"{'k':>2} | {'x1':>16} {'x2':>16}")
for k, xk in enumerate(hist_jd):
print(f"{k:>2} | {xk[0]:>16.4f} {xk[1]:>16.4f}")
Jacobi ইটারেশন টেবিল: k | x1 x2 x3 0 | 0.000000 0.000000 0.000000 1 | 0.600000 2.272727 -1.100000 2 | 1.047273 2.118182 -0.992727 3 | 1.010364 2.087273 -1.097636 4 | 1.028255 2.081091 -1.093345 5 | 1.026778 2.079855 -1.097542 6 | 1.027494 2.079607 -1.097370 7 | 1.027435 2.079558 -1.097538 8 | 1.027463 2.079548 -1.097531 9 | 1.027461 2.079546 -1.097538 10 | 1.027462 2.079546 -1.097538 Gauss-Seidel ইটারেশন টেবিল: k | x1 x2 x3 0 | 0.000000 0.000000 0.000000 1 | 0.600000 2.218182 -0.998182 2 | 1.021455 2.089124 -1.095379 3 | 1.027988 2.079694 -1.097628 4 | 1.027495 2.079534 -1.097546 5 | 1.027463 2.079545 -1.097538 6 | 1.027462 2.079545 -1.097538 7 | 1.027462 2.079545 -1.097538 8 | 1.027462 2.079545 -1.097538 9 | 1.027462 2.079545 -1.097538 10 | 1.027462 2.079545 -1.097538 রেফারেন্স সমাধান (Gaussian elimination): [1.027462, 2.079545, -1.097538] ১০ ইটারেশন পর Jacobi সর্বোচ্চ ভুল: 2.68e-07 ১০ ইটারেশন পর Gauss-Seidel সর্বোচ্চ ভুল: 1.95e-13 === ডায়াগোনালি-ডমিন্যান্ট নয় এমন সিস্টেম === Jacobi ইটারেশন টেবিল (ডাইভার্জিং): k | x1 x2 0 | 0.0000 0.0000 1 | 5.0000 10.0000 2 | -15.0000 -5.0000 3 | 15.0000 55.0000 4 | -105.0000 -35.0000 5 | 75.0000 325.0000 6 | -645.0000 -215.0000 7 | 435.0000 1945.0000 8 | -3885.0000 -1295.0000 9 | 2595.0000 11665.0000 10 | -23325.0000 -7775.0000
১০⁻¹³ নির্ভুলতায় পৌঁছেছে, যেখানে
জ্যাকোবির ১০ ইটারেশন পরও ভুল ১০⁻⁷ মাত্রার — গস-সেইডেল স্পষ্টভাবে দ্রুততর। আর
ডাইভার্জিং কেসে x1, x2-এর মান প্রতি ইটারেশনে বড় হচ্ছে ও চিহ্ন পাল্টাচ্ছে
(০ → ৫ → -১৫ → ১৫ → -১০৫ ...) — এটি কখনো কনভার্জ করবে না, কারণ সারি
|১| < |২| ও |১| < |৩| — ডায়াগোনাল ডমিন্যান্স নেই।
ইটারেটিভ মেথড ডাইরেক্ট মেথডের প্রতিস্থাপন নয়, বরং সম্পূরক — যখন সিস্টেম বড় ও স্পার্স, এবং ডায়াগোনালি-ডমিন্যান্ট (যা বাস্তব ইঞ্জিনিয়ারিং সমস্যায়, যেমন L36-L37-এর ফাইনাইট-ডিফারেন্স গ্রিড, প্রায়ই সত্য হয়), তখন ইটারেটিভ মেথড অনেক বেশি কার্যকর। L38-এ পাওয়ার মেথডে আমরা দেখব ইটারেটিভ ধারণাটি আইগেনভ্যালু সমস্যাতেও কীভাবে প্রয়োগ হয়।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১
কোড সেলে jacobi_step ও gauss_seidel_step-এর মধ্যে ঠিক কোন এক লাইনের
পার্থক্যে এত বড় গতির পার্থক্য তৈরি হয়?
jacobi_step-এ sum(... for j in range(n) if j != i) সবসময়
x_old (পুরনো ভেক্টর) থেকে মান নেয়, আর gauss_seidel_step-এ
x_new থেকে মান নেয় — যা এই একই ধাপে ইতিমধ্যে আপডেট হয়ে যাওয়া মান। এই একটি পরিবর্তনই
তথ্যকে ধাপের মধ্যেই ছড়িয়ে দেয়, ফলে গস-সেইডেল সাধারণত জ্যাকোবির প্রায় দ্বিগুণ গতিতে কনভার্জ করে।
প্র ০২
ডাইভার্জিং উদাহরণে সারি ১-এ |a_11| = ১ আর বাকি উপাদানের যোগফল |২| = ২।
যদি সারি দুটো অদলবদল করা হতো, তাহলে কি সিস্টেমটি ডায়াগোনালি-ডমিন্যান্ট হয়ে যেত?
না — সারি অদলবদল করলে সারি হয়ে যায় [3, 1] ও [1, 2]। প্রথম সারিতে
|৩| > |১| (ডমিন্যান্ট), কিন্তু দ্বিতীয় সারিতে |২| < |১| (এখনো
ডমিন্যান্ট নয়)। এই নির্দিষ্ট 2x2 সিস্টেমের জন্য কোনো সারি-পুনর্বিন্যাসেই উভয় সারি একসাথে
ডায়াগোনালি-ডমিন্যান্ট করা সম্ভব নয় — সমস্যাটি সিস্টেমের গঠনের মধ্যেই নিহিত।
প্র ০৩ ডায়াগোনাল ডমিন্যান্স না থাকলেও কি একটি সিস্টেম মাঝে মাঝে কনভার্জ করতে পারে?
হ্যাঁ — ডায়াগোনাল ডমিন্যান্স কনভারজেন্সের জন্য যথেষ্ট (sufficient) শর্ত, কিন্তু প্রয়োজনীয় (necessary) নয়। কিছু সিস্টেম এই শর্ত পূরণ না করেও কনভার্জ করতে পারে (এটি নির্ভর করে ইটারেশন ম্যাট্রিক্সের eigenvalue-এর উপর — M8-এ eigenvalue-এর ধারণা বিস্তারিত)। তবে ডায়াগোনাল ডমিন্যান্স যাচাই করা সহজ এবং ব্যবহারিকভাবে একটি নির্ভরযোগ্য প্রাথমিক পরীক্ষা।
অনুশীলন
-
চিন্তা করুন: কনভার্জিং উদাহরণে
২০ইটারেশন চালালে জ্যাকোবির ভুল কি১০ইটারেশনের ভুল(২.৬৮×১০⁻⁷)-এর চেয়ে আরও কমবে বলে আপনার মনে হয়?হ্যাঁ — যেহেতু সিস্টেমটি ডায়াগোনালি-ডমিন্যান্ট, জ্যাকোবি নিশ্চিতভাবে কনভার্জ করে, এবং প্রতি ইটারেশনে ভুল একটি স্থির অনুপাতে (রৈখিকভাবে) কমতে থাকে — তাই আরও ১০ ইটারেশন চালালে ভুল আরও কয়েক অর্ডার-অফ-ম্যাগনিটিউড কমে যাবে, machine-precision সীমার কাছাকাছি পৌঁছানো পর্যন্ত।
-
পরীক্ষা করুন: উপরের কোড সেলে
run(A_conv, b_conv, "jacobi", 10)-এর10-কে20-এ পরিবর্তন করে Run চেপে চূড়ান্ত ভুল যাচাই করুন।২০ ইটারেশনে জ্যাকোবির ভুল
১০⁻¹৩মাত্রায় নেমে আসে — machine-precision-এর কাছাকাছি, যা গস-সেইডেলের ১০-ইটারেশন ফলাফলের সমতুল্য। এটি নিশ্চিত করে জ্যাকোবিও নির্ভরযোগ্যভাবে কনভার্জ করে, শুধু গস-সেইডেলের চেয়ে ধীরে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ এরর অ্যানালাইসিস, রুট-ফাইন্ডিং, লিনিয়ার সিস্টেম, ইন্টারপোলেশন, নিউমেরিক্যাল ইন্টিগ্রেশন, ODE সলভিং, আইগেনভ্যালু মেথড, অপ্টিমাইজেশন ও ক্যাপস্টোন।
- Math for AI & ML কোর্স সহোদর কোর্স ভেক্টর ও ম্যাট্রিক্স অপারেশনের গাণিতিক ভিত্তি — এই কোর্স সেই ভিত্তির উপর ইটারেটিভ অ্যালগরিদমের দিকটি যোগ করে।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, Machine Learning, Deep Learning, System Design, Cybersecurity, Cloud Computing & DevOps, এবং আরও অনেক কোর্স।