当前位置:   article > 正文

行列式求值、矩阵求逆_cuda矩阵求逆

cuda矩阵求逆
  1. #include <iostream>
  2. #include <string>
  3. #include <assert.h>
  4. #include <malloc.h>
  5. #include <iostream>
  6. #include <stdlib.h>
  7. #include <memory.h>
  8. #include <time.h>
  9. using namespace std;
  10. //动态分配大小位size的一维数组
  11. template<typename T>
  12. bool allocateMemory1D(T **p, const int size)
  13. {
  14. *p = NULL;
  15. *p = (T *)malloc(size * sizeof(T));
  16. if (*p == NULL) return false;
  17. return true;
  18. }
  19. //动态分配rows行、cols列的二维数组
  20. template<typename T>
  21. bool allocateMemory2D(T ***p, const int rows, const int cols)
  22. {
  23. *p = NULL;
  24. *p = (T **)malloc(rows * sizeof(T *));
  25. if (*p == NULL) return false;
  26. memset(*p, 0, sizeof(T *)* rows);
  27. for (int i = 0; i < rows; i++)
  28. {
  29. (*p)[i] = (T *)malloc(cols * sizeof(T));
  30. if ((*p)[i] == NULL) return false;
  31. }
  32. return true;
  33. }
  34. //释放一维动态数组的空间
  35. template<typename T>
  36. void freeMemory1D(T **p)
  37. {
  38. if (*p != NULL)
  39. {
  40. free(*p);
  41. *p = NULL;
  42. }
  43. }
  44. //释放二维动态数组的空间
  45. template<typename T>
  46. void freeMemory2D(T ***p, const int rows)
  47. {
  48. if (*p != NULL)
  49. {
  50. for (int i = 0; i < rows; i++)
  51. {
  52. if ((*p)[i] != NULL)
  53. {
  54. free((*p)[i]);
  55. (*p)[i] = NULL;
  56. }
  57. }
  58. free(*p);
  59. *p = NULL;
  60. }
  61. }
  62. //template<class T>
  63. //void swap(T &a, T &b)
  64. //{
  65. // T tmp = a;
  66. // a = b;
  67. // b = tmp;
  68. //}
  69. //用随机数填充二维数组(矩阵)
  70. template<typename T, typename V>
  71. bool generateNNumbers2D(T **a, int rows, int cols, V minValue, V maxValue)
  72. {
  73. //assert(a != NULL && rows > 0 && cols > 0);
  74. if (a == NULL || rows < 1 && cols < 1) return false;
  75. if (minValue > maxValue) swap(minValue, maxValue);
  76. const int N = 999999;
  77. srand((unsigned)time(NULL));
  78. for (int i = 0; i < rows; i++)
  79. {
  80. for (int j = 0; j < cols; j++)
  81. {
  82. a[i][j] = rand() % (int)(maxValue - minValue + 1) + minValue + rand() % (N + 1) / (float)(N + 1);
  83. }
  84. }
  85. return true;
  86. }
  87. void displayArray2D(double **a, const int rows, const int cols)
  88. {
  89. assert(a != NULL && rows > 0 && cols > 0);
  90. for (int i = 0; i < rows; i++)
  91. {
  92. printf("%d: ", i + 1);
  93. for (int j = 0; j < cols; j++)
  94. {
  95. printf("%lf ", a[i][j]);
  96. }
  97. printf("\n");
  98. }
  99. }
  100. //降阶法递归求行列式的值,就是按照线性代数书上的公式,我是按照第一行进行展开
  101. template <typename T>
  102. double static det(T **mat, const int n)
  103. {
  104. assert(mat != NULL && n > 0);
  105. if (n == 1) return (double)mat[0][0];
  106. else if (n == 2) return (double)(mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]);
  107. else
  108. {
  109. int i, j, k, flag = 1, col;
  110. double value = 0.0;
  111. T **tmpMat = NULL;
  112. allocateMemory2D(&tmpMat, n - 1, n - 1);
  113. for (i = 0; i < n; i++)
  114. {
  115. for (j = 1; j < n; j++)
  116. {
  117. col = 0;
  118. for (k = 0; k < n; k++)
  119. {
  120. if (k != i)
  121. {
  122. tmpMat[j - 1][col++] = mat[j][k];
  123. }
  124. }
  125. }
  126. value += mat[0][i] * det(tmpMat, n - 1) * flag;
  127. flag = -flag;
  128. }
  129. freeMemory2D(&tmpMat, n - 1);
  130. return value;
  131. }
  132. }
  133. //将矩阵化为上三角矩阵来求行列式的值,精度比上面的降阶法要低,我没有考虑数据
  134. //溢出的情况,适用范围有限(上面也是)。
  135. double static det1(double **mat, const int n)
  136. {
  137. assert(mat && n > 0);
  138. const double PRECESION = 1E-6;
  139. int row, col, i, j;
  140. bool flag = false;
  141. int sign = 1;
  142. double result = 1.0;
  143. for (i = 0; i < n - 1; i++)
  144. {
  145. for (j = i; j < n; j++)
  146. {
  147. if (fabs(mat[i][j]) > PRECESION) break;
  148. }
  149. if (j >= n)
  150. {
  151. flag = true;
  152. break;
  153. }
  154. if (j != i)
  155. {
  156. //swap rows
  157. for (col = 0; col < n; col++)
  158. {
  159. result = mat[i][col];
  160. mat[i][col] = mat[j][col];
  161. mat[j][col] = result;
  162. }
  163. sign = -sign;
  164. }
  165. //sub i row
  166. for (row = j + 1; row < n; row++)
  167. {
  168. double base = mat[row][i] / mat[i][i];
  169. for (col = 0; col < n; col++)
  170. {
  171. mat[row][col] -= mat[i][col] * base;
  172. }
  173. }
  174. }
  175. if (flag)
  176. {
  177. return 0;
  178. }
  179. else
  180. {
  181. result = 1.0;
  182. for (i = 0; i < n; i++)
  183. {
  184. result *= mat[i][i];
  185. }
  186. if (sign < 0)
  187. {
  188. result = -result;
  189. }
  190. }
  191. return result;
  192. }
  193. //求一个矩阵的邻接矩阵,T为输入矩阵,adjointMat存放T对应的邻接矩阵,n为矩阵的阶数
  194. template <typename T>
  195. bool adjointMatrix(T **mat, T ** &adjointMat, int n)
  196. {
  197. int i, j;
  198. if (mat == NULL || n < 1) return false;
  199. if (n == 1)
  200. {
  201. adjointMat[0][0] = 1;
  202. return true;
  203. }
  204. T **tmpMat = NULL;
  205. allocateMemory2D(&tmpMat, n - 1, n - 1);
  206. int sign = -1, row, col, rowIndex, colIndex;
  207. for (i = 0; i < n; i++)
  208. {
  209. sign = -sign;
  210. int s = sign;
  211. for (j = 0; j < n; j++)
  212. {
  213. rowIndex = 0;
  214. for (row = 0; row < n; row++)
  215. {
  216. colIndex = 0;
  217. if (row != i)
  218. {
  219. for (col = 0; col < n; col++)
  220. {
  221. if (col != j)
  222. {
  223. tmpMat[rowIndex][colIndex] = mat[row][col];
  224. colIndex++;
  225. }
  226. }
  227. rowIndex++;
  228. }
  229. }
  230. adjointMat[j][i] = s * det(tmpMat, n - 1);
  231. s = -s;
  232. }
  233. }
  234. freeMemory2D(&tmpMat, n - 1);
  235. return true;
  236. }
  237. //求一个矩阵的逆矩阵
  238. template <typename T>
  239. int inverseMatrix(double d, T **mat, T ** &inverseMat, int n)
  240. {
  241. //参数合法性检查
  242. if (n < 1 || mat == NULL || inverseMat == NULL) return -2;
  243. //double d = det(mat, n);
  244. if (fabs(d) < 1E-6) return -1; //矩阵为奇异矩阵的情况,此时不可逆
  245. for (int row = 0; row < n; row++)
  246. {
  247. for (int col = 0; col < n; col++)
  248. {
  249. inverseMat[row][col] = mat[row][col] / d;
  250. }
  251. }
  252. return 0;
  253. }
  254. //两个矩阵相乘,mat3 = mat1 * mat2
  255. template <typename T>
  256. bool matrixMultiply(T **mat1, T **mat2, T **&mat3, int n)
  257. {
  258. if (mat1 == NULL || mat2 == NULL || n < 1) return false;
  259. for (int row = 0; row < n; row++)
  260. {
  261. for (int col = 0; col < n; col++)
  262. {
  263. double sum = 0.0;
  264. for (int k = 0; k < n; k++)
  265. {
  266. sum += mat1[row][k] * mat2[k][col];
  267. }
  268. mat3[row][col] = sum;
  269. }
  270. }
  271. return true;
  272. }
  273. //误差分析
  274. template <typename T>
  275. bool compareMatrix(T **referenceMat, T **mat, int n, double *absoluteError, double *relativeError)
  276. {
  277. if (referenceMat == NULL || mat == NULL || n < 1 || absoluteError == NULL || relativeError == NULL) return false;
  278. *absoluteError = 0;
  279. *relativeError = 0;
  280. for (int row = 0; row < n; row++)
  281. {
  282. for (int col = 0; col < n; col++)
  283. {
  284. double tmp = fabs(mat[row][col] - referenceMat[row][col]);
  285. *absoluteError += tmp;
  286. if (fabs(referenceMat[row][col]) > 1E-6) *relativeError += tmp / referenceMat[row][col];
  287. }
  288. }
  289. return true;
  290. }
  291. void main(void)
  292. {
  293. int n, i, j, ret;
  294. double **mat = NULL;
  295. double **adjointMat = NULL;
  296. double absouluteError, relativeError, d;
  297. double **tmpMat = NULL;
  298. bool isReversible;
  299. bool isDataAutoGenerate;
  300. char ch;
  301. char buf[256];
  302. cout << "自动生成矩阵吗(y/Y:是):";
  303. cin >> ch;
  304. isDataAutoGenerate = (ch == 'y' || ch == 'Y');
  305. cin.getline(buf, sizeof(buf)); //清空输入缓冲区
  306. cout << "输入行列式的阶数:";
  307. while (cin >> n)
  308. {
  309. allocateMemory2D(&mat, n, n);
  310. if (isDataAutoGenerate)
  311. {
  312. generateNNumbers2D(mat, n, n, -100, 100);
  313. cout << "自动生成的" << n << "阶矩阵为:" << endl;
  314. displayArray2D(mat, n, n);
  315. }
  316. else
  317. {
  318. cout << "依次输入矩阵的每一个元素:\n";
  319. for (i = 0; i < n * n; i++) cin >> mat[i / n][i % n];
  320. }
  321. cout << "分别用两种方法计算行列式的值."<<endl;
  322. d = det(mat, n);
  323. cout << "1.行列式的值为:" << d << endl;
  324. cout << "2.行列式的值为:" << det1(mat, n) << endl;
  325. allocateMemory2D(&adjointMat, n, n);
  326. cout<<"伴随矩阵为:"<<endl;
  327. if (!adjointMatrix(mat, adjointMat, n)) cout<<"伴随矩阵求解失败!"<<endl;
  328. else
  329. {
  330. for (i = 0; i < n; i++)
  331. {
  332. for (j = 0; j < n; j++)
  333. {
  334. cout<<adjointMat[i][j]<<" ";
  335. }
  336. cout<<endl;
  337. }
  338. }
  339. ret = inverseMatrix(d, adjointMat, adjointMat, n);
  340. if (ret == -2)
  341. {
  342. isReversible = false;
  343. cout << "参数错误" << endl;
  344. }
  345. else if (ret == -1)
  346. {
  347. isReversible = false;
  348. cout << "矩阵不可逆" << endl;
  349. }
  350. else
  351. {
  352. isReversible = true;
  353. cout << "逆矩阵:" << endl;
  354. for (i = 0; i < n; i++)
  355. {
  356. for (j = 0; j < n; j++)
  357. {
  358. cout<<adjointMat[i][j]<<" ";
  359. }
  360. cout<<endl;
  361. }
  362. }
  363. if (isReversible)
  364. {
  365. cout << "计算一个矩阵与其对应的逆矩阵的乘积:" << endl;
  366. allocateMemory2D(&tmpMat, n, n);
  367. ret = matrixMultiply(mat, adjointMat, tmpMat, n);
  368. for (i = 0; i < n; i++)
  369. {
  370. for (j = 0; j < n; j++)
  371. {
  372. cout << tmpMat[i][j] << " ";
  373. }
  374. cout << endl;
  375. }
  376. }
  377. //将mat矩阵置为单位矩阵
  378. for (i = 0; i < n; i++)
  379. {
  380. for (j = 0; j < n; j++)
  381. {
  382. if (i == j)
  383. {
  384. mat[i][j] = 1;
  385. }
  386. else mat[i][j] = 0;
  387. }
  388. }
  389. if (isReversible)
  390. {
  391. cout << "原矩阵 * 逆矩阵 和 原矩阵同规模的单位矩阵作对比,看误差多大." << endl;
  392. compareMatrix(mat, tmpMat, n, &absouluteError, &relativeError);
  393. cout << "绝对误差:" << absouluteError << endl;
  394. cout << "相对误差:" << relativeError << endl;
  395. }
  396. freeMemory2D(&mat, n);
  397. freeMemory2D(&adjointMat, n);
  398. freeMemory2D(&tmpMat, n);
  399. cout << "输入行列式的阶数:";
  400. }
  401. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/245614
推荐阅读
相关标签
  

闽ICP备14008679号