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

Section lengths

parent 606c21a6
......@@ -30,7 +30,7 @@ namespace Loco
public:
struct Position
{
std::shared_ptr<const Edge> edge = nullptr;
EdgeConstPtr edge = nullptr;
int offset = 0;
length_type Offset() const;
......@@ -61,8 +61,16 @@ namespace Loco
{
return mPosition;
}
int
Offset() const
{
return mPosition.offset;
}
};
using PointConstPtr = std::shared_ptr<const Point>;
class Section : public DataElement
{
public:
......@@ -79,7 +87,7 @@ namespace Loco
private:
Data mData;
std::vector<std::shared_ptr<const Point>> mPoints;
std::vector<PointConstPtr> mPoints;
virtual std::ostream &
PrintData(std::ostream &os, const std::string &prefix,
......@@ -87,36 +95,37 @@ namespace Loco
public:
Section(GlobalIdent ident, std::string name, const Data &data,
const std::vector<std::shared_ptr<const Point>> &points)
const std::vector<PointConstPtr> &points)
: DataElement(std::move(ident), std::move(name)),
mData(std::move(data)), mPoints(points)
{
}
Section(GlobalIdent ident, std::string name, Data &&data,
std::vector<std::shared_ptr<const Point>> &&points)
std::vector<PointConstPtr> &&points)
: DataElement(std::move(ident), std::move(name)),
mData(std::move(data)), mPoints(std::move(points))
{
}
const std::vector<std::shared_ptr<const Point>> &
const std::vector<PointConstPtr> &
Points() const
{
return mPoints;
}
};
using SectionConstPtr = std::shared_ptr<const Section>;
class Indicator : public DataElement
{
std::shared_ptr<const Section> mSection;
SectionConstPtr mSection;
virtual std::ostream &
PrintData(std::ostream &os, const std::string &prefix,
const std::string &region_hint) const override;
public:
Indicator(GlobalIdent ident, std::string name,
std::shared_ptr<const Section> section)
Indicator(GlobalIdent ident, std::string name, SectionConstPtr section)
: DataElement(std::move(ident), std::move(name)),
mSection(std::move(section))
{
......@@ -124,7 +133,7 @@ namespace Loco
};
class EntryPoint : public DataElement
{
std::shared_ptr<const Section> mSection;
SectionConstPtr mSection;
std::vector<Indicator> mIndicators;
virtual std::ostream &
......@@ -135,8 +144,7 @@ namespace Loco
virtual unsigned Level() const override;
public:
EntryPoint(GlobalIdent ident, std::string name,
std::shared_ptr<const Section> section,
EntryPoint(GlobalIdent ident, std::string name, SectionConstPtr section,
std::vector<Indicator> indicators)
: DataElement(std::move(ident), std::move(name)),
mSection(std::move(section)), mIndicators(std::move(indicators))
......
......@@ -55,8 +55,7 @@ Loco::LogicalGraph::SortEdgePoints(EdgePoints edge_points) -> EdgePoints
for (auto &[edge, point_list] : edge_points)
{
std::sort(point_list.begin(), point_list.end(),
[](const std::shared_ptr<const Point> &a,
const std::shared_ptr<const Point> &b) {
[](const PointConstPtr &a, const PointConstPtr &b) {
return a->GetPosition().offset < b->GetPosition().offset;
});
}
......@@ -65,29 +64,35 @@ Loco::LogicalGraph::SortEdgePoints(EdgePoints edge_points) -> EdgePoints
void
Loco::LogicalGraph::AddNeighbour(unsigned a, unsigned b,
const std::shared_ptr<const Edge> &edge)
const EdgeConstPtr &edge, length_type dist)
{
mNeighbours[a].emplace_back(edge, b, true);
mNeighbours[b].emplace_back(edge, a, false);
mNeighbours[a].emplace_back(edge, b, true, dist);
mNeighbours[b].emplace_back(edge, a, false, dist);
}
void
Loco::LogicalGraph::AddEdge(const std::shared_ptr<const Edge> &edge)
Loco::LogicalGraph::AddEdge(const EdgeConstPtr &edge)
{
AddNeighbour(mNodeId.at(edge->From()), mNodeId.at(edge->To()), edge);
AddNeighbour(mNodeId.at(edge->From()), mNodeId.at(edge->To()), edge,
edge->Length());
return;
}
void
Loco::LogicalGraph::AddPathOfEdge(const std::shared_ptr<const Edge> &edge,
Loco::LogicalGraph::AddPathOfEdge(const EdgeConstPtr &edge,
const PointList &points)
{
AddNeighbour(mNodeId.at(edge->From()), mPointId.at(points.front()), edge);
AddNeighbour(mNodeId.at(edge->From()), mPointId.at(points.front()), edge,
points.front()->Offset());
for (unsigned i = 0; i + 1 < points.size(); ++i)
{
AddNeighbour(mPointId.at(points[i]), mPointId.at(points[i + 1]), edge);
length_type offset_diff = points[i + 1]->Offset() - points[i]->Offset();
AddNeighbour(mPointId.at(points[i]), mPointId.at(points[i + 1]), edge,
offset_diff);
}
AddNeighbour(mPointId.at(points.back()), mNodeId.at(edge->To()), edge);
AddNeighbour(mPointId.at(points.back()), mNodeId.at(edge->To()), edge,
edge->Length() - points.back()->Offset());
}
std::ostream &
......@@ -101,18 +106,19 @@ Loco::LogicalGraph::PrintVertices(std::ostream &os) const
for (unsigned i = 0; i < mPoints.size(); ++i)
{
os << kTabString << "v" << mNodes.size() + i << " [label=\""
<< mPoints[i]->Ident() << "\"]" << std::endl;
<< mPoints[i]->Ident() << ":" << mPoints[i]->Offset() << "\"]"
<< std::endl;
}
return os;
}
std::ostream &
Loco::LogicalGraph::PrintSingleEdge(
std::ostream &os, unsigned a, unsigned b,
const std::shared_ptr<const Edge> &edge) const
Loco::LogicalGraph::PrintSingleEdge(std::ostream &os, unsigned a,
const Neighbour &nb) const
{
return os << kTabString << "v" << a << " -- "
<< "v" << b << " [label=\"" << edge->Ident() << "\"]" << std::endl;
<< "v" << nb.mVertexId << " [label=\"" << nb.mEdge->Ident() << ":"
<< nb.mDistance << "\"]" << std::endl;
}
std::ostream &
......@@ -122,7 +128,7 @@ Loco::LogicalGraph::PrintNeighbours(std::ostream &os, unsigned i) const
{
if (nb.mForward)
{
PrintSingleEdge(os, i, nb.mNeighbour, nb.mEdge);
PrintSingleEdge(os, i, nb);
}
}
return os;
......@@ -170,30 +176,33 @@ Loco::LogicalGraph::InitPointIds(const InputData &data)
}
auto
Loco::LogicalGraph::NodeWithId(unsigned id) const
-> const std::shared_ptr<const Node> &
Loco::LogicalGraph::NodeWithId(unsigned id) const -> const NodeConstPtr &
{
return mNodes[id];
}
auto
Loco::LogicalGraph::PointWithId(unsigned id) const
-> const std::shared_ptr<const Point> &
Loco::LogicalGraph::PointWithId(unsigned id) const -> const PointConstPtr &
{
return mPoints[id - mNodes.size()];
}
auto
Loco::LogicalGraph::FindSectionVertices(
const std::shared_ptr<const Section> &sect) const -> VertexSet
Loco::LogicalGraph::FindSectionVertices(const SectionConstPtr &sect) const
-> std::pair<std::vector<Vertex>, length_type>
{
return VertexSetOfVertices(
FindInnerVertices(VerticesOfPoints(sect->Points())));
auto [vertex_id, len] = FindInnerVertices(VerticesOfPoints(sect->Points()));
std::vector<Vertex> vert;
vert.reserve(vertex_id.size());
std::transform(vertex_id.begin(), vertex_id.end(), std::back_inserter(vert),
[this](auto id) { return VertexWithId(id); });
std::reverse(vert.begin(), vert.end());
return {vert, len};
}
std::vector<unsigned>
Loco::LogicalGraph::VerticesOfPoints(
const std::vector<std::shared_ptr<const Point>> &points) const
const std::vector<PointConstPtr> &points) const
{
std::vector<unsigned> vertices;
vertices.reserve(points.size());
......@@ -203,36 +212,18 @@ Loco::LogicalGraph::VerticesOfPoints(
}
auto
Loco::LogicalGraph::VertexSetOfVertices(
const std::vector<unsigned> &vertices) const -> VertexSet
{
VertexSet vs;
for (auto id : vertices)
{
auto v = VertexWithId(id);
if (std::holds_alternative<std::shared_ptr<const Node>>(v))
{
vs.mNodes.push_back(
std::get<std::shared_ptr<const Node>>(std::move(v)));
continue;
}
vs.mPoints.push_back(
std::get<std::shared_ptr<const Point>>(std::move(v)));
}
return vs;
}
std::vector<unsigned>
Loco::LogicalGraph::FindInnerVertices(
const std::vector<unsigned> &border_vertices) const
-> std::pair<std::vector<unsigned>, length_type>
{
if (border_vertices.size() < 2)
{
return border_vertices;
return {border_vertices, 0};
}
unsigned vc = VertexCount();
std::vector<SEARCH_STATE> state(vc, SEARCH_STATE::UNVISITED);
std::vector<unsigned> pred(vc, vc);
std::vector<length_type> dist(vc, 0);
for (auto i : border_vertices)
{
state[i] = SEARCH_STATE::TERMINAL;
......@@ -245,15 +236,16 @@ Loco::LogicalGraph::FindInnerVertices(
{
for (const auto &nb : mNeighbours[q.front()])
{
switch (state[nb.mNeighbour])
switch (state[nb.mVertexId])
{
case SEARCH_STATE::TERMINAL:
--remain_count;
[[fallthrough]];
case SEARCH_STATE::UNVISITED:
q.push(nb.mNeighbour);
state[nb.mNeighbour] = SEARCH_STATE::OPEN;
pred[nb.mNeighbour] = q.front();
q.push(nb.mVertexId);
state[nb.mVertexId] = SEARCH_STATE::OPEN;
pred[nb.mVertexId] = q.front();
dist[nb.mVertexId] = dist[q.front()] + nb.mDistance;
break;
case SEARCH_STATE::OPEN:
case SEARCH_STATE::CLOSED:
......@@ -272,6 +264,7 @@ Loco::LogicalGraph::FindInnerVertices(
"Section subgraph is not connected");
}
std::vector<unsigned> vertex_set;
length_type max_dist = 0;
for (unsigned i = 1; i < border_vertices.size(); ++i)
{
unsigned v = border_vertices[i];
......@@ -281,16 +274,17 @@ Loco::LogicalGraph::FindInnerVertices(
{
vertex_set.push_back(v);
state[v] = SEARCH_STATE::ADDED;
max_dist = std::max(max_dist, dist[v]);
}
v = pred[v];
}
}
return vertex_set;
return {vertex_set, max_dist};
}
auto
Loco::LogicalGraph::VertexWithId(unsigned id) const
-> std::variant<std::shared_ptr<const Node>, std::shared_ptr<const Point>>
-> std::variant<NodeConstPtr, PointConstPtr>
{
if (id < mNodes.size())
{
......@@ -298,3 +292,13 @@ Loco::LogicalGraph::VertexWithId(unsigned id) const
}
return mPoints[id - mNodes.size()];
}
auto
Loco::LogicalGraph::VertexIdent(const Vertex &v) -> const GlobalIdent &
{
if (std::holds_alternative<PointConstPtr>(v))
{
return std::get<PointConstPtr>(v)->Ident();
}
return std::get<NodeConstPtr>(v)->Ident();
}
......@@ -25,26 +25,23 @@ namespace Loco
public:
struct Neighbour
{
std::shared_ptr<const Edge> mEdge;
unsigned mNeighbour;
bool mForward;
EdgeConstPtr mEdge{};
unsigned mVertexId{};
bool mForward{};
length_type mDistance{};
Neighbour() = default;
Neighbour(std::shared_ptr<const Edge> e, unsigned nb, bool fw)
: mEdge(std::move(e)), mNeighbour(std::move(nb)), mForward(fw)
Neighbour(EdgeConstPtr e, unsigned vertex_id, bool fw,
length_type dist)
: mEdge(std::move(e)), mVertexId(std::move(vertex_id)),
mForward(fw), mDistance(dist)
{
}
};
using PointList = std::vector<std::shared_ptr<const Point>>;
using EdgePoints =
std::unordered_map<std::shared_ptr<const Edge>, PointList>;
struct VertexSet
{
std::vector<std::shared_ptr<const Node>> mNodes;
std::vector<std::shared_ptr<const Point>> mPoints;
};
using PointList = std::vector<PointConstPtr>;
using EdgePoints = std::unordered_map<EdgeConstPtr, PointList>;
using Vertex = std::variant<NodeConstPtr, PointConstPtr>;
enum class SEARCH_STATE
{
......@@ -58,20 +55,19 @@ namespace Loco
private:
std::vector<std::vector<Neighbour>> mNeighbours;
std::vector<std::shared_ptr<const Node>> mNodes;
std::vector<std::shared_ptr<const Point>> mPoints;
std::unordered_map<std::shared_ptr<const Node>, unsigned> mNodeId;
std::unordered_map<std::shared_ptr<const Point>, unsigned> mPointId;
std::vector<NodeConstPtr> mNodes;
std::vector<PointConstPtr> mPoints;
std::unordered_map<NodeConstPtr, unsigned> mNodeId;
std::unordered_map<PointConstPtr, unsigned> mPointId;
static EdgePoints BuildEdgePoints(const InputData &data);
static EdgePoints SortEdgePoints(EdgePoints edge_points);
void InitNodeIds(const InputData &data);
void InitPointIds(const InputData &data);
const std::shared_ptr<const Node> &NodeWithId(unsigned id) const;
const std::shared_ptr<const Point> &PointWithId(unsigned id) const;
std::variant<std::shared_ptr<const Node>, std::shared_ptr<const Point>>
VertexWithId(unsigned id) const;
const NodeConstPtr &NodeWithId(unsigned id) const;
const PointConstPtr &PointWithId(unsigned id) const;
Vertex VertexWithId(unsigned id) const;
unsigned
VertexCount() const
......@@ -79,33 +75,31 @@ namespace Loco
return mNodes.size() + mPoints.size();
}
void AddPathOfEdge(const std::shared_ptr<const Edge> &edge,
const PointList &points);
void AddEdge(const std::shared_ptr<const Edge> &edge);
void AddNeighbour(unsigned a, unsigned b,
const std::shared_ptr<const Edge> &edge);
void AddPathOfEdge(const EdgeConstPtr &edge, const PointList &points);
void AddEdge(const EdgeConstPtr &edge);
void AddNeighbour(unsigned a, unsigned b, const EdgeConstPtr &edge,
length_type dist);
void Build(const InputData &data);
std::ostream &PrintVertices(std::ostream &os) const;
std::ostream &PrintNeighbours(std::ostream &os, unsigned i) const;
std::ostream &
PrintSingleEdge(std::ostream &os, unsigned a, unsigned b,
const std::shared_ptr<const Edge> &edge) const;
std::ostream &PrintSingleEdge(std::ostream &os, unsigned a,
const Neighbour &nb) const;
std::vector<unsigned> VerticesOfPoints(
const std::vector<std::shared_ptr<const Point>> &points) const;
std::vector<unsigned>
VerticesOfPoints(const std::vector<PointConstPtr> &points) const;
std::pair<std::vector<unsigned>, length_type>
FindInnerVertices(const std::vector<unsigned> &border_vertices) const;
VertexSet
VertexSetOfVertices(const std::vector<unsigned> &vertices) const;
public:
LogicalGraph(const InputData &data) { Build(data); }
std::ostream &PrintGraph(std::ostream &os) const;
VertexSet
FindSectionVertices(const std::shared_ptr<const Section> &sect) const;
std::pair<std::vector<Vertex>, length_type>
FindSectionVertices(const SectionConstPtr &sect) const;
static const GlobalIdent &VertexIdent(const Vertex &v);
};
} // namespace Loco
......
......@@ -38,19 +38,21 @@ namespace Loco
using DataElement::DataElement;
};
using NodeConstPtr = std::shared_ptr<const Node>;
class Edge : public DataElement
{
public:
struct Data
{
std::shared_ptr<const Node> from_node = nullptr;
std::shared_ptr<const Node> to_node = nullptr;
NodeConstPtr from_node = nullptr;
NodeConstPtr to_node = nullptr;
length_type len = 0;
};
private:
std::shared_ptr<const Node> mFrom;
std::shared_ptr<const Node> mTo;
NodeConstPtr mFrom;
NodeConstPtr mTo;
length_type mLength;
virtual std::ostream &
......@@ -75,20 +77,22 @@ namespace Loco
{
return mLength;
}
std::shared_ptr<const Node> From() const;
std::shared_ptr<const Node> To() const;
NodeConstPtr From() const;
NodeConstPtr To() const;
};
using EdgeConstPtr = std::shared_ptr<const Edge>;
} // namespace Loco
inline auto
Loco::Edge::From() const -> std::shared_ptr<const Node>
Loco::Edge::From() const -> NodeConstPtr
{
return mFrom;
}
inline auto
Loco::Edge::To() const -> std::shared_ptr<const Node>
Loco::Edge::To() const -> NodeConstPtr
{
return mTo;
}
......
......@@ -40,20 +40,20 @@ Loco::SectionGraph::InitSectionInfo(const InputData &data,
void
Loco::SectionGraph::AddInfoForSection(const LogicalGraph &logical_graph,
std::shared_ptr<const Section> sect)
SectionConstPtr sect)
{
auto vertices = logical_graph.FindSectionVertices(sect);
auto [vertices, len] = logical_graph.FindSectionVertices(sect);
mSectionId[sect] = mSections.size();
for (const auto &point : vertices.mPoints)
for (const auto &v : vertices)
{
mPointSections[point].push_back(mSections.size());
}
for (const auto &node : vertices.mNodes)
{
mNodeSections[node].push_back(mSections.size());
if (std::holds_alternative<PointConstPtr>(v))
{
mPointSections[std::get<PointConstPtr>(v)].push_back(mSections.size());
continue;
}
mNodeSections[std::get<NodeConstPtr>(v)].push_back(mSections.size());
}
mSections.emplace_back(std::move(sect), std::move(vertices));
// Also add section to points and nodes, see above
mSections.emplace_back(std::move(sect), std::move(vertices), len);
}
std::ostream &
......@@ -91,14 +91,27 @@ Loco::SectionGraph::PrintSectionInfo(std::ostream &os) const
{
for (unsigned i = 0; i < mSections.size(); ++i)
{
os << "[" << mSections[i].mSection->Ident() << "]" << std::endl;
os << kTabString << "id = " << i << std::endl;
print_data_vector(os, mSections[i].mSection->Points(), kTabString,
"border-points", "");
print_data_vector(os, mSections[i].mVertices.mNodes, kTabString, "nodes",
"");
print_data_vector(os, mSections[i].mVertices.mPoints, kTabString,
"points", "");
mSections[i].Print(os, i);
}
return os;
}
std::ostream &
Loco::SectionGraph::SectionInfo::Print(std::ostream &os, unsigned id) const
{
os << "[" << mSection->Ident() << "]" << std::endl;
os << kTabString << "id = " << id << std::endl;
os << kTabString << "length = " << mLength << std::endl;
print_data_vector(os, mSection->Points(), kTabString, "border-points", "");
if (!mVertices.empty())
{
os << kTabString
<< "vertices = " << LogicalGraph::VertexIdent(mVertices.front());
std::for_each(
mVertices.begin() + 1, mVertices.end(), [&os](const auto &v) {
os << " " << kArraySep << " " << LogicalGraph::VertexIdent(v);
});
os << std::endl;
}
return os;
}
......
......@@ -25,31 +25,34 @@ namespace Loco
public:
struct SectionInfo
{
std::shared_ptr<const Section> mSection{};
LogicalGraph::VertexSet mVertices{};
SectionConstPtr mSection{};
std::vector<LogicalGraph::Vertex> mVertices{};
length_type mLength;
std::optional<unsigned> mConflictGroupId{};
std::vector<unsigned> mNeighbours;
std::vector<unsigned> mConflicts;
SectionInfo() = default;
SectionInfo(std::shared_ptr<const Section> sect,
LogicalGraph::VertexSet vertices)
: mSection(std::move(sect)), mVertices(vertices)
SectionInfo(SectionConstPtr sect,
std::vector<LogicalGraph::Vertex> vertices,
length_type len)
: mSection(std::move(sect)), mVertices(std::move(vertices)),
mLength(len)
{
}
std::ostream &Print(std::ostream &os, unsigned id) const;
};
private:
std::vector<SectionInfo> mSections;
std::unordered_map<std::shared_ptr<const Section>, unsigned> mSectionId;
std::unordered_map<SectionConstPtr, unsigned> mSectionId;
std::vector<std::vector<unsigned>> mConflictGroups;
std::unordered_map<std::shared_ptr<const Node>, std::vector<unsigned>>
mNodeSections;
std::unordered_map<std::shared_ptr<const Point>, std::vector<unsigned>>
mPointSections;
std::unordered_map<NodeConstPtr, std::vector<unsigned>> mNodeSections;
std::unordered_map<PointConstPtr, std::vector<unsigned>> mPointSections;