ট্র্যাক
/
Julia
Julia
/
সিলেবাস
/
রৈখিক সমীকরণ সমাধান
রৈ

রৈখিক সমীকরণ সমাধান মধ্যে Julia

{one: "১টি অনুশীলনী", other: "%{count}টি অনুশীলনী"}

রৈখিক সমীকরণ সমাধান সম্পর্কে

মনে পড়ে, হাই স্কুলে যখন প্রথম বীজগণিত শিখেছিলেন?

সাধারণত আমাদের সমীকরণের একটি সিস্টেম দেওয়া হতো, আর x ও y-এর মান বের করতে বলা হতো।

4x - 3y = -2
2x + 7y = 16

দুটি সমীকরণ, দুটি অজানা: সামান্য প্রতিস্থাপন করলেই আপনি দেখতে পাবেন x = 1, y = 2।

আগের উদাহরণটির বাম দিকটি আবার দেখুন। এটা এমন দেখায় যেন একটি ম্যাট্রিক্স [4 -3; 2 7] একটি অজানা ভেক্টর [x, y]-কে গুণ করে ভেক্টর [-2, 16] দিচ্ছে।

রৈখিক বীজগণিতের নোটেশনে: A x = b, যেখানে প্রচলিত নিয়ম অনুযায়ী ম্যাট্রিক্সের জন্য বড় হাতের অক্ষর আর ভেক্টরের জন্য ছোট হাতের অক্ষর ব্যবহার করা হয়।

A x = 0 এবং নালস্পেস

একটি গুরুত্বপূর্ণ বিশেষ ক্ষেত্র হলো যখন আমাদের সব সমীকরণের ডান দিকে শূন্য থাকে।

4x - 3y = 0
2x + 7y = 0

উপরের উদাহরণে একমাত্র সমাধান হলো x = y = 0, যা সাধারণত তেমন আকর্ষণীয় নয়।

A x = 0-এর নন-ট্রিভিয়াল সমাধান কেবল তখনই থাকে যখন A-এর নির্ধারক শূন্য হয়।

julia> using LinearAlgebra

julia> A = [4 -3; 2 7]
2×2 Matrix{Int64}:
 4  -3
 2   7

julia> det(A)  # not zero!
34.0

এর বদলে এই সমীকরণগুলো ভাবুন:

4x - 3y = 0
8x + 6y = 0

দ্বিতীয় সমীকরণটি আসলে প্রথম সমীকরণের দ্বিগুণ, তাই এটি নতুন কোনো তথ্য যোগ করে না। যেসব মানে x = 0.75y হয়, সেগুলোই একটি সমাধান হবে।

এই (x, y) মানগুলো দ্বিমাত্রিক জগতে একটি সরলরেখা বরাবর অবস্থিত। এখানে অসীম সংখ্যক সমাধান আছে, আর এগুলো ম্যাট্রিক্সের নালস্পেস গঠন করে।

এক্ষেত্রে ম্যাট্রিক্সের সারিগুলো রৈখিকভাবে স্বাধীন নয়, আর ম্যাট্রিক্সের র‍্যাঙ্ক সারি বা কলামের সংখ্যার চেয়ে কম।

julia> A = [4 -3; 8 -6]
2×2 Matrix{Int64}:
 4  -3
 8  -6

julia> det(A)
0.0

julia> size(A)  # total number of rows and columns
(2, 2)

julia> rank(A)  # number of linearly-independent rows (or columns)
1

julia> nullspace(A)
2×1 Matrix{Float64}:
 -0.6
 -0.8

julia> nullspace(A) |> norm  # Julia returns unit vectors when possible
1.0

nullspace() ফাংশনটি একটি মাত্র বিন্দু রিটার্ন করে, যেটিকে নরমালাইজ করে একক ভেক্টর বানানো হয়েছে, তবে এই ভেক্টরের যেকোনো স্কেলার গুণিতকও নালস্পেসের মধ্যেই থাকে।

A x = b সমাধান করা

