Lineer Cebir#

Ders Notları: 5#

Lineer Cebir

  • Doğrusal denklem seti çözümleri

  • Matematik de bir yere kadar

  • Sorunlar, sorunsallar…

  • Özdeğer ve özvektörlerin kısa yoldan bulunması

  • Tavsiyeler

Dr. Emre S. Taşcı, emre.tasci@hacettepe.edu.tr
Fizik Mühendisliği Bölümü
Hacettepe Üniversitesi

Doğrusal denklem seti çözümleri#

\(n\times n\)’lik matrisle, n bilinmeyenli n denklem arasında yakın bir bağ vardır. Örneğin, iki bilinmeyenli iki denklemimiz olsun:

\[\begin{split}3x+2y = 7\\x-y=-1\end{split}\]

Bunu matris çarpımı şeklinde yazabiliriz, yazalım hatta:

\[\begin{split}\begin{bmatrix}3&2\\1&-1\end{bmatrix}_{(2\times 2)}\cdot\left( \begin{matrix}x\\y\end{matrix} \right)_{(2\times 1)}= \left(\begin{matrix}7\\-1\end{matrix}\right)_{(2\times 1)}\end{split}\]

Yani aslında yaptığımız şey, şu çarpma işlemindeki \(x\)’i çözmekten ibaret:

\[A\cdot\vec{x} = \vec{b}\]

Skaler çarpım olsa, \(b\)’yi \(A\)’ya böler, muradımıza ererdik ama matrislerde bildiğimiz anlamda bir bölme yok. Biraz felsefi takılırsak, aslında \(b\)’yi \(A\)’ya bölmüyoruz, eşitliğin iki yanını da \(A\)nın çarpma işlemine göre ters elemanı ile çarpıyoruz – skaler çarpımda bu işlemin tersi bölmeye denk geliyor, matrislerin çarpımında ise matrisin tersi ile çarpmaya, özetle, şöyle bir şey yaptığımız:

\[A^{-1}\cdot A\cdot\vec{x} = A^{-1}\cdot \vec{b}\]

Yönler önemli, işlem sırası değil. \(A^{-1}\cdot A\) işlemini sıralamada öne alıp yaptığımızda, birim elemana dönüşüp eşitliğin sol yanında \(\vec{x}\)’i yalnız bırakıyoruz, sağ taraf da bildiğimiz bir matris çarpımı, gayet kolay.

Örneğimize dönersek, bu örneği iki farklı şekilde çözebiliriz (biri diğerinin kestirmesi aslında). İlk olarak sağ tarafı, yukarı yazdığımız şekilde yazıp, \(A\)’nın tersi ile \(b\)’yi çarparız:

import numpy as np
A = np.array([[3,2],[1,-1]])
b = np.array([[7],[-1]])
A_inv = np.linalg.inv(A)

print(np.dot(A_inv,b))
[[1.]
 [2.]]

