ReducedRowEchelonForm.cc 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Reduced row echelon form via Gauss-Jordan elimination
  2. // with partial pivoting. This can be used for computing
  3. // the rank of a matrix.
  4. //
  5. // Running time: O(n^3)
  6. //
  7. // INPUT: a[][] = an nxn matrix
  8. //
  9. // OUTPUT: rref[][] = an nxm matrix (stored in a[][])
  10. // returns rank of a[][]
  11. #include <iostream>
  12. #include <vector>
  13. #include <cmath>
  14. using namespace std;
  15. const double EPSILON = 1e-10;
  16. typedef double T;
  17. typedef vector<T> VT;
  18. typedef vector<VT> VVT;
  19. int rref(VVT &a) {
  20. int n = a.size();
  21. int m = a[0].size();
  22. int r = 0;
  23. for (int c = 0; c < m; c++) {
  24. int j = r;
  25. for (int i = r+1; i < n; i++)
  26. if (fabs(a[i][c]) > fabs(a[j][c])) j = i;
  27. if (fabs(a[j][c]) < EPSILON) continue;
  28. swap(a[j], a[r]);
  29. T s = 1.0 / a[r][c];
  30. for (int j = 0; j < m; j++) a[r][j] *= s;
  31. for (int i = 0; i < n; i++) if (i != r) {
  32. T t = a[i][c];
  33. for (int j = 0; j < m; j++) a[i][j] -= t * a[r][j];
  34. }
  35. r++;
  36. }
  37. return r;
  38. }
  39. int main(){
  40. const int n = 5;
  41. const int m = 4;
  42. double A[n][m] = { {16,2,3,13},{5,11,10,8},{9,7,6,12},{4,14,15,1},{13,21,21,13} };
  43. VVT a(n);
  44. for (int i = 0; i < n; i++)
  45. a[i] = VT(A[i], A[i] + n);
  46. int rank = rref (a);
  47. // expected: 4
  48. cout << "Rank: " << rank << endl;
  49. // expected: 1 0 0 1
  50. // 0 1 0 3
  51. // 0 0 1 -3
  52. // 0 0 0 2.78206e-15
  53. // 0 0 0 3.22398e-15
  54. cout << "rref: " << endl;
  55. for (int i = 0; i < 5; i++){
  56. for (int j = 0; j < 4; j++)
  57. cout << a[i][j] << ' ';
  58. cout << endl;
  59. }
  60. }