এখন ধরুন আপনার কাছে ১০০০টি অজানা নিয়ে ১০০০টি সমীকরণ আছে? এটা যদি হাস্যকর শোনায়, মনে রাখবেন যে বেতার ডিজিটাল ট্রান্সডিউসার এখন সস্তা ও বহুমুখী (স্ট্রেইন, বাতাসের গতি, ৩-অক্ষের ত্বরণ, যা-ই হোক...)। একটি ঝুলন্ত সেতুর মতো আধুনিক স্থাপনা নজরে রাখতে সেগুলোর ১০০০টি থাকা সম্পূর্ণ যুক্তিসঙ্গত। ডেটা স্ট্রিম বিশ্লেষণ করার জন্য একটি কন্ট্রোল সিস্টেম থাকা দরকার, যা পরিস্থিতি উদ্বেগজনক হলে সতর্ক সংকেত দিতে প্রস্তুত থাকবে।

আবারও, A x = b, যেখানে আমাদের কাছে A (ইঞ্জিনিয়ারিং ডিজাইন থেকে) আর b (ট্রান্সডিউসার থেকে মাপা মান) আছে, কিন্তু x খুঁজে বের করতে হবে।

এ বিষয়ে অনভিজ্ঞ কারও প্রথম ভাবনা হয়তো হবে, A দিয়ে "ভাগ করে" এটাকে ডান দিকে (RHS) সরিয়ে নেওয়া।

আসলে A-এর একটি বিপরীত ম্যাট্রিক্স আছে (বর্গ ম্যাট্রিক্সের বেশিরভাগেরই থাকে, সবগুলোর নয়: নির্ধারক শূন্য হওয়া চলবে না), আর এই হিসাব কাজ করে (ধীরে!)।

julia> A = [4 -3; 2 7]
2×2 Matrix{Int64}:
 4  -3
 2   7

julia> b = [-2, 16]
2-element Vector{Int64}:
 -2
 16

# the inverse matrix
julia> inv(A)
2×2 Matrix{Float64}:
  0.205882   0.0882353
 -0.0588235  0.117647

julia> inv(A) * b
2-element Vector{Float64}:
 0.9999999999999999
 2.0

দুর্ভাগ্যবশত, বিপরীত ম্যাট্রিক্স নির্ণয় করা ছোট ম্যাট্রিক্সের জন্য ধীর, আর বড় ম্যাট্রিক্সের জন্য অত্যন্ত ধীর। যদি হিসাব চলাকালীনই আপনার সেতু ধসে পড়ে, তাহলে এটা মোটেই আদর্শ নয়!

ভাগ্যক্রমে, অন্য অ্যালগরিদমগুলো অনেক বেশি দ্রুত (এক্ষেত্রে গাউসীয় এলিমিনেশন)।

Julia (Matlab-এর অনুকরণে) সমাধানের জন্য কেবল একটি ব্যাকস্ল্যাশ ব্যবহার করে (কারিগরি ভাষায় "left division")।

julia> x = A \ b
2-element Vector{Float64}:
 1.0
 2.0

এটি একটি সাধারণ উদাহরণ, তবে খেয়াল রাখার মতো কয়েকটি বিষয় আছে।

  • সহগগুলোকে কলামে সাজাতে হবে, তাই অনুপস্থিত পদগুলোর জন্য প্রয়োজনমতো শূন্য বসান।
  • সমীকরণগুলো (এবং তাই ম্যাট্রিক্সের সারিগুলো) রৈখিকভাবে স্বাধীন হতে হবে। যদি ৩ নম্বর সারি কেবল ১ ও ২ নম্বর সারির যোগফল হয়, তবে এটি নতুন কোনো তথ্য যোগ করে না এবং সমস্যাটি আন্ডার-ডিটারমাইন্ড হয়ে যায়।

rank() কমান্ডটি রৈখিকভাবে স্বাধীন সারি/কলামের সংখ্যা দেবে, তাই লক্ষ্য রাখুন এটি যেন অজানা ভ্যারিয়েবলের সংখ্যার সমান হয়।

