☠ 10. Feladat

öröklés

Készítsük el a saját mátrix osztályunkat, aminek az exp() taggfüggvénye a mátrix exponciálisát adja vissza (tehát nem egyszerűen a mátrix elemeinek exponencializáltját). Az osztályunk minden más tekinetben ugyanúgy viselkedjen, mint a numpy mátrixosztálya. Kis segitség: https://docs.scipy.org/doc/numpy/user/basics.subclassing.html

Megoldás

Mivel a mátrix osztály a numpy modulban található, először ezt hívjuk meg, továbbá a math modul factorial() függvényére is szükségünk lehet

In [1]:
import numpy as np
from math import factorial as fact

A feladatot megvalósító sajatmatrix osztály az np.matrix osztály leszármazottja kell legyen, hogy annak összes funkcióját tudja. Mivel ez az osztály tudja a mátrixok helyes módon való összeadását, számmal szorzását, egymással való szorzását és hatványozását, csak az exp() függvény elkészítésére kell koncentrálni.

Az exponenciálist hatványsor segítségével értelmezzük, így az összegzés egy for-ciklus segítségével oldható meg legegyszerűbben. Mivel az exponenciális végtelen tag összege, ezért pontosan nem lehet ezzel a módszerrel kiszámolni, de mivel a számítógép úgyis csak véges tizedes jegyet tárol, nem kell végtelen mátrixot összeadni, csak annyit, hogy a további tagok, kerekítve 0-t adjanak.

Ismert, hogy az exponenciális függvény hatványsora mindig konvergens, úgyhogy előbb utóbb biztos eljutunk egy pontig, amikor már a soron következő tag elég kicsi ahhoz, hogy kezelje a gép. Ez azért jelenik meg, mert a faktoriális sorozat gyorsabban tart a végtelenhez, mint a polinom, és ezzel osztva az eredmény kicsi lesz. Mivel azonban a faktoriális függvény eredménye egész, ezért ha elég nagy számmal akarunk osztani ahhoz, hogy a gép kezelni tudja, OverflowError-t fog dobni. Ennek a kiszűrésével, megtalálható, hogy hol kell leállni.

In [2]:
class sajatmatrix(np.matrix):
    '''Mátrix-osztály, ami tudja kezelni a mátrix exponenciálisát is.'''
    def exp(self):
        '''Függvény, mely a mátrix exponenciálisát adja vissza'''
        eredmeny = self**0                              # Az eredményt a sor 0. tagjával indítjuk, ehhez adjuk hozzá a többit
        k = 1                                           # Futóváltozó, a hatványsor tagjának sorszámáról
        try:                                            # Kivételkezelés a hiba kiszűrésére
            while ((self**k)/fact(k) > self*0).any():   # Addig menjen a ciklus amíg következő tag nem a nullmátrix
                eredmeny = eredmeny + (self**k)/fact(k) # A hatványsor k. tagját hozzáadjuk az eredményhez
                k += 1 
        except OverflowError:                           # Elkapjuk a hibát, amikor túl kicsi lesz a hatványsor tagja
            pass
        return eredmeny

És most nézzünk néhány példát, amivel ellenőrizhetjük az osztály működését:

In [3]:
a = sajatmatrix('1., 0; 0, 1')
b = sajatmatrix('1, 2; 3, 4')
c = sajatmatrix('0.5, 1.23, 2.56; 3.14, 2.7, 0; 4, 13, 11')
In [4]:
a.exp()
Out[4]:
matrix([[2.7182818284590455, 0.0],
        [0.0, 2.7182818284590455]], dtype=object)
In [5]:
b.exp()
Out[5]:
matrix([[51.96895619672053, 74.73656456493545],
        [112.10484684822, 164.07380304499895]], dtype=object)
In [6]:
c.exp()
Out[6]:
matrix([[40459.041312968315, 81963.54164399992, 59483.31510574322],
        [12655.502591587363, 25631.759681938693, 18599.94250573133],
        [187395.51288964073, 379625.1735928235, 275496.8848005675]], dtype=object)