2009-12-11 14 views
11

के निर्धारक को कैसे ढूंढें मुझे 4x4 से 8x8 के लिए मैट्रिक्स के निर्धारक को खोजने के लिए कुछ सी ++ कोड मिला। यह ठीक काम करता है, लेकिन मेरे प्रोजेक्ट को मैट्रिस की आवश्यकता है जो 18x18 या अधिक हैं, और कोड बहुत धीमा है। कोड रिकर्सिव है, लेकिन 18x18 मैट्रिक्स से निपटने के लिए सही अवधारणा का पुनरावृत्ति है? मैं निर्धारक को और कैसे ढूंढ सकता हूं?बड़े मैट्रिक्स

+0

@ पेगाह एक प्रश्न का उत्तर देने के लिए, "आपका उत्तर" पर स्क्रॉल करें। हम प्रश्न और उत्तर अलग रखना पसंद करते हैं। – phihag

उत्तर

25

मुझे लगता है कि आप Laplace's formula का विस्तार करने के लिए उपयोग कर रहे हैं। आप गति में हासिल करना चाहते हैं, तो आप (दो निचले और ऊपरी-विकर्ण मैट्रिक्स में) जो आप 2*n^3/3 FLOPS में एक संशोधित गॉस-जोर्डन उन्मूलन के साथ प्राप्त कर सकते हैं अपने मैट्रिक्स MLU decomposition का उपयोग कर विघटित कर सकते हैं और उसके बाद के रूप में निर्धारक गणना:

det(M) = det(L) * det(U), जो त्रिकोणीय matrices के लिए सिर्फ उनके विकर्ण में प्रविष्टियों का उत्पाद है।

यह प्रक्रिया अभी भी O(n!) से तेज होगी।

संपादित करें: आप Crout's method का भी उपयोग कर सकते हैं, जो व्यापक रूप से कार्यान्वित किया जाता है।

+0

यदि मैट्रिक्स सममित सकारात्मक-निश्चित है, तो Cholesky का कारककरण सबसे तेज़, संख्यात्मक रूप से सर्वोत्तम तरीका है। – Paul

+0

@ पॉल: यह सच है, लेकिन मुझे यकीन नहीं है कि कैसे मैट्रिक्स सकारात्मक-निश्चित है, इसलिए मैंने इसे छोड़ दिया। –

+0

त्रिभुज मैट्रिक्स के निर्धारक की गणना करना सरल है: विकर्ण तत्वों को गुणा करें, क्योंकि ऑफ-विकर्ण शर्तों के कॉफ़ैक्टर्स 0 हैं। एलयू अपघटन का उपयोग करके इसे और सरल बना दिया जाता है, क्योंकि एल एक इकाई है, कम त्रिभुज मैट्रिक्स, यानी इसके विकर्ण तत्व अधिकांश कार्यान्वयन में सभी 1 हैं। इसके लिए, आपको अक्सर यू – rcollyer

9

ठीक है, हम में से कई लोग इस क्षेत्र में काम नहीं कर रहे हैं, 18x18 को एक बड़े मैट्रिक्स के रूप में मानेंगे और आपके द्वारा चुने गए लगभग किसी भी तकनीक को किसी भी आधुनिक कंप्यूटर पर पर्याप्त तेज़ी से होना चाहिए। न ही हम में से कई रिकर्सिव एल्गोरिदम के साथ मैट्रिक्स प्रश्नों से निपटेंगे, जो पुनरावृत्त लोगों का उपयोग करने की अधिक संभावना है - लेकिन यह इस तथ्य का प्रतिबिंब हो सकता है कि मैट्रिक्स समस्याओं पर काम करने वाले बहुत से लोग वैज्ञानिक और इंजीनियरों कंप्यूटर वैज्ञानिक नहीं हैं।