julia> rank(A)
2

আয়তাকার ম্যাট্রিক্স

কিশোর বয়সের শুরুতেই আপনি সম্ভবত শিখেছেন যে N অজানা বের করতে N সমীকরণের একটি সিস্টেম দরকার।

গণিতের বেশিরভাগ বিষয়ের মতোই, বাস্তবতা একটু বেশি সূক্ষ্ম (শুধু আগের অংশে উল্লেখ করা রৈখিক স্বাধীনতার বিষয়টি নয়)।

"খুব কম" সারি

N-1 সমীকরণ (ম্যাট্রিক্স A-এর সারি) নিয়ে সমস্যাটি আন্ডার-ডিটারমাইন্ড হয়ে যায়। তাহলে কি হতাশায় হাল ছেড়ে দেব?

তা নির্ভর করে!

N-1 সমীকরণে এখনও অনেক তথ্য থাকে। জ্যামিতিকভাবে বললে, N-মাত্রিক জগতে সমাধানকে একটি বিন্দু হিসেবে নির্ধারণ করতে N দরকার, কিন্তু N-1 আমাদের জানাবে যে সমাধানটি অবশ্যই কোথাও একটি সরলরেখার উপর অবস্থিত।

এতে আমাদের হাতে অসীম সংখ্যক সমাধান থাকে, কিন্তু একইসাথে কোনো সমাধান নেই এমন অসীম প্যারামিটার স্পেসও থাকে।

আপনার সমাধানের সরলরেখাটি কি প্যারামিটার স্পেসের এমন একটি অঞ্চলের মধ্য দিয়ে যায়, যা নিয়ে একজন সুনামধন্য ইঞ্জিনিয়ারের চিন্তা করা উচিত? নাকি এমন একটি অঞ্চল, যা জনসাধারণের জন্য স্থাপনাটি বন্ধ করার যৌক্তিকতা তৈরি করে (তীব্র আড়াআড়ি বাতাসে ঝুলন্ত সেতু দুলতে পারে)? এটা নির্ধারণ করতে আরও কিছু হিসাব করে দেখার মূল্য নিশ্চয়ই আছে!

julia> A3 = [4 -3 1; 2 2 2; 3 -4 -3]
3×3 Matrix{Int64}:
 4  -3   1
 2   2   2
 3  -4  -3

julia> b3 = [1, 12, -14]
3-element Vector{Int64}:
   1
  12
 -14

# fully-determined solution
julia> A3 \ b3
3-element Vector{Float64}:
 1.0
 2.0
 3.0

# remove row 3 from A3 and B3
julia> A2 = A3[1:2, :]
2×3 Matrix{Int64}:
 4  -3  1
 2   2  2

julia> b2 = b3[1:2]
2-element Vector{Int64}:
  1
 12

# an under-determined solution
julia> z1 = A2 \ b2
3-element Vector{Float64}:
 1.594594594594594
 2.445945945945947
 1.9594594594594592

ব্যাকস্ল্যাশ সলভার আমাদের একটি সমাধান দিয়ে দেয়! অনানুষ্ঠানিকভাবে, এটা দৃশ্যত সবচেয়ে ছোট নর্মের সমাধান (জ্যামিতিকভাবে মূলবিন্দুর সবচেয়ে কাছে)।

অন্য সমাধানগুলো পেতে আমাদের A2-এর nullspace দরকার।

মূল সমাধানের সাথে নালস্পেসের যেকোনো স্কেলার গুণিতক যোগ করলে আরেকটি বৈধ সমাধান পাওয়া যায়।

# get the nummspace of A2
julia> N = nullspace(A2)
3×1 Matrix{Float64}:
 -0.46499055497527725
 -0.3487429162314578
  0.813733471206735

# add a random multiple of the nullspace to the earlier solution
julia> z = z1 + rand() * N
3×1 Matrix{Float64}:
 1.274331860650258
 2.205748895487695
 2.5199192438620472

