/** * Controller helper routine. * * Wait for the next running slave to finish a task. Note that if no * slaves are currently processing tasks, this routine will block forever! */ int ctrlWaitForSlave() { long result; MPI_Status status; MPI_Recv(&result, 1, MPI_LONG, MPI_ANY_SOURCE, TAG_RESULT, MPI_COMM_WORLD, &status); nRunningSlaves--; int slave = status.MPI_SOURCE; ctrlLogStamp() << "Task completed by slave " << slave << "." << std::endl; char triLabel[MAX_TRI_LABEL_LEN + 1]; if (result == RESULT_OK || result == RESULT_HAS_NEW) { if (result == RESULT_HAS_NEW) { // The original packet label comes through first so we can // write it to the log. It will come through again shortly // as part of the set of equivalent triangulations. MPI_Recv(triLabel, MAX_TRI_LABEL_LEN + 1, MPI_CHAR, slave, TAG_RESULT_DATA, MPI_COMM_WORLD, &status); ctrlLogStamp() << "WARNING: Has unseen equivalent: " << triLabel << std::endl; nHasNew++; } equivs.clear(); NPacket* p; NTriangulation* tri; while (1) { MPI_Recv(triLabel, MAX_TRI_LABEL_LEN + 1, MPI_CHAR, slave, TAG_RESULT_DATA, MPI_COMM_WORLD, &status); if (*triLabel == 0) break; p = tree->findPacketLabel(triLabel); if (! p) { ctrlLogStamp() << "ERROR: Returned equivalent [" << triLabel << "] not found." << std::endl; hasError = true; } else { tri = dynamic_cast<NTriangulation*>(p); if (! tri) { ctrlLogStamp() << "ERROR: Returned equivalent [" << triLabel << "] is not a triangulation!" << std::endl; hasError = true; } else equivs.insert(tri); } } ctrlLogStamp() << "Resulting set contains " << equivs.size() << " equivalent(s)." << std::endl; // In equivs we now have a list of all triangulations // equivalent to orig. // Is this an equivalence class we're already seen? TriSet::iterator tit; ClassMap::iterator cit, cit2; for (tit = equivs.begin(); tit != equivs.end(); tit++) { cit = eClass.find(*tit); if (cit != eClass.end()) break; } if (tit != equivs.end()) { // We found an equivalence class. Insert everything we // haven't seen yet, and merge the classes of everything // we have. int c, cOld; c = cit->second; for (tit = equivs.begin(); tit != equivs.end(); tit++) { cit = eClass.find(*tit); if (cit == eClass.end()) eClass.insert(std::make_pair(*tit, c)); else if (cit->second != c) { // Merge the two equivalence classes. cOld = cit->second; for (cit = eClass.begin(); cit != eClass.end(); cit++) if (cit->second == cOld) cit->second = c; nClasses--; } } } else { // No such equivalence class. Insert everything. int c = nextClass++; for (tit = equivs.begin(); tit != equivs.end(); tit++) eClass.insert(std::make_pair(*tit, c)); nClasses++; } } else if (result == RESULT_NON_MINIMAL) { MPI_Recv(triLabel, MAX_TRI_LABEL_LEN + 1, MPI_CHAR, slave, TAG_RESULT_DATA, MPI_COMM_WORLD, &status); ctrlLogStamp() << "Non-minimal triangulation: " << triLabel << std::endl; nNonMin++; } else if (result == RESULT_ERR) { char errMsg[MAX_ERR_MSG_LEN + 1]; MPI_Recv(errMsg, MAX_ERR_MSG_LEN + 1, MPI_CHAR, slave, TAG_RESULT_DATA, MPI_COMM_WORLD, &status); ctrlLogStamp() << "ERROR: " << errMsg << std::endl; hasError = true; } else { ctrlLogStamp() << "ERROR: Unknown result code " << result << " received from slave." << std::endl; hasError = true; } return slave; }
void processTree() { TriSet::iterator tit; ClassMap::iterator cit, cit2; int c, cOld; NTriangulation* t; for (NPacket* p = tree; p; p = p->nextTreePacket()) if (p->type() == PACKET_TRIANGULATION) { // A triangulation to process. t = static_cast<NTriangulation*>(p); fprintf(stderr, "Processing %s ...\n", t->label().c_str()); nTris++; nonMin = false; orig = static_cast<NTriangulation*>(p); equivs.clear(); equivs.insert(orig); tryMovesUp(orig, argUp); if (nonMin) { allNonMin.push_back(orig); nNonMin++; continue; } // In equivs we now have a list of all triangulations // equivalent to orig. // Is this an equivalence class we're already seen? for (tit = equivs.begin(); tit != equivs.end(); tit++) { cit = eClass.find(*tit); if (cit != eClass.end()) break; } if (tit != equivs.end()) { // We found an equivalence class. Insert everything we // haven't seen yet, and merge the classes of everything // we have. c = cit->second; for (tit = equivs.begin(); tit != equivs.end(); tit++) { cit = eClass.find(*tit); if (cit == eClass.end()) eClass.insert(std::make_pair(*tit, c)); else if (cit->second != c) { // Merge the two equivalence classes. cOld = cit->second; for (cit = eClass.begin(); cit != eClass.end(); cit++) if (cit->second == cOld) cit->second = c; nClasses--; } } } else { // No such equivalence class. Insert everything. c = nextClass++; for (tit = equivs.begin(); tit != equivs.end(); tit++) eClass.insert(std::make_pair(*tit, c)); nClasses++; } } // Finished progress reporting. fprintf(stderr, "\n"); // Write the summary of results. if (! allNonMin.empty()) { printf("NON-MINIMAL TRIANGULATIONS:\n\n"); for (std::list<NTriangulation*>::const_iterator it = allNonMin.begin(); it != allNonMin.end(); it++) printf(" %s\n", (*it)->label().c_str()); printf("\n"); } if (nClasses) { printf("EQUIVALENCE CLASSES:\n\n"); if (outFile) { newTree = new NContainer(); newTree->setLabel("Equivalence Classes"); } int classNum = 1; std::string className; NContainer* classCnt = 0; for (cit = eClass.begin(); cit != eClass.end(); cit++) if (cit->second >= 0) { // The first triangulation of a new equivalence class. c = cit->second; std::ostringstream s; s << "Class " << classNum << " : " << cit->first->homology().str(); className = s.str(); classNum++; printf("%s\n\n", className.c_str()); if (outFile) { classCnt = new NContainer(); classCnt->setLabel(className); newTree->insertChildLast(classCnt); } // Find the triangulations in this class, and erase the // class as we go. for (cit2 = cit; cit2 != eClass.end(); cit2++) if (cit2->second == c) { printf(" %s\n", cit2->first->label().c_str()); if (outFile) { t = new NTriangulation(*(cit2->first)); t->setLabel(cit2->first->label()); classCnt->insertChildLast(t); } cit2->second = -1; } printf("\n"); } } printf("Final statistics:\n"); printf(" Triangulations read: %ld\n", nTris); printf(" Equivalence classes: %ld\n", nClasses); printf(" New triangulations: %ld\n", nNew); printf(" Non-minimal triangulations: %ld\n", nNonMin); }