मेरा सुझाव है कि आप सी ++ में न्यूमेरिकल व्यंजनों को देखें। जरूरी नहीं कि आपको सबसे अच्छा कोड मिलेगा, लेकिन यह अध्ययन और सीखने के लिए एक पाठ है। बेहतर कोड के लिए, बूस्ट की अच्छी प्रतिष्ठा है और हमेशा बीएलएएस और इंटेल मैथ्स कर्नेल लाइब्रेरी या एएमडी कोर मैथ्स लाइब्रेरी जैसी चीज़ें होती हैं। मुझे लगता है कि इनमें से सभी को निर्धारक-खोज दिनचर्या के कार्यान्वयन हैं जो 18x18 मैट्रिक्स से बहुत जल्दी निपटेंगे। Cholesky अपघटन (या इसके संस्करण, एलडीएल टी, एल एक इकाई कम त्रिकोणीय मैट्रिक्स और डी एक विकर्ण मैट्रिक्स) एक सममित यदि सत्यापित करने के लिए इस्तेमाल किया जा सकता:

1

जब से मैं टिप्पणी नहीं कर सकता, मैं इस जोड़ना चाहते हैं मैट्रिक्स सकारात्मक/नकारात्मक निश्चित है: यदि यह सकारात्मक निश्चित है, तो डी के तत्व सभी सकारात्मक हैं, और Cholesky अपघटन एक नकारात्मक संख्या के वर्ग रूट के बिना सफलतापूर्वक खत्म हो जाएगा। यदि मैट्रिक्स नकारात्मक निश्चित है, तो डी के तत्व सभी नकारात्मक हैं, मैट्रिक्स के पास Cholesky अपघटन नहीं होगा, लेकिन इसका नकारात्मक होगा।

"त्रिभुज मैट्रिक्स के निर्धारक की गणना करना सरल है: विकर्ण तत्वों को गुणा करें, क्योंकि ऑफ-विकर्ण शर्तों के कॉफ़ैक्टर्स 0 हैं। एलयू अपघटन का उपयोग करके इसे और सरल बना दिया जाता है, क्योंकि एल एक इकाई है, कम त्रिभुज मैट्रिक्स, यानी इसके विकर्ण तत्व सभी कार्यान्वयन में सभी 1 हैं। इसके लिए, आपको अक्सर यू के निर्धारक की गणना करना पड़ता है। "

  • आप यहां ध्यान देने के लिए भूल गए हैं कि गॉसियन उन्मूलन के सभी व्यावहारिक कार्यान्वयन अतिरिक्त संख्यात्मक स्थिरता के लिए (आंशिक) पिवोटिंग का उपयोग करते हैं; तो आपका विवरण अधूरा है; एक अपघटन चरण के दौरान किए गए पंक्ति स्वैप की संख्या की गणना करता है, और यू के सभी विकर्ण तत्वों को एक साथ गुणा करने के बाद, स्वैप की संख्या विषम होने पर इस उत्पाद को अस्वीकार कर दिया जाना चाहिए।

कोड के लिए, एनआर मुक्त नहीं है; मैं इसके बजाय लैपैक/क्लैपैक/लैपैक ++ @http://www.netlib.org/ पर एक नज़र डालने का सुझाव देता हूं। संदर्भ के लिए, मैं गोल्ब और वैन लोन द्वारा "मैट्रिक्स कंप्यूटेशंस" को इंगित करने से बेहतर नहीं कर सकता।

0

मुझे लगता है कि यह शायद काम कर सकता है।

मैंने इसे लिखा जब मैंने संख्यात्मक विश्लेषण पाठ्यक्रम का अध्ययन किया।

इस मैट्रिक्स

पहले, कॉपी और के रूप में 'Matrix.h'