# our random z is a valid solution, recovering b2 = [1, 12]
julia> A2 * z
2×1 Matrix{Float64}:
  0.9999999999999947
 12.0

একইভাবে, N-2 সমীকরণ (অসীম) সমাধানগুলোকে একটি তলে সীমাবদ্ধ করবে, আর এখানেও একই নীতিগুলো খাটে।

"খুব বেশি" সারি

উল্টো পরিস্থিতি আসে যখন অজানার চেয়ে বেশি সমীকরণ থাকে, তবুও কোনোভাবে সেগুলো রৈখিকভাবে স্বাধীন হয়।

বাস্তব প্রকৌশলে এটি সম্পূর্ণ স্বাভাবিক, আর এটাকে ভালো বিষয় হিসেবেই দেখা হয়!

ট্রান্সডিউসারের নির্ভুলতা সীমিত, b ভেক্টরের নির্ভুলতাও সীমিত, আর হিসাবে নয়েজ থাকে। এখন সমাধানটি হয় কোলাহলযুক্ত ডেটার সাথে একটি সর্বনিম্ন বর্গ ফিট।

সবচেয়ে সহজ কৌশলটি হলো ম্যাট্রিক্সের pseudoinverse ব্যবহার করা, যেটি Julia pinv() ফাংশন হিসেবে বাস্তবায়ন করে।

এটি একটি (নন-সিঙ্গুলার) বর্গ ম্যাট্রিক্সের বিপরীত ম্যাট্রিক্সের মতোই ব্যবহার করা যায়, যা সঠিক সমাধানের বদলে ভ্যারিয়েবলগুলোর একটি সর্বনিম্ন বর্গ অনুমান দেয়।

# create 5-row A and b for 2 variables
julia> A5 = [4 -3; 2 7; -1 2; 1 -1; 3 1]
5×2 Matrix{Int64}:
  4  -3
  2   7
 -1   2
  1  -1
  3   1

julia> rank(A5)
2

# add some random-normal noise to b5
julia> b5n = [-2, 16, 3, -1, 5] + randn(5) * 0.1
5-element Vector{Float64}:
 -1.9337349223581917
 16.024913008059457
  3.0087646177373992
 -0.8675748721176717
  4.914568047308805

# solve to get x ≈ 1, y ≈ 2, using the pseudoinverse
julia> pinv(A5) * b5n
2-element Vector{Float64}:
 1.006117942769543
 1.9962973764508272

আইগেনভ্যালু ও আইগেনভেক্টর

আগের অংশে A x = b-এর সমাধান বর্ণনা করা হয়েছে, যা পরিচিত বীজগণিতের সমতুল্য।

এই অংশটি A x = λ x-এর সমাধান নিয়ে, যেখানে λ একটি স্কেলার।

এটি বিশেষভাবে রৈখিক বীজগণিতের একটি ধারণা, তবে আমরা এটাকে জ্যামিতিকভাবে ব্যাখ্যা করতে পারি:

x ও λ-এর উপযুক্ত মানের জন্য, বর্গ ম্যাট্রিক্স A অশূন্য ভেক্টর x-কে দৈর্ঘ্যে λ গুণ স্কেল করে, কিন্তু তার দিক বদলায় না (ঋণাত্মক λ দিকটি উল্টে দেওয়া ছাড়া)।

এটা শুনতে খুব সীমিত পরিসরের মনে হয়, কিন্তু বাস্তবে এটি অবিশ্বাস্যরকম কাজের!

পরিভাষা: λ-এর বৈধ মানগুলো A-এর আইগেনভ্যালু, আর x-এর সংশ্লিষ্ট মানগুলো A-এর আইগেনভেক্টর। দুর্ভাগ্যবশত, মাঝপথে ভাষা বদলে ফেলা এমন শব্দ নিয়ে আমাদের কেবল মেনে নিয়েই চলতে হয়।

