GaussJordan.cc 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Gauss-Jordan elimination with full pivoting.
  2. // Uses:
  3. // (1) solving systems of linear equations (AX=B)
  4. // (2) inverting matrices (AX=I)
  5. // (3) computing determinants of square matrices
  6. // Running time: O(n^3)
  7. // INPUT: a[][] = an nxn matrix
  8. // b[][] = an nxm matrix
  9. // OUTPUT: X = an nxm matrix (stored in b[][])
  10. // A^{-1} = an nxn matrix (stored in a[][])
  11. // returns determinant of a[][]
  12. typedef double T;
  13. typedef vector<T> VT;
  14. typedef vector<VT> VVT;
  15. T GaussJordan(VVT &a, VVT &b) {
  16. const int n = a.size();
  17. const int m = b[0].size();
  18. VI irow(n), icol(n), ipiv(n);
  19. T det = 1;
  20. for (int i = 0; i < n; i++) {
  21. int pj = -1, pk = -1;
  22. for (int j = 0; j < n; j++) if (!ipiv[j])
  23. for (int k = 0; k < n; k++) if (!ipiv[k])
  24. if (pj == -1 || fabs(a[j][k]) > fabs(a[pj][pk])) { pj = j; pk = k; }
  25. if (fabs(a[pj][pk]) < EPS) { cerr << "Matrix is singular." << endl; exit(0); }
  26. ipiv[pk]++;
  27. swap(a[pj], a[pk]);
  28. swap(b[pj], b[pk]);
  29. if (pj != pk) det *= -1;
  30. irow[i] = pj;
  31. icol[i] = pk;
  32. T c = 1.0 / a[pk][pk];
  33. det *= a[pk][pk];
  34. a[pk][pk] = 1.0;
  35. for (int p = 0; p < n; p++) a[pk][p] *= c;
  36. for (int p = 0; p < m; p++) b[pk][p] *= c;
  37. for (int p = 0; p < n; p++) if (p != pk) {
  38. c = a[p][pk];
  39. a[p][pk] = 0;
  40. for (int q = 0; q < n; q++) a[p][q] -= a[pk][q] * c;
  41. for (int q = 0; q < m; q++) b[p][q] -= b[pk][q] * c;
  42. }
  43. }
  44. for (int p = n-1; p >= 0; p--) if (irow[p] != icol[p]) {
  45. for (int k = 0; k < n; k++) swap(a[k][irow[p]], a[k][icol[p]]);
  46. }
  47. return det;
  48. }
  49. int main() {
  50. const int n = 4;
  51. const int m = 2;
  52. double A[n][n] = { {1,2,3,4},{1,0,1,0},{5,3,2,4},{6,1,4,6} };
  53. double B[n][m] = { {1,2},{4,3},{5,6},{8,7} };
  54. VVT a(n), b(n);
  55. for (int i = 0; i < n; i++) {
  56. a[i] = VT(A[i], A[i] + n);
  57. b[i] = VT(B[i], B[i] + m);
  58. }
  59. double det = GaussJordan(a, b);
  60. // expected: 60
  61. cout << "Determinant: " << det << endl;
  62. // expected: -0.233333 0.166667 0.133333 0.0666667
  63. // 0.166667 0.166667 0.333333 -0.333333
  64. // 0.233333 0.833333 -0.133333 -0.0666667
  65. // 0.05 -0.75 -0.1 0.2
  66. cout << "Inverse: " << endl;
  67. for (int i = 0; i < n; i++) {
  68. for (int j = 0; j < n; j++)
  69. cout << a[i][j] << ' ';
  70. cout << endl;
  71. }
  72. // expected: 1.63333 1.3
  73. // -0.166667 0.5
  74. // 2.36667 1.7
  75. // -1.85 -1.35
  76. cout << "Solution: " << endl;
  77. for (int i = 0; i < n; i++) {
  78. for (int j = 0; j < m; j++)
  79. cout << b[i][j] << ' ';
  80. cout << endl;
  81. }
  82. }