int order(const RCP<OrderingSolution<lno_t, gno_t> > &solution) { int ierr= 0; HELLO; lno_t *perm; perm = (lno_t *) (solution->getPermutation()); if (perm==0){ // Throw exception std::cerr << "perm is NULL" << std::endl; ierr = -1; } // Get local graph. const size_t nVtx = model->getLocalNumVertices(); ArrayView<const gno_t> edgeIds; ArrayView<const lno_t> offsets; ArrayView<StridedData<lno_t, scalar_t> > wgts; model->getEdgeList(edgeIds, offsets, wgts); // Store degrees together with index so we can sort. Teuchos::Array<std::pair<lno_t, size_t> > degrees(nVtx); for (lno_t i=0; i<(lno_t)nVtx; i++){ degrees[i].first = i; degrees[i].second = offsets[i+1] - offsets[i]; } // Sort degrees. SortPairs<lno_t,size_t> zort; bool inc = true; // TODO: Add user parameter zort.sort(degrees, inc); // Copy permuted indices to perm. for (lno_t i=0; i<(lno_t)nVtx; i++){ perm[i] = degrees[i].first; } solution->setHavePerm(true); return ierr; }
int order( const RCP<GraphModel<Adapter> > &model, const RCP<OrderingSolution<typename Adapter::gid_t, typename Adapter::lno_t> > &solution, const RCP<Teuchos::ParameterList> &pl, const RCP<Teuchos::Comm<int> > &comm ) { int ierr= 0; HELLO; // Check size of communicator: serial only. // TODO: Remove this test when RCM works on local graph. if (comm->getSize() > 1){ throw std::runtime_error("RCM currently only works in serial."); } // Get local graph. ArrayView<const gno_t> edgeIds; ArrayView<const lno_t> offsets; ArrayView<StridedData<lno_t, scalar_t> > wgts; // TODO: edgeIds should be of type lno_t for getLocalEdgeList. Needs revisit. //model->getLocalEdgeList(edgeIds, offsets, wgts); // BUGGY! // Use global graph for now. This only works in serial! ArrayView<const int> procIds; size_t numEdges = model->getEdgeList( edgeIds, procIds, offsets, wgts); //cout << "Debug: Local graph from getLocalEdgeList" << endl; //cout << "edgeIds: " << edgeIds << endl; //cout << "offsets: " << offsets << endl; const size_t nVtx = model->getLocalNumVertices(); // RCM constructs invPerm, not perm ArrayRCP<lno_t> invPerm = solution->getPermutationRCP(true); // Check if there are actually edges to reorder. // If there are not, then just use the natural ordering. if (numEdges == 0) { for (size_t i = 0; i < nVtx; ++i) { invPerm[i] = i; } return 0; } // Set the label of each vertex to invalid. Tpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid(); for (size_t i = 0; i < nVtx; ++i) { invPerm[i] = INVALID; } // Loop over all connected components. // Do BFS within each component. lno_t root; std::queue<lno_t> Q; size_t count = 0; // CM label, reversed later size_t next = 0; // next unmarked vertex Teuchos::Array<std::pair<lno_t, size_t> > children; // children and their degrees while (count < nVtx) { // Find suitable root vertex for this component. // First find an unmarked vertex, use to find root in next component. while ((next < nVtx) && (static_cast<Tpetra::global_size_t>(invPerm[next]) != INVALID)) next++; // Select root method. Pseudoperipheral usually gives the best // ordering, but the user may choose a faster method. std::string root_method = pl->get("root_method", "pseudoperipheral"); if (root_method == string("first")) root = next; else if (root_method == string("smallest_degree")) root = findSmallestDegree(next, nVtx, edgeIds, offsets); else if (root_method == string("pseudoperipheral")) root = findPseudoPeripheral(next, nVtx, edgeIds, offsets); else { // This should never happen if pl was validated. } // Label connected component starting at root Q.push(root); //cout << "Debug: invPerm[" << root << "] = " << count << endl; invPerm[root] = count++; while (Q.size()){ // Get a vertex from the queue lno_t v = Q.front(); Q.pop(); //cout << "Debug: v= " << v << ", offsets[v] = " << offsets[v] << endl; // Add unmarked children to list of pairs, to be added to queue. children.resize(0); for (lno_t ptr = offsets[v]; ptr < offsets[v+1]; ++ptr){ lno_t child = edgeIds[ptr]; if (static_cast<Tpetra::global_size_t>(invPerm[child]) == INVALID){ // Not visited yet; add child to list of pairs. std::pair<lno_t,size_t> newchild; newchild.first = child; newchild.second = offsets[child+1] - offsets[child]; children.push_back(newchild); } } // Sort children by increasing degree // TODO: If edge weights, sort children by decreasing weight, SortPairs<lno_t,size_t> zort; zort.sort(children); typename Teuchos::Array<std::pair<lno_t,size_t> >::iterator it = children.begin (); for ( ; it != children.end(); ++it){ // Push children on the queue in sorted order. lno_t child = it->first; invPerm[child] = count++; // Label as we push on Q Q.push(child); //cout << "Debug: invPerm[" << child << "] = " << count << endl; } } } // Reverse labels for RCM bool reverse = true; // TODO: Make parameter if (reverse) { lno_t temp; for (size_t i=0; i < nVtx/2; ++i) { // Swap (invPerm[i], invPerm[nVtx-i]) temp = invPerm[i]; invPerm[i] = invPerm[nVtx-1-i]; invPerm[nVtx-1-i] = temp; } } solution->setHaveInverse(true); return ierr; }