শিক্ষার্থীদের সাধারণত ২×২ ম্যাট্রিক্সের আইগেনভ্যালু/আইগেনভেক্টর হাতে হাতে কীভাবে বের করতে হয় তা শেখানো হয়, তবে কম্পিউটার ব্যবহার করা অনেক সহজ (যদিও সাধারণ ক্ষেত্রে একটি n×n ম্যাট্রিক্সের জন্য এটি এখনও বেশ ধীর, আর এর স্কেলিং O(n^3))।

julia> A = rand(-9:9, 2, 2)
2×2 Matrix{Int64}:
 9  5
 3  2

julia> F = eigen(A)
Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}}
values:
2-element Vector{Float64}:
  0.27984674554472466
 10.720153254455274
vectors:
2×2 Matrix{Float64}:
 -0.497417  0.945605
  0.867511  0.325317

# eigenvalues
julia> F.values
2-element Vector{Float64}:
  0.27984674554472466
 10.720153254455274

# each column is an eigenvector, normalized to a unit vector
julia> F.vectors
2×2 Matrix{Float64}:
 -0.497417  0.945605
  0.867511  0.325317

সাধারণভাবে, একটি n×n ম্যাট্রিক্সের nটি আইগেনভ্যালু থাকে, যদিও মানগুলো সবসময় আলাদা নাও হতে পারে। এগুলোকে একটি n-তম ঘাতের বহুপদীর (যাকে চারিত্রিক বহুপদী বলা হয়) মূল হিসেবে ভাবুন, যা একই হতে পারে, আর বাস্তব মানের ম্যাট্রিক্সের ক্ষেত্রেও প্রায়ই জটিল সংখ্যা হয়।

প্রতিটি আইগেনভেক্টর একটি দিক নির্দেশ করে, আর যেকোনো স্কেলার গুণিতকও একটি বৈধ আইগেনভেক্টর। পরবর্তী হিসাবের সুবিধার জন্য Julia একক ভেক্টর রিটার্ন করে, যাদের নর্ম ১।

প্রয়োগ

আইগেনভেক্টর কেন গুরুত্বপূর্ণ, তা ব্যাখ্যা করা আদর্শভাবে কয়েকটি ছোট অনুচ্ছেদের বদলে ৫০০ পাতার একটি পাঠ্যবইয়ের কাজ। এই বিষয়টি আধুনিক ফলিত গণিতের অনেক অংশে ছড়িয়ে আছে।

সবচেয়ে বড় পরিসরে বললে, আইগেনভেক্টর একটি ডেটাসেটের "সবচেয়ে গুরুত্বপূর্ণ" অক্ষগুলো (দিকগুলো) উপস্থাপন করে। আইগেনভ্যালু প্রতিটি অক্ষের "আপেক্ষিক গুরুত্ব" নির্দেশ করে (ইনপুটের নরমালাইজেশন নিয়ে কিছু অনুমানের সাপেক্ষে)।

এর আসলে কী অর্থ হয়, তা নির্ভর করে প্রয়োগের উপর।

প্রিন্সিপাল কম্পোনেন্ট অ্যানালাইসিস

একটি সাধারণ ডেটা সায়েন্স সমস্যায় আমাদের হয়তো ১০০ বা তার বেশি "ফিচার" থাকে, যেগুলো ডেটার কলাম হিসেবে সংরক্ষিত। প্রায় অনিবার্যভাবেই নয়েজ, বাহুল্য আর অবাঞ্ছিত পারস্পরিক সম্পর্ক থাকবে।

আমাদের মাত্রা হ্রাস করতে হবে, আর বিশৃঙ্খলায় শৃঙ্খলা আনতে PCA একটি উপায়:

  • ডেটার কোভারিয়েন্স ম্যাট্রিক্স নির্ণয় করুন।
  • এখন আমাদের হাতে একটি বর্গ ম্যাট্রিক্স আছে, তাই এরপর আইগেনভ্যালু ও আইগেনভেক্টর নির্ণয় করুন।
  • আইগেনভ্যালুর অবরোহ ক্রম অনুযায়ী আইগেনভেক্টরগুলো সাজান (আরও নির্দিষ্টভাবে, পরম মান |λ|)।
  • উপরের kটি আইগেনভেক্টরই এখন আপনার principal components, যেখানে k মূল ফিচার সংখ্যার চেয়ে যথেষ্ট ছোট।
  • সম্পূর্ণ ডেটাসেটকে এই kটি অক্ষের উপর প্রক্ষেপণ করুন, আর মজার প্যাটার্ন খুঁজতে শুরু করুন।

