2016-02-25 12:07:21 +00:00
|
|
|
|
/*******************************************************************************
|
|
|
|
|
Grid physics library, www.github.com/paboyle/Grid
|
|
|
|
|
|
|
|
|
|
Source file: programs/Hadrons/Graph.hpp
|
|
|
|
|
|
|
|
|
|
Copyright (C) 2015
|
|
|
|
|
|
|
|
|
|
Author: Antonin Portelli <antonin.portelli@me.com>
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
|
|
|
|
|
|
See the full license in the file "LICENSE" in the top level distribution
|
|
|
|
|
directory.
|
|
|
|
|
*******************************************************************************/
|
2015-11-05 14:28:14 +00:00
|
|
|
|
|
|
|
|
|
#ifndef Hadrons_Graph_hpp_
|
|
|
|
|
#define Hadrons_Graph_hpp_
|
|
|
|
|
|
|
|
|
|
#include <Hadrons/Global.hpp>
|
|
|
|
|
|
|
|
|
|
BEGIN_HADRONS_NAMESPACE
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
|
* Oriented graph class *
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
// I/O for edges
|
|
|
|
|
template <typename T>
|
|
|
|
|
std::ostream & operator<<(std::ostream &out, const std::pair<T, T> &e)
|
|
|
|
|
{
|
|
|
|
|
out << "\"" << e.first << "\" -> \"" << e.second << "\"";
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// main class
|
|
|
|
|
template <typename T>
|
|
|
|
|
class Graph
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
typedef std::pair<T, T> Edge;
|
|
|
|
|
public:
|
|
|
|
|
// constructor
|
2016-05-07 21:19:38 +01:00
|
|
|
|
Graph(void);
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// destructor
|
|
|
|
|
virtual ~Graph(void) = default;
|
|
|
|
|
// access
|
2015-12-02 19:33:34 +00:00
|
|
|
|
void addVertex(const T &value);
|
|
|
|
|
void addEdge(const Edge &e);
|
|
|
|
|
void addEdge(const T &start, const T &end);
|
|
|
|
|
void removeVertex(const T &value);
|
|
|
|
|
void removeEdge(const Edge &e);
|
|
|
|
|
void removeEdge(const T &start, const T &end);
|
|
|
|
|
unsigned int size(void) const;
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// tests
|
|
|
|
|
bool gotValue(const T &value) const;
|
|
|
|
|
// graph topological manipulations
|
2015-12-07 15:46:36 +00:00
|
|
|
|
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;
|
2016-05-07 21:19:38 +01:00
|
|
|
|
std::vector<T> topoSort(const bool randomize = false);
|
2015-12-07 15:46:36 +00:00
|
|
|
|
std::vector<std::vector<T>> allTopoSort(void);
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// I/O
|
|
|
|
|
friend std::ostream & operator<<(std::ostream &out, const Graph<T> &g)
|
|
|
|
|
{
|
|
|
|
|
out << "{";
|
|
|
|
|
for (auto &e: g.edgeSet_)
|
|
|
|
|
{
|
|
|
|
|
out << e << ", ";
|
|
|
|
|
}
|
|
|
|
|
if (g.edgeSet_.size() != 0)
|
|
|
|
|
{
|
|
|
|
|
out << "\b\b";
|
|
|
|
|
}
|
|
|
|
|
out << "}";
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
2015-12-02 19:33:34 +00:00
|
|
|
|
private:
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// vertex marking
|
2015-12-02 19:33:34 +00:00
|
|
|
|
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;
|
2016-05-07 21:19:38 +01:00
|
|
|
|
const T * getRandomMarked(const bool isMarked = true);
|
2015-12-02 19:33:34 +00:00
|
|
|
|
const T * getFirstUnmarked(void) const;
|
2016-05-07 21:19:38 +01:00
|
|
|
|
const T * getRandomUnmarked(void);
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// prune marked/unmarked vertices
|
2015-12-02 19:33:34 +00:00
|
|
|
|
void removeMarked(const bool isMarked = true);
|
|
|
|
|
void removeUnmarked(void);
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// depth-first search marking
|
|
|
|
|
void depthFirstSearch(void);
|
|
|
|
|
void depthFirstSearch(const T &root);
|
|
|
|
|
private:
|
2016-05-07 21:19:38 +01:00
|
|
|
|
std::map<T, bool> isMarked_;
|
|
|
|
|
std::set<Edge> edgeSet_;
|
|
|
|
|
std::mt19937 gen_;
|
2015-11-05 14:28:14 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-12-07 18:26:38 +00:00
|
|
|
|
// build depedency matrix from topological sorts
|
|
|
|
|
template <typename T>
|
|
|
|
|
std::map<T, std::map<T, bool>>
|
|
|
|
|
makeDependencyMatrix(const std::vector<std::vector<T>> &topSort);
|
|
|
|
|
|
2015-11-05 14:28:14 +00:00
|
|
|
|
/******************************************************************************
|
|
|
|
|
* template implementation *
|
2016-05-06 14:35:11 +01:00
|
|
|
|
******************************************************************************
|
|
|
|
|
* in all the following V is the number of vertex and E is the number of edge
|
|
|
|
|
* in the worst case E = V^2
|
|
|
|
|
*/
|
|
|
|
|
|
2016-05-07 21:19:38 +01:00
|
|
|
|
// constructor /////////////////////////////////////////////////////////////////
|
|
|
|
|
template <typename T>
|
|
|
|
|
Graph<T>::Graph(void)
|
|
|
|
|
{
|
|
|
|
|
std::random_device rd;
|
|
|
|
|
|
|
|
|
|
gen_.seed(rd());
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// access //////////////////////////////////////////////////////////////////////
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: log(V)
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::addVertex(const T &value)
|
|
|
|
|
{
|
|
|
|
|
isMarked_[value] = false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::addEdge(const Edge &e)
|
|
|
|
|
{
|
|
|
|
|
addVertex(e.first);
|
|
|
|
|
addVertex(e.second);
|
|
|
|
|
edgeSet_.insert(e);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::addEdge(const T &start, const T &end)
|
|
|
|
|
{
|
|
|
|
|
addEdge(Edge(start, end));
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::removeVertex(const T &value)
|
|
|
|
|
{
|
|
|
|
|
// remove vertex from the mark table
|
|
|
|
|
auto vIt = isMarked_.find(value);
|
|
|
|
|
|
|
|
|
|
if (vIt != isMarked_.end())
|
|
|
|
|
{
|
|
|
|
|
isMarked_.erase(vIt);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
HADRON_ERROR("vertex " << value << " does not exists");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove all edges containing the vertex
|
|
|
|
|
auto pred = [&value](const Edge &e)
|
|
|
|
|
{
|
|
|
|
|
return ((e.first == value) or (e.second == value));
|
|
|
|
|
};
|
|
|
|
|
auto eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
|
|
|
|
|
|
|
|
|
|
while (eIt != edgeSet_.end())
|
|
|
|
|
{
|
|
|
|
|
edgeSet_.erase(eIt);
|
|
|
|
|
eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::removeEdge(const Edge &e)
|
|
|
|
|
{
|
|
|
|
|
auto eIt = edgeSet_.find(e);
|
|
|
|
|
|
|
|
|
|
if (eIt != edgeSet_.end())
|
|
|
|
|
{
|
|
|
|
|
edgeSet_.erase(eIt);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
HADRON_ERROR("edge " << e << " does not exists");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::removeEdge(const T &start, const T &end)
|
|
|
|
|
{
|
|
|
|
|
removeEdge(Edge(start, end));
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(1)
|
2015-12-02 19:33:34 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
unsigned int Graph<T>::size(void) const
|
|
|
|
|
{
|
|
|
|
|
return isMarked_.size();
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// tests ///////////////////////////////////////////////////////////////////////
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
bool Graph<T>::gotValue(const T &value) const
|
|
|
|
|
{
|
2016-01-14 04:23:51 +00:00
|
|
|
|
auto it = isMarked_.find(value);
|
|
|
|
|
|
|
|
|
|
if (it == isMarked_.end())
|
2015-11-05 14:28:14 +00:00
|
|
|
|
{
|
2016-01-14 04:23:51 +00:00
|
|
|
|
return false;
|
2015-11-05 14:28:14 +00:00
|
|
|
|
}
|
2016-01-14 04:23:51 +00:00
|
|
|
|
else
|
2015-11-05 14:28:14 +00:00
|
|
|
|
{
|
2016-01-14 04:23:51 +00:00
|
|
|
|
return true;
|
2015-11-05 14:28:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// vertex marking //////////////////////////////////////////////////////////////
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::mark(const T &value, const bool doMark)
|
|
|
|
|
{
|
2016-01-14 04:23:51 +00:00
|
|
|
|
if (gotValue(value))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
{
|
2016-01-14 04:23:51 +00:00
|
|
|
|
isMarked_[value] = doMark;
|
2015-11-05 14:28:14 +00:00
|
|
|
|
}
|
2016-01-14 04:23:51 +00:00
|
|
|
|
else
|
2015-11-05 14:28:14 +00:00
|
|
|
|
{
|
|
|
|
|
HADRON_ERROR("vertex " << value << " does not exists");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::markAll(const bool doMark)
|
|
|
|
|
{
|
|
|
|
|
for (auto &v: isMarked_)
|
|
|
|
|
{
|
|
|
|
|
mark(v.first, doMark);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::unmark(const T &value)
|
|
|
|
|
{
|
|
|
|
|
mark(value, false);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::unmarkAll(void)
|
|
|
|
|
{
|
|
|
|
|
markAll(false);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
bool Graph<T>::isMarked(const T &value) const
|
|
|
|
|
{
|
2016-01-14 04:23:51 +00:00
|
|
|
|
if (gotValue(value))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
{
|
|
|
|
|
return isMarked_.at(value);
|
|
|
|
|
}
|
2016-01-14 04:23:51 +00:00
|
|
|
|
else
|
2015-11-05 14:28:14 +00:00
|
|
|
|
{
|
|
|
|
|
HADRON_ERROR("vertex " << value << " does not exists");
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-07 21:19:38 +01:00
|
|
|
|
// complexity: O(log(V))
|
|
|
|
|
template <typename T>
|
|
|
|
|
const T * Graph<T>::getRandomMarked(const bool isMarked)
|
|
|
|
|
{
|
|
|
|
|
auto pred = [&isMarked](const std::pair<T, bool> &v)
|
|
|
|
|
{
|
|
|
|
|
return (v.second == isMarked);
|
|
|
|
|
};
|
|
|
|
|
std::uniform_int_distribution<unsigned int> dis(0, size() - 1);
|
|
|
|
|
auto rIt = isMarked_.begin();
|
|
|
|
|
|
|
|
|
|
std::advance(rIt, dis(gen_));
|
|
|
|
|
auto vIt = std::find_if(rIt, isMarked_.end(), pred);
|
|
|
|
|
if (vIt != isMarked_.end())
|
|
|
|
|
{
|
|
|
|
|
return &(vIt->first);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
vIt = std::find_if(isMarked_.begin(), rIt, pred);
|
|
|
|
|
if (vIt != rIt)
|
|
|
|
|
{
|
|
|
|
|
return &(vIt->first);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(log(V))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
const T * Graph<T>::getFirstUnmarked(void) const
|
|
|
|
|
{
|
|
|
|
|
return getFirstMarked(false);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-07 21:19:38 +01:00
|
|
|
|
// complexity: O(log(V))
|
|
|
|
|
template <typename T>
|
|
|
|
|
const T * Graph<T>::getRandomUnmarked(void)
|
|
|
|
|
{
|
|
|
|
|
return getRandomMarked(false);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-05 14:28:14 +00:00
|
|
|
|
// prune marked/unmarked vertices //////////////////////////////////////////////
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V^2*log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
2015-12-02 19:33:34 +00:00
|
|
|
|
void Graph<T>::removeMarked(const bool isMarked)
|
2015-11-05 14:28:14 +00:00
|
|
|
|
{
|
|
|
|
|
auto isMarkedCopy = isMarked_;
|
|
|
|
|
|
|
|
|
|
for (auto &v: isMarkedCopy)
|
|
|
|
|
{
|
|
|
|
|
if (v.second == isMarked)
|
|
|
|
|
{
|
|
|
|
|
removeVertex(v.first);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V^2*log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
2015-12-02 19:33:34 +00:00
|
|
|
|
void Graph<T>::removeUnmarked(void)
|
2015-11-05 14:28:14 +00:00
|
|
|
|
{
|
2015-12-02 19:33:34 +00:00
|
|
|
|
removeMarked(false);
|
2015-11-05 14:28:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// depth-first search marking //////////////////////////////////////////////////
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::depthFirstSearch(void)
|
|
|
|
|
{
|
|
|
|
|
depthFirstSearch(isMarked_.begin()->first);
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
void Graph<T>::depthFirstSearch(const T &root)
|
|
|
|
|
{
|
|
|
|
|
std::vector<T> adjacentVertex;
|
|
|
|
|
|
|
|
|
|
mark(root);
|
|
|
|
|
adjacentVertex = getAdjacentVertices(root);
|
|
|
|
|
for (auto &v: adjacentVertex)
|
|
|
|
|
{
|
|
|
|
|
if (!isMarked(v))
|
|
|
|
|
{
|
|
|
|
|
depthFirstSearch(v);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// graph topological manipulations /////////////////////////////////////////////
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
std::vector<T> Graph<T>::getAdjacentVertices(const T &value) const
|
|
|
|
|
{
|
|
|
|
|
std::vector<T> adjacentVertex;
|
|
|
|
|
|
|
|
|
|
auto pred = [&value](const Edge &e)
|
|
|
|
|
{
|
|
|
|
|
return ((e.first == value) or (e.second == value));
|
|
|
|
|
};
|
|
|
|
|
auto eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
|
|
|
|
|
|
|
|
|
|
while (eIt != edgeSet_.end())
|
|
|
|
|
{
|
|
|
|
|
if (eIt->first == value)
|
|
|
|
|
{
|
|
|
|
|
adjacentVertex.push_back((*eIt).second);
|
|
|
|
|
}
|
|
|
|
|
else if (eIt->second == value)
|
|
|
|
|
{
|
|
|
|
|
adjacentVertex.push_back((*eIt).first);
|
|
|
|
|
}
|
|
|
|
|
eIt = find_if(++eIt, edgeSet_.end(), pred);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return adjacentVertex;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V^2*log(V))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V^2*log(V))
|
2015-11-05 14:28:14 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
std::vector<Graph<T>> Graph<T>::getConnectedComponents(void) const
|
|
|
|
|
{
|
2015-12-02 19:33:34 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-07 21:19:38 +01:00
|
|
|
|
// topological sort using a directed DFS algorithm
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: O(V*log(V))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
template <typename T>
|
2016-05-07 21:19:38 +01:00
|
|
|
|
std::vector<T> Graph<T>::topoSort(const bool randomize)
|
2015-12-02 19:33:34 +00:00
|
|
|
|
{
|
2015-12-07 15:46:36 +00:00
|
|
|
|
std::stack<T> buf;
|
|
|
|
|
std::vector<T> res;
|
2015-12-02 19:33:34 +00:00
|
|
|
|
const T *vPt;
|
|
|
|
|
std::map<T, bool> tmpMarked(isMarked_);
|
2015-12-07 15:46:36 +00:00
|
|
|
|
|
2015-12-02 19:33:34 +00:00
|
|
|
|
// visit function
|
|
|
|
|
std::function<void(const T &)> visit = [&](const T &v)
|
|
|
|
|
{
|
|
|
|
|
if (tmpMarked.at(v))
|
|
|
|
|
{
|
|
|
|
|
HADRON_ERROR("cannot topologically sort a cyclic graph");
|
|
|
|
|
}
|
2016-05-07 21:19:38 +01:00
|
|
|
|
if (!isMarked(v))
|
2015-12-02 19:33:34 +00:00
|
|
|
|
{
|
2016-05-07 21:19:38 +01:00
|
|
|
|
std::vector<T> child = getChildren(v);
|
|
|
|
|
|
2015-12-02 19:33:34 +00:00
|
|
|
|
tmpMarked[v] = true;
|
2016-05-07 21:19:38 +01:00
|
|
|
|
if (randomize)
|
|
|
|
|
{
|
|
|
|
|
std::shuffle(child.begin(), child.end(), gen_);
|
|
|
|
|
}
|
2015-12-02 19:33:34 +00:00
|
|
|
|
for (auto &c: child)
|
|
|
|
|
{
|
|
|
|
|
visit(c);
|
|
|
|
|
}
|
2016-05-07 21:19:38 +01:00
|
|
|
|
mark(v);
|
2015-12-02 19:33:34 +00:00
|
|
|
|
tmpMarked[v] = false;
|
2015-12-07 15:46:36 +00:00
|
|
|
|
buf.push(v);
|
2015-12-02 19:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// reset temporary marks
|
|
|
|
|
for (auto &v: tmpMarked)
|
|
|
|
|
{
|
|
|
|
|
tmpMarked.at(v.first) = false;
|
|
|
|
|
}
|
2015-12-07 15:46:36 +00:00
|
|
|
|
|
2015-12-02 19:33:34 +00:00
|
|
|
|
// loop on unmarked vertices
|
2016-05-07 21:19:38 +01:00
|
|
|
|
unmarkAll();
|
|
|
|
|
if (randomize)
|
|
|
|
|
{
|
|
|
|
|
vPt = getRandomUnmarked();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
vPt = getFirstUnmarked();
|
|
|
|
|
}
|
2015-12-02 19:33:34 +00:00
|
|
|
|
while (vPt)
|
|
|
|
|
{
|
|
|
|
|
visit(*vPt);
|
2016-05-07 21:19:38 +01:00
|
|
|
|
if (randomize)
|
|
|
|
|
{
|
|
|
|
|
vPt = getRandomUnmarked();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
vPt = getFirstUnmarked();
|
|
|
|
|
}
|
2015-12-02 19:33:34 +00:00
|
|
|
|
}
|
|
|
|
|
unmarkAll();
|
2015-11-05 14:28:14 +00:00
|
|
|
|
|
2015-12-07 15:46:36 +00:00
|
|
|
|
// create result vector
|
|
|
|
|
while (!buf.empty())
|
|
|
|
|
{
|
|
|
|
|
res.push_back(buf.top());
|
|
|
|
|
buf.pop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generate all possible topological sorts
|
|
|
|
|
// Y. L. Varol & D. Rotem, Comput. J. 24(1), pp. 83–84, 1981
|
|
|
|
|
// http://comjnl.oupjournals.org/cgi/doi/10.1093/comjnl/24.1.83
|
2016-05-07 21:19:38 +01:00
|
|
|
|
// complexity: O(V*log(V)) (from the paper, but really ?)
|
2015-12-07 15:46:36 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
std::vector<std::vector<T>> Graph<T>::allTopoSort(void)
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::vector<T>> res;
|
|
|
|
|
std::map<T, std::map<T, bool>> iMat;
|
|
|
|
|
|
|
|
|
|
// create incidence matrix
|
|
|
|
|
for (auto &v1: isMarked_)
|
|
|
|
|
for (auto &v2: isMarked_)
|
|
|
|
|
{
|
|
|
|
|
iMat[v1.first][v2.first] = false;
|
|
|
|
|
}
|
|
|
|
|
for (auto &v: isMarked_)
|
|
|
|
|
{
|
|
|
|
|
auto cVec = getChildren(v.first);
|
|
|
|
|
|
|
|
|
|
for (auto &c: cVec)
|
|
|
|
|
{
|
|
|
|
|
iMat[v.first][c] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generate initial topological sort
|
|
|
|
|
res.push_back(topoSort());
|
|
|
|
|
|
|
|
|
|
// generate all other topological sorts by permutation
|
|
|
|
|
std::vector<T> p = res[0];
|
|
|
|
|
const unsigned int n = size();
|
|
|
|
|
std::vector<unsigned int> loc(n);
|
|
|
|
|
unsigned int i, k, k1;
|
|
|
|
|
T obj_k, obj_k1;
|
|
|
|
|
bool isFinal;
|
|
|
|
|
|
|
|
|
|
for (unsigned int j = 0; j < n; ++j)
|
|
|
|
|
{
|
|
|
|
|
loc[j] = j;
|
|
|
|
|
}
|
|
|
|
|
i = 0;
|
|
|
|
|
while (i < n-1)
|
|
|
|
|
{
|
|
|
|
|
k = loc[i];
|
|
|
|
|
k1 = k + 1;
|
|
|
|
|
obj_k = p[k];
|
|
|
|
|
if (k1 >= n)
|
|
|
|
|
{
|
|
|
|
|
isFinal = true;
|
|
|
|
|
obj_k1 = obj_k;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isFinal = false;
|
|
|
|
|
obj_k1 = p[k1];
|
|
|
|
|
}
|
|
|
|
|
if (iMat[res[0][i]][obj_k1] or isFinal)
|
|
|
|
|
{
|
|
|
|
|
for (unsigned int l = k; l >= i + 1; --l)
|
|
|
|
|
{
|
|
|
|
|
p[l] = p[l-1];
|
|
|
|
|
}
|
|
|
|
|
p[i] = obj_k;
|
|
|
|
|
loc[i] = i;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
p[k] = obj_k1;
|
|
|
|
|
p[k1] = obj_k;
|
|
|
|
|
loc[i] = k1;
|
|
|
|
|
i = 0;
|
|
|
|
|
res.push_back(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-02 19:33:34 +00:00
|
|
|
|
return res;
|
2015-11-05 14:28:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-07 18:26:38 +00:00
|
|
|
|
// build depedency matrix from topological sorts ///////////////////////////////
|
2016-05-06 14:35:11 +01:00
|
|
|
|
// complexity: can be V!
|
2015-12-07 18:26:38 +00:00
|
|
|
|
template <typename T>
|
|
|
|
|
std::map<T, std::map<T, bool>>
|
|
|
|
|
makeDependencyMatrix(const std::vector<std::vector<T>> &topSort)
|
|
|
|
|
{
|
|
|
|
|
std::map<T, std::map<T, bool>> m;
|
|
|
|
|
const std::vector<T> &vList = topSort[0];
|
|
|
|
|
|
|
|
|
|
for (auto &v1: vList)
|
|
|
|
|
for (auto &v2: vList)
|
|
|
|
|
{
|
|
|
|
|
bool dep = true;
|
|
|
|
|
|
|
|
|
|
for (auto &t: topSort)
|
|
|
|
|
{
|
|
|
|
|
auto i1 = std::find(t.begin(), t.end(), v1);
|
|
|
|
|
auto i2 = std::find(t.begin(), t.end(), v2);
|
|
|
|
|
|
|
|
|
|
dep = dep and (i1 - i2 > 0);
|
|
|
|
|
if (!dep) break;
|
|
|
|
|
}
|
|
|
|
|
m[v1][v2] = dep;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-05 14:28:14 +00:00
|
|
|
|
END_HADRONS_NAMESPACE
|
|
|
|
|
|
|
|
|
|
#endif // Hadrons_Graph_hpp_
|