1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Python矩阵计算类:计算矩阵加和 矩阵乘积 矩阵转置 矩阵行列式值 伴随矩阵和逆矩阵

Python矩阵计算类:计算矩阵加和 矩阵乘积 矩阵转置 矩阵行列式值 伴随矩阵和逆矩阵

时间:2024-07-18 20:21:36

相关推荐

Python矩阵计算类:计算矩阵加和 矩阵乘积 矩阵转置 矩阵行列式值 伴随矩阵和逆矩阵

最近在Python程序设计中遇到一道设计矩阵计算类的题目,原题目要求计算矩阵加和和矩阵乘积,而我出于设计和挑战自己的目的,为自己增加难度,因此设计出矩阵计算类,不仅可以求出矩阵加和和矩阵乘积,还能计算出矩阵转置、矩阵行列式值、伴随矩阵和逆矩阵。在此和大家分享一下,如有不足之处请多多指教。

矩阵计算类中最普遍使用的是列表的方法,由于数据结构还在学习,所以我只使用简单的列表方法来实现。其中我设计了两个类,一个是父类matrix,一个是子类matrixcalcu,采用单继承。父类包括了构造函数以及矩阵输入打印函数,在子类中,构造函数没有重写,而是包括矩阵的各类计算函数以及析构函数。

父类matrix的定义如下:

class matrix:def __init__(self,i,j,d,r,matrix,matrixo): #构造函数,说明属性self.i = i#matrix列self.j = j#matrix行self.d = d #matrixo列self.r = r #matrixo行self.matrix = matrixself.matrixo = matrixodef scanf(self,matrixes,m,n):#定义矩阵打印函数self.matrixes = matrixesself.m = mself.n = nmatrain = []if self.n>len(self.matrixes): print('Error.')else:for s in range(self.m):#对每一行d=self.matrixes[self.n*s:self.n*(s+1)] #用切片提取出每一行的行向量matrain.append(d)matrains = np.array(matrain) #采用数组形式表示return matrains

父类构造函数里面定义了两个计算对象,以及他们的行列值。而输入打印函数scanf是将输入列表转化为矩阵的形式,通过切片方法提取出行向量,再附加到空列表中,为了方便接下来调用矩阵元素,我是用numpy中的array方法,将其以数组的形式打印出来。

接下来是子类matrixcalcu里面的矩阵计算函数,在矩阵乘积中需要判断左右矩阵的列、行是否相等,因此设计行列属性判断函数Victium:

class matrixcalcu(matrix): #继承def Victium(self): #行列属性判断函数,用于矩阵乘积if self.i == self.r:return 0else:return 1

矩阵加和函数就比较简单了,只需要将矩阵之间对应元素相加即可:

def Add(self): #矩阵加和函数if len(self.matrix)!=len(self.matrixo):#维度判断print('Error.')else:res =[] for n in range(len(self.matrix)):resma= self.matrix[n]+self.matrixo[n] #对应元素相加res.append(resma) #计算结果作为元素载入列表self.matrixes = resresend = self.scanf(self.matrixes,self.j,self.i) #打印结果return resend

矩阵转置函数需要根据转置时索引的变化规律来设计for循环,同时注意到,非方阵在转置后行列属性颠倒,因此不可调用scanf函数进行打印,需要重写打印函数:

def Transpose(self,matrixess,vitr,vith): #转置函数self.matrixess = matrixessself.vitr = vitr #行self.vith = vith #列mid=[]Tran = []if self.i>len(self.matrix): #转置条件判断print('Error.')else:for s1 in range(self.vith):for s2 in range(self.vitr): midd = self.matrixess[s1+self.vith*s2] #在两层for循环中,依次提取每列行 #索引一样的元素,作为新的列向量的元素mid.append(midd)self.matrixes = midfor s in range(self.vith): #由于转置后行列数颠倒,因此打印时for #循环的条件也要变化,即行变为列midout=self.matrixes[self.vitr*s:self.vitr*(s+1)]#输出的列用切片提取Tran.append(midout)Trans = np.array(Tran)return (Trans)

