minimum_degree_ordering.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. //-*-c++-*-
  2. //=======================================================================
  3. // Copyright 1997-2001 University of Notre Dame.
  4. // Authors: Lie-Quan Lee
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //=======================================================================
  10. /*
  11. This file is to demo how to use minimum_degree_ordering algorithm.
  12. Important Note: This implementation requires the BGL graph to be
  13. directed. Therefore, nonzero entry (i, j) in a symmetrical matrix
  14. A coresponds to two directed edges (i->j and j->i).
  15. The bcsstk01.rsa is an example graph in Harwell-Boeing format,
  16. and bcsstk01 is the ordering produced by Liu's MMD implementation.
  17. Link this file with iohb.c to get the harwell-boeing I/O functions.
  18. To run this example, type:
  19. ./minimum_degree_ordering bcsstk01.rsa bcsstk01
  20. */
  21. #include <boost/config.hpp>
  22. #include <fstream>
  23. #include <iostream>
  24. #include "boost/graph/adjacency_list.hpp"
  25. #include "boost/graph/graph_utility.hpp"
  26. #include "boost/graph/minimum_degree_ordering.hpp"
  27. void terminate(const char* msg)
  28. {
  29. std::cerr << msg << std::endl;
  30. abort();
  31. }
  32. //copy and modify from mtl harwell boeing stream
  33. struct harwell_boeing
  34. {
  35. harwell_boeing(char* filename) {
  36. int Nrhs;
  37. char* Type;
  38. Type = new char[4];
  39. isComplex = false;
  40. // Never called:
  41. //readHB_info(filename, &M, &N, &nonzeros, &Type, &Nrhs);
  42. colptr = (int *)malloc((N+1)*sizeof(int));
  43. if ( colptr == NULL ) terminate("Insufficient memory for colptr.\n");
  44. rowind = (int *)malloc(nonzeros*sizeof(int));
  45. if ( rowind == NULL ) terminate("Insufficient memory for rowind.\n");
  46. if ( Type[0] == 'C' ) {
  47. isComplex = true;
  48. val = (double *)malloc(nonzeros*sizeof(double)*2);
  49. if ( val == NULL ) terminate("Insufficient memory for val.\n");
  50. } else {
  51. if ( Type[0] != 'P' ) {
  52. val = (double *)malloc(nonzeros*sizeof(double));
  53. if ( val == NULL ) terminate("Insufficient memory for val.\n");
  54. }
  55. }
  56. // Never called:
  57. //readHB_mat_double(filename, colptr, rowind, val);
  58. cnt = 0;
  59. col = 0;
  60. delete [] Type;
  61. }
  62. ~harwell_boeing() {
  63. free(colptr);
  64. free(rowind);
  65. free(val);
  66. }
  67. inline int nrows() const { return M; }
  68. int cnt;
  69. int col;
  70. int* colptr;
  71. bool isComplex;
  72. int M;
  73. int N;
  74. int nonzeros;
  75. int* rowind;
  76. double* val;
  77. };
  78. int main(int argc, char* argv[])
  79. {
  80. using namespace std;
  81. using namespace boost;
  82. if (argc < 2) {
  83. cout << argv[0] << " HB file" << endl;
  84. return -1;
  85. }
  86. int delta = 0;
  87. if ( argc >= 4 )
  88. delta = atoi(argv[3]);
  89. harwell_boeing hbs(argv[1]);
  90. //must be BGL directed graph now
  91. typedef adjacency_list<vecS, vecS, directedS> Graph;
  92. int n = hbs.nrows();
  93. cout << "n is " << n << endl;
  94. Graph G(n);
  95. int num_edge = 0;
  96. for (int i = 0; i < n; ++i)
  97. for (int j = hbs.colptr[i]; j < hbs.colptr[i+1]; ++j)
  98. if ( (hbs.rowind[j - 1] - 1 ) > i ) {
  99. add_edge(hbs.rowind[j - 1] - 1, i, G);
  100. add_edge(i, hbs.rowind[j - 1] - 1, G);
  101. num_edge++;
  102. }
  103. cout << "number of off-diagnal elements: " << num_edge << endl;
  104. typedef std::vector<int> Vector;
  105. Vector inverse_perm(n, 0);
  106. Vector perm(n, 0);
  107. Vector supernode_sizes(n, 1); // init has to be 1
  108. boost::property_map<Graph, vertex_index_t>::type
  109. id = get(vertex_index, G);
  110. Vector degree(n, 0);
  111. minimum_degree_ordering
  112. (G,
  113. make_iterator_property_map(&degree[0], id, degree[0]),
  114. &inverse_perm[0],
  115. &perm[0],
  116. make_iterator_property_map(&supernode_sizes[0], id, supernode_sizes[0]),
  117. delta, id);
  118. if ( argc >= 3 ) {
  119. ifstream input(argv[2]);
  120. if ( input.fail() ) {
  121. cout << argv[3] << " is failed to open!. " << endl;
  122. return -1;
  123. }
  124. int comp;
  125. bool is_correct = true;
  126. int i;
  127. for ( i=0; i<n; i++ ) {
  128. input >> comp;
  129. if ( comp != inverse_perm[i]+1 ) {
  130. cout << "at i= " << i << ": " << comp
  131. << " ***is NOT EQUAL to*** " << inverse_perm[i]+1 << endl;
  132. is_correct = false;
  133. }
  134. }
  135. for ( i=0; i<n; i++ ) {
  136. input >> comp;
  137. if ( comp != perm[i]+1 ) {
  138. cout << "at i= " << i << ": " << comp
  139. << " ***is NOT EQUAL to*** " << perm[i]+1 << endl;
  140. is_correct = false;
  141. }
  142. }
  143. if ( is_correct )
  144. cout << "Permutation and inverse permutation are correct. "<< endl;
  145. else
  146. cout << "WARNING -- Permutation or inverse permutation is not the "
  147. << "same ones generated by Liu's " << endl;
  148. }
  149. return 0;
  150. }