(eşitliğin sol tarafında \(\vec{x}\), yani \(\left( \begin{matrix}x\\y\end{matrix} \right)\) olduğundan, birebir eşleşmeyle, \(x\)’in 1, \(y\)’nin 2 olduğunu hemen anlıyoruz.

Diğer yöntem ise olayın arka planını, formülasyonu vs. atlayıp, sonuca odaklanmamızı sağlıyor. Basitçe “çöz” (solve) deyip, keyfimize bakıyoruz:

print(np.linalg.solve(A,b))
[[1.]
 [2.]]

2. dersimizin uygulamaları arasında, bir de dönüş operatörünü gördük, nasıl bir şeydi? Şu şekil bir şeydi (\(\theta\) pozitif yönde, yani saat-yönünün tersine dönüşü işaret ediyor, aman dikkat!):

\[\begin{split}R_{\theta}=\begin{bmatrix}\cos{\theta}&-\sin{\theta}\\\sin{\theta}&\cos{\theta}\end{bmatrix}\end{split}\]

Bu dönüş matrisini kullanarak, iki boyutta istediğimiz herhangi bir \(\left( \begin{matrix}x_0\\y_0\end{matrix} \right)\) noktasını istediğimiz \(\theta\) açısıyla çevirebiliyorduk, örneğin:

theta = np.pi / 6
R = np.array([[np.cos(theta),-np.sin(theta)],[np.sin(theta),np.cos(theta)]])
p = np.array([[3.2],[1.7]])
p_ussu =np.dot(R,p)
print(p_ussu)
[[1.92128129]
 [3.07224319]]

Bakalım gerçekten 30 derece (nam-ı diğer: \(\pi/6\)) döndürmüş mü? Nasıl anlarız?.. önce bir çizdirip bakalım (biraz yeni bir şeyler, çokça da kafamızı kullanıyoruz), sonra daha güzel bir şey yapalım:

import matplotlib.pyplot as plt

noktalar = np.empty((0,2))
noktalar = np.append(noktalar,p.T,axis=0)
noktalar = np.append(noktalar,p_ussu.T,axis=0)

plt.xlim([0,4])
plt.ylim([0,4])
plt.plot(noktalar[:,0],noktalar[:,1],"*")

# noktalarin merkeze uzakligini hesaplayalim
r = np.linalg.norm(p)
print(r)

yay = np.empty((0,2))
theta1 = np.arctan(p[1]/p[0])
theta2 = np.arctan(p_ussu[1]/p_ussu[0])
print (theta1,theta2)
print(np.rad2deg(theta2-theta1))

#for theta_0 in np.linspace(theta1,theta2,100):
for theta_0 in np.linspace(0,np.pi/2,200):
    #print(theta_0,r*np.cos(theta_0),r*np.sin(theta_0))
    plt.plot(r*np.cos(theta_0),r*np.sin(theta_0),".r")
#print(noktalar)

plt.plot(noktalar[:,0],noktalar[:,1],"*b")
plt.plot([0,noktalar[0,0]],[0,noktalar[0,1]],"k-")
plt.plot([0,noktalar[1,0]],[0,noktalar[1,1]],"k-")
plt.show()
3.6235341863986883
[0.48833395] [1.01193273]
[30.]
_images/b234867243e20dc7e326dc2ab7dc8725c671f1b4c6d544581d44a962eec22ab1.png

Gayet 30 derece gibi görünüyor, ama siz bilirsiniz. (İşte tam da aynı nedenden dolayı, bilimde genel olarak çizimleri değil de, sayısal değerleri baz alıyoruz). Sayısal değerlerin uğrak mekanı da lineer cebir. Örneğin \(\vec{a}\) ile \(\vec{b}\) vektörleri arasındaki açıyı hesaplamanızı istesem, aklınıza hemen skaler çarpımın formülü gelir (geliyor, değil mi?), ne de olsa:

\[\vec{a}\cdot\vec{b} = |\vec{a}|\,|\vec{b}|\,\cos(\theta)\]

buradan \(\theta\)’yı çekersek:

\[\theta = \arccos\left(\frac{\vec{a}\cdot\vec{b}}{|\vec{a}|\,|\vec{b}|}\right)\]

hemen örneğimizde uygulayalım bunu:

boy_p = np.linalg.norm(p)
boy_p_ussu = np.linalg.norm(p_ussu)
# (ikisi ayni boydalar tabii ki de! 8)

aci = np.arccos(np.dot(p.T,p_ussu)/(boy_p*boy_p_ussu))
# vektorlerimiz (2x1) boyutlarinda olduklarindan, 
# carpabilmek icin ilkini (1x2) haline getiriyoruz:
# -> (1x2)*(2x1)
print(np.rad2deg(aci))
[[30.]]

Matematik de bir yere kadar#

Peki sizce niye durup dururken bunları (”n bilinmeyenli n denklemin çözümü” ile “bir noktayı döndürmek”) tekrardan hatırladık? İkisi de kendince güzel konular ama sonuçta tekrar ediyorsak bir sebebi olmalı. Soruya soruyla karşılık verirsek:

Denklemleri çözmek için katsayılar matrisinin tersi ile sonuç vektörünü çarpmakla, dönüş matrisini döndürmek istediğimiz noktaya vurdurmak arasında matematiksel olarak bir fark var mı?

(burada “matematiksel olarak” deyimini “bilgisayar açısından” diye okuyun)

05_mindblown.jpg Mindblown!

Bizim matrisleri ne amaçla çarptırdığımızın önemi bizde saklı - bilgisayara göre hepsi aynı - bir matrisle, bir vektörü çarptırmak. Şu halde, en karmaşık denklemi bile bir noktayı döndürmek olarak düşünebilir, yorumlayabiliriz (birazdan bu tanıma bir küçük ekleme daha yapacağım), nasıl yaklaşırsak yaklaşalım, hepsi aynı kapıya çıkıyor zira.

Peki hazır döndürmeyle ilgilenmekteyken, bir de boy değiştirmece özelliğini eklemeye çalışalım. Mesela, (1,1) noktasında bir noktamız olsun: bunun merkeze uzaklığının \(\sqrt{1^2 + 1^2} = \sqrt{2}\) olduğunu, x-ekseni ile yaptığı açının da \(45^o\) olduğunu hemen söyleyebiliriz. Bu noktanın yerini \(\vec{d}\) pozisyon vektörü ile gösterecek olursak kolayca: \(\vec{d} = \hat{\imath} + \hat{\jmath}\) olduğunu da biliriz. Vektörümüzü lineer cebir notasyonunda yazalım:

\[\begin{split}\vec{d} = \left( \begin{matrix}1\\1\end{matrix} \right)\end{split}\]

Bileşenlerin boyunu iki katına çıkartırsak, o zaman da şöyle bir şey olur:

\[\begin{split}\vec{d'} = \left( \begin{matrix}2\\2\end{matrix} \right)\end{split}\]

\((2\times1)\)lik \(\vec{d}\) vektörünü neyle çarpabiliriz ki bize \(\vec{d'}\)nü versin? Sonucun da \((2\times1)\) boyunda bir vektör olduğunu bildiğimize göre, çarpan şeyin boyutunun \((2\times2)\)lik bir matris olması şart. Hazırsanız cevabı yazıyorum:

\[\begin{split}\begin{bmatrix}2&0\\0&2\end{bmatrix}_{(2\times 2)}\cdot\left( \begin{matrix}1\\1\end{matrix} \right)_{(2\times 1)}= \left(\begin{matrix}2\\2\end{matrix}\right)_{(2\times 1)}\end{split}\]

Rica ediyorum, şöyle bir arkanıza yaslanın, kafanızdan yukarıdaki çarpma işlemini yapın, çalıştığından emin olun. (1,1) noktası belki de çok basitti, hem simetrik, tam anlaşılmıyor. O yüzden gelin bir de (7,11) noktasına uygulayalım:

\[\begin{split}\begin{bmatrix}2&0\\0&2\end{bmatrix}_{(2\times 2)}\cdot\left( \begin{matrix}7\\11\end{matrix} \right)_{(2\times 1)}= \left(\begin{matrix}14\\22\end{matrix}\right)_{(2\times 1)}\end{split}\]

siz işlemi yine kafanızdan teyit ededurun, biz de kompütere soralım arada:

spak_zzt.jpg Mr. Spak Kabakulak! / Turist Ömer Uzay Yolunda (1973 – Star Trek’in ilk filminin 1979 yılında çekildiğine dikkatinizi çekerim! 8) [dizi: 1966-1969]

M2 = np.array([[2,0],[0,2]])
d  = np.array([[1],[1]])

print(np.dot(M2,d))
print("-"*45)
p = np.array([[7],[11]])
print(np.dot(M2,p))
[[2]
 [2]]
---------------------------------------------
[[14]
 [22]]

Doğru yani sonuçta, boy uzatma/kısaltma operatörü birim matrisinin istenen oranla çarpılması sonucunda oranın köşegenlere yerleştiği şekil.

Peki o halde şuna da cevap verelim bakalım: önce \(\theta\) kadar döndürüp, sonra boyunu \(k\) katına nasıl çıkarırız?

Cevap zaten soruda saklı: önce \(\theta\) kadar döndürün, sonra boyunu \(k\) katına çıkarın ;)

\[\begin{split}\left( \begin{matrix}x_0'\\y_0'\end{matrix} \right)=\begin{bmatrix}k&0\\0&k\end{bmatrix}\begin{bmatrix}\cos{\theta}&-\sin{\theta}\\\sin{\theta}&\cos{\theta}\end{bmatrix}\left( \begin{matrix}x_0\\y_0\end{matrix} \right)\end{split}\]

Yukarıda da bahsettiğimiz üzere, yönler/yerler önemli, işlem sırası değil, o zaman yerleri değiştirmeden iki matrisi çarpalım:

\[\begin{split}\left( \begin{matrix}x_0'\\y_0'\end{matrix} \right)=\begin{bmatrix}k\cos\theta &-k\sin\theta\\k\sin\theta&k\cos\theta\end{bmatrix}\left( \begin{matrix}x_0\\y_0\end{matrix} \right)\end{split}\]

Bir vektörü döndürdüğünüzde, boyu değişmez, bunu da dönüş operatörünün determinantının 1 olmasından anlıyoruz: \(\cos^2\theta - (-sin^2\theta) = \cos^2\theta+\sin^2\theta = 1\).

O zaman elimizde bir başlangıç vektörü, bir de bitiş vektörü varsa, bu iki vektörü kullanarak, vektörün ne kadar döndürüldüğünü de, boyunun ne kadar değiştiğini de anlayabiliriz. Çünkü, iki boyut özelinde konuşursak, bileşke operatörümüzün \((2\times2)\)’lik bir matris olduğunu biliyoruz, dahası köşegendeki değerleri birbirine, köşegen dışı değerler de birbirinin eksilisine eşit. Örnek üzerinden gidelim:

Ayşe’nin merkezden (2,3) noktasına uzanan bir vektörü var, bir gün ona şaka yapmak isteyen Betül, Ayşe dışarıdayken, Ayşe’nin vektörünü \(\theta\) kadar döndürüp, \(k\) kadar da boyunu değiştiriyor. Ayşe eve geldiğinde vektörünün bu yeni durumda merkezden (-2.69856,0.17404) noktasına uzandığını görüyorsa, Betül vektörü kaç derecelik açıyla döndürüp, boyunu ne kadar değiştirmiştir?

Önce ölçeklendirme katsayısı \(k\)’yı hesaplayalım: Bir vektörü ne kadar döndürürseniz döndürün, boyu değişmez. O halde başlangıçtaki ve sondaki vektörlerin boyunun oranı bize doğrudan \(k\)’yı verecek:

v1 = np.array([[2],[3]])
v2 = np.array([[-2.69856],[0.17404]])

v1_boy = np.linalg.norm(v1)
v2_boy = np.linalg.norm(v2)
print("v1'in boyu :",v1_boy)
print("v2'nin boyu:",v2_boy)
print("boylarin orani: k=|v2|/|v1|:",v2_boy/v1_boy)
v1'in boyu : 3.605551275463989
v2'nin boyu: 2.704166414109901
boylarin orani: k=|v2|/|v1|: 0.7500008202662182

Gördük ki, %75 oranında bir kısalma söz konusu, yani ölçek operatörü:

\[\begin{split}\begin{bmatrix}0.75&0\\0&0.75\end{bmatrix}\end{split}\]

şeklinde, işlem zincirimiz ise an itibarı ile:

\[\begin{split}\left( \begin{matrix}-2.69856\\0.17404\end{matrix} \right)=\begin{bmatrix}0.75&0\\0&0.75\end{bmatrix}\begin{bmatrix}\cos\theta &-\sin\theta\\\sin\theta&\cos\theta\end{bmatrix}\left( \begin{matrix}2\\3\end{matrix} \right)\end{split}\]

durumunda.

Şimdi sıra, kaç derecelik açıyla döndürdüğüne geldi. Bunun için eşitliğin iki yanını soldan, ölçek operatörümüzün tersi ile çarpacağız. Bu durumda sol taraf:

\[\begin{split}\begin{bmatrix}0.75&0\\0&0.75\end{bmatrix}^{-1}\,\left( \begin{matrix}-2.69856\\0.17404\end{matrix} \right)\end{split}\]

sağ taraf ise: $\(\underbrace{\begin{bmatrix}0.75&0\\0&0.75\end{bmatrix}^{-1}\,\begin{bmatrix}0.75&0\\0&0.75\end{bmatrix}}_{\mathbb{1}}\begin{bmatrix}\cos\theta &-\sin\theta\\\sin\theta&\cos\theta\end{bmatrix}\left( \begin{matrix}2\\3\end{matrix} \right)=\begin{bmatrix}\cos\theta &-\sin\theta\\\sin\theta&\cos\theta\end{bmatrix}\left( \begin{matrix}2\\3\end{matrix} \right)\)$

olacak.

Sol tarafı hesaplattıralım bakalım:

K = 0.75*np.eye(2,2)
print(K)
print("-"*45)

K_ters = np.linalg.inv(K)
print(K_ters)
print("-"*45)

K_ters_x_v2 = np.dot(K_ters,v2)
print(K_ters_x_v2)
[[0.75 0.  ]
 [0.   0.75]]
---------------------------------------------
[[1.33333333 0.        ]
 [0.         1.33333333]]
---------------------------------------------
[[-3.59808   ]
 [ 0.23205333]]

Sağ tarafın çarpma işlemini yaparsak:

\[\begin{split}\begin{bmatrix}\cos\theta &-\sin\theta\\\sin\theta&\cos\theta\end{bmatrix}\left( \begin{matrix}2\\3\end{matrix} \right) = \left( \begin{matrix}2\cos\theta-3\sin\theta\\2\sin\theta+3\cos\theta\end{matrix} \right)\end{split}\]

bunu da \(\cos\theta\) ve \(\sin\theta\) terimleri cinsinden yazarsak:

\[\begin{split}\left( \begin{matrix}2\cos\theta-3\sin\theta\\2\sin\theta+3\cos\theta\end{matrix} \right)=\begin{bmatrix}2&-3\\3&2\end{bmatrix}\left( \begin{matrix}\cos\theta\\\sin\theta\end{matrix} \right) \end{split}\]

(herkes görebildi mi?)

İki tarafı birbirine eşitlediğimizde ise:

\[\begin{split}\left( \begin{matrix}-3.59808 \\0.23205333 \end{matrix} \right) =\begin{bmatrix}2&-3\\3&2\end{bmatrix}\left( \begin{matrix}\cos\theta\\\sin\theta\end{matrix} \right)\end{split}\]

e kaldı ki, bu tam da en başta yaptığımız iki bilinmeyenli iki denklemin çözümü. Hemen çözelim o zaman (buradaki bilinmeyenlerimiz \(\cos\theta\) ve \(\sin\theta\)):

A = np.array([[2,-3],[3,2]])
b = np.array([[-3.59808],[0.23205333]])

[[cost],[sint]] = np.linalg.solve(A,b)
print("cos(t):",cost,"\nsin(t):",sint)

theta_c = np.rad2deg(np.arccos(cost))
print(theta_c)

theta_s = np.rad2deg(np.arcsin(sint))
print(theta_s)
cos(t): -0.5000000007692308 
sin(t): 0.8660266661538462
120.0000000508919
60.00014465719476

Kosinüsü \(-1/2\), sinüsü ise \(\frac{\sqrt{3}}{2} = 0.86603\) olan bir açı arıyoruz. İlkini 120 ile 210 dereceler, ikincisini ise 60 ile 120 dereceler karşılıyor. Kosinüsün negatif, sinüsün pozitif olduğu bölge II. bölge olduğundan, cevabımız: 120 derece olarak bulunuyor. Demek ki Betül, Ayşe’nin vektörünü 120 derece çevirip, boyunu da %75 oranında kısaltmış.

Bu işi yaparken kullandığı birleşik, ikisi bir arada, yıkıyorum-çıkıyorum operatörünün matris temsili şu şekilde oluyor haliyle:

K = 0.75*np.eye(2,2)
theta = np.deg2rad(120)
R = np.array([[np.cos(theta),-np.sin(theta)],[np.sin(theta),np.cos(theta)]])
KR = np.dot(K,R)
print(KR)
[[-0.375      -0.64951905]
 [ 0.64951905 -0.375     ]]
\[\begin{split}\begin{bmatrix}0.75&0\\0&0.75\end{bmatrix}\begin{bmatrix}\cos{120^o} &-\sin{120^o}\\\sin{120^o}&\cos{120^o}\end{bmatrix}=\begin{bmatrix}-0.37500&-0.64952\\0.64952&-0.37500\end{bmatrix}\end{split}\]

Sağlamamızı yapalım:

print(np.dot(KR,v1))
print(v2)
[[-2.69855716]
 [ 0.17403811]]
[[-2.69856]
 [ 0.17404]]

Alıştırma: KR operatörünün rastgele ürettiğiniz 10 vektörün hepsini de \(120^o\) döndürüp, boyunu da %75 kısalttığını teyit edin.

Çok zor alıştırma: KR operatörün verilen her vektörü \(120^o\) döndürüp, boyunu da %75 kısalttığını ispatlayın.

Sorunlar, sorunsallar…#

Tabii ki her matris işlemi bu şekilde düzgün davranmaz. Örnek olarak şuna bir bakalım:

\[\begin{split}\begin{bmatrix}2&3\\4&5\end{bmatrix}\end{split}\]

-Hızlıca- yukarıdaki örnekte takip ettiğimiz akıl yolunu izleyelim: \(\vec{p}=\left( \begin{matrix}1\\0\end{matrix} \right)\) vektörüne vurdurduğumuzda:

\[\begin{split}\vec{p}' = \begin{bmatrix}2&3\\4&5\end{bmatrix}\left( \begin{matrix}1\\0\end{matrix} \right) = \left( \begin{matrix}2\\4\end{matrix} \right)\end{split}\]
A = np.array([[2,3],[4,5]])
p = np.array([[1],[0]])
p_ussu = np.dot(A,p)
print(p_ussu)
p_ussu_boy = np.linalg.norm(p_ussu)
print(p_ussu_boy)
[[2]
 [4]]
4.47213595499958

Yeni vektörün uzama oranı: \(\sqrt{2^2+4^2}=2\sqrt5 = 4.47213595499958\)

Dönüş operatörü:

K=np.sqrt(20)*np.eye(2,2)
K_ters = np.linalg.inv(K)
R = np.dot(K_ters,A)
print(R)
[[0.4472136  0.67082039]
 [0.89442719 1.11803399]]

Siz sinüsü -0.671 ve 0.894; kosinüsü de aynı anda hem 0.447, hem de 1.118(!!!) olan bir açı biliyor musunuz? Ben bilemiyorum.

İşin kötüsü, gariplikler burada da bitmiyor. Dönüşüm matrisimizi \(\vec{p}=\left( \begin{matrix}1\\0\end{matrix} \right)\) vektörü yerine, bu sefer \(\vec{q}=\left( \begin{matrix}1\\1\end{matrix} \right)\) vektörüne vurdurup, yeni vektörün boyunun ölçüsünü alalım:

A = np.array([[2,3],[4,5]])
q = np.array([[1],[1]])
q_boy = np.linalg.norm(q)
print(q_boy)
q_ussu = np.dot(A,q)
print(q_ussu)
q_ussu_boy = np.linalg.norm(q_ussu)
print(q_ussu_boy)
print("-"*45)
print(q_ussu_boy/q_boy)
1.4142135623730951
[[5]
 [9]]
10.295630140987
---------------------------------------------
7.280109889280518

Yeni vektörün uzama oranı: 7.28. Yani bir nevi nabza göre şerbet veriyor. Vektörümüz (1,0)sa 4.47 oranında uzatıyor, yok (1,1) ise 7.28.. Bunları sineye çekip, vektör başına ne kadar döndürdüğünü sorsak, o da muamma…

Baştaki örneğe dönelim: (1,0)’ı (2,4)’e taşımıştı, büyütme oranını 4.47 hesaplayıp, açıyı sayısal olarak bulmaya kalktığımızda garip şeylerle karşılaşmıştık. Halbuki kafamızı kullanarak o vektör için uygulanan dönüş açısını bulabiliriz:

plt.arrow(0,0,1,0,color="blue",head_width=0.2,length_includes_head=True)
plt.arrow(0,0,2,4,color="red",head_width=0.2,length_includes_head=True)
plt.xlim(-1,3)
plt.ylim(-1,5)
plt.show()
_images/9e32f43bbf46b7deee300ae253114857acd2b8749b747151d18e4f4a560954ba.png

Vektörler bariz, aradaki açıyı yine eski usül, skaler çarpımdan hesaplayalım:

v1 = np.array([1,0])
#v2 = np.array([2,4])
v2 = np.dot(A,v1)
v1_boy = np.linalg.norm(v1)
v2_boy = np.linalg.norm(v2)
aci = np.rad2deg(np.arccos(np.dot(v1,v2)/(v1_boy*v2_boy)))
print("Açı:",aci,"derece")
Açı: 63.43494882292201 derece

(isteyince oluyormuş demek ki 8).

(1,1)i (5,9)a götürdüğünde ne kadar çeviriyormuş, ona da bakalım:

v1 = np.array([1,1])
#v2 = np.array([5,9])
v2 = np.dot(A,v1)
v1_boy = np.linalg.norm(v1)
v2_boy = np.linalg.norm(v2)
aci = np.rad2deg(np.arccos(np.dot(v1,v2)/(v1_boy*v2_boy)))
print("Açı:",aci,"derece")
Açı: 15.945395900922879 derece

Buradan şunu görüyoruz: (1,1)’i, (1,0)’dan çok daha az çeviriyor.

Şöyle bir oyun oynayalım o halde: (1,0)’dan başlayalım, x-ekseniyle yaptığı açıyı hesaplayalım (\(0^o\)), sonra operatörü vurduralım, türettiğimiz vektörün x-ekseniyle yaptığı açıyı hesaplayalım, sonra bir daha vurduralım, bu şekilde n kere tekrar edelim, bakalım nereye varacağız:

n = 10
v1 = np.array([1,0])
v1_boy = np.linalg.norm(v1)
v1_aci = np.rad2deg(np.arctan2(v1[1],v1[0]))
print("Açı:",v1_aci)
for i in range(n):
    v1 = np.dot(A,v1)
    v1_boy = np.linalg.norm(v2)
    v1_aci = np.rad2deg(np.arctan2(v1[1],v1[0]))
    print("Açı:",v1_aci)
    
Açı: 0.0
Açı: 63.43494882292201
Açı: 60.25511870305778
Açı: 60.376251248826186
Açı: 60.37167490861922
Açı: 60.37184784907869
Açı: 60.371841313706504
Açı: 60.371841560676515
Açı: 60.37184155134358
Açı: 60.371841551696264
Açı: 60.371841551682934

ilginç… türetilen vektörler belli bir açıya (\(60.372^o\)) yakınsıyor. Başka bir başlangıç noktasından (örneğin (1,1)’den) başlayalım:

n = 10
v1 = np.array([1,1])
v1_boy = np.linalg.norm(v1)
v1_aci = np.rad2deg(np.arctan2(v1[1],v1[0]))
print("Açı:",v1_aci)
for i in range(n):
    v1 = np.dot(A,v1)
    v1_boy = np.linalg.norm(v2)
    v1_aci = np.rad2deg(np.arctan2(v1[1],v1[0]))
    print("Açı:",v1_aci)
Açı: 45.0
Açı: 60.94539590092286
Açı: 60.35013649242442
Açı: 60.37266173752195
Açı: 60.371810557014264
Açı: 60.37184272296377
Açı: 60.37184150742105
Açı: 60.371841553356084
Açı: 60.371841551620214
Açı: 60.37184155168581
Açı: 60.37184155168333

!!!

Aynı yere ulaştık! İyice kafadan uydurup, oradan başlayalım:

n = 10
v1 = np.random.randint(low=0,high=100,size=2)
print(v1)
v1_boy = np.linalg.norm(v1)
v1_aci = np.rad2deg(np.arctan2(v1[1],v1[0]))
print("Açı:",v1_aci)
for i in range(n):
    v1 = np.dot(A,v1)
    v1_boy = np.linalg.norm(v1)
    v1_aci = np.rad2deg(np.arctan2(v1[1],v1[0]))
    print("Açı:",v1_aci)
[6 4]
Açı: 33.690067525979785
Açı: 61.38954033403479
Açı: 60.333284793053544
Açı: 60.37329846695326
Açı: 60.37178649504424
Açı: 60.37184363225914
Açı: 60.371841473059014
Açı: 60.371841554654615
Açı: 60.371841551571144
Açı: 60.371841551687666
Açı: 60.37184155168327

Hepsinde de aynı yere varıyoruz!

Akla çok doğal bir soru geliyor: ilk vektörümüzü doğrudan bu açılı çizginin üzerinde bir vektör versem, onu dönüştürmeye kalktığımda ne elde ederim? Hemen bakalım:

theta = 60.371841551683396
v_x = 1
v_y = v_x*np.tan(np.deg2rad(theta))
v = np.array([v_x,v_y])
print(v)
aci = np.rad2deg(np.arctan2(v[1],v[0]))
print("Açı:",aci)
print("-"*45)
v_ussu = np.dot(A,v)
print(v_ussu)
aci = np.rad2deg(np.arctan2(v_ussu[1],v_ussu[0]))
print("Açı:",aci)
[1.         1.75830574]
Açı: 60.371841551683396
---------------------------------------------
[ 7.27491722 12.7915287 ]
Açı: 60.37184155168343

Bu doğrultuda verdiğimizde vektörümüzün yönü değişmedi, sadece boyu değişti, değişim oranını da hesaplayalım:

boy_degisim_orani = v_ussu/v
print(boy_degisim_orani)
[7.27491722 7.27491722]

\(x\) bileşeni de, \(y\) bileşeni de 7.275 katına çıkmış. Bu süreci şu şekilde yazabiliriz demek oluyor bu:

\[\begin{split}\vec{p}' = A\cdot\vec{p}= \begin{bmatrix}2&3\\4&5\end{bmatrix}\left( \begin{matrix}1\\1.7583\end{matrix} \right) = \left( \begin{matrix}7.275\\12.792\end{matrix} \right)=7.275\left( \begin{matrix}1\\1.7583\end{matrix} \right)\end{split}\]

Yani, bu özel yöndeki vektöre, dönüşüm operatörünü vurdurduğumuzda, vektörün yönü değişmeyip, sadece boyu değişiyor. Bir operatör için böyle bir vektör bulursak, o vektöre, o operatörün özvektörü (eigenvector); boydaki değişim oranına da o operatörün özdeğeri (eigenvalue) deriz.

Bariz bilgi: Eğer \(\left( \begin{matrix}x_1\\y_1\end{matrix} \right)\), bir \(A\) operatörünün \(\lambda\) özdeğerli özvektörü ise, \(r\in\mathbb{C}\) olmak üzere, \(\left( \begin{matrix}r.x_1\\r.y_1\end{matrix} \right)\) da aynı operatörün aynı özdeğerli özvektörüdür:

\[\begin{split}A\left( \begin{matrix}x_1\\y_1\end{matrix} \right)=\lambda \left( \begin{matrix}x_1\\y_1\end{matrix} \right)\\ A\left( \begin{matrix}r.x_1\\r.y_1\end{matrix} \right)=\lambda \left( \begin{matrix}r.x_1\\r.y_1\end{matrix} \right)\end{split}\]

Ödev: \(A=\begin{bmatrix}2&3\\4&5\end{bmatrix}\) operatörü için:

  • \(\left( \begin{matrix}-0.49437\\-0.86925\end{matrix} \right)\),

  • \(\left( \begin{matrix}-0.79681\\0.60423\end{matrix} \right)\)

vektörlerini inceleyin. Bunlar özvektör ise, özdeğerlerini hesaplayıp, yukarıda bulduğumuz \(\left( \begin{matrix}1\\1.7583\end{matrix} \right)\) özvektörü ile karşılaştırın.

Alıştırma: \(90^0\) dönüş operatörünün özvektörünü ve özdeğerini bulun (bulamazsanız da yorumlayın (süper!); bulursanız da (muhteşem ötesi!!!))

Özdeğer ve özvektörlerin kısa yoldan bulunması#

Özdeğer ve özvektörler başta klasik mekanik ve kuantum mekaniği olmak üzere fizikte çok önemlidirler çünkü her şeyi dönüştüren bir işlemi “ehlileştiren” bir özel durumu işaret ederler. Bu özel durum, karmaşık (dolaşık, iç içe geçmiş) bir denklem sistemini, birbirinden bağımsız denklemler cinsinden ayırıp, ifade etmemizi, tek tek basitçe çözmemizi sağlarlar (ek olarak uygulamaların olduğu bir notu ekleyeceğim). Matris işlemlerini verilen girdiye bağlı parametreleri olan bir dönüş ve boyut değiştiriş olarak düşünürsek, aslında yaptığımız iş yukarıda da anlatmaya çalıştığımız üzere, bu işlemden yönel olarak etkilenmeyen özel vektörler (yönler) bulmaktan ibaret.

Gerek fizikte, gerekse matematikte özdeğer ve özvektörlerin bulunması çoğu zaman epey kritik olduğundan, bu işi bizler için yapan fonksiyonların olması da kaçınılmazdır:

A = np.array([[2,3],[4,5]])
print(A)
print()
[ozdegerler,ozvektorler] = np.linalg.eig(A)
print("Özdeğerler: ",ozdegerler,"\n-----\nÖzvektörler:\n",ozvektorler)
[[2 3]
 [4 5]]

Özdeğerler:  [-0.27491722  7.27491722] 
-----
Özvektörler:
 [[-0.79681209 -0.49436913]
 [ 0.60422718 -0.86925207]]
# Sağlamasını yapalim: 

ozv_1 = ozvektorler[:,0]
print("1. Özvektör: ozv_1 = ",ozv_1)
s_1 = np.dot(A,ozv_1)
print("A.ozv_1 : s_1 = ",s_1)
print("s_1/ozv_1 = ",s_1/ozv_1)

print("-"*45)

ozv_2 = ozvektorler[:,1]
print("2. Özvektör: ozv_2 = ",ozv_2)
s_2 = np.dot(A,ozv_2)
print("A.ozv_2 : s_2 = ",s_2)
print("s_2/ozv_2 = ",s_2/ozv_2)
1. Özvektör: ozv_1 =  [-0.79681209  0.60422718]
A.ozv_1 : s_1 =  [ 0.21905736 -0.16611246]
s_1/ozv_1 =  [-0.27491722 -0.27491722]
---------------------------------------------
2. Özvektör: ozv_2 =  [-0.49436913 -0.86925207]
A.ozv_2 : s_2 =  [-3.59649447 -6.32373687]
s_2/ozv_2 =  [7.27491722 7.27491722]

Görüleceği üzere, matrisin özvektörle çarpılmasının sonucu tam da beklediğimiz üzere, özvektörün ilgili özdeğer katına eşit!

Tavsiyeler:#