编程实现矩阵运算

矩阵运算是很多算法都需要用到的基础运算。为了方便实现各种各样的算法,这里使用python语言,编写了矩阵类,用来实现矩阵各种常用的运算操作。具体的设计方案以及代码实现如下文所示。

1、矩阵类需要实现的方法(函数)

        矩阵类基于numpy库来实现,这样会让代码的数量大大减少,看起来更简洁。定义矩阵类的名称为Mat,矩阵一共实现了37个方法(函数),各个方法实现的功能如下。

(1)矩阵实例化函数__init__

        该函数用来创建一个矩阵实例,并对矩阵元素进行初始化。

(2)设置矩阵元素值的函数set_elements

        该函数用来设置矩阵各元素的值。

(3)矩阵元素重置为1的函数set_ones

        该函数用来将矩阵的元素值全部重置为1。

(4)矩阵元素重置为0的函数set_zeros

        该函数用来将矩阵的元素全部重置为0。

(5)矩阵重置为单位矩阵的函数set_identify

        该函数用来将矩阵重置为单位矩阵,即把矩阵的对角线元素设为1,其他元素设为0。

(6)矩阵索引取值函数__getitem__

        该函数可以实现按照索引值来获取矩阵元素值的功能,如m[i,j]表示获取第i行第j列的元素。

(7)矩阵索引设置元素值函数__setitem__

        该函数可实现按索引值来设置矩阵元素值的功能,如m[i,j]=1表示将第i行第j列的元素设为1。

(8)矩阵转置函数transpose

        该函数用来实现矩阵元素的转置。

(9)矩阵余子式函数cofactor

        该函数用来获取矩阵的余子式矩阵。

(10)矩阵行列式计算函数det

        该函数用来计算矩阵行列式的数值。

(11)矩阵的伴随矩阵计算函数adjoint

        该函数用来计算矩阵的伴随矩阵。

(12)求逆矩阵函数inverse

        该函数用来计算矩阵的逆矩阵。

(13)取负运算符重载函数__neg__

        该函数用来实现矩阵的取负运算符功能,如-m表示对矩阵m取负操作,功能是实现矩阵全部元素的取负操作。

(14)减号运算符重载函数__sub__、__isub__、__rsub__

        此三个函数实现了减(-)运算符的重载,实现了矩阵与矩阵、矩阵与数值、数值与矩阵的逐元素相减操作,如m3=m1-m2、m3=m1-1、m3=1-m1、m2-=m1等矩阵操作。

(15)加号运算符重载函数__add__、__iadd__、__radd__

        此三个函数实现了加(+)运算符的重载,实现了矩阵与矩阵、矩阵与数值、数值与矩阵的逐元素相加操作,如m3=m1+m2、m3=m1+1、m3=1+m1,m2+=m1等矩阵操作。

(16)乘号运算符重载函数__mul__、__imul__、__rmul__

        此三个函数实现了乘(*)运算符的重载,实现了矩阵与矩阵、矩阵与数值、数值与矩阵的逐元素相乘操作,如m3=m1*m2、m3=m1*2、m3=2*m1,m2*=m1等矩阵操作。

(17)除号运算符重载函数__truediv__、__itruediv__、__rtruediv__

        此三个函数实现了除(/)运算符的重载,实现了矩阵与矩阵、矩阵与数值、数值与矩阵的逐元素相除操作,如m3=m1/m2、m3=m1/2、m3=2*m1、m2/=m1等矩阵操作。

