mirror of
https://github.com/paboyle/Grid.git
synced 2024-11-10 07:55:35 +00:00
Hadrons: graph topological sort
This commit is contained in:
parent
339e983172
commit
6f090e22c0
@ -57,29 +57,32 @@ void Application::run(void)
|
||||
{
|
||||
Graph<string> g;
|
||||
|
||||
cout << g << endl;
|
||||
g.addEdge("A", "B");
|
||||
g.addEdge("B", "D");
|
||||
g.addEdge("D", "E");
|
||||
g.addEdge("E", "C");
|
||||
g.addEdge("C", "A");
|
||||
g.addEdge("Z", "Y");
|
||||
g.addEdge("Z", "W");
|
||||
g.addEdge("Z", "R");
|
||||
g.addEdge("W", "R");
|
||||
auto v = g.getAdjacentVertices("B");
|
||||
for (auto &s: v)
|
||||
g.addEdge("U", "I");
|
||||
|
||||
cout << g << endl;
|
||||
auto vec = g.getConnectedComponents();
|
||||
for (auto &h: vec)
|
||||
{
|
||||
cout << s << " ";
|
||||
cout << h << endl;
|
||||
}
|
||||
for (auto &h: vec)
|
||||
{
|
||||
auto top = h.topoSort();
|
||||
while (!top.empty())
|
||||
{
|
||||
cout << top.top() << " ";
|
||||
top.pop();
|
||||
}
|
||||
cout << endl;
|
||||
cout << g << endl;
|
||||
g.depthFirstSearch();
|
||||
g.removedMarked();
|
||||
cout << g << endl;
|
||||
g.depthFirstSearch();
|
||||
g.removedMarked();
|
||||
cout << g << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// parse parameter file ////////////////////////////////////////////////////////
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <Grid.h>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
|
||||
#define BEGIN_HADRONS_NAMESPACE \
|
||||
namespace Hadrons {\
|
||||
|
@ -54,11 +54,16 @@ public:
|
||||
void removeVertex(const T &value);
|
||||
void removeEdge(const Edge &e);
|
||||
void removeEdge(const T &start, const T &end);
|
||||
unsigned int size(void) const;
|
||||
// tests
|
||||
bool gotValue(const T &value) const;
|
||||
// graph topological manipulations
|
||||
std::vector<T> getAdjacentVertices(const T &value) const;
|
||||
std::vector<T> getChildren(const T &value) const;
|
||||
std::vector<T> getParents(const T &value) const;
|
||||
std::vector<T> getRoots(void) const;
|
||||
std::vector<Graph<T>> getConnectedComponents(void) const;
|
||||
std::stack<T> topoSort(void);
|
||||
// I/O
|
||||
friend std::ostream & operator<<(std::ostream &out, const Graph<T> &g)
|
||||
{
|
||||
@ -75,14 +80,18 @@ public:
|
||||
|
||||
return out;
|
||||
}
|
||||
public:
|
||||
private:
|
||||
// vertex marking
|
||||
void mark(const T &value, const bool doMark = true);
|
||||
void markAll(const bool doMark = true);
|
||||
void unmark(const T &value);
|
||||
void unmarkAll(void);
|
||||
bool isMarked(const T &value) const;
|
||||
const T * getFirstMarked(const bool isMarked = true) const;
|
||||
const T * getFirstUnmarked(void) const;
|
||||
// prune marked/unmarked vertices
|
||||
void removedMarked(const bool isMarked = true);
|
||||
void removedUnmarked(void);
|
||||
void removeMarked(const bool isMarked = true);
|
||||
void removeUnmarked(void);
|
||||
// depth-first search marking
|
||||
void depthFirstSearch(void);
|
||||
void depthFirstSearch(const T &root);
|
||||
@ -165,6 +174,12 @@ void Graph<T>::removeEdge(const T &start, const T &end)
|
||||
removeEdge(Edge(start, end));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
unsigned int Graph<T>::size(void) const
|
||||
{
|
||||
return isMarked_.size();
|
||||
}
|
||||
|
||||
// tests ///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
bool Graph<T>::gotValue(const T &value) const
|
||||
@ -195,12 +210,27 @@ void Graph<T>::mark(const T &value, const bool doMark)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Graph<T>::markAll(const bool doMark)
|
||||
{
|
||||
for (auto &v: isMarked_)
|
||||
{
|
||||
mark(v.first, doMark);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Graph<T>::unmark(const T &value)
|
||||
{
|
||||
mark(value, false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Graph<T>::unmarkAll(void)
|
||||
{
|
||||
markAll(false);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Graph<T>::isMarked(const T &value) const
|
||||
{
|
||||
@ -216,9 +246,34 @@ bool Graph<T>::isMarked(const T &value) const
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T * Graph<T>::getFirstMarked(const bool isMarked) const
|
||||
{
|
||||
auto pred = [&isMarked](const std::pair<T, bool> &v)
|
||||
{
|
||||
return (v.second == isMarked);
|
||||
};
|
||||
auto vIt = std::find_if(isMarked_.begin(), isMarked_.end(), pred);
|
||||
|
||||
if (vIt != isMarked_.end())
|
||||
{
|
||||
return &(vIt->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T * Graph<T>::getFirstUnmarked(void) const
|
||||
{
|
||||
return getFirstMarked(false);
|
||||
}
|
||||
|
||||
// prune marked/unmarked vertices //////////////////////////////////////////////
|
||||
template <typename T>
|
||||
void Graph<T>::removedMarked(const bool isMarked)
|
||||
void Graph<T>::removeMarked(const bool isMarked)
|
||||
{
|
||||
auto isMarkedCopy = isMarked_;
|
||||
|
||||
@ -232,9 +287,9 @@ void Graph<T>::removedMarked(const bool isMarked)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Graph<T>::removedUnmarked(void)
|
||||
void Graph<T>::removeUnmarked(void)
|
||||
{
|
||||
removedMarked(false);
|
||||
removeMarked(false);
|
||||
}
|
||||
|
||||
// depth-first search marking //////////////////////////////////////////////////
|
||||
@ -288,10 +343,128 @@ std::vector<T> Graph<T>::getAdjacentVertices(const T &value) const
|
||||
return adjacentVertex;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> Graph<T>::getChildren(const T &value) const
|
||||
{
|
||||
std::vector<T> child;
|
||||
|
||||
auto pred = [&value](const Edge &e)
|
||||
{
|
||||
return (e.first == value);
|
||||
};
|
||||
auto eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
|
||||
|
||||
while (eIt != edgeSet_.end())
|
||||
{
|
||||
child.push_back((*eIt).second);
|
||||
eIt = find_if(++eIt, edgeSet_.end(), pred);
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> Graph<T>::getParents(const T &value) const
|
||||
{
|
||||
std::vector<T> parent;
|
||||
|
||||
auto pred = [&value](const Edge &e)
|
||||
{
|
||||
return (e.second == value);
|
||||
};
|
||||
auto eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
|
||||
|
||||
while (eIt != edgeSet_.end())
|
||||
{
|
||||
parent.push_back((*eIt).first);
|
||||
eIt = find_if(++eIt, edgeSet_.end(), pred);
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> Graph<T>::getRoots(void) const
|
||||
{
|
||||
std::vector<T> root;
|
||||
|
||||
for (auto &v: isMarked_)
|
||||
{
|
||||
auto parent = getParents(v.first);
|
||||
|
||||
if (parent.size() == 0)
|
||||
{
|
||||
root.push_back(v.first);
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<Graph<T>> Graph<T>::getConnectedComponents(void) const
|
||||
{
|
||||
std::vector<Graph<T>> res;
|
||||
Graph<T> copy(*this);
|
||||
|
||||
while (copy.size() > 0)
|
||||
{
|
||||
copy.depthFirstSearch();
|
||||
res.push_back(copy);
|
||||
res.back().removeUnmarked();
|
||||
res.back().unmarkAll();
|
||||
copy.removeMarked();
|
||||
copy.unmarkAll();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// topological sort using Kahn's algorithm
|
||||
template <typename T>
|
||||
std::stack<T> Graph<T>::topoSort(void)
|
||||
{
|
||||
std::stack<T> res;
|
||||
const T *vPt;
|
||||
std::map<T, bool> tmpMarked(isMarked_);
|
||||
|
||||
// visit function
|
||||
std::function<void(const T &)> visit = [&](const T &v)
|
||||
{
|
||||
if (tmpMarked.at(v))
|
||||
{
|
||||
HADRON_ERROR("cannot topologically sort a cyclic graph");
|
||||
}
|
||||
if (!this->isMarked(v))
|
||||
{
|
||||
std::vector<T> child = this->getChildren(v);
|
||||
|
||||
tmpMarked[v] = true;
|
||||
for (auto &c: child)
|
||||
{
|
||||
visit(c);
|
||||
}
|
||||
this->mark(v);
|
||||
tmpMarked[v] = false;
|
||||
res.push(v);
|
||||
}
|
||||
};
|
||||
|
||||
// reset temporary marks
|
||||
for (auto &v: tmpMarked)
|
||||
{
|
||||
tmpMarked.at(v.first) = false;
|
||||
}
|
||||
// loop on unmarked vertices
|
||||
vPt = getFirstUnmarked();
|
||||
while (vPt)
|
||||
{
|
||||
visit(*vPt);
|
||||
vPt = getFirstUnmarked();
|
||||
}
|
||||
unmarkAll();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
END_HADRONS_NAMESPACE
|
||||
|
Loading…
Reference in New Issue
Block a user