//Title: Matrix Header File 
//Writer: Say OL 
//This is a beginner code not an expert one 
//No responsibilty for any errors 
//Use for your own risk 
using namespace std; 
int row,col,Row,Col; 
double Coefficient; 
//Input Matrix 
void Input(double Matrix[9][9],int Row,int Col) 
{ 
    for(row=1;row<=Row;row++) 
     for(col=1;col<=Col;col++) 
     { 
      cout<<"e["<<row<<"]["<<col<<"]="; 
      cin>>Matrix[row][col]; 
     } 
} 
//Output Matrix 
void Output(double Matrix[9][9],int Row,int Col) 
{ 
    for(row=1;row<=Row;row++) 
    { 
     for(col=1;col<=Col;col++) 
      cout<<Matrix[row][col]<<"\t"; 
     cout<<endl; 
    } 
} 
//Copy Pointer to Matrix 
void CopyPointer(double (*Pointer)[9],double Matrix[9][9],int Row,int Col) 
{ 
    for(row=1;row<=Row;row++) 
     for(col=1;col<=Col;col++) 
      Matrix[row][col]=Pointer[row][col]; 
} 
//Copy Matrix to Matrix 
void CopyMatrix(double MatrixInput[9][9],double MatrixTarget[9][9],int Row,int Col) 
{ 
    for(row=1;row<=Row;row++) 
     for(col=1;col<=Col;col++) 
      MatrixTarget[row][col]=MatrixInput[row][col]; 
} 
//Transpose of Matrix 
double MatrixTran[9][9]; 
double (*(Transpose)(double MatrixInput[9][9],int Row,int Col))[9] 
{ 
    for(row=1;row<=Row;row++) 
     for(col=1;col<=Col;col++) 
      MatrixTran[col][row]=MatrixInput[row][col]; 
    return MatrixTran; 
} 
//Matrix Addition 
double MatrixAdd[9][9]; 
double (*(Addition)(double MatrixA[9][9],double MatrixB[9][9],int Row,int Col))[9] 
{ 
    for(row=1;row<=Row;row++) 
     for(col=1;col<=Col;col++) 
      MatrixAdd[row][col]=MatrixA[row][col]+MatrixB[row][col]; 
    return MatrixAdd; 
} 
//Matrix Subtraction 
double MatrixSub[9][9]; 
double (*(Subtraction)(double MatrixA[9][9],double MatrixB[9][9],int Row,int Col))[9] 
{ 
    for(row=1;row<=Row;row++) 
     for(col=1;col<=Col;col++) 
      MatrixSub[row][col]=MatrixA[row][col]-MatrixB[row][col]; 
    return MatrixSub; 
} 
//Matrix Multiplication 
int mRow,nCol,pCol,kcol; 
double MatrixMult[9][9]; 
double (*(Multiplication)(double MatrixA[9][9],double MatrixB[9][9],int mRow,int nCol,int pCol))[9] 
{ 
    for(row=1;row<=mRow;row++) 
     for(col=1;col<=pCol;col++) 
     { 
      MatrixMult[row][col]=0.0; 
      for(kcol=1;kcol<=nCol;kcol++) 
       MatrixMult[row][col]+=MatrixA[row][kcol]*MatrixB[kcol][col]; 
     } 
    return MatrixMult; 
} 
//Interchange Two Rows 
double RowTemp[9][9]; 
double MatrixInter[9][9]; 
double (*(InterchangeRow)(double MatrixInput[9][9],int Row,int Col,int iRow,int jRow))[9] 
{ 
    CopyMatrix(MatrixInput,MatrixInter,Row,Col); 
    for(col=1;col<=Col;col++) 
    { 
     RowTemp[iRow][col]=MatrixInter[iRow][col]; 
     MatrixInter[iRow][col]=MatrixInter[jRow][col]; 
     MatrixInter[jRow][col]=RowTemp[iRow][col]; 
    } 
    return MatrixInter; 
} 
//Pivote Downward 
double MatrixDown[9][9]; 
double (*(PivoteDown)(double MatrixInput[9][9],int Row,int Col,int tRow,int tCol))[9] 
{ 
    CopyMatrix(MatrixInput,MatrixDown,Row,Col); 
    Coefficient=MatrixDown[tRow][tCol]; 
    if(Coefficient!=1.0) 
     for(col=1;col<=Col;col++) 
      MatrixDown[tRow][col]/=Coefficient; 
    if(tRow<Row) 
     for(row=tRow+1;row<=Row;row++) 
     { 
      Coefficient=MatrixDown[row][tCol]; 
      for(col=1;col<=Col;col++) 
       MatrixDown[row][col]-=Coefficient*MatrixDown[tRow][col]; 
     } 
return MatrixDown; 
} 
//Pivote Upward 
double MatrixUp[9][9]; 
double (*(PivoteUp)(double MatrixInput[9][9],int Row,int Col,int tRow,int tCol))[9] 
{ 
    CopyMatrix(MatrixInput,MatrixUp,Row,Col); 
    Coefficient=MatrixUp[tRow][tCol]; 
    if(Coefficient!=1.0) 
     for(col=1;col<=Col;col++) 
      MatrixUp[tRow][col]/=Coefficient; 
    if(tRow>1) 
     for(row=tRow-1;row>=1;row--) 
     { 
      Coefficient=MatrixUp[row][tCol]; 
      for(col=1;col<=Col;col++) 
       MatrixUp[row][col]-=Coefficient*MatrixUp[tRow][col]; 
     } 
    return MatrixUp; 
} 
//Pivote in Determinant 
double MatrixPiv[9][9]; 
double (*(Pivote)(double MatrixInput[9][9],int Dim,int pTarget))[9] 
{ 
    CopyMatrix(MatrixInput,MatrixPiv,Dim,Dim); 
    for(row=pTarget+1;row<=Dim;row++) 
    { 
     Coefficient=MatrixPiv[row][pTarget]/MatrixPiv[pTarget][pTarget]; 
     for(col=1;col<=Dim;col++) 
     { 
      MatrixPiv[row][col]-=Coefficient*MatrixPiv[pTarget][col]; 
     } 
    } 
    return MatrixPiv; 
} 
//Determinant of Square Matrix 
int dCounter,dRow; 
double Det; 
double MatrixDet[9][9]; 
double Determinant(double MatrixInput[9][9],int Dim) 
{ 
    CopyMatrix(MatrixInput,MatrixDet,Dim,Dim); 
    Det=1.0; 
    if(Dim>1) 
    { 
     for(dRow=1;dRow<Dim;dRow++) 
     { 
      dCounter=dRow; 
      while((MatrixDet[dRow][dRow]==0.0)&(dCounter<=Dim)) 
      { 
       dCounter++; 
       Det*=-1.0; 
       CopyPointer(InterchangeRow(MatrixDet,Dim,Dim,dRow,dCounter),MatrixDet,Dim,Dim); 
      } 
      if(MatrixDet[dRow][dRow]==0) 
      { 
       Det=0.0; 
       break; 
      } 
      else 
      { 
       Det*=MatrixDet[dRow][dRow]; 
       CopyPointer(Pivote(MatrixDet,Dim,dRow),MatrixDet,Dim,Dim); 
      } 
     } 
     Det*=MatrixDet[Dim][Dim]; 
    } 
    else Det=MatrixDet[1][1]; 
    return Det; 
} 
//Matrix Identity 
double MatrixIdent[9][9]; 
double (*(Identity)(int Dim))[9] 
{ 
    for(row=1;row<=Dim;row++) 
     for(col=1;col<=Dim;col++) 
      if(row==col) 
       MatrixIdent[row][col]=1.0; 
      else 
       MatrixIdent[row][col]=0.0; 
    return MatrixIdent; 
} 
//Join Matrix to be Augmented Matrix 
double MatrixJoin[9][9]; 
double (*(JoinMatrix)(double MatrixA[9][9],double MatrixB[9][9],int Row,int ColA,int ColB))[9] 
{ 
    Col=ColA+ColB; 
    for(row=1;row<=Row;row++) 
     for(col=1;col<=Col;col++) 
      if(col<=ColA) 
       MatrixJoin[row][col]=MatrixA[row][col]; 
      else 
       MatrixJoin[row][col]=MatrixB[row][col-ColA]; 
    return MatrixJoin; 
} 
//Inverse of Matrix 
double (*Pointer)[9]; 
double IdentMatrix[9][9]; 
int Counter; 
double MatrixAug[9][9]; 
double MatrixInv[9][9]; 
double (*(Inverse)(double MatrixInput[9][9],int Dim))[9] 
{ 
    Row=Dim; 
    Col=Dim+Dim; 
    Pointer=Identity(Dim); 
    CopyPointer(Pointer,IdentMatrix,Dim,Dim); 
    Pointer=JoinMatrix(MatrixInput,IdentMatrix,Dim,Dim,Dim); 
    CopyPointer(Pointer,MatrixAug,Row,Col); 
    for(Counter=1;Counter<=Dim;Counter++) 
    { 
     Pointer=PivoteDown(MatrixAug,Row,Col,Counter,Counter); 
     CopyPointer(Pointer,MatrixAug,Row,Col); 
    } 
    for(Counter=Dim;Counter>1;Counter--) 
    { 
     Pointer=PivoteUp(MatrixAug,Row,Col,Counter,Counter); 
     CopyPointer(Pointer,MatrixAug,Row,Col); 
    } 
    for(row=1;row<=Dim;row++) 
     for(col=1;col<=Dim;col++) 
      MatrixInv[row][col]=MatrixAug[row][col+Dim]; 
    return MatrixInv; 
} 
//Gauss-Jordan Elemination 
double MatrixGJ[9][9]; 
double VectorGJ[9][9]; 
double (*(GaussJordan)(double MatrixInput[9][9],double VectorInput[9][9],int Dim))[9] 
{ 
    Row=Dim; 
    Col=Dim+1; 
    Pointer=JoinMatrix(MatrixInput,VectorInput,Dim,Dim,1); 
    CopyPointer(Pointer,MatrixGJ,Row,Col); 
    for(Counter=1;Counter<=Dim;Counter++) 
    { 
     Pointer=PivoteDown(MatrixGJ,Row,Col,Counter,Counter); 
     CopyPointer(Pointer,MatrixGJ,Row,Col); 
    } 
    for(Counter=Dim;Counter>1;Counter--) 
    { 
     Pointer=PivoteUp(MatrixGJ,Row,Col,Counter,Counter); 
     CopyPointer(Pointer,MatrixGJ,Row,Col); 
    } 
    for(row=1;row<=Dim;row++) 
     for(col=1;col<=1;col++) 
      VectorGJ[row][col]=MatrixGJ[row][col+Dim]; 
    return VectorGJ; 
} 
//Generalized Gauss-Jordan Elemination 
double MatrixGGJ[9][9]; 
double VectorGGJ[9][9]; 
double (*(GeneralizedGaussJordan)(double MatrixInput[9][9],double VectorInput[9][9],int Dim,int vCol))[9] 
{ 
    Row=Dim; 
    Col=Dim+vCol; 
    Pointer=JoinMatrix(MatrixInput,VectorInput,Dim,Dim,vCol); 
    CopyPointer(Pointer,MatrixGGJ,Row,Col); 
    for(Counter=1;Counter<=Dim;Counter++) 
    { 
     Pointer=PivoteDown(MatrixGGJ,Row,Col,Counter,Counter); 
     CopyPointer(Pointer,MatrixGGJ,Row,Col); 
    } 
    for(Counter=Dim;Counter>1;Counter--) 
    { 
     Pointer=PivoteUp(MatrixGGJ,Row,Col,Counter,Counter); 
     CopyPointer(Pointer,MatrixGGJ,Row,Col); 
    } 
    for(row=1;row<=Row;row++) 
     for(col=1;col<=vCol;col++) 
      VectorGGJ[row][col]=MatrixGGJ[row][col+Dim]; 
    return VectorGGJ; 
} 
//Matrix Sparse, Three Diagonal Non-Zero Elements 
double MatrixSpa[9][9]; 
double (*(Sparse)(int Dimension,double FirstElement,double SecondElement,double ThirdElement))[9] 
{ 
    MatrixSpa[1][1]=SecondElement; 
    MatrixSpa[1][2]=ThirdElement; 
    MatrixSpa[Dimension][Dimension-1]=FirstElement; 
    MatrixSpa[Dimension][Dimension]=SecondElement; 
    for(int Counter=2;Counter<Dimension;Counter++) 
    { 
     MatrixSpa[Counter][Counter-1]=FirstElement; 
     MatrixSpa[Counter][Counter]=SecondElement; 
     MatrixSpa[Counter][Counter+1]=ThirdElement; 
    } 
    return MatrixSpa; 
} 