(18)整除运算符重载函数__floordiv__、__ifloordiv__、__rfloordiv__

        此三个函数实现了整(//)运算符的重载,实现了矩阵与矩阵、矩阵与数值、数值与矩阵的逐元素整除操作,如m3=m1//m2、m3=m1//2、m3=2//m1、m2//=m1等矩阵操作。

(19)求模运算符重载函数__mod__、__imod__、__rmod__

        此三个函数实现了求模(%)运算符的重载,实现了矩阵与矩阵、矩阵与数值、数值与矩阵的逐元素求模操作,如m3=m1%m2、m3=m1%2、m3=2%m1、m2%=m1等矩阵操作。

(20)求幂运算符重载函数__pow__、__ipow__、__rpow__

        此三个函数实现了求幂(**)运算符的重载,实现了矩阵与矩阵、矩阵与数值、数值与矩阵的逐元素求幂操作,如m3=m1**m2、m3=m1**2、m3=2**m1、m2**=m1等矩阵操作。

(21)矩阵乘运算符重载函数__matmul__

        此函数实现了矩阵乘(@)运算符的重载,实现了两个矩阵相乘的操作,如m3=m1@m2。

(22)矩阵比较运算符重载函数__eq__、__ne__

        此两个函数实现了比较运算符(==,!=)的重载,实现了比较两个矩阵是否相等的操作,如m1==m2、m1!=m2。

2、代码实现矩阵运算

        以下是使用python代码实现矩阵的运算,以及代码的一些简要的注释:

import numpy as np

class Mat(object):
    def __init__(self,rows,cols,init_data=None):
        '''
        初始化实例\r
        rows:矩阵的行数\r
        cols:矩阵的列数\r
        init_data:用于初始化矩阵的数据,可以是二维的列表、numpy、矩阵
        '''
        self.rows=rows
        self.cols=cols
        self.elements=np.zeros((self.rows,self.cols),np.float32)
        self.set_elements(init_data)

    def set_elements(self,data):
        '''
        设置矩阵各元素的值\r
        data:用于设置矩阵元素的数据,可以是二维的列表、numpy、矩阵
        '''
        if type(data)==type(None):
            return
        elif type(data)==list:
            data=np.array(data)
        elif type(data)==Mat:
            data=data.elements
        else :
            pass
        for i in range(self.rows):
            for j in range(self.cols):
                self.elements[i,j]=data[i,j]
    
    def set_ones(self,):
        '''
        将矩阵元素设置为1
        '''
        self.elements=np.ones((self.rows,self.cols))
        return self
    def set_zeros(self,):
        '''
        设置矩阵元素为0
        '''
        self.elements=np.zeros((self.rows,self.cols))
        return self
    
    def set_identity(self,):
        '''
        设置矩阵为单位矩阵
        '''
        self.set_zeros()
        for i in range(self.rows):
            self.elements[i,i]=1
        return self

    def __getitem__(self,index):
        '''
        根据索引获取矩阵的元素值\r
        index:包括了行索值和列索引值的元组
        '''
        i,j=index
        return self.elements[i,j]
    
    def __setitem__(self,index,val):
        '''
        通过索引设置指定的元素值\r
        index:包括了行索引值和列索引值\r
        val:设置的值
        '''
        i,j=index
        self.elements[i,j]=val
    
    def transpose(self,):
        '''
        矩阵转置
        '''
        rst=Mat(self.cols,self.rows,np.transpose(self.elements,(1,0)))
        return rst
    
    def cofactor(self,i,j):
        '''
        矩阵的余子式矩阵\r
        i:行索引值\r
        j:列索引值
        '''
        if self.rows<1 or self.cols<1:
            return None
        else:
            rst=Mat(self.rows-1,self.cols-1)
            k=0
            for ii in range(self.rows):
                if ii==i:
                    continue
                t=0
                for jj in range(self.cols):
                    if jj==j:
                        continue
                    rst[k,t]=self[ii,jj]
                    t+=1
                k+=1
        return rst
    
    def det(self,):
        '''
        矩阵行列式的值
        '''
        if self.rows!=self.cols:
            return None
        elif self.rows==1:
            return self[0,0]
        else:
            d=0
            for i in range(self.rows):
                d+=(-1)**i*self[i,0]*self.cofactor(i,0).det()
            return d
    
    def adjoint(self,):
        '''
        矩阵的伴随矩阵
        '''
        if self.rows!=self.cols:
           return None
        rst=Mat(self.rows,self.cols)
        for i in range(self.rows):
           for j in range(self.cols):
               Aij=(-1)**(i+j)*self.cofactor(i,j).det()
               rst.elements[j,i]=Aij
        return rst

    def inverse(self,):
        '''
        矩阵的逆矩阵
        '''
        A=self.det()
        if A==None or A==0:
            return None
        else:
            return self.adjoint()/A

    def __neg__(self,):
        '''
        矩阵逐元素取负
        '''
        rst=Mat(self.cols,self.rows,-self.elements)
        return rst

    def __sub__(self,m):
        '''
        矩阵与矩阵逐元素相减,或者矩阵与值逐元素相减\r
        m:矩阵或者数值
        '''
        if type(m)==Mat:
            rst=Mat(self.cols,self.rows,self.elements-m.elements)
        else:
            rst=Mat(self.cols,self.rows,self.elements-m)
        return rst

    def __isub__(self,m):
        '''
        矩阵与矩阵逐元素原位相减,或者数值与矩阵逐元素原位相减\r
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            self.elements-=m.elements
        else:
            self.elements-=m
        return self

    def __rsub__(self,m):
        '''
        矩阵与矩阵逐元素相减,或者数值与矩阵逐元素相减\n
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            rst=Mat(self.cols,self.rows,m.elements-self.elements)
        else:
            rst=Mat(self.cols,self.rows,m-self.elements)
        return rst

    def __add__(self,m):
        '''
        矩阵与矩阵逐元素相加,或者矩阵与值逐元素相加\r
        m:矩阵或者数值
        '''
        if type(m)==Mat:
            rst=Mat(self.cols,self.rows,self.elements+m.elements)
        else:
            rst=Mat(self.cols,self.rows,self.elements+m)
        return rst

    def __iadd__(self,m):
        '''
        矩阵与矩阵逐元素原位相加,或者数值与矩阵逐元素原位相加\r
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            self.elements+=m.elements
        else:
            self.elements+=m
        return self

    def __radd__(self,m):
        '''
        矩阵与矩阵逐元素相加,或者数值与矩阵逐元素相加\n
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            rst=Mat(self.cols,self.rows,m.elements+self.elements)
        else:
            rst=Mat(self.cols,self.rows,m+self.elements)
        return rst

    def __mul__(self,m):
        '''
        矩阵与矩阵逐元素相乘,或者矩阵与值逐元素相乘\r
        m:矩阵或者数值
        '''
        if type(m)==Mat:
            rst=Mat(self.cols,self.rows,self.elements*m.elements)
        else:
            rst=Mat(self.cols,self.rows,self.elements*m)
        return rst

    def __imul__(self,m):
        '''
        矩阵与矩阵逐元素原位相乘,或者数值与矩阵逐元素原位相乘\r
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            self.elements*=m.elements
        else:
            self.elements*=m
        return self

    def __rmul__(self,m):
        '''
        矩阵与矩阵逐元素相乘,或者数值与矩阵逐元素相乘\n
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            rst=Mat(self.cols,self.rows,m.elements*self.elements)
        else:
            rst=Mat(self.cols,self.rows,m*self.elements)
        return rst

    def __truediv__(self,m):
        '''
        矩阵与矩阵逐元素相除,或者矩阵与值逐元素相除\r
        m:矩阵或者数值
        '''
        if type(m)==Mat:
            rst=Mat(self.cols,self.rows,self.elements/m.elements)
        else:
            rst=Mat(self.cols,self.rows,self.elements/m)
        return rst

    def __itruediv__(self,m):
        '''
        矩阵与矩阵逐元素原位相除,或者数值与矩阵逐元素原位相除\r
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            self.elements/=m.elements
        else:
            self.elements/=m
        return self

    def __rtruediv__(self,m):
        '''
        矩阵与矩阵逐元素相除,或者数值与矩阵逐元素相除\n
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            rst=Mat(self.cols,self.rows,m.elements/self.elements)
        else:
            rst=Mat(self.cols,self.rows,m/self.elements)
        return rst

    def __floordiv__(self,m):
        '''
        矩阵与矩阵逐元素整除,或者矩阵与值逐元素整除\r
        m:矩阵或者数值
        '''
        if type(m)==Mat:
            rst=Mat(self.cols,self.rows,self.elements//m.elements)
        else:
            rst=Mat(self.cols,self.rows,self.elements//m)
        return rst

    def __ifloordiv__(self,m):
        '''
        矩阵与矩阵逐元素原位整除,或者数值与矩阵逐元素原位整除\r
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            self.elements//=m.elements
        else:
            self.elements//=m
        return self

    def __rfloordiv__(self,m):
        '''
        矩阵与矩阵逐元素整除,或者数值与矩阵逐元素整除\n
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            rst=Mat(self.cols,self.rows,m.elements//self.elements)
        else:
            rst=Mat(self.cols,self.rows,m//self.elements)
        return rst

    def __mod__(self,m):
        '''
        矩阵与矩阵逐元素求模,或者矩阵与值逐元素求模\r
        m:矩阵或者数值
        '''
        if type(m)==Mat:
            rst=Mat(self.cols,self.rows,self.elements%m.elements)
        else:
            rst=Mat(self.cols,self.rows,self.elements%m)
        return rst

    def __imod__(self,m):
        '''
        矩阵与矩阵逐元素原位求模,或者数值与矩阵逐元素原位求模\r
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            self.elements%=m.elements
        else:
            self.elements%=m
        return self

    def __rmod__(self,m):
        '''
        矩阵与矩阵逐元素求模,或者数值与矩阵逐元素求模\n
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            rst=Mat(self.cols,self.rows,m.elements%self.elements)
        else:
            rst=Mat(self.cols,self.rows,m%self.elements)
        return rst

    def __pow__(self,m):
        '''
        矩阵与矩阵逐元素求幂,或者矩阵与值逐元素求幂\r
        m:矩阵或者数值
        '''
        if type(m)==Mat:
            rst=Mat(self.cols,self.rows,self.elements**m.elements)
        else:
            rst=Mat(self.cols,self.rows,self.elements**m)
        return rst

    def __ipow__(self,m):
        '''
        矩阵与矩阵逐元素原位求幂,或者数值与矩阵逐元素原位求幂\r
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            self.elements**=m.elements
        else:
            self.elements**=m
        return self

    def __rpow__(self,m):
        '''
        矩阵与矩阵逐元素求幂,或者数值与矩阵逐元素求幂\n
        m:矩阵或者数值
        '''
        if type(m) ==Mat:
            rst=Mat(self.cols,self.rows,m.elements**self.elements)
        else:
            rst=Mat(self.cols,self.rows,m**self.elements)
        return rst

    def __matmul__(self,m):
        '''
        矩阵乘\r
        m:矩阵
        '''
        rst=Mat(self.rows,m.cols)
        for i in range(self.rows):
            for j in range(m.cols):
                rst.elements[i,j]=np.sum(self.elements[i,:]*m.elements[:,j])
        return rst
    
    def __eq__(self,m):
        '''
        判断矩阵是否相等\r
        m:矩阵
        '''
        if type(m)!=Mat:
            return False
        elif self.rows !=m.rows or self.cols !=m.cols:
            return False
        else:
            for i in range(self.rows):
                for j in range(self.cols):
                    if self.elements[i,j]!=m.elements[i,j]:
                        return False
        return True
    
    def __ne__(self,m):
        '''
        判断矩阵是否不等\r
        m:矩阵
        '''
        if type(m)!=Mat:
            return True
        elif self.rows !=m.rows or self.cols !=m.cols:
            return True
        else:
            for i in range(self.rows):
                for j in range(self.cols):
                    if self.elements[i,j]!=m.elements[i,j]:
                        return True
        return False

猜你喜欢

转载自blog.csdn.net/qq_28249373/article/details/129282753