而对于矩阵乘积函数即点乘函数,需要考虑到左乘和右乘的问题,利用if条件语句即可分开,然后把左乘或者右乘的选择作为函数参数,当然,不同维度的矩阵相乘也放在左乘的计算程序里面。开始时需要调用Victium函数进行矩阵乘积条件判断:

#点乘函数分左乘和右乘,普通乘包括在左乘中,点乘函数设计思路是调用转置函数#Transpose将右矩阵转置,然后左矩阵和右矩阵的转置中各行向量之间进行对应元#素相乘后求和,作为结果矩阵的元素。def Pointmul(self,LR): #点乘函数,参数LR即选择左乘(包括普通乘)或右乘self.LR = LRjudge = self.Victium()pointmul = []pandas = []if judge == 1: #点乘条件判断print("Error.")else:matranspose = self.Transpose(self.matrix,self.j,self.i)matransposeo = self.Transpose(self.matrixo,self.r,self.d)matrain = self.scanf(self.matrix,self.j,self.i)matraino = self.scanf(self.matrixo,self.r,self.d)pointadd = 0if LR == 'left' or LR == 'not equal': #左乘(matrix*matrixo)或者普通乘法 #(非方阵相乘)for p1 in range(self.j):#第一层for循环是matrix中行向量的索引for p2 in range(self.d):#第二层for循环是matrixo的转置中行向量的索引for p3 in range(self.i): #第三层for循环是每个行向量中元素值的索引point = (matrain[p1])[p3]*(matransposeo[p2])[p3]pointadd=pointadd+pointpointmul.append(pointadd)pointadd = 0elif LR == 'right': #右乘(matrixo*matrix)for p1 in range(self.j): #第一层for循环是matrixo中行向量的索引for p2 in range(self.d): #第二层for循环是matrix的转置中行向量的索引for p3 in range(self.i): #第三层for循环是行向量中元素值的索引point = (matraino[p1])[p3]*(matranspose[p2])[p3]pointadd=pointadd+pointpointmul.append(pointadd)pointadd = 0else: #遇到恶意输入,显示出错print("Error.")self.matrixes = pointmulfor q in range(self.j): #若左右矩阵行列数不同,则需要更换for循环条件panda=self.matrixes[self.d*q:self.d*(q+1)] #输出的列用切片提取pandas.append(panda)pandaso = np.array(pandas)return (pandaso)

求矩阵行列式的值函数,需要判断矩阵是否为方阵,然后该函数最多可计算到四维方阵,计算时,采用代数余子式的方式求解行列式值,并统一以第一行元素来求:

#矩阵行列式的值函数,采用的是计算第一行元素的代数余子式与其乘积再求和的方法求解def Det(self,matrixd,vit):#矩阵行列式的值函数(仅限三维方阵和四维方阵)self.matrixd = matrixdself.vit = vitmatrixding = self.scanf(self.matrixd,self.vit,self.vit)row = list(range(self.vit)) #行数变化del row[0] #因为求第一行的元素行列式,所以row=[1,2]rest = []det = 0if (self.i !=self.j or self.d !=self.r) and(self.vit**2 !=len(self.matrixd)):print("Error.")elif self.vit == 3: #三维方阵for v in range(self.vit): #求取代数余子式,对与第一行的每个元素for w in row :#对于除第一行外的每一行,即索引[1]和索引[2]s = np.delete(matrixding[w],v) #删除第v个元素rest.append(s)#构成该元素代数余子式元素行向量cdet =self.matrixd[v]* ((-1)**v)*(rest[0][0]*rest[1][1]-rest[0][1]*rest[1][0 ]) #计算代数余子式和元素之积det = det+cdetrest = [] #rest必须清空,重新装填下一个代数余子式元素行向量elif self.vit == 4: #四维方阵row = list(range(self.vit))del row[0] matrixcopy = self.matrixd[:]#由于接下来要调用Det函数,因此原列表matrixd需要拷贝for v in range(self.vit):for w in row :s = np.delete(matrixding[w],v)for I in range(3): #由于接下来要调用Det函数,因此rest必须是列表形式rest.append(s[I])#用for循环将获取的元素附加到rest空列表中,而不是 #保留数组形式detn = self.Det(rest,3) #类似递归调用,调用自身的Det函数,求取代数余子式值cdet = matrixcopy[v]*((-1)**v)*detn #此时,matrixd的内容已经变化,需要用拷贝 #的matrixcopy来调用第一行元素det = det+cdet rest = [] #rest清空,理由同上else:print("Error.")#遇到恶意输入,显示出错return det

