31 #ifndef INCLUDE_MOLASSEMBLER_RANKING_HIERARCHICAL_TREE_H
32 #define INCLUDE_MOLASSEMBLER_RANKING_HIERARCHICAL_TREE_H
34 #include "boost/variant.hpp"
46 using namespace std::string_literals;
49 namespace Molassembler {
72 static std::string adaptMolGraph_(std::string molGraph);
75 static void writeGraphvizFiles_(
76 const std::vector<std::string>& graphvizStrings
112 boost::optional<BondStereopermutator> stereopermutatorOption;
116 using BglType = boost::adjacency_list<
132 boost::bidirectionalS,
140 class SequenceRuleOneVertexComparator;
143 class SequenceRuleTwoVertexComparator;
146 class SequenceRuleThreeEdgeComparator;
149 class SequenceRuleFourVariantComparator;
152 class SequenceRuleFiveVariantComparator;
155 class VariantHasInstantiatedStereopermutator;
161 class VariantSourceNode;
164 class VariantStereopermutatorStringRepresentation;
170 class VariantLikePair;
173 class GraphvizWriter;
182 using VariantType = boost::variant<TreeVertexIndex, TreeEdgeIndex>;
188 std::vector<TreeVertexIndex> firstPath, secondPath;
204 const std::string adaptedMolGraphviz_;
214 unsigned adjacentTerminalHydrogens_(
const TreeVertexIndex& index)
const;
220 bool isCycleClosureDuplicateVertex_(
const TreeVertexIndex& index)
const;
227 std::vector<TreeVertexIndex> auxiliaryAdjacentsToRank_(
229 const std::vector<TreeVertexIndex>& excludeIndices
233 template<
typename ComparisonSets>
234 bool notEmpty_(
const ComparisonSets& comparisonSets)
const {
237 [](
const auto& mapPair) ->
bool {
238 return !mapPair.second.empty();
247 unsigned nonDuplicateDegree_(
const TreeVertexIndex& index)
const;
256 std::vector<TreeVertexIndex> addBondOrderDuplicates_(
257 const TreeVertexIndex& treeSource,
258 const TreeVertexIndex& treeTarget
262 std::unordered_set<TreeVertexIndex> treeIndicesInBranch_(TreeVertexIndex index)
const;
265 std::unordered_set<AtomIndex> molIndicesInBranch_(TreeVertexIndex index)
const;
268 unsigned duplicateDepth_(TreeVertexIndex index)
const;
271 unsigned depthOfNode_(TreeVertexIndex index)
const;
274 unsigned mixedDepth_(
const TreeVertexIndex& vertexIndex)
const;
277 unsigned mixedDepth_(
const TreeEdgeIndex& edgeIndex)
const;
283 JunctionInfo junction_(
const TreeVertexIndex& a,
const TreeVertexIndex& b)
const;
286 bool molIndexExistsInBranch_(
288 TreeVertexIndex treeIndex
300 std::vector<TreeVertexIndex> expand_(
301 const TreeVertexIndex& index,
302 const std::unordered_set<AtomIndex>& molIndicesInBranch
310 template<
typename SetValueType,
typename ComparatorType>
312 const std::multiset<SetValueType, ComparatorType>& a,
313 const std::multiset<SetValueType, ComparatorType>& b
315 return std::lexicographical_compare(
320 ComparatorType {*
this}
352 template<
typename SetValueType,
typename ComparatorType>
356 std::multiset<SetValueType, ComparatorType>
359 std::vector<TreeVertexIndex>
363 for(
const auto& undecidedSet : undecidedSets) {
365 Temple::Adaptors::allPairs(undecidedSet),
367 if(multisetCompare_(comparisonSets.at(a), comparisonSets.at(b))) {
369 }
else if(multisetCompare_(comparisonSets.at(b), comparisonSets.at(a))) {
377 std::string toString(TreeVertexIndex vertex)
const;
378 std::string toString(
const TreeEdgeIndex& edge)
const;
379 std::string toString(
const VariantType& vertexOrEdge)
const;
403 typename MultisetValueType,
404 typename MultisetComparatorType
409 std::multiset<MultisetValueType, MultisetComparatorType>
418 typename MultisetValueType,
419 typename MultisetComparatorType
420 >
struct EdgeInserter<true, MultisetValueType, MultisetComparatorType> {
424 std::multiset<MultisetValueType, MultisetComparatorType>
429 comparisonSets.at(branchIndex).insert(edgeIndex);
436 typename MultisetValueType,
437 typename MultisetComparatorType
442 std::multiset<MultisetValueType, MultisetComparatorType>
451 typename MultisetValueType,
452 typename MultisetComparatorType
457 std::multiset<MultisetValueType, MultisetComparatorType>
462 comparisonSets.at(branchIndex).insert(vertexIndex);
498 typename MultisetValueType,
499 typename MultisetComparatorType
503 const boost::optional<unsigned>& depthLimitOptional = boost::none
507 insertEdges || insertVertices,
508 "During BFS, you must insert either edges, vertices, or both into the "
509 " comparison sets, but definitely not neither"
515 && !std::is_same<MultisetValueType, TreeVertexIndex>::value
518 && !std::is_same<MultisetValueType, TreeEdgeIndex>::value
520 "Multiset value type and insert booleans are mismatched"
524 if(depthLimitOptional.value_or(std::numeric_limits<unsigned>::max()) == 0) {
542 std::multiset<MultisetValueType, MultisetComparatorType>
554 std::vector<TreeVertexIndex>
560 std::unordered_set<TreeVertexIndex> visitedVertices;
568 visitedVertices.insert(sourceIndex);
573 for(
const auto& undecidedSet : undecidedSets) {
574 for(
const auto& undecidedBranch : undecidedSet) {
575 comparisonSets.emplace(
580 vertexInserter.execute(
588 edgeInserter.execute(
591 boost::edge(sourceIndex, undecidedBranch, tree_).
first
595 auto forwardEdge = boost::edge(sourceIndex, undecidedBranch, tree_);
596 auto backwardEdge = boost::edge(undecidedBranch, sourceIndex, tree_);
598 edgeInserter.execute(
610 seeds[undecidedBranch] = {undecidedBranch};
615 compareBFSSets_(comparisonSets, undecidedSets, orderingHelper);
620 if (buildTypeIsDebug) {
623 Log::particulars.count(Log::Particulars::RankingTreeDebugInfo) > 0
624 && notEmpty_(comparisonSets)
626 std::string header = (
631 ) +
"R"s + std::to_string(ruleNumber)
634 writeGraphvizFiles_({
639 collectSeeds_(seeds, undecidedSets)
661 !undecidedSets.empty()
663 && relevantSeeds_(seeds, undecidedSets)
664 && depth < depthLimitOptional.value_or(std::numeric_limits<unsigned>::max())
667 for(
const auto& undecidedSet: undecidedSets) {
668 for(
const auto& undecidedBranch: undecidedSet) {
677 comparisonSets.at(undecidedBranch).clear();
679 std::vector<TreeVertexIndex> newSeeds;
681 for(
const auto& seed : seeds.at(undecidedBranch)) {
685 visitedVertices.insert(seed);
689 auto inIterPair = boost::in_edges(seed, tree_);
690 inIterPair.first != inIterPair.second;
693 const auto& inEdge = *inIterPair.first;
695 auto edgeSource = boost::source(inEdge, tree_);
698 if(visitedVertices.count(edgeSource) == 0) {
699 vertexInserter.execute(
705 edgeInserter.execute(
711 newSeeds.push_back(edgeSource);
718 auto outIterPair = boost::out_edges(seed, tree_);
719 outIterPair.first != outIterPair.second;
722 const auto& outEdge = *outIterPair.first;
724 auto edgeTarget = boost::target(outEdge, tree_);
727 if(!bfsDownOnly && visitedVertices.count(edgeTarget) > 0) {
731 vertexInserter.execute(
737 edgeInserter.execute(
744 if(!tree_[edgeTarget].isDuplicate) {
745 newSeeds.push_back(edgeTarget);
751 seeds.at(undecidedBranch) = std::move(newSeeds);
756 compareBFSSets_(comparisonSets, undecidedSets, orderingHelper);
764 if (buildTypeIsDebug) {
766 Log::particulars.count(Log::Particulars::RankingTreeDebugInfo) > 0
767 && notEmpty_(comparisonSets)
773 header +=
"R"s + std::to_string(ruleNumber);
775 writeGraphvizFiles_({
780 collectSeeds_(seeds, undecidedSets)
796 static std::unordered_set<TreeVertexIndex> collectSeeds_(
799 std::vector<TreeVertexIndex>
802 std::vector<TreeVertexIndex>
807 template<
typename ValueType,
typename ComparatorType>
809 const std::string& title,
813 std::multiset<ValueType, ComparatorType>
816 std::vector<TreeVertexIndex>
820 std::set<TreeVertexIndex> activeBranches;
821 for(
const auto& set : undecidedSets) {
822 for(
const auto& value : set) {
823 activeBranches.insert(value);
827 struct DisplayGraphVertexData {
828 std::string representation;
831 using DisplayGraph = boost::adjacency_list<
849 DisplayGraphVertexData
852 std::set<TreeVertexIndex> colorVertices;
853 std::set<TreeVertexIndex> squareVertices;
857 auto baseVertex = boost::add_vertex(graph);
858 graph[baseVertex].representation = toString(base);
860 squareVertices.insert(baseVertex);
862 for(
const auto& branchIterPair : comparisonSet) {
863 const auto& treeBranchIndex = branchIterPair.first;
864 const auto& treeBranchMultiset = branchIterPair.second;
866 auto branchVertex = boost::add_vertex(graph);
867 graph[branchVertex].representation = toString(treeBranchIndex);
869 squareVertices.insert(branchVertex);
871 if(activeBranches.count(treeBranchIndex) > 0) {
872 colorVertices.insert(branchVertex);
875 boost::add_edge(baseVertex, branchVertex, graph);
877 typename DisplayGraph::vertex_descriptor continuation = branchVertex;
878 for(
const auto& multisetValue : treeBranchMultiset) {
879 auto newVertex = boost::add_vertex(graph);
880 graph[newVertex].representation = toString(multisetValue);
882 boost::add_edge(continuation, newVertex, graph);
883 continuation = newVertex;
887 class SmallGraphWriter {
889 const DisplayGraph& graphBase_;
890 const std::string title_;
891 const std::set<TreeVertexIndex> colorVertices_;
892 const std::set<TreeVertexIndex> squareVertices_;
896 const DisplayGraph& base,
898 std::set<TreeVertexIndex> colorVertices,
899 std::set<TreeVertexIndex> squareVertices
900 ) : graphBase_(base),
901 title_(std::move(title)),
902 colorVertices_(std::move(colorVertices)),
903 squareVertices_(std::move(squareVertices))
906 void operator() (std::ostream& os)
const {
907 os <<
" graph [fontname = \"Arial\", layout=\"dot\"];\n"
908 <<
" node [fontname = \"Arial\", shape = circle, style = filled];\n"
909 <<
" edge [fontname = \"Arial\"];\n"
910 << R
"( labelloc="t"; label=")" << title_ << "\"\n";
915 const typename DisplayGraph::vertex_descriptor& vertexIndex
917 if(vertexIndex == rootIndex) {
918 os << R
"([label=")" << title_ << "\\n-\\n" << graphBase_[rootIndex].representation << R
"(")";
920 os << R
"([label=")" << graphBase_[vertexIndex].representation << R"(")";
923 if(colorVertices_.count(vertexIndex) > 0) {
924 os << R
"(, fillcolor="tomato", fontcolor="white")";
927 if(squareVertices_.count(vertexIndex) > 0) {
928 os << R
"(, shape="square")";
936 const typename DisplayGraph::edge_descriptor&
941 SmallGraphWriter propertyWriter {graph, title, colorVertices, squareVertices};
943 std::stringstream ss;
945 boost::write_graphviz(
957 std::string _make4BGraph(
958 const TreeVertexIndex& sourceIndex,
961 std::set<VariantType>
962 >& representativeStereodescriptors,
963 const TreeVertexIndex& branchA,
964 const TreeVertexIndex& branchB,
966 std::vector<VariantType>
969 std::vector<VariantType>
972 std::vector<VariantType>
973 >::reverse_iterator& branchAIter,
975 std::vector<VariantType>
976 >::reverse_iterator& branchBIter
981 std::vector<AtomIndex>
984 std::vector<TreeVertexIndex>
1006 static bool relevantSeeds_(
1009 std::vector<TreeVertexIndex>
1012 std::vector<TreeVertexIndex>
1025 void applySequenceRules_(
1026 const boost::optional<AngstromPositions>& positionsOption
1055 std::vector<TreeVertexIndex>
1056 > auxiliaryApplySequenceRules_(
1057 TreeVertexIndex sourceIndex,
1058 const std::vector<TreeVertexIndex>& adjacentsToRank,
1059 const boost::optional<unsigned>& depthLimitOptional = boost::none
1076 std::string molGraphviz,
1078 const std::vector<AtomIndex>& excludeIndices = {},
1079 ExpansionOption expansionMethod = ExpansionOption::OnlyRequiredBranches,
1080 const boost::optional<AngstromPositions>& positionsOption = boost::none
1093 std::vector<AtomIndex>
1094 > getRanked()
const;
1101 std::string dumpGraphviz(
1102 const std::string& title =
"",
1103 const std::unordered_set<TreeVertexIndex>& squareVertices = {},
1104 const std::unordered_set<TreeVertexIndex>& colorVertices = {},
1105 const std::set<TreeEdgeIndex>& colorEdges = {}
OrderDiscoveryHelper< TreeVertexIndex > branchOrderingHelper_
The helper instance for discovering the ordering of the to-rank branches.
Definition: RankingTree.h:199
void compareBFSSets_(const std::map< TreeVertexIndex, std::multiset< SetValueType, ComparatorType > > &comparisonSets, const std::vector< std::vector< TreeVertexIndex > > &undecidedSets, OrderDiscoveryHelper< TreeVertexIndex > &orderingHelper) const
Definition: RankingTree.h:353
std::vector< std::vector< T > > getUndecidedSets() const
Returns grouped data (in descending order) whose internal order is undecided.
Definition: OrderDiscoveryHelper.h:424
Helper struct to insert vertices into the comparion set.
Definition: RankingTree.h:438
BglType::vertex_descriptor TreeVertexIndex
Type of tree vertex accessor.
Definition: RankingTree.h:178
Central class for unified IUPAC-like ranking of organic and inorganic structures. ...
Definition: RankingTree.h:62
Represents the connectivity of atoms of a molecule.
Definition: Graph.h:57
void runBFS_(TreeVertexIndex sourceIndex, OrderDiscoveryHelper< TreeVertexIndex > &orderingHelper, const boost::optional< unsigned > &depthLimitOptional=boost::none) const
Definition: RankingTree.h:500
std::string dumpGraphviz() const
Dumps a graphviz string for visualization of relationships.
Definition: OrderDiscoveryHelper.h:468
Basic Logging functionality for debugging.
Bond distance modelling functions.
Handle arrangements of substituents at corners of an atom-centered shape.
boost::variant< TreeVertexIndex, TreeEdgeIndex > VariantType
Variant type of both.
Definition: RankingTree.h:182
Molecule class interface.
bool isDuplicate
Whether this vertex in the tree represents a duplicate.
Definition: RankingTree.h:101
Manages all stereopermutators that are part of a Molecule.
Definition: StereopermutatorList.h:30
void forEach(const Container &container, Callable &&callable)
Apply a callable for all values of a container.
Definition: Functional.h:165
static unsigned debugMessageCounter_
Definition: RankingTree.h:67
std::size_t AtomIndex
Unsigned integer atom index type. Used to refer to particular atoms.
Definition: Types.h:51
Provides pair-generation within a single container or two.
Handle rotational arrangements of adjacent atom-centered shapes.
Defines a compile-time constant boolean indicating the build type.
constexpr Get< 0 > first
Calls std::get<0> on any argument it is invoked with.
Definition: Functor.h:123
Data class to store junction vertex and paths from the source vertices.
Definition: RankingTree.h:185
ExpansionOption
Definition: RankingTree.h:89
boost::optional< AtomStereopermutator > stereopermutatorOption
A vertex-central stereopermutator may be instantiated here or may not.
Definition: RankingTree.h:104
Graph class to help in gradual discovery of ordering relations.
AtomIndex molIndex
The original molecule index this vertex represents.
Definition: RankingTree.h:99
Helper struct to insert edges into the comparison set.
Definition: RankingTree.h:405
bool notEmpty_(const ComparisonSets &comparisonSets) const
Returns whether any of the comparison multisets has an entry.
Definition: RankingTree.h:234
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
bool multisetCompare_(const std::multiset< SetValueType, ComparatorType > &a, const std::multiset< SetValueType, ComparatorType > &b) const
Definition: RankingTree.h:311
std::string makeBFSStateGraph_(const std::string &title, const TreeVertexIndex &base, const std::map< TreeVertexIndex, std::multiset< ValueType, ComparatorType > > &comparisonSet, const std::vector< std::vector< TreeVertexIndex > > &undecidedSets) const
Creates a graphviz representation of the BFS state.
Definition: RankingTree.h:808
Data class that sets which supplementary data is stored for a tree edge.
Definition: RankingTree.h:111
BglType::edge_descriptor TreeEdgeIndex
Type of tree edge accessor.
Definition: RankingTree.h:180
BglType tree_
The BGL Graph representing the acyclic tree.
Definition: RankingTree.h:196
Data class that sets which supplementary data is stored for a tree vertex.
Definition: RankingTree.h:97
boost::adjacency_list< boost::setS, boost::vecS, boost::bidirectionalS, VertexData, EdgeData > BglType
The BGL Graph type used to store the tree.
Definition: RankingTree.h:137
bool all_of(const Container &container, UnaryPredicate &&predicate=UnaryPredicate{})
all_of shorthand
Definition: Functional.h:244
void addLessThanRelationship(const T &a, const T &b)
Add a less-than relationship to the graph.
Definition: OrderDiscoveryHelper.h:448