मेरी विधि में, मैं कन्वर्ट कोड को बचाने से संबंधित न केवल निर्धारक लेकिन अन्य कार्यों है प्राथमिक पंक्ति संचालन का उपयोग कर ऊपरी त्रिकोणीय मैट्रिक्स के लिए मैट्रिक्स

और निर्धारक विकर्ण तत्वों का उत्पाद है।

यहाँ नमूना कोड

#include<iostream> 
#include<conio.h> 
#include"Matrix.h" 
int Dim; 
double Matrix[9][9]; 
int main() 
{ 
    cout<<"Enter matrix dimension: "; 
    cin>>Dim; 
    cout<<"Enter matrix elements:"<<endl; 
    Input(Matrix,Dim,Dim); 
    cout<<"Your matrix:"<<endl; 
    Output(Matrix,Dim,Dim); 
    cout<<"The determinant: "<<Determinant(Matrix,Dim)<<endl; 
    getch(); 
} 
1

अजगर कोड समारोह det_recursive किसी भी आकार के एक वर्ग मैट्रिक्स के लिए काम करता है। हालांकि, चूंकि यह लेपलेस के सूत्र का विस्तार करने के पुनरावर्ती बेवकूफ विधि का उपयोग कर रहा है क्योंकि यह बड़े आकार के मैट्रिस के लिए बहुत धीमा है।