对于伴随矩阵,是由原先矩阵的各个元素的代数余子式作为其元素值,同时在位置上进行转置,计算时,不仅要考虑Det函数里面计算代数余子式的方法和思路,还要考虑换行,一共需要三个for循环,最后调用Transpose函数将矩阵转置,得到伴随矩阵。

#伴随矩阵函数,设计思路是参考Det函数,计算代数余子式,并再次调用Transpose函数转置def Accompany(self,matrixf,vit): #伴随矩阵函数self.matrixf = matrixf self.vit = vitmatrixfing = self.scanf(self.matrixf,self.vit,self.vit)fish = []fishparent = []if (self.i !=self.j or self.d !=self.r) and(self.vit**2 !=len(self.matrixf)): #伴随矩阵条件判断print("Error.")elif self.vit == 3:#三维方阵row = list(range(self.vit))for J in range(self.vit): #第一层for循环是随行变化,求完一行元素的代数余子式,进行下一行f = row[J] # 将row[J]赋值与f,便于row最后恢复del row[J] #删除对应的行,输出依次为[1,2],[0,2],[0,1]for v1 in range(self.vit): #第二层for循环是每一行的元素的索引for w1 in row: #第三层for循环是除该行外的另外两行sg = np.delete(matrixfing[w1],v1) #将该两行进行代数余子式元素求取,#装入fish列表中fish.append(sg)fisher = ((-1)**(v1+w1))*(fish[0][0]*fish[1][1]-fish[0][1]*fish[1][0])#计算代数余子式fishparent.append(fisher)fish = [] #fish列表清空,装载下一行元素的代数余子式,至此 #完成一行的元素的代数余子式row.insert(J,f) #恢复row,将f插入到row中,row恢复为[0,1,2]fishg = self.Transpose(fishparent,self.vit,self.vit)#将fishparent转置,fishg为原矩阵的伴随矩阵elif self.vit == 4: #四维方阵row = list(range(self.vit))for J in range(self.vit):f = row[J]del row[J]for v1 in range(4):for w1 in row:sg = np.delete(matrixfing[w1],v1) #至此求解方法和三维矩阵一样for I in range(3):fish.append(sg[I])#由于下面计算代数余子式的值要调用Det函数,因#此fish必须为列表harry = self.Det(fish,3) #调用Det函数计算代数余子式fisher = ((-1)**(v1+w1))*harryfishparent.append(fisher)fish = []row.insert(J,f)fishg = self.Transpose(fishparent,4,4)else:print("Error.") #遇到恶意输入,显示出错return fishg

最后计算逆矩阵,根据逆矩阵计算公式,如果有原矩阵的伴随矩阵及其行列式的值,就可以得到该矩阵的逆矩阵了,直接调用Accompany函数和Det函数即可:

#逆矩阵函数,有了伴随矩阵函数Accompany和矩阵行列式值函数Det,逆矩阵函数就直接调用这两个函数即#可简单实现def Reverse(self,matrixh,viti):#逆矩阵函数self.matrixh = matrixhself.viti = vitiaccompanison = self.Accompany(matrixh,viti) #该矩阵的伴随矩阵accompansiondetison = self.Det(matrixh,viti)#该矩阵的行列式的值detisonreversion = []for u in range(viti):for t in range(viti):end = accompanison[u][t]/detison #求解逆矩阵每个元素的值reversion.append(end)reverse = self.scanf(reversion,viti,viti)#逆矩阵打印return reverse

