Commit 687207b2 authored by Kučera Petr RNDr. Ph.D.'s avatar Kučera Petr RNDr. Ph.D.
Browse files

Subgraph of SectionGraph

parent 53372b06
......@@ -18,6 +18,15 @@
namespace Loco
{
enum class SEARCH_STATE
{
UNVISITED,
OPEN,
CLOSED,
TERMINAL,
ADDED
};
// Like PhysicalGraph, but subdivided with points
// Physical nodes are in the graph as well
class LogicalGraph
......@@ -43,15 +52,6 @@ namespace Loco
using EdgePoints = std::unordered_map<EdgeConstPtr, PointList>;
using Vertex = std::variant<NodeConstPtr, PointConstPtr>;
enum class SEARCH_STATE
{
UNVISITED,
OPEN,
CLOSED,
TERMINAL,
ADDED
};
private:
std::vector<std::vector<Neighbour>> mNeighbours;
......
......@@ -12,6 +12,7 @@
#include <algorithm>
#include <numeric>
#include <queue>
#include "section_graph.h"
......@@ -236,6 +237,12 @@ Loco::SectionGraph::BuildPlaces()
}
}
auto
Loco::SectionGraph::PlaceOfSection(unsigned section_id) const -> SGPlaceConstPtr
{
return mPlaces[mSections[section_id].mConflictGroupId];
}
std::ostream &
Loco::SectionGraph::PrintPlaceIdents(std::ostream &os,
const std::string &sep) const
......@@ -284,3 +291,147 @@ Loco::SectionGraph::PrintConflictGroups(std::ostream &os) const
}
return os;
}
auto
Loco::SectionGraph::GetSubgraph(
const std::vector<SectionConstPtr> &sources,
const std::vector<SectionConstPtr> &targets) const -> Subgraph
{
return GetSubgraphWithIds(SectionIds(sources), SectionIds(targets));
}
std::vector<unsigned>
Loco::SectionGraph::SectionIds(
const std::vector<SectionConstPtr> &sections) const
{
std::vector<unsigned> sect_id;
sect_id.reserve(sections.size());
std::transform(
sections.begin(), sections.end(), std::back_inserter(sect_id),
[this](const SectionConstPtr &sect) { return mSectionId.at(sect); });
return sect_id;
}
auto
Loco::SectionGraph::GetSubgraphWithIds(std::vector<unsigned> sources,
std::vector<unsigned> targets) const
-> Subgraph
{
if (sources.empty() || targets.empty())
{
return {sources, targets, {}};
}
// Run BFS from sources,
// Mark the nodes which have path from the source (CLOSED and TERMINAL at the
// end)
// Store all possible predecessors of all nodes
std::vector<SEARCH_STATE> state(mSections.size(), SEARCH_STATE::UNVISITED);
std::vector<std::vector<unsigned>> pred(mSections.size());
std::queue<unsigned> q;
for (auto i : sources)
{
state[i] = SEARCH_STATE::OPEN;
q.push(i);
}
for (auto i : targets)
{
state[i] = SEARCH_STATE::TERMINAL;
}
while (!q.empty())
{
for (const auto &nb : mSections[q.front()].mNeighbours)
{
if (state[nb] == SEARCH_STATE::UNVISITED)
{
q.push(nb);
state[nb] = SEARCH_STATE::OPEN;
}
pred[nb].push_back(q.front());
}
if (state[q.front()] != SEARCH_STATE::TERMINAL)
{
state[q.front()] = SEARCH_STATE::CLOSED;
}
q.pop();
}
// Find nodes from which there is a path to one of the targets
std::vector<std::vector<unsigned>> succ(mSections.size());
std::vector<SEARCH_STATE> back_state(mSections.size(),
SEARCH_STATE::UNVISITED);
for (auto i : targets)
{
back_state[i] = SEARCH_STATE::OPEN;
q.push(i);
}
for (auto i : sources)
{
back_state[i] = SEARCH_STATE::TERMINAL;
}
while (!q.empty())
{
for (const auto &p : pred[q.front()])
{
if (back_state[p] == SEARCH_STATE::UNVISITED)
{
q.push(p);
back_state[p] = SEARCH_STATE::OPEN;
}
succ[q.front()].push_back(p);
}
if (back_state[q.front()] != SEARCH_STATE::TERMINAL)
{
back_state[q.front()] = SEARCH_STATE::CLOSED;
}
q.pop();
}
// Prune the pred and succ nodes which are not reachable from both sides
// Nodes which are either sources or targets or have pred and succ nonempty
// are the nodes of the subgraphs
std::unordered_map<unsigned, Subgraph::NodeInfo> node_info;
// prune the predecessors
auto unreachable = [&state, &back_state](unsigned i) {
return (state[i] != SEARCH_STATE::CLOSED
&& state[i] != SEARCH_STATE::TERMINAL)
|| (back_state[i] != SEARCH_STATE::CLOSED
&& back_state[i] != SEARCH_STATE::TERMINAL);
};
for (unsigned i = 0; i < mSections.size(); ++i)
{
if (unreachable(i))
{
continue;
}
if (state[i] == SEARCH_STATE::TERMINAL)
{
// Targets have no successors
succ[i].clear();
}
else
{
succ[i].erase(
std::remove_if(succ[i].begin(), succ[i].end(), unreachable),
succ[i].end());
}
if (back_state[i] == SEARCH_STATE::TERMINAL)
{
// Sources have no predecessors
pred[i].clear();
}
else
{
pred[i].erase(
std::remove_if(pred[i].begin(), pred[i].end(), unreachable),
pred[i].end());
}
if (state[i] == SEARCH_STATE::TERMINAL
|| back_state[i] == SEARCH_STATE::TERMINAL
|| (!pred[i].empty() && !succ[i].empty()))
{
node_info.insert({i, {std::move(succ[i]), std::move(pred[i])}});
}
}
return {sources, targets, node_info};
}
......@@ -21,6 +21,7 @@ namespace Loco
// Two sections are incident if they share a logical point
// Two sections are conflicting if they share a physical point
// Conflicting sections are grouped together into a meta section
class SectionGraph
{
public:
......@@ -45,6 +46,22 @@ namespace Loco
std::ostream &Print(std::ostream &os, unsigned id) const;
};
struct Subgraph
{
struct NodeInfo
{
std::vector<unsigned> mSucc;
std::vector<unsigned> mPred;
};
std::vector<unsigned> mSources;
std::vector<unsigned> mTargets;
std::unordered_map<unsigned, NodeInfo> mSections;
Subgraph(std::vector<unsigned> sources, std::vector<unsigned> targets,
std::unordered_map<unsigned, NodeInfo> mSections);
};
private:
std::vector<SectionInfo> mSections;
std::unordered_map<SectionConstPtr, unsigned> mSectionId;
......@@ -72,7 +89,14 @@ namespace Loco
void ChangeIdOfConflictGroup(unsigned old_id, unsigned new_id);
void CompressConflictGroups();
void BuildPlaces();
SGPlaceConstPtr PlaceOfSection(unsigned section_id) const;
std::vector<unsigned>
SectionIds(const std::vector<SectionConstPtr> &sect) const;
std::ostream &PrintVertices(std::ostream &os) const;
Subgraph GetSubgraphWithIds(std::vector<unsigned> sources,
std::vector<unsigned> targets) const;
Subgraph GetSubgraph(const std::vector<SectionConstPtr> &sources,
const std::vector<SectionConstPtr> &targets) const;
public:
SectionGraph(const InputData &data, const LogicalGraph &logical_graph)
......@@ -83,12 +107,15 @@ namespace Loco
std::ostream &PrintGraph(std::ostream &os) const;
std::ostream &PrintSectionInfo(std::ostream &os) const;
const std::vector<SGPlaceConstPtr> &Places() const;
std::ostream &PrintPlaceIdents(std::ostream &os,
const std::string &sep) const;
std::ostream &PrintPlaceDesc(std::ostream &os) const;
std::ostream &PrintConflictGroups(std::ostream &os) const;
};
using SectionGraphConstPtr = std::shared_ptr<const SectionGraph>;
using SGSubgraphConstPtr = std::shared_ptr<const SectionGraph::Subgraph>;
} // namespace Loco
template <class T, class F>
......@@ -120,10 +147,4 @@ Loco::SectionGraph::BuildPairs(
}
}
inline auto
Loco::SectionGraph::Places() const -> const std::vector<SGPlaceConstPtr> &
{
return mPlaces;
}
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment