# A szokásos import
%pylab inline

"""
Explanation: Lineáris algebra
A lineáris algebra a sokváltozós lineáris egyenletrendszerek megoldásával, illetve megoldhatóságának vizsgálatával foglalkozik. 
A lineáris algebra gyakorlati jelentősége abban mutatkozik meg, hogy számos bonyolult matematikai probléma numerikus megoldása sok esetben egy sok (esetenként igen sok, akár több millió) ismeretlenes lineáris egyenletrendszerre vezet. Az alábbiakban a numpy csomag lineáris algebrai rutinjaival fogunk megismerkedni. Először a matrix típust vizsgáljuk meg, mely segítségével egszerű vektor-mátrix műveletek tömören fogalmazhatóak meg. Ezután a solve lineáris egyenletrendszereket megoldó függvény használatát sajátítjuk el, végül az eig sajátérték-, illetve sajátvektor-kereső rutinnal ismerkedünk meg.
End of explanation
"""


# két minta array
A=array([[1,2],
         [3,4]])

B=array([[2,2],
         [2,2]])


"""
Explanation: Mátrixok és mátrix vektor műveletek
A korábbiakban rendszeresen használtuk a numpy csomag array válltozóit. Ezek sok szempontból hasznosnak bizonyultak, de alapvetően táblázatként működtek, és nem a lineáris algebrában megszokott mátrixként. Ennek a legszembetűnőbb megnyilvánulása az, hogy a rájuk értelmezett műveletek szigorúan elemenként értendőek voltak. Azaz a * elemenkénti szorzást és nem mátrixszorzást jelent. Például az alább definiált A és B tömbök
End of explanation
"""


A*B

"""
Explanation: egymással összeszorozva egy olyan array -t adnak végeredményül, amelynek elemei az A és a B elemeinek szorzata: 
$$ (AB){ij}=A{ij}B_{ij} $$
End of explanation
"""


B*A

"""
Explanation: Ez a művelet természetesen nem érzékeny a műveleti sorrendre, azaz A*B=B*A:
End of explanation
"""


# Így definiálunk mátrixokat
Am=matrix(A)
Bm=matrix(B)

"""
Explanation: A numpy rendelkezik egy matrix típussal is, ami sok szempontból hasonlóan viselkedik, mint az array, de bizonyos műveletek, például a * is a lineáris algebrában megszokott módon van definiálva. Azaz itt a *-jel az alábbiakat jelenti:
$$ (A*B){ij}=\sum_l A{il}B_{lj} $$
A matrix()-függvény  array vagy list típusú változókból matrix típusú változókat csinál:
End of explanation
"""


Am*Bm

Bm*Am

"""
Explanation: Figyeljük meg, hogy az Am és Bm változókra miként hat a * művelet:
End of explanation
"""


Am.T  # Ez az Am mátrix transzponáltja

Am+1.0j*Bm #Ez egy komplex mátrix

(Am+1.0j*Bm).H  # Ez a komplex  mátrix adjungáltja, azaz a transzponált konjugáltja

trace(Am) # A mátrix nyoma, (vagy spur-ja) azaz a diagonális elemek összege

trace(A) # A trace ugyan úgy működik array-ekre

det(Am) # A mátrix determinánsa

det(A) # A determináns is alkalmazható array-ekre

inv(Am) # A mátrix inverze.. ugyebár ez nem feltétlenül létezik

inv(A) # Ez is megy array -ekre

inv(Am)*Am # Ennek egységnek kell lennie

"""
Explanation: A szorzás eredménye tehát ahogy vártuk, függ a műveleti sorrendtől!
Nézzünk meg egypár hasznos lineáris algebrai mátrixműveletet:
End of explanation
"""


# az ismert mennyiségek definiálása:
phi=pi/6;
#Ez az A mátrix
A=matrix([[cos(phi), -sin(phi)],
         [sin(phi),  cos(phi)]])
#Ez pedig a b oszlopvektor, figyeljünk a zárójelezésre!!!
b=matrix([[0],
          [1]])

x=solve(A,b)

x

"""
Explanation: Lineáris egyenletrendszerek
Az egyik gyakran előforduló lineáris algebrai feladat az egyenletrendszerek megoldása. Például keressük azt az $x$ vektort amely teljesíti a
$$ \mathbf{A}x=b$$
egyenletet, ahol $\mathbf{A}$ egy ismert mátrix és $b$ egy ismert vektor. A numpy csomag az ilyen formában megadott egyenletrendszer megoldására a solve függvényt kínálja. 
Fgyelem: ez a függvény nem keverendő össze a sympy csomag azonos nevű függvényével, amely tetszőleges algebrai egyenletrendszerre kínál analitikus megoldást. A numpy modul solve függvénye szigorúan csak numerikus lineáris algebrai feladatok megoldására alkalmas!
Vizsgáljuk meg egy példát ! Keressük meg azt a síkbeli vektort, amit ha $\varphi=30^\circ$-al az óra járásával megegyező irányban elforgatunk, akkor az $y$ irányú egységvektort kapjuk! 
Azaz 
$$A=\begin{pmatrix}
\cos(\varphi) & -\sin(\varphi)\ 
\sin(\varphi) & \cos(\varphi)
\end{pmatrix}$$ valamint
$$b=\begin{pmatrix}
0 \ 
1  
\end{pmatrix}$$
End of explanation
"""


M=matrix(zeros((10,10))) # Így gyártunk egy 10x10-es üres mátrixot.
for i in range(9):#A mellékátlók 1-el rövidebbek mint a mátrix mérete!
    M[i,i+1]=-1.0 #A mellékátlók feltöltése -1 -el
    M[i+1,i]=-1.0 


M # nézzük meg a mátrixot

"""
Explanation: Sajátérték-probléma
A másik sokszor felmerülő lineáris algebrai problémakör egy mátrix sajátértékeinek és sajátvektorainak meghatározása. Legyen $A$ egy ismert mátrix, és keressük tehát azon $x$ vektorokat, illetve azon $\lambda$ számokat, melyek teljesítik az alábbi feltételt.
$$ \mathbf{M}x=\lambda x.$$
Ilyen jellegű problémákat az eig rutin segítségével tudunk megoldani. Lássunk erre is egy példát!
Legyen $M$ egy 10x10-es mátrix, melynek mindkét első mellékátlója -1, a többi elem pedig nulla!
End of explanation
"""


ertek,vektor=eig(M)

"""
Explanation: A sajátérték-probléma megoldása:
End of explanation
"""


ertek

vektor

"""
Explanation: Most az ertek valtozó tartalmazza a saját értékeket illetve a vektor a sajátvektorokat.
End of explanation
"""


#ez tehát a nullvektor kell hogy legyen:
M*vektor[:,3]-vektor[:,3]*ertek[3]

"""
Explanation: Az $i$-edik sajátvektort a vektor változó i-edik oszlopa, vektor[:,i] tartalmazza.
Ez a sajátvektor az $i$-edik, ertek[i] sajátértékhez tartozó megoldása az $Mx=\lambda x$ sajátérték-problémának.
Ellenőrizzük ezt le:
End of explanation
"""


plot(vektor[:,0],'o-',label='elso sajatvektor')
plot(vektor[:,1],'+--',label='masodik sajatvektor')
legend()

"""
Explanation: Jelenítsük meg a két legkisebb sajátértékhez tartozó sajátfüggvényt!
End of explanation
"""