最后是析构函数:

def __del__(self): #析构函数print("Matrix's task is finished.")

在主函数中调用矩阵计算类的各个方法进行验证:

if __name__ == '__main__':S1 = [1,2,3,4,5,3,2,3,4]S2 = [0,9,3,2,6,1,8,3,0]S3 = [0,9,3,2,6,1,8,3,0,4,4,6,0,9,1,1]D1 = matrix(3,3,3,3,S1,S2)D2 = matrix(3,3,3,3,S2,S1)S = matrixcalcu(3,3,3,3,S1,S2)print("矩阵1:\n",D1.scanf(S1,3,3))print("矩阵2:\n",D2.scanf(S2,3,3))print("矩阵加和:\n",S.Add())print("矩阵1转置:\n",S.Transpose(S1,3,3))print("矩阵2转置:\n",S.Transpose(S2,3,3))print("矩阵S3转置:\n",S.Transpose(S3,4,4))print("矩阵左乘积:\n",S.Pointmul('left'))print("矩阵右乘积:\n",S.Pointmul('right'))print("矩阵1行列式值:\n",S.Det(S1,3))print("矩阵S3行列式值:\n",S.Det(S3,4))print("矩阵1的伴随矩阵:\n",S.Accompany(S1,3))print("矩阵2的伴随矩阵:\n",S.Accompany(S2,3))print("矩阵S3的伴随矩阵:\n",S.Accompany(S3,4))print("矩阵1的逆矩阵:\n",S.Reverse(S1,3))print("矩阵2的逆矩阵:\n",S.Reverse(S2,3))del S

通过设置三个列表S1、S2、S3作为测试对象,来验证矩阵计算类,其中S1、S2为含9个元素的列表,S3是含16个元素的列表,输出结果如下:

矩阵1:[[1 2 3][4 5 3][2 3 4]]矩阵2:[[0 9 3][2 6 1][8 3 0]]矩阵加和:[[ 1 11 6][ 6 11 4][10 6 4]]矩阵1转置:[[1 4 2][2 5 3][3 3 4]]矩阵2转置:[[0 2 8][9 6 3][3 1 0]]矩阵S3转置:[[0 6 0 0][9 1 4 9][3 8 4 1][2 3 6 1]]矩阵左乘积:[[28 30 5][34 75 17][38 48 9]]矩阵右乘积:[[42 54 39][28 37 28][20 31 33]]矩阵1行列式值:-3矩阵S3行列式值:-408矩阵1的伴随矩阵:[[ 11 -1 9][-10 2 -9][ 2 -1 3]]矩阵2的伴随矩阵:[[ -3 -9 9][ 8 24 -6][-42 -72 18]]矩阵S3的伴随矩阵:[[-302 -68 19 286][ -12 0 -6 60][ 300 0 -54 -276][-192 0 108 144]]矩阵1的逆矩阵:[[-3.66666667 0.33333333 -3. ][ 3.33333333 -0.66666667 3. ][-0.66666667 0.33333333 -1. ]]矩阵2的逆矩阵:[[ 0.05555556 0.16666667 -0.16666667][-0.14814815 -0.44444444 0.11111111][ 0.77777778 1.33333333 -0.33333333]]Matrix's task is finished.

通过自己计算验证,该结果是正确的。本次测试中输入的是两个相同维度的矩阵,读者可以通过下载程序后输入任意m*n矩阵进行验证,结果也是可以的,各类方法都严格遵循矩阵计算的前提条件,因此如果输入的不是方阵,那么部分方法输出会是Error。

若有不足或者更好的思路,可以在评论区留言,晚生可以好好学习并改进,多谢您的过目。

矩阵类py文件提取地址:

链接:/s/1ypULq5l7GZdD0quPAbfidw

提取码:plfv

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。