#ifndef POSET_H #define POSET_H #include #include #include #include #include #include "util.h" template class Poset { public: Poset(); ~Poset(); void addRelationship(T first, T second); void addVertex(T vertex); bool zeroDependencies(T vertex); std::set getDependsOn(T dependency); std::vector getTopoSort(); static void test(); private: //backing data structures std::map> adjMatrix; std::set verticies; }; template Poset::Poset() { //Nothing needed } template Poset::~Poset() { //Ditto } template void Poset::addRelationship(T first, T second) { verticies.insert(first); verticies.insert(second); adjMatrix[first][second] = true; } template void Poset::addVertex(T vertex) { verticies.insert(vertex); } template bool Poset::zeroDependencies(T vertex) { auto depMapItr = adjMatrix.find(vertex); if (depMapItr == adjMatrix.end()) return true; for (auto i : depMapItr->second) if (i.second == true) return false; return true; } template std::set Poset::getDependsOn(T dependency) { std::set vertsThatDependOn; for (auto i : adjMatrix) { auto depItr = i.second.find(dependency); if (depItr != i.second.end() && depItr->second) vertsThatDependOn.insert(i.first); } return vertsThatDependOn; } template std::vector Poset::getTopoSort() { std::vector sorted; std::queue toDo; for (auto i : verticies) if (zeroDependencies(i)) toDo.push(i); while(!toDo.empty()) { T current = toDo.front(); toDo.pop(); sorted.push_back(current); for (T depOnCurrent : getDependsOn(current)) { adjMatrix[depOnCurrent][current] = false; //Remove the edge to current, since current's now been taken care of if (zeroDependencies(depOnCurrent)) toDo.push(depOnCurrent); } } return sorted; } //would make it just an int specilization, but then we get multiple definition complaints.... template void Poset::test() { std::string result; { Poset poset; poset.addVertex(1000); for (int i = 0; i < 20; i++) poset.addRelationship(i,i+1); result = ""; for (int i : poset.getTopoSort()) result += intToString(i) + " "; //std::cout << result << std::endl; assert(result == "20 1000 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 "); //Note that sets do not have a set order, so this could change //This is why the 1000 is in an odd, yet valid, position } { Poset poset; for (int i = 0; i < 20; i+=2) poset.addRelationship(i,i+1); result = ""; for (int i : poset.getTopoSort()) result += intToString(i) + " "; //std::cout << result << std::endl; assert(result == "1 3 5 7 9 11 13 15 17 19 0 2 4 6 8 10 12 14 16 18 "); } std::cout << "Poset tests passed" << std::endl; } #endif