20 #ifndef INCLUDE_MOLASSEMBLER_ORDER_DISCORVERY_HELPER
21 #define INCLUDE_MOLASSEMBLER_ORDER_DISCORVERY_HELPER
23 #include "boost/graph/adjacency_list.hpp"
24 #include "boost/graph/graphviz.hpp"
30 namespace Molassembler {
43 using DependencyGraphType = boost::adjacency_list<
64 using VertexIndexType =
typename DependencyGraphType::vertex_descriptor;
67 std::map<T, VertexIndexType> sourceMap_;
68 DependencyGraphType graph_;
88 std::vector<VertexIndexType>
91 typename DependencyGraphType::vertex_iterator iter, end;
92 std::tie(iter, end) = boost::vertices(graph_);
95 auto outDegree = boost::out_degree(*iter, graph_);
97 if(degreeToSetMap.count(outDegree) == 0) {
98 degreeToSetMap[outDegree] = {*iter};
100 degreeToSetMap.at(outDegree).push_back(*iter);
112 [&](
const auto& mapIterPair) -> std::vector<T> {
115 [&](
const auto& index) -> T {
116 return graph_[index].data;
123 VertexIndexType addItem_(
const T& item) {
124 auto newIndex = boost::add_vertex(graph_);
126 graph_[newIndex].data = item;
143 void operator() (std::ostream& os)
const {
144 os <<
"graph [fontname = \"Arial\", layout = \"dot\"];\n"
145 <<
"node [fontname = \"Arial\", shape = circle, style = filled];\n"
146 <<
"edge [fontname = \"Arial\"];\n";
149 void operator() (std::ostream& os,
const VertexIndexType& vertexIndex)
const {
150 os << R
"([label=")" << baseRef_.graph_[vertexIndex].data << R"("])";
153 void operator() (std::ostream& ,
const typename DependencyGraphType::edge_descriptor& )
const {
168 template<
typename Container>
171 std::begin(container),
187 std::map<VertexIndexType, VertexIndexType> vertexMapping;
189 for(VertexIndexType i = 0; i < boost::num_vertices(other.graph_); ++i) {
191 const auto& vertexData = other.graph_[i].data;
192 if(sourceMap_.count(vertexData) > 0) {
193 vertexMapping.emplace(
195 sourceMap_.at(vertexData)
202 auto edgeIterPair = boost::edges(other.graph_);
203 edgeIterPair.first != edgeIterPair.second;
206 auto otherEdgeSource = boost::source(*edgeIterPair.first, other.graph_);
207 auto otherEdgeTarget = boost::target(*edgeIterPair.first, other.graph_);
210 vertexMapping.count(otherEdgeSource) > 0
211 && vertexMapping.count(otherEdgeTarget) > 0
213 auto thisEdgeSource = vertexMapping.at(otherEdgeSource);
214 auto thisEdgeTarget = vertexMapping.at(otherEdgeTarget);
217 auto thisGraphEdge = boost::edge(
224 if(thisGraphEdge.second) {
229 auto inverseGraphEdge = boost::edge(
235 if(inverseGraphEdge.second) {
236 throw "Contradicting information in other OrderDiscoveryHelper graph!";
240 boost::add_edge(thisEdgeSource, thisEdgeTarget, graph_);
245 addTransferabilityEdges();
260 std::map<VertexIndexType, VertexIndexType> vertexMapping;
263 for(VertexIndexType i = 0; i < boost::num_vertices(other.graph_); ++i) {
265 const auto& vertexData = other.graph_[i].data;
266 if(sourceMap_.count(vertexData) == 0) {
267 auto newIndex = addItem_(other.graph_[i].data);
268 vertexMapping.emplace(
273 vertexMapping.emplace(
275 sourceMap_.at(vertexData)
282 auto edgeIterPair = boost::edges(other.graph_);
283 edgeIterPair.first != edgeIterPair.second;
286 auto otherEdgeSource = boost::source(*edgeIterPair.first, other.graph_);
287 auto otherEdgeTarget = boost::target(*edgeIterPair.first, other.graph_);
289 auto thisEdgeSource = vertexMapping.at(otherEdgeSource);
290 auto thisEdgeTarget = vertexMapping.at(otherEdgeTarget);
293 auto thisGraphEdge = boost::edge(
300 if(thisGraphEdge.second) {
305 auto inverseGraphEdge = boost::edge(
311 if(inverseGraphEdge.second) {
312 throw "Contradicting information in other OrderDiscoveryHelper graph!";
316 boost::add_edge(thisEdgeSource, thisEdgeTarget, graph_);
319 addTransferabilityEdges();
332 for(VertexIndexType i = 0; i < boost::num_vertices(graph_); ++i) {
333 std::vector<VertexIndexType> seeds;
336 auto edgeIterPair = boost::out_edges(i, graph_);
337 edgeIterPair.first != edgeIterPair.second;
341 boost::target(*edgeIterPair.first, graph_)
346 std::vector<VertexIndexType> newSeeds;
348 for(
const auto& seed: seeds) {
349 if(!boost::edge(i, seed, graph_).
second) {
350 boost::add_edge(i, seed, graph_);
354 auto edgeIterPair = boost::out_edges(seed, graph_);
355 edgeIterPair.first != edgeIterPair.second;
358 newSeeds.emplace_back(
359 boost::target(*edgeIterPair.first, graph_)
364 seeds = std::move(newSeeds);
365 }
while(!seeds.empty());
374 template<
typename It>
376 if(boost::num_vertices(graph_) > 0) {
382 for(; iter != end; ++iter) {
391 template<
typename Container>
395 Temple::Traits::getValueType<Container>,
398 "Container value must match OrderDiscoveryHelper's template argument T"
402 std::begin(container),
415 return getSetsByDegree_();
426 return Temple::copy_if(
428 [](
const auto& set) ->
bool {
429 return set.size() > 1;
439 auto N = boost::num_vertices(graph_);
441 return(boost::num_edges(graph_) == N * (N - 1) / 2);
469 GraphvizWriter propertyWriter(*
this);
471 std::stringstream ss;
473 boost::write_graphviz(
496 if(sourceMap_.count(a) == 0 || sourceMap_.count(b) == 0) {
501 auto smallerEdge = boost::edge(sourceMap_.at(a), sourceMap_.at(b), graph_);
502 return smallerEdge.second;
std::vector< std::vector< T > > getUndecidedSets() const
Returns grouped data (in descending order) whose internal order is undecided.
Definition: OrderDiscoveryHelper.h:424
void setUnorderedValues(It iter, const It end)
Range-abstracted.
Definition: OrderDiscoveryHelper.h:375
Definition: OrderDiscoveryHelper.h:39
auto map_stl(const Container< T, Dependents< T >...> &container, UnaryFunction &&function)
Definition: Functional.h:73
Container aiding in gradual discovery of order.
Definition: OrderDiscoveryHelper.h:37
std::vector< std::vector< T > > getSetsByDegree_() const
Get a grouped list of the ordered data sorted by out_degree ascending.
Definition: OrderDiscoveryHelper.h:77
std::string dumpGraphviz() const
Dumps a graphviz string for visualization of relationships.
Definition: OrderDiscoveryHelper.h:468
std::vector< std::vector< T > > getSets() const
Get a list of sets (in descending order) as currently discovered.
Definition: OrderDiscoveryHelper.h:413
constexpr Get< 1 > second
Calls std::get<1> on any argument it is invoked with.
Definition: Functor.h:125
void addRelationshipsFromOther(const OrderDiscoveryHelper &other)
Transfer relationships from another OrderDiscoveryHelper.
Definition: OrderDiscoveryHelper.h:185
bool isTotallyOrdered() const
Returns whether the total order has been discovered or not.
Definition: OrderDiscoveryHelper.h:438
void addAllFromOther(const OrderDiscoveryHelper &other)
Adds vertices and edges from another instance, then adds transferability edges.
Definition: OrderDiscoveryHelper.h:258
void setUnorderedValues(Container &&container)
Container-abstracted.
Definition: OrderDiscoveryHelper.h:392
constexpr auto map(const ArrayType< T, size > &array, UnaryFunction &&function)
Maps all elements of any array-like container with a unary function.
Definition: Containers.h:62
void addTransferabilityEdges()
Adds missing transferability edges.
Definition: OrderDiscoveryHelper.h:331
Definition: OrderDiscoveryHelper.h:136
OrderDiscoveryHelper(const Container &container)
Arbitrary container constructor.
Definition: OrderDiscoveryHelper.h:169
bool isSmaller(const T &a, const T &b) const
Check if a value is smaller than another.
Definition: OrderDiscoveryHelper.h:495
Functional-style container-related algorithms.
void addLessThanRelationship(const T &a, const T &b)
Add a less-than relationship to the graph.
Definition: OrderDiscoveryHelper.h:448