एक और तकनीक मैट्रिक्स को गॉस उन्मूलन तकनीक का उपयोग करके ऊपरी त्रिकोणीय रूप में बदलने के लिए है। फिर मैट्रिक्स का निर्धारक मूल मैट्रिक्स के त्रिभुज रूपांतरित रूपांतरित रूप के विकर्ण तत्वों का उत्पाद है।

मूल रूप से numpy सबसे तेज़ है लेकिन आंतरिक रूप से यह कुछ प्रकार की रैखिक मैट्रिक्स रूपांतरण विधि का उपयोग करता है जो कि गॉस उन्मूलन करता है। हालांकि, मुझे यकीन नहीं है कि यह वास्तव में क्या है!

In[1] 
import numpy as np 

In[2] 
mat = np.random.rand(9,9) 
print("numpy asnwer = ", np.linalg.det(mat)) 

Out[2] 
numpy asnwer = 0.016770106020608373 

In[3] 
def det_recursive(A): 
    if A.shape[0] != A.shape[1]: 
     raise ValueError('matrix {} is not Square'.format(A)) 

    sol = 0 
    if A.shape != (1,1): 
     for i in range(A.shape[0]): 
      sol = sol + (-1)**i * A[i, 0] * det_recursive(np.delete(np.delete(A, 0, axis= 1), i, axis= 0)) 
     return sol 
    else: 
     return A[0,0] 
