ম্যাট্রিক্স নর্ম, কন্ডিশন নাম্বার ও এরর বাউন্ড
এই পাঠে যা শিখবেন
- ম্যাট্রিক্স নর্ম কী এবং ইনফিনিটি-নর্ম কীভাবে হাতে গণনা করা হয়
- কন্ডিশন নাম্বারের সংজ্ঞা এবং এটি L04-এর কন্ডিশনিং ধারণার সাথে কীভাবে সম্পর্কিত
- Gauss-Jordan পদ্ধতিতে হাতে ম্যাট্রিক্স ইনভার্স বের করা
- একটি সত্যিকারের, চলমান Python ডেমো — ভালো বনাম খারাপ-কন্ডিশনড ম্যাট্রিক্সের কন্ডিশন নাম্বার ও perturbation-প্রতিক্রিয়া তুলনা
১ · ম্যাট্রিক্স নর্ম — একটি ম্যাট্রিক্সের "আকার"
একটি সংখ্যার absolute value যেমন তার "আকার" বোঝায়, তেমনি একটি ম্যাট্রিক্সের নর্ম তার সামগ্রিক "আকার" একটি একক সংখ্যায় প্রকাশ করে। এই পাঠে আমরা ইনফিনিটি-নর্ম ব্যবহার করি, যা গণনা করা সবচেয়ে সহজ:
$$\|A\|_\infty = \max_{i} \sum_{j} |a_{ij}|$$অর্থাৎ প্রতিটি সারির উপাদানগুলোর absolute value যোগ করে, তারপর সব সারির মধ্যে সর্বোচ্চ যোগফলটি নেওয়া হয়।
২ · কন্ডিশন নাম্বার — সংবেদনশীলতার পরিমাপ
L04-এ আমরা ধারণাগতভাবে দেখেছিলাম একটি সিস্টেম "ভালো" বা "খারাপ" কন্ডিশনড হতে পারে। এখন সেই ধারণাটিকে একটি সুনির্দিষ্ট সংখ্যায় রূপান্তর করা যাক:
$$\kappa(A) = \|A\| \times \|A^{-1}\|$$
κ(A) যত বড়, সিস্টেমটি তত বেশি ill-conditioned — অর্থাৎ b-এর একটি ছোট
পরিবর্তন x-এ একটি বড়, অসামঞ্জস্যপূর্ণ পরিবর্তন ঘটাতে পারে। κ(A) = ১ সবচেয়ে
ভালো (আদর্শ) কন্ডিশনিং নির্দেশ করে; κ(A) যত বড় হয়, ততই সিস্টেম সংবেদনশীল হয়ে ওঠে —
এমনকি সঠিকভাবে বাস্তবায়িত গসিয়ান এলিমিনেশন/পিভোটিং (L10-L12) থাকলেও।
A⁻¹ এমন একটি ম্যাট্রিক্স যেন A × A⁻¹ = I (আইডেন্টিটি ম্যাট্রিক্স)। Gauss-Jordan পদ্ধতিতে [A | I] augmented ম্যাট্রিক্সে এলিমিনেশন চালিয়ে [I | A⁻¹] রূপে পৌঁছানো যায়।কন্ডিশন নাম্বার সরাসরি একটি এরর বাউন্ড দেয়: relative input error-কে
κ(A) গুণ করলে relative output error-এর একটি উচ্চ-সীমা পাওয়া যায় (আনুমানিক)।যখন
A singular-এর (ডিটারমিন্যান্ট শূন্য) খুব কাছাকাছি চলে যায়, A⁻¹-এর উপাদান বিশাল হয়ে যায়, ফলে κ(A)ও বিশাল হয়ে যায় — L12-এর near-singular সিস্টেমের সাথে সরাসরি সম্পর্কিত।৩ · একটি সত্যিকারের ডেমো — ভালো বনাম খারাপ-কন্ডিশনড ম্যাট্রিক্স
নিচে একটি সাধারণ ইনফিনিটি-নর্ম ফাংশন এবং Gauss-Jordan পদ্ধতিতে একটি হাতে-লেখা ম্যাট্রিক্স-ইনভার্স
ফাংশন লেখা হয়েছে। দুটি 2x2 ম্যাট্রিক্সে — একটি স্পষ্টত ভালো-কন্ডিশনড, আরেকটি প্রায়-singular (খারাপ
কন্ডিশনড) — কন্ডিশন নাম্বার গণনা করে তুলনা করা হয়েছে, এবং সবশেষে b-তে ছোট perturbation-এর
প্রকৃত প্রভাব দেখানো হয়েছে।
def inf_norm(A):
# ম্যাট্রিক্স ইনফিনিটি-নর্ম = সারিগুলোর absolute-value যোগফলের মধ্যে সর্বোচ্চটি
return max(sum(abs(v) for v in row) for row in A)
def mat_inverse(A):
n = len(A)
M = [A[i][:] + [1.0 if i == j else 0.0 for j in range(n)] for i in range(n)]
for col in range(n):
pivot_row = max(range(col, n), key=lambda r: abs(M[r][col]))
if abs(M[pivot_row][col]) < 1e-15:
raise ValueError("ম্যাট্রিক্সটি singular -- inverse নেই")
M[col], M[pivot_row] = M[pivot_row], M[col]
pivot_val = M[col][col]
M[col] = [v / pivot_val for v in M[col]]
for r in range(n):
if r != col:
factor = M[r][col]
M[r] = [M[r][k] - factor * M[col][k] for k in range(2 * n)]
return [row[n:] for row in M]
def mat_mult(X, Y):
n, m, p = len(X), len(Y), len(Y[0])
return [[sum(X[i][t] * Y[t][j] for t in range(m)) for j in range(p)] for i in range(n)]
def condition_number(A):
A_inv = mat_inverse(A)
return inf_norm(A) * inf_norm(A_inv), A_inv
print("=== ভালোভাবে-কন্ডিশনড (well-conditioned) ম্যাট্রিক্স ===")
A_good = [[4.0, 1.0], [2.0, 3.0]]
cond_good, Ainv_good = condition_number(A_good)
print("A =", A_good)
print("||A||_inf =", inf_norm(A_good))
print("A^-1 =", [[round(v, 6) for v in row] for row in Ainv_good])
print("||A^-1||_inf =", round(inf_norm(Ainv_good), 6))
print(f"কন্ডিশন নাম্বার κ(A) = {cond_good:.6f}")
print()
print("=== খারাপভাবে-কন্ডিশনড (ill-conditioned) ম্যাট্রিক্স ===")
A_bad = [[1.0, 1.0], [1.0, 1.0001]]
cond_bad, Ainv_bad = condition_number(A_bad)
print("A =", A_bad)
print("||A||_inf =", inf_norm(A_bad))
print("A^-1 =", [[round(v, 4) for v in row] for row in Ainv_bad])
print("||A^-1||_inf =", round(inf_norm(Ainv_bad), 4))
print(f"কন্ডিশন নাম্বার κ(A) = {cond_bad:.4f}")
print()
print(f"তুলনা: κ(A_good) = {cond_good:.4f} বনাম κ(A_bad) = {cond_bad:.2f}")
print(f"অনুপাত = {cond_bad / cond_good:.1f}x")
def solve_2x2(A, b):
det = A[0][0]*A[1][1] - A[0][1]*A[1][0]
x0 = (b[0]*A[1][1] - A[0][1]*b[1]) / det
x1 = (A[0][0]*b[1] - b[0]*A[1][0]) / det
return [x0, x1]
b1 = [2.0, 2.0]
b2 = [2.0, 2.001] # b-তে মাত্র 0.001 পার্থক্য
print()
print("=== ছোট perturbation-এর প্রভাব (b-তে 0.001 পরিবর্তন) ===")
for name, A in [("good", A_good), ("bad", A_bad)]:
x1 = solve_2x2(A, b1)
x2 = solve_2x2(A, b2)
change = max(abs(x1[i]-x2[i]) for i in range(2))
print(f"{name}: x পরিবর্তন = {change:.6f}")
=== ভালোভাবে-কন্ডিশনড (well-conditioned) ম্যাট্রিক্স === A = [[4.0, 1.0], [2.0, 3.0]] ||A||_inf = 5.0 A^-1 = [[0.3, -0.1], [-0.2, 0.4]] ||A^-1||_inf = 0.6 কন্ডিশন নাম্বার κ(A) = 3.000000 === খারাপভাবে-কন্ডিশনড (ill-conditioned) ম্যাট্রিক্স === A = [[1.0, 1.0], [1.0, 1.0001]] ||A||_inf = 2.0000999999999998 A^-1 = [[10001.0, -10000.0], [-10000.0, 10000.0]] ||A^-1||_inf = 20001.0 কন্ডিশন নাম্বার κ(A) = 40004.0001 তুলনা: κ(A_good) = 3.0000 বনাম κ(A_bad) = 40004.00 অনুপাত = 13334.7x === ছোট perturbation-এর প্রভাব (b-তে 0.001 পরিবর্তন) === good: x পরিবর্তন = 0.000400 bad: x পরিবর্তন = 10.000000
κ = ৩, খারাপ-কন্ডিশনডের
κ ≈ ৪০,০০৪ — ১৩,৩৩৪ গুণ বেশি। আর এর ব্যবহারিক ফলাফল সরাসরি দেখা যাচ্ছে:
b-তে মাত্র ০.০০১ পরিবর্তনে ভালো-কন্ডিশনড সিস্টেমে x নড়ে মাত্র
০.০০০৪, কিন্তু খারাপ-কন্ডিশনড সিস্টেমে x নড়ে পুরো ১০.০ — একই
ইনপুট-পরিবর্তনের জন্য ২৫,০০০ গুণ বড় আউটপুট-পরিবর্তন।
কন্ডিশন নাম্বার একটি সিস্টেমের অন্তর্নিহিত বৈশিষ্ট্য — এটি কোনো নির্দিষ্ট এলিমিনেশন অ্যালগরিদমের ত্রুটি
নয় (L12-এর পিভোটিং এটি ঠিক করতে পারে না)। বাস্তব ব্যবহারে, যদি κ(A) অনেক বড় হয়, তাহলে
সিস্টেমটি নিজেই পুনর্গঠন করা প্রয়োজন হতে পারে (যেমন regularization, বা সমস্যার ভৌত মডেলিং পুনর্বিবেচনা)
— শুধু আরও নির্ভুল arithmetic ব্যবহার করে এটি সমাধান করা যায় না। L50-এ forward/backward error
analysis-এ এই ধারণাটি আরও গভীরভাবে বিশ্লেষণ করা হবে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১
কোড সেলে if abs(M[pivot_row][col]) < 1e-15: লাইনটি কেন আছে, এবং এটি L12-এর কোন
ধারণার সাথে সরাসরি সম্পর্কিত?
এটি Gauss-Jordan ইনভার্স-গণনায় partial pivoting প্রয়োগ করছে (L12-এর একই কৌশল) — কলামের মধ্যে সবচেয়ে বড় absolute মান খুঁজে পিভোট হিসেবে বেছে নিচ্ছে, এবং যদি সেটিও কার্যত শূন্য হয় তাহলে ম্যাট্রিক্সটি সত্যিই singular ধরে নিয়ে একটি স্পষ্ট এরর ছুঁড়ে দিচ্ছে — নীরবে ভুল উত্তর দেওয়ার বদলে।
প্র ০২
A_bad-এর দুটি সারি ([1,1] ও [1, 1.0001]) প্রায় হুবহু একই
— এটি জ্যামিতিকভাবে কী বোঝায়, এবং কেন এটি কন্ডিশন নাম্বার এত বড় করে তোলে?
দুটি সমীকরণ প্রায় একই সরলরেখা প্রতিনিধিত্ব করে — তারা প্রায় সমান্তরাল। জ্যামিতিকভাবে, এই দুই রেখার
ছেদবিন্দু (সমাধান) একটি অত্যন্ত সংকীর্ণ কোণে ঘটে, তাই ছেদবিন্দুর অবস্থান যেকোনো একটি রেখার সামান্য
নড়াচড়ায় (যা b-এর পরিবর্তনের সমতুল্য) নাটকীয়ভাবে বদলে যায় — এটাই বড় কন্ডিশন নাম্বারের
জ্যামিতিক অর্থ।
প্র ০৩
যদি A_bad-এর দ্বিতীয় সারি ঠিক [1, 1] (অর্থাৎ প্রথম সারির হুবহু কপি)
হতো, তাহলে mat_inverse ফাংশনে কী ঘটত?
তখন ম্যাট্রিক্সটি সত্যিকারের singular হয়ে যেত (ডিটারমিন্যান্ট ঠিক শূন্য) — কোনো ইনভার্স অস্তিত্ব
থাকত না। কোড সেলে pivot_row নির্বাচনের পরও abs(M[pivot_row][col]) শূন্যের
কাছাকাছি থেকে যেত, এবং raise ValueError("ম্যাট্রিক্সটি singular -- inverse নেই")
লাইনটি কার্যকর হতো — কন্ডিশন নাম্বার তখন গাণিতিকভাবে অসীম।
অনুশীলন
-
চিন্তা করুন: উপরের কোড সেলে
A_bad-এর1.0001-কে1.00001(আরও কাছাকাছি) করলে কন্ডিশন নাম্বার আরও বাড়বে না কমবে বলে আপনার মনে হয়?বাড়বে — সারি দুটো যত বেশি একে অপরের কাছাকাছি (প্রায়-সমান্তরাল) হয়, ম্যাট্রিক্সটি তত বেশি singular-এর কাছাকাছি চলে যায়, এবং
A⁻¹-এর উপাদান তত বেশি বিশাল হয়ে যায় — ফলে কন্ডিশন নাম্বার আরও অনেক বেশি বড় হবে। -
পরীক্ষা করুন: উপরের কোড সেলে
A_bad-এর1.0001-কে1.00001-এ পরিবর্তন করে Run চেপে নতুন কন্ডিশন নাম্বার যাচাই করুন।নতুন কন্ডিশন নাম্বার প্রায়
κ ≈ ৪০০,০০৪-এর কাছাকাছি চলে যায় — আগের৪০,০০৪-এর প্রায় ১০ গুণ, ঠিক যেমন অনুমান করা হয়েছিল। এই প্যাটার্নটি সাধারণীকরণযোগ্য: পিভটের কাছাকাছি দূরত্ব যত ছোট হয়, কন্ডিশন নাম্বার তার বিপরীত অনুপাতে বাড়ে।
আরও পড়ুন · 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, এবং আরও অনেক কোর্স।