Für Vorlesungen, bitte die Webseite verwenden. https://flavigny.de/lecture
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

153 行
4.2KB

  1. #include <iostream> // notwendig zur Ausgabe
  2. #include <vector>
  3. #include "hdnum.hh" // hdnum header
  4. namespace hdnum {
  5. template<typename REAL>
  6. class SparseMatrix {
  7. struct MatrixEntry {
  8. int i;
  9. int j;
  10. REAL value;
  11. };
  12. public:
  13. void AddEntry (int i, int j, REAL value) {
  14. if (i < 0 || j < 0)
  15. HDNUM_ERROR("Zeilen und Spalten dürfen nicht negativ sein!");
  16. // create new matrix entry
  17. MatrixEntry entry;
  18. entry.i = i;
  19. entry.j = j;
  20. entry.value = value;
  21. // add entry to entries vector
  22. entries.insert(entries.begin(), entry);
  23. }
  24. template<typename V>
  25. void mv (Vector<V>& y, const Vector<V>& x) {
  26. // iterate through all entries
  27. for(typename std::vector<MatrixEntry>::iterator it = entries.begin(); it != entries.end(); ++it) {
  28. if ((*it).i > y.size() || (*it).j > x.size())
  29. HDNUM_ERROR("Vektor(en) hat/haben falsche Dimension!");
  30. // modify corresponding vector entry
  31. y[(*it).i] += x[(*it).j] * (*it).value;
  32. }
  33. }
  34. private:
  35. // vector storing non-zero elements
  36. std::vector<MatrixEntry> entries;
  37. };
  38. }
  39. // zum Test, fluss matrizen aus rohrleitungsnetzwerk
  40. hdnum::SparseMatrix<double> flussMatrixSparse(int N) {
  41. hdnum::SparseMatrix<double> A;
  42. // berechnung der kantenlaenge
  43. int n = floor(sqrt(N+1));
  44. for(int i = 0; i < N; i++) {
  45. int edges = 0;
  46. if ((i+1)%n != 0) { // nicht linker rand
  47. edges++;
  48. if (i-1 >= 0) A.AddEntry(i, i-1, -1);
  49. }
  50. if ((i+2)%n != 0) { // nicht rechter rand
  51. edges++;
  52. A.AddEntry(i, i+1, -1);
  53. }
  54. if (i+n < N) { // nicht unterer rand
  55. edges++;
  56. A.AddEntry(i, i+n, -1);
  57. }
  58. if (i-n >= -1) { // nicht oberer rand
  59. edges++;
  60. if (i-n >= 0) A.AddEntry(i, i-n, -1);
  61. }
  62. A.AddEntry(i, i, edges);
  63. }
  64. return A;
  65. }
  66. // Funktion zum Aufstellen der Matrix (aus rohrleitungsnetzwerk)
  67. hdnum::DenseMatrix<double> flussMatrix(int N) {
  68. hdnum::DenseMatrix<double> A(N,N);
  69. // berechnung der kantenlaenge
  70. int n = floor(sqrt(N+1));
  71. for(int i = 0; i < N; i++) {
  72. int edges = 0;
  73. if ((i+1)%n != 0) { // nicht linker rand
  74. edges++;
  75. if (i-1 >= 0) A(i, i-1) = -1; // falls nicht der referenzknoten
  76. }
  77. if ((i+2)%n != 0) { // nicht rechter rand
  78. edges++;
  79. A(i, i+1) = -1;
  80. }
  81. if (i+n < N) { // nicht unterer rand
  82. edges++;
  83. A(i, i+n) = -1;
  84. }
  85. if (i-n >= -1) { // nicht oberer rand
  86. edges++;
  87. if (i-n >= 0) A(i, i-n) = -1; // falls nicht der referenzknoten
  88. }
  89. A(i, i) = edges;
  90. }
  91. return A;
  92. }
  93. // funktion zum testen
  94. void testMatrixVectorProduct(int N) {
  95. hdnum::SparseMatrix<double> A = flussMatrixSparse(N);
  96. hdnum::DenseMatrix<double> B = flussMatrix(N);
  97. // test vektor
  98. hdnum::Vector<double> x(N);
  99. for(int i=0; i<N; i++) {
  100. x[i] = i+1;
  101. }
  102. hdnum::Vector<double> y1(N);
  103. hdnum::Vector<double> y2(N);
  104. // Pretty-printing fuer Vektoren
  105. x.scientific(false);
  106. x.width(15);
  107. // test ob Ax = Bx
  108. A.mv(y1, x);
  109. B.mv(y2, x);
  110. std::cout << "Mit Sparse Matrix: " << y1 << std::endl;
  111. std::cout << "Mit Dense Matrix: " << y2;
  112. }
  113. int main () {
  114. // testMatrixVectorProduct(15);
  115. // messe zeiten fuer n=4,...,14 und N = 2^n
  116. for(int n=4; n<=14; n++) {
  117. int N = pow(2, n);
  118. // test vektor
  119. hdnum::Vector<double> x(N);
  120. for(int i=0; i<N; i++) {
  121. x[i] = i+1;
  122. }
  123. hdnum::Vector<double> y(N);
  124. hdnum::SparseMatrix<double> A = flussMatrixSparse(N);
  125. hdnum::DenseMatrix<double> B = flussMatrix(N);
  126. // timer hier fuer die SparseMatrix implementierung
  127. hdnum::Timer myTimer;
  128. A.mv(y, x);
  129. std::cout << N << " " << myTimer.elapsed() << std::endl;
  130. }
  131. }