Molassembler  1.0.0
Molecule graph and conformer library
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
RankingTree.h
Go to the documentation of this file.
1 
31 #ifndef INCLUDE_MOLASSEMBLER_RANKING_HIERARCHICAL_TREE_H
32 #define INCLUDE_MOLASSEMBLER_RANKING_HIERARCHICAL_TREE_H
33 
34 #include "boost/variant.hpp"
35 
40 #include "Molassembler/Log.h"
41 #include "Molassembler/Molecule.h"
43 
45 
46 using namespace std::string_literals;
47 
48 namespace Scine {
49 namespace Molassembler {
50 
62 class RankingTree {
63 private:
67  static unsigned debugMessageCounter_;
68 
72  static std::string adaptMolGraph_(std::string molGraph);
73 
75  static void writeGraphvizFiles_(
76  const std::vector<std::string>& graphvizStrings
77  );
78 
79 public:
82 
89  enum class ExpansionOption {
91  OnlyRequiredBranches,
93  Full
94  };
95 
97  struct VertexData {
102 
104  boost::optional<AtomStereopermutator> stereopermutatorOption;
105 
106  // This is the place for eventual atomic number deviations
107  // boost::optional<double> deviantAtomicNumber;
108  };
109 
111  struct EdgeData {
112  boost::optional<BondStereopermutator> stereopermutatorOption;
113  };
114 
116  using BglType = boost::adjacency_list<
117  /* OutEdgeListS = Type of Container for edges of a vertex
118  * Options: vector, list, slist, set, multiset, unordered_set
119  * Choice: setS
120  */
121  boost::setS,
122  /* VertexListS = Type of Container for vertices
123  * Options: vector, list, slist, set, multiset, unordered_set
124  * Choice: vecS, removing vertices does not occur
125  */
126  boost::vecS,
127  /* DirectedS = Is the graph directed or not?
128  * Choice: Bidirectional. Although a tree is merely directional, and not
129  * bi-directional, we nevertheless also need fast access to in_edges, so
130  * we choose bidirectional
131  */
132  boost::bidirectionalS,
133  // VertexProperty = What information is stored about vertices?
134  VertexData,
135  // EdgeProperty = What information is stored about edges?
136  EdgeData
137  >;
138 
139  // IUPAC Sequence rule one tree vertex comparator
140  class SequenceRuleOneVertexComparator;
141 
142  // IUPAC Sequence rule two tree vertex comparator
143  class SequenceRuleTwoVertexComparator;
144 
145  // IUPAC Sequence rule three tree edge comparator
146  class SequenceRuleThreeEdgeComparator;
147 
148  // IUPAC Sequence rule four tree vertex and edge mixed comparator
149  class SequenceRuleFourVariantComparator;
150 
151  // IUPAC Sequence rule five tree vertex and edge mixed comparator
152  class SequenceRuleFiveVariantComparator;
153 
154  // Returns whether the vertex or edge has an instantiated Stereopermutator
155  class VariantHasInstantiatedStereopermutator;
156 
157  // Returns the mixed depth (see mixedDepth_ functions) of the vertex or edge
158  class VariantDepth;
159 
160  // Returns the source node of a vertex (identity) or an edge (source node)
161  class VariantSourceNode;
162 
163  // Returns a string representation of the stereopermutator on vertex or edge
164  class VariantStereopermutatorStringRepresentation;
165 
166  /*
167  * Returns whether two variants' stereopermutators form a like pair or not
168  * according to the sub-rules in IUPAC sequence rule four.
169  */
170  class VariantLikePair;
171 
173  class GraphvizWriter;
175 
176 private:
178  using TreeVertexIndex = BglType::vertex_descriptor;
180  using TreeEdgeIndex = BglType::edge_descriptor;
182  using VariantType = boost::variant<TreeVertexIndex, TreeEdgeIndex>;
183 
185  struct JunctionInfo {
186  TreeVertexIndex junction;
187 
188  std::vector<TreeVertexIndex> firstPath, secondPath;
189  };
190 
192  static constexpr TreeVertexIndex rootIndex = 0;
193 
194 /* State */
197 
200 
201  // Closures
202  const Graph& graph_;
203  const StereopermutatorList& stereopermutatorsRef_;
204  const std::string adaptedMolGraphviz_;
205 
206 /* Minor helper classes and functions */
208  TreeVertexIndex parent_(const TreeVertexIndex& index) const;
209 
211  std::vector<TreeVertexIndex> adjacents_(TreeVertexIndex index) const;
212 
214  unsigned adjacentTerminalHydrogens_(const TreeVertexIndex& index) const;
215 
217  bool isBondSplitDuplicateVertex_(const TreeVertexIndex& index) const;
218 
220  bool isCycleClosureDuplicateVertex_(const TreeVertexIndex& index) const;
221 
227  std::vector<TreeVertexIndex> auxiliaryAdjacentsToRank_(
228  TreeVertexIndex sourceIndex,
229  const std::vector<TreeVertexIndex>& excludeIndices
230  ) const;
231 
233  template<typename ComparisonSets>
234  bool notEmpty_(const ComparisonSets& comparisonSets) const {
235  return Temple::all_of(
236  comparisonSets,
237  [](const auto& mapPair) -> bool {
238  return !mapPair.second.empty();
239  }
240  );
241  }
242 
247  unsigned nonDuplicateDegree_(const TreeVertexIndex& index) const;
248 
256  std::vector<TreeVertexIndex> addBondOrderDuplicates_(
257  const TreeVertexIndex& treeSource,
258  const TreeVertexIndex& treeTarget
259  );
260 
262  std::unordered_set<TreeVertexIndex> treeIndicesInBranch_(TreeVertexIndex index) const;
263 
265  std::unordered_set<AtomIndex> molIndicesInBranch_(TreeVertexIndex index) const;
266 
268  unsigned duplicateDepth_(TreeVertexIndex index) const;
269 
271  unsigned depthOfNode_(TreeVertexIndex index) const;
272 
274  unsigned mixedDepth_(const TreeVertexIndex& vertexIndex) const;
275 
277  unsigned mixedDepth_(const TreeEdgeIndex& edgeIndex) const;
278 
283  JunctionInfo junction_(const TreeVertexIndex& a, const TreeVertexIndex& b) const;
284 
286  bool molIndexExistsInBranch_(
287  AtomIndex molIndex,
288  TreeVertexIndex treeIndex
289  ) const;
290 
291 /* Major helper functions */
300  std::vector<TreeVertexIndex> expand_(
301  const TreeVertexIndex& index,
302  const std::unordered_set<AtomIndex>& molIndicesInBranch
303  );
304 
310  template<typename SetValueType, typename ComparatorType>
312  const std::multiset<SetValueType, ComparatorType>& a,
313  const std::multiset<SetValueType, ComparatorType>& b
314  ) const {
315  return std::lexicographical_compare(
316  std::begin(a),
317  std::end(a),
318  std::begin(b),
319  std::end(b),
320  ComparatorType {*this}
321  );
322  }
323 
352  template<typename SetValueType, typename ComparatorType>
354  const std::map<
356  std::multiset<SetValueType, ComparatorType>
357  >& comparisonSets,
358  const std::vector<
359  std::vector<TreeVertexIndex>
360  >& undecidedSets,
362  ) const {
363  for(const auto& undecidedSet : undecidedSets) {
365  Temple::Adaptors::allPairs(undecidedSet),
366  [&](const TreeVertexIndex a, const TreeVertexIndex b) {
367  if(multisetCompare_(comparisonSets.at(a), comparisonSets.at(b))) {
368  orderingHelper.addLessThanRelationship(a, b);
369  } else if(multisetCompare_(comparisonSets.at(b), comparisonSets.at(a))) {
370  orderingHelper.addLessThanRelationship(b, a);
371  }
372  }
373  );
374  }
375  }
376 
377  std::string toString(TreeVertexIndex vertex) const;
378  std::string toString(const TreeEdgeIndex& edge) const;
379  std::string toString(const VariantType& vertexOrEdge) const;
380 
381  /* Some helper structs to get runBFS_ to compile smoothly. Although the
382  * boolean template parameters to runBFS_ are logically constexpr, and any
383  * false branches of if (boolean template parameter) are removed during
384  * optimization, they must compile! This requirement is removed in C++17
385  * if-constexpr structures.
386  *
387  * So EdgeInserter and VertexInserter's primary template (with boolean
388  * parameter specifying whether they should perform a task or not) does
389  * nothing, and there is a partial template specialization for the case
390  * that the boolean template parameter is true, in which case the task is
391  * performed.
392  *
393  * Classes are necessary since partial function specialization is impossible.
394  *
395  * When modernizing the code to C++17, remove those classes and employ much
396  * more legible if-constexpr in all ifs in runBFS_ using only constexpr
397  * template parameters.
398  */
399 
401  template<
402  bool insertEdges,
403  typename MultisetValueType,
404  typename MultisetComparatorType
405  > struct EdgeInserter {
406  static void execute(
407  std::map<
409  std::multiset<MultisetValueType, MultisetComparatorType>
410  >& /* comparisonSets */,
411  const TreeVertexIndex& /* branchIndex */,
412  const TreeEdgeIndex& /* edgeIndex */
413  ) { /* do nothing */ }
414  };
415 
417  template<
418  typename MultisetValueType,
419  typename MultisetComparatorType
420  > struct EdgeInserter<true, MultisetValueType, MultisetComparatorType> {
421  static void execute(
422  std::map<
424  std::multiset<MultisetValueType, MultisetComparatorType>
425  >& comparisonSets,
426  const TreeVertexIndex& branchIndex,
427  const TreeEdgeIndex& edgeIndex
428  ) {
429  comparisonSets.at(branchIndex).insert(edgeIndex);
430  }
431  };
432 
434  template<
435  bool insertVertices,
436  typename MultisetValueType,
437  typename MultisetComparatorType
438  > struct VertexInserter {
439  static void execute(
440  std::map<
442  std::multiset<MultisetValueType, MultisetComparatorType>
443  >& /* comparisonSets */,
444  const TreeVertexIndex& /* branchIndex */,
445  const TreeVertexIndex& /* vertexIndex */
446  ) { /* do nothing */ }
447  };
448 
450  template<
451  typename MultisetValueType,
452  typename MultisetComparatorType
453  > struct VertexInserter<true, MultisetValueType, MultisetComparatorType> {
454  static void execute(
455  std::map<
457  std::multiset<MultisetValueType, MultisetComparatorType>
458  >& comparisonSets,
459  const TreeVertexIndex& branchIndex,
460  const TreeVertexIndex& vertexIndex
461  ) {
462  comparisonSets.at(branchIndex).insert(vertexIndex);
463  }
464  };
465 
493  template<
494  unsigned ruleNumber,
495  bool bfsDownOnly,
496  bool insertEdges,
497  bool insertVertices,
498  typename MultisetValueType,
499  typename MultisetComparatorType
500  > void runBFS_(
501  TreeVertexIndex sourceIndex,
503  const boost::optional<unsigned>& depthLimitOptional = boost::none
504  ) const {
505  /* Static safety checks */
506  static_assert(
507  insertEdges || insertVertices,
508  "During BFS, you must insert either edges, vertices, or both into the "
509  " comparison sets, but definitely not neither"
510  );
511 
512  static_assert(
513  (
514  insertEdges
515  && !std::is_same<MultisetValueType, TreeVertexIndex>::value
516  ) || (
517  insertVertices
518  && !std::is_same<MultisetValueType, TreeEdgeIndex>::value
519  ),
520  "Multiset value type and insert booleans are mismatched"
521  );
522 
523  // Check if depthLimit prohibits first comparison too
524  if(depthLimitOptional.value_or(std::numeric_limits<unsigned>::max()) == 0) {
525  return;
526  }
527 
528  /* Declarations */
529 
530  /* For each branch to compare, keep a multiset of all the encountered
531  * indices in the branch. The multiset keeps a descending order of the
532  * indices according to sequence rule 1 and can be lexicographically
533  * compared against one another using the SequenceRuleOneVertexComparator
534  *
535  * NOTE: Do not use operator [] to access members in comparisonSets. This
536  * old form of accessible and assignable proxy object forces a
537  * default-instantiation of the Comparator, which the
538  * MultisetComparatorTypes cannot do. Always use .at().
539  */
540  std::map<
542  std::multiset<MultisetValueType, MultisetComparatorType>
543  > comparisonSets;
544 
545  /* For each branch to compare, keep a set of seed indices to follow in an
546  * iteration. These are expanded in each iteration as long as the branch
547  * they contain remains relevant (i.e. its relation to the other branches
548  * is still unclear): They themselves are placed in the comparisonSet,
549  * while their respective adjacents are the new seeds for the next
550  * iteration.
551  */
552  std::map<
553  TreeVertexIndex,
554  std::vector<TreeVertexIndex>
555  > seeds;
556 
557  /* In case the BFS in not down-only, we have to track which indices we
558  * have visited to ensure BFS doesn't backtrack or reuse vertices.
559  */
560  std::unordered_set<TreeVertexIndex> visitedVertices;
561 
562 
563  /* Initialization */
566 
567  if(!bfsDownOnly) { // Initialization is only necessary in this case
568  visitedVertices.insert(sourceIndex);
569  }
570 
571  auto undecidedSets = orderingHelper.getUndecidedSets();
572 
573  for(const auto& undecidedSet : undecidedSets) {
574  for(const auto& undecidedBranch : undecidedSet) {
575  comparisonSets.emplace(
576  undecidedBranch,
577  *this
578  );
579 
580  vertexInserter.execute(
581  comparisonSets,
582  undecidedBranch,
583  undecidedBranch
584  );
585 
586  if(insertEdges) {
587  if(bfsDownOnly) {
588  edgeInserter.execute(
589  comparisonSets,
590  undecidedBranch,
591  boost::edge(sourceIndex, undecidedBranch, tree_).first
592  );
593  } else {
594  // Need to be direction-agnostic
595  auto forwardEdge = boost::edge(sourceIndex, undecidedBranch, tree_);
596  auto backwardEdge = boost::edge(undecidedBranch, sourceIndex, tree_);
597 
598  edgeInserter.execute(
599  comparisonSets,
600  undecidedBranch,
601  (
602  forwardEdge.second
603  ? forwardEdge.first
604  : backwardEdge.first
605  )
606  );
607  }
608  }
609 
610  seeds[undecidedBranch] = {undecidedBranch};
611  }
612  }
613 
614  // Compare undecided multisets, and add any discoveries to the ordering helper
615  compareBFSSets_(comparisonSets, undecidedSets, orderingHelper);
616 
617  // Update the undecided sets
618  undecidedSets = orderingHelper.getUndecidedSets();
619 
620  if /* C++17 constexpr */ (buildTypeIsDebug) {
621  // Write debug graph files if the corresponding log particular is set
622  if(
623  Log::particulars.count(Log::Particulars::RankingTreeDebugInfo) > 0
624  && notEmpty_(comparisonSets)
625  ) {
626  std::string header = (
627  (
628  bfsDownOnly
629  ? ""s
630  : "aux "s
631  ) + "R"s + std::to_string(ruleNumber)
632  );
633 
634  writeGraphvizFiles_({
635  adaptedMolGraphviz_,
636  dumpGraphviz(
637  header,
638  {sourceIndex},
639  collectSeeds_(seeds, undecidedSets)
640  ),
641  makeBFSStateGraph_(
642  header,
643  sourceIndex,
644  comparisonSets,
645  undecidedSets
646  ),
647  orderingHelper.dumpGraphviz()
648  });
649  }
650  }
651 
652  unsigned depth = 1;
653 
654  /* Loop BFS */
655 
656  /* As long as there are undecided sets and seeds whose expansion could be
657  * relevant for those undecided sets, continue BFS
658  */
659  while(
660  // Undecided indices remain
661  !undecidedSets.empty()
662  // Seeds exist that are relevant to the undecided sets
663  && relevantSeeds_(seeds, undecidedSets)
664  && depth < depthLimitOptional.value_or(std::numeric_limits<unsigned>::max())
665  ) {
666  // BFS Step
667  for(const auto& undecidedSet: undecidedSets) {
668  for(const auto& undecidedBranch: undecidedSet) {
669  /* Clear the comparison set at undecided branches prior to inserting
670  * anything. This doesn't change anything semantically, since
671  * everything from the prior iteration (or initialization) must have
672  * compared equal within this undecidedSet.
673  *
674  * Makes for cleaner visualization and reduces the number of
675  * Comparator calls during insert and lexicographical_compare.
676  */
677  comparisonSets.at(undecidedBranch).clear();
678 
679  std::vector<TreeVertexIndex> newSeeds;
680 
681  for(const auto& seed : seeds.at(undecidedBranch)) {
682 
683  if(!bfsDownOnly) {
684  // Mark as visited
685  visitedVertices.insert(seed);
686 
687  // In-edges are only relevant for omnidirectional BFS
688  for(
689  auto inIterPair = boost::in_edges(seed, tree_);
690  inIterPair.first != inIterPair.second;
691  ++inIterPair.first
692  ) {
693  const auto& inEdge = *inIterPair.first;
694 
695  auto edgeSource = boost::source(inEdge, tree_);
696 
697  // Check if already placed
698  if(visitedVertices.count(edgeSource) == 0) {
699  vertexInserter.execute(
700  comparisonSets,
701  undecidedBranch,
702  edgeSource
703  );
704 
705  edgeInserter.execute(
706  comparisonSets,
707  undecidedBranch,
708  inEdge
709  );
710 
711  newSeeds.push_back(edgeSource);
712  }
713  }
714  }
715 
716  // Out edges are considered in all cases
717  for( // Out-edges
718  auto outIterPair = boost::out_edges(seed, tree_);
719  outIterPair.first != outIterPair.second;
720  ++outIterPair.first
721  ) {
722  const auto& outEdge = *outIterPair.first;
723 
724  auto edgeTarget = boost::target(outEdge, tree_);
725 
726  // Skip this vertex if in omnidirectional BFS and already-seen node
727  if(!bfsDownOnly && visitedVertices.count(edgeTarget) > 0) {
728  continue;
729  }
730 
731  vertexInserter.execute(
732  comparisonSets,
733  undecidedBranch,
734  edgeTarget
735  );
736 
737  edgeInserter.execute(
738  comparisonSets,
739  undecidedBranch,
740  outEdge
741  );
742 
743  // Add out edge target to seeds only if non-terminal
744  if(!tree_[edgeTarget].isDuplicate) {
745  newSeeds.push_back(edgeTarget);
746  }
747  }
748  }
749 
750  // Overwrite seeds
751  seeds.at(undecidedBranch) = std::move(newSeeds);
752  }
753  }
754 
755  // Make comparisons in all undecided sets
756  compareBFSSets_(comparisonSets, undecidedSets, orderingHelper);
757 
758  // Recalculate the undecided sets
759  undecidedSets = orderingHelper.getUndecidedSets();
760 
761  // Increment depth
762  ++depth;
763 
764  if /* C++17 constexpr */ (buildTypeIsDebug) {
765  if(
766  Log::particulars.count(Log::Particulars::RankingTreeDebugInfo) > 0
767  && notEmpty_(comparisonSets)
768  ) {
769  std::string header;
770  if(!bfsDownOnly) {
771  header += "aux "s;
772  }
773  header += "R"s + std::to_string(ruleNumber);
774 
775  writeGraphvizFiles_({
776  adaptedMolGraphviz_,
777  dumpGraphviz(
778  header,
779  {sourceIndex},
780  collectSeeds_(seeds, undecidedSets)
781  ),
782  makeBFSStateGraph_(
783  header,
784  sourceIndex,
785  comparisonSets,
786  undecidedSets
787  ),
788  orderingHelper.dumpGraphviz()
789  });
790  }
791  }
792  }
793  }
794 
795  // Flatten the undecided branches' seeds into a single set
796  static std::unordered_set<TreeVertexIndex> collectSeeds_(
797  const std::map<
798  TreeVertexIndex,
799  std::vector<TreeVertexIndex>
800  >& seeds,
801  const std::vector<
802  std::vector<TreeVertexIndex>
803  >& undecidedSets
804  );
805 
807  template<typename ValueType, typename ComparatorType>
808  std::string makeBFSStateGraph_(
809  const std::string& title,
810  const TreeVertexIndex& base,
811  const std::map<
813  std::multiset<ValueType, ComparatorType>
814  >& comparisonSet,
815  const std::vector<
816  std::vector<TreeVertexIndex>
817  >& undecidedSets
818  ) const {
819 
820  std::set<TreeVertexIndex> activeBranches;
821  for(const auto& set : undecidedSets) {
822  for(const auto& value : set) {
823  activeBranches.insert(value);
824  }
825  }
826 
827  struct DisplayGraphVertexData {
828  std::string representation;
829  };
830 
831  using DisplayGraph = boost::adjacency_list<
832  /* OutEdgeListS = Type of Container for edges of a vertex
833  * Options: vector, list, slist, set, multiset, unordered_set
834  * Choice: setS
835  */
836  boost::setS,
837  /* VertexListS = Type of Container for vertices
838  * Options: vector, list, slist, set, multiset, unordered_set
839  * Choice: vecS, removing vertices does not occur
840  */
841  boost::vecS,
842  /* DirectedS = Is the graph directed or not?
843  * Choice: Directed, do not need bidirectional
844  */
845  boost::directedS,
846  /* VertexProperty = What information is stored about vertices?
847  * Choice: Atom, containing an index and an element type
848  */
849  DisplayGraphVertexData
850  >;
851 
852  std::set<TreeVertexIndex> colorVertices;
853  std::set<TreeVertexIndex> squareVertices;
854 
855  DisplayGraph graph;
856 
857  auto baseVertex = boost::add_vertex(graph);
858  graph[baseVertex].representation = toString(base);
859 
860  squareVertices.insert(baseVertex);
861 
862  for(const auto& branchIterPair : comparisonSet) {
863  const auto& treeBranchIndex = branchIterPair.first;
864  const auto& treeBranchMultiset = branchIterPair.second;
865 
866  auto branchVertex = boost::add_vertex(graph);
867  graph[branchVertex].representation = toString(treeBranchIndex);
868 
869  squareVertices.insert(branchVertex);
870 
871  if(activeBranches.count(treeBranchIndex) > 0) {
872  colorVertices.insert(branchVertex);
873  }
874 
875  boost::add_edge(baseVertex, branchVertex, graph);
876 
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);
881 
882  boost::add_edge(continuation, newVertex, graph);
883  continuation = newVertex;
884  }
885  }
886 
887  class SmallGraphWriter {
888  private:
889  const DisplayGraph& graphBase_;
890  const std::string title_;
891  const std::set<TreeVertexIndex> colorVertices_;
892  const std::set<TreeVertexIndex> squareVertices_;
893 
894  public:
895  SmallGraphWriter(
896  const DisplayGraph& base,
897  std::string title,
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))
904  {}
905 
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";
911  }
912 
913  void operator() (
914  std::ostream& os,
915  const typename DisplayGraph::vertex_descriptor& vertexIndex
916  ) const {
917  if(vertexIndex == rootIndex) {
918  os << R"([label=")" << title_ << "\\n-\\n" << graphBase_[rootIndex].representation << R"(")";
919  } else {
920  os << R"([label=")" << graphBase_[vertexIndex].representation << R"(")";
921  }
922 
923  if(colorVertices_.count(vertexIndex) > 0) {
924  os << R"(, fillcolor="tomato", fontcolor="white")";
925  }
926 
927  if(squareVertices_.count(vertexIndex) > 0) {
928  os << R"(, shape="square")";
929  }
930 
931  os << R"(])";
932  }
933 
934  void operator() (
935  std::ostream& /* os */,
936  const typename DisplayGraph::edge_descriptor& /* edge */
937  ) const { /* do nothing particular for edges */ }
938 
939  };
940 
941  SmallGraphWriter propertyWriter {graph, title, colorVertices, squareVertices};
942 
943  std::stringstream ss;
944 
945  boost::write_graphviz(
946  ss,
947  graph,
948  propertyWriter,
949  propertyWriter,
950  propertyWriter
951  );
952 
953  return ss.str();
954  }
955 
957  std::string _make4BGraph(
958  const TreeVertexIndex& sourceIndex,
959  const std::map<
960  TreeVertexIndex,
961  std::set<VariantType>
962  >& representativeStereodescriptors,
963  const TreeVertexIndex& branchA,
964  const TreeVertexIndex& branchB,
965  const std::vector<
966  std::vector<VariantType>
967  >& branchAOrders,
968  const std::vector<
969  std::vector<VariantType>
970  >& branchBOrders,
971  const std::vector<
972  std::vector<VariantType>
973  >::reverse_iterator& branchAIter,
974  const std::vector<
975  std::vector<VariantType>
976  >::reverse_iterator& branchBIter
977  ) const;
978 
980  std::vector<
981  std::vector<AtomIndex>
982  > mapToAtomIndices_(
983  const std::vector<
984  std::vector<TreeVertexIndex>
985  >& treeRankingSets
986  ) const;
987 
1006  static bool relevantSeeds_(
1007  const std::map<
1008  TreeVertexIndex,
1009  std::vector<TreeVertexIndex>
1010  >& seeds,
1011  const std::vector<
1012  std::vector<TreeVertexIndex>
1013  >& undecidedSets
1014  );
1015 
1025  void applySequenceRules_(
1026  const boost::optional<AngstromPositions>& positionsOption
1027  );
1028 
1054  std::vector<
1055  std::vector<TreeVertexIndex>
1056  > auxiliaryApplySequenceRules_(
1057  TreeVertexIndex sourceIndex,
1058  const std::vector<TreeVertexIndex>& adjacentsToRank,
1059  const boost::optional<unsigned>& depthLimitOptional = boost::none
1060  ) const;
1061 
1062 public:
1065 
1073  RankingTree(
1074  const Graph& graph,
1075  const StereopermutatorList& stereopermutators,
1076  std::string molGraphviz,
1077  AtomIndex atomToRank,
1078  const std::vector<AtomIndex>& excludeIndices = {},
1079  ExpansionOption expansionMethod = ExpansionOption::OnlyRequiredBranches,
1080  const boost::optional<AngstromPositions>& positionsOption = boost::none
1081  );
1083 
1086 
1092  std::vector<
1093  std::vector<AtomIndex>
1094  > getRanked() const;
1095 
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 = {}
1106  ) const;
1108 };
1109 
1110 } // namespace Molassembler
1111 } // namespace Scine
1112 
1113 #endif
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&lt;0&gt; 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