//-*-c++-*- //======================================================================= // Copyright 1997-2001 University of Notre Dame. // Authors: Lie-Quan Lee // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= /* This file is to demo how to use minimum_degree_ordering algorithm. Important Note: This implementation requires the BGL graph to be directed. Therefore, nonzero entry (i, j) in a symmetrical matrix A coresponds to two directed edges (i->j and j->i). The bcsstk01.rsa is an example graph in Harwell-Boeing format, and bcsstk01 is the ordering produced by Liu's MMD implementation. Link this file with iohb.c to get the harwell-boeing I/O functions. To run this example, type: ./minimum_degree_ordering bcsstk01.rsa bcsstk01 */ #include #include #include #include "boost/graph/adjacency_list.hpp" #include "boost/graph/graph_utility.hpp" #include "boost/graph/minimum_degree_ordering.hpp" void terminate(const char* msg) { std::cerr << msg << std::endl; abort(); } // copy and modify from mtl harwell boeing stream struct harwell_boeing { harwell_boeing(char* filename) { int Nrhs; char* Type; Type = new char[4]; isComplex = false; // Never called: // readHB_info(filename, &M, &N, &nonzeros, &Type, &Nrhs); colptr = (int*)malloc((N + 1) * sizeof(int)); if (colptr == NULL) terminate("Insufficient memory for colptr.\n"); rowind = (int*)malloc(nonzeros * sizeof(int)); if (rowind == NULL) terminate("Insufficient memory for rowind.\n"); if (Type[0] == 'C') { isComplex = true; val = (double*)malloc(nonzeros * sizeof(double) * 2); if (val == NULL) terminate("Insufficient memory for val.\n"); } else { if (Type[0] != 'P') { val = (double*)malloc(nonzeros * sizeof(double)); if (val == NULL) terminate("Insufficient memory for val.\n"); } } // Never called: // readHB_mat_double(filename, colptr, rowind, val); cnt = 0; col = 0; delete[] Type; } ~harwell_boeing() { free(colptr); free(rowind); free(val); } inline int nrows() const { return M; } int cnt; int col; int* colptr; bool isComplex; int M; int N; int nonzeros; int* rowind; double* val; }; int main(int argc, char* argv[]) { using namespace std; using namespace boost; if (argc < 2) { cout << argv[0] << " HB file" << endl; return -1; } int delta = 0; if (argc >= 4) delta = atoi(argv[3]); harwell_boeing hbs(argv[1]); // must be BGL directed graph now typedef adjacency_list< vecS, vecS, directedS > Graph; int n = hbs.nrows(); cout << "n is " << n << endl; Graph G(n); int num_edge = 0; for (int i = 0; i < n; ++i) for (int j = hbs.colptr[i]; j < hbs.colptr[i + 1]; ++j) if ((hbs.rowind[j - 1] - 1) > i) { add_edge(hbs.rowind[j - 1] - 1, i, G); add_edge(i, hbs.rowind[j - 1] - 1, G); num_edge++; } cout << "number of off-diagnal elements: " << num_edge << endl; typedef std::vector< int > Vector; Vector inverse_perm(n, 0); Vector perm(n, 0); Vector supernode_sizes(n, 1); // init has to be 1 boost::property_map< Graph, vertex_index_t >::type id = get(vertex_index, G); Vector degree(n, 0); minimum_degree_ordering(G, make_iterator_property_map(°ree[0], id, degree[0]), &inverse_perm[0], &perm[0], make_iterator_property_map(&supernode_sizes[0], id, supernode_sizes[0]), delta, id); if (argc >= 3) { ifstream input(argv[2]); if (input.fail()) { cout << argv[3] << " is failed to open!. " << endl; return -1; } int comp; bool is_correct = true; int i; for (i = 0; i < n; i++) { input >> comp; if (comp != inverse_perm[i] + 1) { cout << "at i= " << i << ": " << comp << " ***is NOT EQUAL to*** " << inverse_perm[i] + 1 << endl; is_correct = false; } } for (i = 0; i < n; i++) { input >> comp; if (comp != perm[i] + 1) { cout << "at i= " << i << ": " << comp << " ***is NOT EQUAL to*** " << perm[i] + 1 << endl; is_correct = false; } } if (is_correct) cout << "Permutation and inverse permutation are correct. " << endl; else cout << "WARNING -- Permutation or inverse permutation is not the " << "same ones generated by Liu's " << endl; } return 0; }