নিউটনের ডিভাইডেড ডিফারেন্স
এই পাঠে যা শিখবেন
- ডিভাইডেড ডিফারেন্স কী এবং কীভাবে একটি রিকার্সিভ টেবিল আকারে গণনা করা হয়
- নিউটনের ফর্মে ইন্টারপোলেটিং পলিনোমিয়াল কীভাবে লেখা হয়, এবং কেন এটি ক্রমান্বয়ে সম্প্রসারণযোগ্য
- Python-এ হাতে-লেখা ডিভাইডেড-ডিফারেন্স টেবিল ও Horner-স্টাইল মূল্যায়ন বাস্তবায়ন করা
- লাগ্রাঞ্জ (L16) ও নিউটন ফর্মের ফলাফল সরাসরি ক্রস-চেক করে যাচাই করা
১ · ডিভাইডেড ডিফারেন্স কী
ডিভাইডেড ডিফারেন্সDivided Differenceএকটি রিকার্সিভভাবে সংজ্ঞায়িত পরিমাণ যা ডেটা পয়েন্টগুলোর মধ্যে "গড় পরিবর্তনের হার"-এর ক্রমবর্ধমান-মাত্রার সাধারণীকরণ — ডেরিভেটিভের একটি ডিসক্রিট সংস্করণ।
সবচেয়ে সহজ (শূন্য-মাত্রার) ডিভাইডেড ডিফারেন্স হলো শুধু f[xᵢ] = yᵢ। প্রথম-মাত্রার ডিভাইডেড
ডিফারেন্স হলো দুই বিন্দুর মধ্যে ঢাল (slope):
উচ্চতর-মাত্রার ডিভাইডেড ডিফারেন্স রিকার্সিভভাবে সংজ্ঞায়িত — একটি মাত্রার টেবিল দিয়ে পরের মাত্রার টেবিল বের করা যায়:
$$f[x_i, ..., x_{i+k}] = \frac{f[x_{i+1}, ..., x_{i+k}] - f[x_i, ..., x_{i+k-1}]}{x_{i+k} - x_i}$$এই সংখ্যাগুলোই নিউটনের ইন্টারপোলেটিং পলিনোমিয়ালের সহগ (coefficient) হয়ে যায়:
$$P(x) = f[x_0] + f[x_0,x_1](x-x_0) + f[x_0,x_1,x_2](x-x_0)(x-x_1) + \cdots$$ডিভাইডেড ডিফারেন্স একটি ত্রিভুজাকার টেবিলে সাজানো যায় — প্রতিটি নতুন কলাম আগের কলাম থেকে গণনা হয়, ঠিক পাস্কালের ত্রিভুজের মতো একটি প্যাটার্নে।
একটি নতুন ডেটা পয়েন্ট
(xₙ₊₁,yₙ₊₁) যোগ করলে শুধু টেবিলের একটি নতুন তির্যক (diagonal) গণনা করলেই হয় — আগের সব হিসাব অক্ষত থাকে, লাগ্রাঞ্জ ফর্মের মতো সব আবার করতে হয় না।নিউটন ফর্ম মূল্যায়ন করতে Horner-এর পদ্ধতির মতো ভেতর থেকে বাইরের দিকে গুণ-যোগ করলে দক্ষতার সাথে গণনা করা যায় (O(n) প্রতি মূল্যায়নে, একবার সহগ গণনা হয়ে গেলে)।
২ · একটি সত্যিকারের ডেমো — L16-এর একই ডেটাসেটে নিউটন ফর্ম
নিচের কোড সেলে ঠিক L16-এর একই ৫টি sin(x) স্যাম্পল পয়েন্ট
(x = 0.0, 0.5, 1.0, 1.5, 2.0) ব্যবহার করে প্রথমে সম্পূর্ণ ডিভাইডেড-ডিফারেন্স টেবিল গণনা করা
হয়েছে, তারপর নিউটন ফর্মে x = 1.2 ও x = 1.9 বিন্দুতে মান বের করে সরাসরি L16-এর
লাগ্রাঞ্জ ফলাফলের সাথে তুলনা করা হয়েছে।
import math
xs = [0.0, 0.5, 1.0, 1.5, 2.0]
ys = [math.sin(x) for x in xs]
def divided_diff_table(xs, ys):
n = len(xs)
table = [ys[:]]
for level in range(1, n):
prev = table[-1]
new_row = []
for i in range(n - level):
val = (prev[i+1] - prev[i]) / (xs[i+level] - xs[i])
new_row.append(val)
table.append(new_row)
coeffs = [table[k][0] for k in range(n)]
return coeffs, table
coeffs, table = divided_diff_table(xs, ys)
print("ডিভাইডেড-ডিফারেন্স টেবিল (প্রতিটি সারি একটি মাত্রা):")
for level, row in enumerate(table):
print(f" মাত্রা {level}: " + ", ".join(f"{v:.6f}" for v in row))
print()
print("নিউটন সহগ (f[x0], f[x0,x1], ...):")
for i, c in enumerate(coeffs):
print(f" c{i} = {c:.6f}")
def newton_eval(xs, coeffs, x):
n = len(coeffs)
result = coeffs[-1]
for k in range(n - 2, -1, -1):
result = result * (x - xs[k]) + coeffs[k]
return result
def lagrange_interpolate(xs, ys, x):
total = 0.0
n = len(xs)
for i in range(n):
term = ys[i]
for j in range(n):
if j != i:
term *= (x - xs[j]) / (xs[i] - xs[j])
total += term
return total
for x_new in [1.2, 1.9]:
p_newton = newton_eval(xs, coeffs, x_new)
p_lagrange = lagrange_interpolate(xs, ys, x_new)
true_val = math.sin(x_new)
print()
print(f"x_new = {x_new}")
print(f" নিউটন P({x_new}) = {p_newton:.8f}")
print(f" লাগ্রাঞ্জ P({x_new}) = {p_lagrange:.8f}")
print(f" দুই মেথডের পার্থক্য = {abs(p_newton - p_lagrange):.2e}")
print(f" প্রকৃত math.sin({x_new}) = {true_val:.8f}")
y-মানগুলো, আর সহগ পাওয়া যায়
টেবিলের বাম কিনারা থেকে: c0=0.000000, c1=0.958851, c2=-0.234760, c3=-0.118188, c4=0.033627।
x = 1.2-তে নিউটন ফর্ম দেয় ০.৯৩১৮৭২২৫ এবং লাগ্রাঞ্জ ফর্মও দেয়
ঠিক ০.৯৩১৮৭২২৫ — পার্থক্য মাত্র 1.11 × 10⁻¹⁶ (বিশুদ্ধ ফ্লোটিং-পয়েন্ট
রাউন্ড-অফ, বাস্তবে ০)। x = 1.9-তেও একই ঘটনা — দুই ফর্মই ০.৯৪৬৬১৩৪৪
দেয়। এটি নিশ্চিত করে দুটো অ্যালগরিদম গাণিতিকভাবে একই পলিনোমিয়াল প্রকাশ করছে, শুধু ভিন্নভাবে গণনা করে।
লাগ্রাঞ্জ ও নিউটন ফর্ম — দুটোই একই ইউনিক ইন্টারপোলেটিং পলিনোমিয়াল বর্ণনা করে, শুধু আলাদা "বেসিসে" লেখা। লাগ্রাঞ্জ ফর্ম বোঝা সহজ কিন্তু নতুন পয়েন্ট যোগ করলে সব আবার গণনা করতে হয়; নিউটন ফর্ম সামান্য বেশি জটিল কিন্তু ক্রমান্বয়ে সম্প্রসারণযোগ্য এবং Horner-স্টাইল মূল্যায়নে দক্ষ। বাস্তব সংখ্যাসূচক লাইব্রেরিগুলো প্রায়ই নিউটন ফর্মের একটি রূপ ব্যবহার করে, ঠিক এই কারণে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১
কোড সেলের ফলাফলে নিউটন ও লাগ্রাঞ্জ ফর্মের পার্থক্য 1.11 × 10⁻¹⁶ — ঠিক ০
নয়, যদিও গাণিতিকভাবে তাদের একই হওয়ার কথা। কেন?
এই ক্ষুদ্র পার্থক্য ফ্লোটিং-পয়েন্ট নির্ভুলতার সীমাবদ্ধতা থেকে আসে (L02/L03-এ বিস্তারিত) — দুটো
অ্যালগরিদম ভিন্ন ক্রমে যোগ-বিয়োগ-গুণ করে, আর প্রতিটি অপারেশনে সামান্য রাউন্ড-অফ এরর জমা হতে পারে।
1.11 × 10⁻¹⁶ হলো IEEE 754 ডাবল-প্রিসিশন ফ্লোটের যথার্থতার সীমার (মেশিন এপসিলনের) মাত্রার
কাছাকাছি — এটি "ভুল" নয়, বরং প্রমাণ করে দুটো ফলাফল কার্যত অভিন্ন।
প্র ০২
ডিভাইডেড-ডিফারেন্স টেবিলে মাত্রা ৪-এর মান (c4 = 0.033627) সবচেয়ে ছোট। এই সহগগুলো
মাত্রা বাড়ার সাথে সাধারণত ছোট হতে থাকা কী ইঙ্গিত দেয়?
উচ্চতর-মাত্রার ডিভাইডেড ডিফারেন্স ফাংশনের উচ্চতর-মাত্রার ডেরিভেটিভের সাথে সম্পর্কিত (আসলে
f[x₀,...,xₙ] ≈ f⁽ⁿ⁾(ξ)/n! কোনো ξ-এর জন্য)। sin(x)-এর মতো
মসৃণ, ভালো-আচরণকারী ফাংশনের জন্য উচ্চতর ডেরিভেটিভগুলো n!-এর তুলনায় দ্রুত বাড়ে না, তাই
সহগগুলো ছোট হতে থাকে — এটি একটি ইঙ্গিত যে পলিনোমিয়াল ইন্টারপোলেশন এখানে ভালো কাজ করবে (L18-এ দেখানো
হবে সব ফাংশনের জন্য এটি সত্য নয়)।
প্র ০৩
যদি ডেটাসেটে একটি ৬ষ্ঠ পয়েন্ট (2.5, sin(2.5)) যোগ করা হয়, নিউটন ফর্মে ঠিক কী নতুন
কাজ করতে হবে — আর লাগ্রাঞ্জ ফর্মে কী করতে হবে?
নিউটন ফর্মে শুধু ডিভাইডেড-ডিফারেন্স টেবিলে একটি নতুন তির্যক (একটি নতুন সহগ c5) গণনা করতে
হবে — আগের c0 থেকে c4 অপরিবর্তিত থাকে। লাগ্রাঞ্জ ফর্মে প্রতিটি বেসিস
পলিনোমিয়াল Lᵢ(x)-এর সংজ্ঞাতেই সব xⱼ জড়িত থাকে, তাই ৬টি পয়েন্টের সবগুলো
বেসিস আবার নতুন করে গণনা করতে হবে। এটাই নিউটন ফর্মের ব্যবহারিক সুবিধার মূল কারণ।
অনুশীলন
-
চিন্তা করুন: ডিভাইডেড-ডিফারেন্স টেবিলের মাত্রা ১-এর প্রথম মান
(
f[x0,x1] = 0.958851) আসলে(y1-y0)/(x1-x0)— অর্থাৎsin(0.5)ওsin(0.0)-এর মধ্যে গড় ঢাল। এটিsin'(0) = cos(0) = 1-এর কত কাছাকাছি হবে বলে আপনার ধারণা?বেশ কাছাকাছি হওয়ার কথা, কারণ
0থেকে0.5একটি ছোট ইন্টারভাল এবংsin(x)এই রেঞ্জে প্রায় লিনিয়ার আচরণ করে। গণনা করলে0.958851পাওয়া যায়, যা প্রকৃতcos(0) = 1-এর তুলনায়০.০৪-এর কাছাকাছি কম — একটি ছোট কিন্তু লক্ষণীয় পার্থক্য, কারণ গড় ঢাল সবসময় ঠিক তাৎক্ষণিক ডেরিভেটিভের সমান হয় না। -
পরীক্ষা করুন: উপরের কোড সেলে
print(f"f[x0,x1] থেকে অনুমিত ঢাল: {coeffs[1]:.6f}, cos(0)={math.cos(0):.6f}")যোগ করে Run চেপে আপনার অনুমান যাচাই করুন।আউটপুট দেখাবে
coeffs[1] = 0.958851এবংcos(0) = 1.000000— পার্থক্য0.041149, যা নিশ্চিত করে ধারণাটি সঠিক ছিল: ডিভাইডেড ডিফারেন্স ডেরিভেটিভের একটি আনুমানিক (কিন্তু নিখুঁত নয়) সংস্করণ, বিশেষত যখন ইন্টারভাল যথেষ্ট ছোট হয়।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- L18 · রুঙ্গের ফেনোমেনন ও পিসওয়াইজ ইন্টারপোলেশন পরবর্তী পাঠ উঁচু-ডিগ্রি পলিনোমিয়াল ইন্টারপোলেশন কখন বিপজ্জনকভাবে ভুল হয়ে যায় — একটি সত্যিকারের, গণনাকৃত ডেমো।
- L16 · লাগ্রাঞ্জ ফর্ম আগের পাঠ একই পলিনোমিয়াল লেখার আরেকটি রূপ — যেখান থেকে এই পাঠের ক্রস-চেক শুরু হয়েছে।
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ এরর অ্যানালাইসিস, রুট-ফাইন্ডিং, লিনিয়ার সিস্টেম, ইন্টারপোলেশন, নিউমেরিক্যাল ইন্টিগ্রেশন, ODE সলভিং, আইগেনভ্যালু মেথড, অপ্টিমাইজেশন ও ক্যাপস্টোন।