​ 

In[4] 
print("recursive asnwer = ", det_recursive(mat)) 

Out[4] 
recursive asnwer = 0.016770106020608397 

In[5] 
def det_gauss_elimination(a,tol=1.0e-9): 
    """ 
    calculate determinant using gauss-elimination method 
    """ 
    a = np.copy(a) 

    assert(a.shape[0] == a.shape[1]) 
    n = a.shape[0] 

    # Set up scale factors 
    s = np.zeros(n) 

    mult = 0 
    for i in range(n): 
     s[i] = max(np.abs(a[i,:])) # find the max of each row 
    for k in range(0, n-1): #pivot row 
     # Row interchange, if needed 
     p = np.argmax(np.abs(a[k:n,k])/s[k:n]) + k 
     if abs(a[p,k]) < tol: 
      print("Matrix is singular") 
      return 0 
     if p != k: 
      a[[k,p],:] = a[[p, k],:] 
      s[k],s[p] = s[p],s[k] 
      mult = mult + 1 
​ 
     # convert a to upper triangular matrix 
     for i in range(k+1,n): 
      if a[i,k] != 0.0: # skip if a(i,k) is already zero 
       lam = a [i,k]/a[k,k] 
       a[i,k:n] = a[i,k:n] - lam*a[k,k:n] 
​ 
    deter = np.prod(np.diag(a))* (-1)**mult 
    return deter 

In[6] 
print("gauss elimination asnwer = ", det_gauss_elimination(mat)) 

Out[6] 
gauss elimination asnwer = 0.016770106020608383 

In[7] 
print("numpy time") 
%timeit -n3 -r3 np.linalg.det(mat) 
print("\nrecursion time") 
%timeit -n3 -r3 det_recursive(mat) 
print("\ngauss_elimination time") 
%timeit -n3 -r3 det_gauss_elimination(mat) 

Out[7] 
numpy time 
40.8 µs ± 17.2 µs per loop (mean ± std. dev. of 3 runs, 3 loops each) 

recursion time 
10.1 s ± 128 ms per loop (mean ± std. dev. of 3 runs, 3 loops each) 

gauss_elimination time 
472 µs ± 106 µs per loop (mean ± std. dev. of 3 runs, 3 loops each) 
संबंधित मुद्दे