এই রূপে PCA ব্যবহার করেছেন নানা ধরনের দলের মানুষ, যেমন চিকিৎসাবিজ্ঞানীরা, যারা ওষুধ ডিজাইনে আণবিক ধর্ম উন্নত করার চেষ্টা করছেন, আর রাজনৈতিক প্রচারকেরা, যারা জনমত জরিপের ডেটা থেকে ভোটারদের পছন্দ বোঝার চেষ্টা করছেন। আপনাকে জিনিস বিক্রি করার চেষ্টা করা মার্কেটিং দলগুলোও সম্ভবত এটি ব্যবহার করে, তবে যেকোনো প্রযুক্তিই ভালো বা মন্দ দুটো কাজেই ব্যবহার করা যায়।

PCA ন্যূনতম Julia ইনস্টলেশনের অংশ নয়, তবে (Exercism-এর বাইরে) MultivariateStats প্যাকেজে আপনার প্রয়োজনীয় সবকিছু আছে।

ইমেজ প্রসেসিং

PCA ধারণাটিকে আরেক ধাপ এগিয়ে নিলে, ডিজিটাল ইমেজ আসলে পিক্সেল মানের ম্যাট্রিক্স মাত্র, আর আমরা সেগুলোর জন্য প্রিন্সিপাল কম্পোনেন্ট নির্ণয় করতে পারি।

দশকের পর দশক ধরে এটি ইমেজ কম্প্রেশনে ব্যবহৃত হয়ে আসছে, যেখানে ফাইলের আকার কমানোর সময় কোনটি সংরক্ষণ করা সবচেয়ে জরুরি, তার দিশা দেয় PCA।

ক্রমবর্ধমানভাবে, মুখ শনাক্তকরণের মতো ইমেজ ক্লাসিফায়ারের একটি অপরিহার্য অংশ হয়ে উঠছে PCA। পরেরবার যখন কোনো বিমানবন্দর দিয়ে হেঁটে যাবেন, মনে রাখবেন বিগ ব্রাদার কেবল দেখছে না, সে যা দেখছে তা বোঝার জন্য রৈখিক বীজগণিতও ব্যবহার করছে!

মেকানিক্যাল ইঞ্জিনিয়ারিং

কম বিতর্কিতভাবে, একটি যান্ত্রিক উপাদানের প্রিন্সিপাল অক্ষগুলো হলো তার জড়তার ভ্রামক টেনসর I-এর আইগেনভেক্টর (একটু ভিন্ন নামের একটি ম্যাট্রিক্স)।

আপনার গাড়ির প্রতিটি চাকাতেই সম্ভবত এক বা একাধিক ব্যালান্স ওয়েট থাকে, যা এই টেনসর I-এর কর্ণের বাইরের উপাদানগুলো শূন্য করার জন্য সমন্বয় করা হয়। গ্যারেজের মেকানিক নিঃসন্দেহে এই গণিত করা এড়িয়ে যান (বিমান ডিজাইনার আর রকেট ইঞ্জিনিয়ারদের বিপরীতে), কিন্তু "দোলা" শব্দটি কেবল টেনসরের ক্রস-টার্মগুলো বোঝানোর একটি সাধারণ প্রতিদিনের শব্দ, যা এক্ষেত্রে আপনার যাত্রাকে কম আরামদায়ক করে তুলবে আর বিয়ারিংয়ের উপর যান্ত্রিক ক্ষয় বাড়াবে।

GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি নতুন একটি উইন্ডো বা ট্যাবে খুলবে