নিউটন-রাফসন মেথড
এই পাঠে যা শিখবেন
- নিউটন-রাফসন আপডেট সূত্র জ্যামিতিকভাবে (ট্যানজেন্ট লাইন হিসেবে) বোঝা
- একটি সমীকরণে নিউটন-রাফসন বাস্তবায়ন করা এবং বাইসেকশনের তুলনায় এর গতি সংখ্যাগতভাবে দেখা
- কোয়াড্রেটিক কনভারজেন্স সত্যিকারের এরর অনুপাত গণনা করে অভিজ্ঞতামূলকভাবে যাচাই করা
- ডেরিভেটিভ শূন্যের কাছাকাছি হলে কী ঘটে তা একটি প্রকৃত ব্যর্থতার উদাহরণে দেখা
- কীভাবে সংখ্যাগতভাবে অস্থির (unstable) কোড নিরাপদে গার্ড করে ক্র্যাশ বা ইনফিনিট লুপ এড়ানো যায়
১ · নিউটন-রাফসনের ধারণা — ট্যানজেন্ট লাইন ব্যবহার করা
L06-এ আমরা দেখেছি ফিক্সড-পয়েন্ট ইটারেশনের সাফল্য নির্ভর করে g(x)-এর ঢালের উপর — রুটের কাছে
g'(x) যত ছোট, তত দ্রুত কনভারজেন্স। নিউটন-রাফসন
মেথডNewton-Raphson methodপ্রতি ধাপে বর্তমান বিন্দুতে ফাংশনের ট্যানজেন্ট লাইন টেনে, সেই লাইনটি কোথায় x-অক্ষ ছেদ করে তাকে পরবর্তী অনুমান হিসেবে নেওয়ার মেথড — সূত্র: x_{n+1} = x_n - f(x_n)/f'(x_n)।
মূলত এই ধারণাটিকে চরম পর্যায়ে নিয়ে যায়: এটি এমন একটি g(x) বেছে নেয় যাতে রুটের কাছে
g'(x) ≈ 0 হয় — অর্থাৎ প্রায় ইনস্ট্যান্ট কনভারজেন্স।
জ্যামিতিকভাবে ধারণাটি সরল: বর্তমান অনুমান x_n-এ ফাংশনের ট্যানজেন্ট (স্পর্শক) লাইন আঁকো,
তারপর সেই সরলরেখাটি কোথায় x-অক্ষ অতিক্রম করে সেটাই পরবর্তী অনুমান x_{n+1} ধরো। যেহেতু একটি
ভালো-আচরণ ফাংশন রুটের কাছে প্রায় তার ট্যানজেন্ট লাইনের মতোই আচরণ করে, এই "লাইন দিয়ে অনুমান" পদ্ধতি খুব
দ্রুত প্রকৃত রুটের কাছে পৌঁছে যায়।
$$x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}$$
২ · কোয়াড্রেটিক কনভারজেন্স — একই সমীকরণে
L05 ও L06-এর মতো একই সমীকরণ f(x) = x³ - x - 2 ব্যবহার করা যাক, যার
f'(x) = 3x² - 1। শুরুর অনুমান x₀ = 1.2 থেকে নিউটন-রাফসন প্রয়োগ করলে:
reference_root = 1.5213797068045678
def f(x):
return x**3 - x - 2
def fprime(x):
return 3 * x**2 - 1
x = 1.2
print(f"{'ইটার':>4} {'x':>16} {'f(x)':>14} {'এরর':>16}")
errors = []
for i in range(1, 8):
fx = f(x)
fpx = fprime(x)
x_new = x - fx / fpx
err = abs(x_new - reference_root)
errors.append(err)
print(f"{i:4d} {x_new:16.10f} {fx:+14.8f} {err:16.12f}")
x = x_new
print()
print("=== কোয়াড্রেটিক কনভারজেন্স যাচাই: err[i] বনাম err[i-1]^2 ===")
for i in range(1, 4):
prev, cur = errors[i-1], errors[i]
print(f"err[{i}] = {cur:.3e} err[{i-1}]^2 = {prev**2:.3e} অনুপাত = {cur/(prev**2):.4f}")
err[i] / err[i-1]²
মোটামুটি ০.৬৮ থেকে ০.৭৭-এর মধ্যে স্থির থাকে — এটাই কোয়াড্রেটিক কনভারজেন্স
-এর সংজ্ঞাগত বৈশিষ্ট্য: err[i] ≈ C · err[i-1]², যেখানে C একটি প্রায়-স্থির
ধ্রুবক। (ইটারেশন ৪-এর পর এরর ফ্লোটিং-পয়েন্ট নির্ভুলতার সীমায় পৌঁছে যায় বলে অনুপাত গণনা অর্থহীন হয়ে
পড়ে — L02/L03-এ ফ্লোটিং-পয়েন্ট সীমাবদ্ধতা বিস্তারিত আলোচনা করা হয়েছে।)
L05-এ বাইসেকশন একই সমীকরণে 10⁻⁸ নির্ভুলতায় পৌঁছাতে আনুমানিক ১৯–২০ ইটারেশন প্রয়োজন
ছিল (এরর বাউন্ড সূত্র দিয়ে গণনা করা)। নিউটন-রাফসন মাত্র ৫ ইটারেশনে মেশিন-প্রিসিশন
নির্ভুলতায় পৌঁছে যায় — এটাই লিনিয়ার বনাম কোয়াড্রেটিক কনভারজেন্সের ব্যবহারিক পার্থক্য, যা L09-এ সব
মেথড একসাথে তুলনা করে আরও স্পষ্ট করা হবে।
৩ · একটি প্রকৃত ব্যর্থতা — ডেরিভেটিভ শূন্যের কাছাকাছি
নিউটন-রাফসনের সূত্রে f'(x_n) হর (denominator)-এ থাকে — তাই f'(x_n) শূন্যের
কাছাকাছি হলে ধাপটি বিশাল হয়ে যেতে পারে, রুট থেকে অনেক দূরে "লাফ" দিতে পারে। আমাদের ফাংশন
f'(x) = 3x² - 1 = 0 হয় যখন x = ±1/√3 ≈ ±0.5774। শুরুর অনুমান
x₀ = 0.58 নিলে (এই বিন্দুর খুব কাছে) কী ঘটে দেখা যাক — কোডে একটি ম্যাগনিটিউড-ক্যাপ ও একটি
সর্বোচ্চ-ইটারেশন-সংখ্যা রাখা হয়েছে যাতে সেলটি নিরাপদে থামে।
import math
def f(x):
return x**3 - x - 2
def fprime(x):
return 3 * x**2 - 1
x = 0.58 # f'(x) প্রায় শূন্য, এই বিন্দুর কাছে
print(f"শুরুর বিন্দু x0 = {x}, যেখানে f'(x0) = {fprime(x):.6f} (প্রায় শূন্য)")
print()
print(f"{'ইটার':>4} {'x':>18} {'f(x)':>16} {'fprime(x)':>14}")
MAX_ITER = 8
CAP = 1e15
for i in range(1, MAX_ITER + 1):
fx = f(x)
fpx = fprime(x)
if abs(fpx) < 1e-10:
print(f"{i:4d} ডেরিভেটিভ ~০ ({fpx:.2e}) -- নিউটন ধাপ অসংজ্ঞায়িত, থামানো হলো")
break
x_new = x - fx / fpx
print(f"{i:4d} {x_new:18.6f} {fx:+16.8f} {fpx:14.8f}")
if not math.isfinite(x_new) or abs(x_new) > CAP:
print(" ... মান cap ছাড়িয়ে গেছে বা অসীম, মেথড ব্যর্থ হয়েছে, থামানো হলো")
break
x = x_new
x লাফ দিয়ে ২৫৯.৮-এ চলে যায় (শুরুর বিন্দু 0.58
থেকে!) — কারণ f'(0.58) ≈ 0.0092, প্রায় শূন্য, তাই f(x)/f'(x) একটি বিশাল
সংখ্যা হয়ে যায়। এরপর ফাংশনটি ধীরে ধীরে রুটের দিকে ফিরে আসতে থাকে (কারণ x = 259.8-এ
ফাংশনের ঢাল খুব বড়, তাই নিউটন ধাপ ছোট হয়ে যায়), কিন্তু এটি এখন কার্যত বাইসেকশনের চেয়েও ধীরগতির —
মূল কোয়াড্রেটিক গতির সুবিধা সম্পূর্ণ হারিয়ে গেছে। এটাই দেখায় কেন নিউটন-রাফসন বাস্তবে সবসময় একটি
সর্বোচ্চ-ইটারেশন সীমা এবং ডেরিভেটিভ-শূন্য পরীক্ষা নিয়ে বাস্তবায়ন করা উচিত।
নিউটন-রাফসন বাইসেকশনের চেয়ে অনেক দ্রুত (কোয়াড্রেটিক বনাম লিনিয়ার কনভারজেন্স), কিন্তু এই গতির মূল্য হলো নিশ্চয়তার অভাব — ডেরিভেটিভ শূন্যের কাছাকাছি হলে, বা শুরুর অনুমান রুট থেকে অনেক দূরে হলে, মেথডটি সম্পূর্ণ ব্যর্থ হতে পারে বা ভুল রুটের দিকে চলে যেতে পারে। এই ট্রেড-অফ — গতি বনাম নিশ্চয়তা — এই পুরো মডিউলের কেন্দ্রীয় থিম, যা L08 ও L09-এ আরও গভীরভাবে অন্বেষণ করা হবে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ কোয়াড্রেটিক কনভারজেন্স যাচাই সেলে ইটারেশন ৪ ও এর পরের অনুপাত গণনা করা হয়নি। কেন?
কারণ ইটারেশন ৪-এর মধ্যেই এরর ডাবল-প্রিসিশন ফ্লোটিং-পয়েন্টের সর্বনিম্ন সীমায় (প্রায়
2.22 × 10⁻¹⁶, মেশিন এপসিলন) পৌঁছে যায়। এর পরের প্রতিটি "এরর" মান আসলে ফ্লোটিং-পয়েন্ট
রাউন্ড-অফের শব্দ (noise), সমীকরণের প্রকৃত কনভারজেন্স আচরণ নয় — তাই সেই পয়েন্টের পরে অনুপাত অর্থহীন
এবং প্রচণ্ড বড় বা অস্থির সংখ্যা দেখায় (L03-এ রাউন্ড-অফ এরর বিস্তারিত আলোচনা করা হয়েছে)।
প্র ০২
ব্যর্থতার উদাহরণে x₀ = 0.58 ছিল রুট (1.5214) থেকে অনেক দূরে, কিন্তু
f'(x) = 0-এর বিন্দু (0.5774) থেকে অত্যন্ত কাছে। কোনটি সমস্যার আসল কারণ?
f'(x) ≈ 0-এর নৈকট্যই আসল কারণ, রুট থেকে দূরত্ব নয়। নিউটন-রাফসনের সূত্র
x_{n+1} = x_n - f(x_n)/f'(x_n)-এ হর ছোট হলে পুরো ভগ্নাংশটি বিশাল হয়ে যায়, যতই
লব (numerator) ছোট হোক না কেন। এটি বাইসেকশনের সাথে একটি গুরুত্বপূর্ণ পার্থক্য — বাইসেকশন কখনো
"বিভ্রান্ত" হয় না, কারণ এটি ঢাল ব্যবহারই করে না (L05-এর প্রশ্ন ৩-এর সাথে তুলনা করুন)।
প্র ০৩ যদি একটি সমীকরণের ডেরিভেটিভ পুরো ইন্টারভাল জুড়ে কোথাও শূন্যের কাছাকাছি না হয়, তাহলে কি নিউটন-রাফসন সবসময় নিরাপদ বলে বিবেচনা করা যায়?
তুলনামূলকভাবে বেশি নিরাপদ, কিন্তু সম্পূর্ণ নিশ্চয়তা এখনও নেই — একাধিক রুট থাকলে মেথডটি ভুল রুটের দিকে কনভার্জ করতে পারে, অথবা কিছু ফাংশনে (বিশেষত ইনফ্লেকশন পয়েন্ট বা দোলায়মান ফাংশনে) সাইকেলে আটকে যেতে পারে যা কখনোই কনভার্জ করে না। তাই বাস্তব বাস্তবায়নে সবসময় একটি সর্বোচ্চ-ইটারেশন সীমা রাখা হয় — যেমন এই পাঠের কোডে করা হয়েছে।
অনুশীলন
-
চিন্তা করুন: প্রথম কোড সেলে
x₀ = 1.2-এর বদলেx₀ = 2.0থেকে শুরু করলে (রুট থেকে আরও দূরে), মোট ইটারেশন সংখ্যায় কী প্রভাব পড়বে বলে আপনার ধারণা?কোয়াড্রেটিক কনভারজেন্স শুধু রুটের "যথেষ্ট কাছে" পৌঁছানোর পরই প্রযোজ্য হয় — তাই দূরে শুরু করলে হয়তো ১–২টি অতিরিক্ত ইটারেশন লাগতে পারে যতক্ষণ না সিকোয়েন্সটি রুটের কাছাকাছি পৌঁছায়, তারপর একই দ্রুত কোয়াড্রেটিক আচরণ শুরু হবে। মোটের ওপর, নিউটন-রাফসন এখনও বাইসেকশনের চেয়ে অনেক কম ইটারেশনে কনভার্জ করবে।
-
পরীক্ষা করুন: দ্বিতীয় কোড সেলে
x = 0.58-কেx = 0.577350(প্রায় হুবহু1/√3) করে Run চেপে দেখুন কী ঘটে।f'(x)আরও কাছাকাছি শূন্যে যাবে (আরও ছোট মান), তাই প্রথম ধাপে লাফটি আরও বিশাল হবে (হাজার হাজার বা লক্ষাধিক মাত্রার) — কোডেরabs(fpx) < 1e-10চেক-টি হয়তো ট্রিগার হবে যদি ডেরিভেটিভ যথেষ্ট ছোট হয়ে যায়, যা মেথডটিকে নিরাপদে থামিয়ে দেবে ক্র্যাশ না করেই।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ M2-এর বাকি পাঠগুলো — সেকেন্ট মেথড, রেগুলা ফালসি, ও কনভারজেন্স রেট তুলনা।
- পরবর্তী পাঠ — সেকেন্ট মেথড ও রেগুলা ফালসি L08 ডেরিভেটিভ গণনা এড়িয়ে দুটি বিন্দুর মধ্য দিয়ে সিকান্ট লাইন ব্যবহার করে নিউটন-রাফসনের প্রায় সমান গতি পাওয়ার কৌশল — সরাসরি সংখ্যাগত তুলনাসহ।
- আগের পাঠ — ফিক্সড-পয়েন্ট ইটারেশন L06 নিউটন-রাফসন আসলে ফিক্সড-পয়েন্ট ইটারেশনেরই একটি বিশেষ রূপ — সেই সংযোগ বুঝতে।