Molassembler  3.0.0
Molecule graph and conformer library
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ImplicitBoundsGraph.h
Go to the documentation of this file.
1 
12 #ifndef INCLUDE_DISTANCE_GEOMETRY_IMPLICIT_BOUNDS_GRAPH_H
13 #define INCLUDE_DISTANCE_GEOMETRY_IMPLICIT_BOUNDS_GRAPH_H
14 
15 // #define MOLASSEMBLER_IMPLICIT_GRAPH_USE_SPECIALIZED_GOR1_ALGORITHM
16 
17 #include "boost/property_map/property_map.hpp"
18 #include "Eigen/Core"
20 
23 
24 #include <array>
25 #include <map>
26 #include <tuple>
27 
28 namespace Scine {
29 namespace Molassembler {
30 
31 namespace Random {
32 class Engine;
33 } // namespace Random
34 
35 // Forward-declare PrivateGraph
36 class PrivateGraph;
37 
38 namespace DistanceGeometry {
39 
40 // Forward-declarations
41 class DistanceBoundsMatrix;
42 
144 public:
145  using VertexDescriptor = unsigned long;
146  using EdgeDescriptor = std::pair<VertexDescriptor, VertexDescriptor>;
147 
148  /* To outer indexing */
149  [[gnu::const]] inline static VertexDescriptor left(const VertexDescriptor a) noexcept {
150  return 2 * a;
151  }
152 
153  [[gnu::const]] inline static VertexDescriptor right(const VertexDescriptor a) noexcept {
154  return 2 * a + 1;
155  }
156 
157  [[gnu::const]] inline static VertexDescriptor internal(const VertexDescriptor i) noexcept {
158  // Integer division rounds down, which is perfect
159  return i / 2;
160  }
161 
162 private:
165 
167  std::array<Utils::ElementType, 2> heaviestAtoms_;
168 
170  Eigen::MatrixXd distances_;
171 
172  static void explainContradictionPaths_(
173  VertexDescriptor a,
174  VertexDescriptor b,
175  const std::vector<VertexDescriptor>& predecessors,
176  const std::vector<double>& distances
177  );
178 
179 public:
180  using BoundsMatrix = Eigen::MatrixXd;
181 
183  const PrivateGraph& inner,
184  BoundsMatrix bounds
185  );
186 
187  /* Information */
194  VertexDescriptor num_vertices() const;
195 
202  VertexDescriptor num_edges() const;
203 
213  std::pair<EdgeDescriptor, bool> edge(VertexDescriptor i, VertexDescriptor j) const;
214 
219  bool hasExplicit(const EdgeDescriptor& edge) const;
220 
221  /* To inner indexing */
226  [[gnu::const]] inline static bool isLeft(const VertexDescriptor i) noexcept {
227  return i % 2 == 0;
228  }
229 
230  [[gnu::const]] inline static bool sameSide(const VertexDescriptor i, const VertexDescriptor j) noexcept {
231  return i % 2 == j % 2;
232  }
233 
242  Result<Eigen::MatrixXd> makeDistanceBounds() const noexcept;
243 
259  Result<Eigen::MatrixXd> makeDistanceMatrix(Random::Engine& engine) noexcept;
260 
262  Result<Eigen::MatrixXd> makeDistanceMatrix(Random::Engine& engine, Partiality partiality) noexcept;
263 
268  inline VertexDescriptor source(const EdgeDescriptor& e) const {
269  return e.first;
270  }
271 
276  inline VertexDescriptor target(const EdgeDescriptor& e) const {
277  return e.second;
278  }
279 
284  inline const Eigen::MatrixXd& getMatrix() const {
285  return distances_;
286  }
287 
292  VertexDescriptor out_degree(VertexDescriptor i) const;
293 
294  /* These are all O(1) */
295  double& lowerBound(VertexDescriptor a, VertexDescriptor b);
296  double& upperBound(VertexDescriptor a, VertexDescriptor b);
297 
298  double lowerBound(VertexDescriptor a, VertexDescriptor b) const;
299  double upperBound(VertexDescriptor a, VertexDescriptor b) const;
300 
305  double maximalImplicitLowerBound(VertexDescriptor i) const;
306 
308  struct EdgeWeightMap : public boost::put_get_helper<double, EdgeWeightMap> {
309  using value_type = double;
310  using reference = double;
311  using key_type = EdgeDescriptor;
312 
313  const ImplicitBoundsGraph* basePtr_;
314 
315  EdgeWeightMap(const ImplicitBoundsGraph& base);
316  double operator [] (const EdgeDescriptor& e) const;
317  double operator () (const EdgeDescriptor& e) const;
318  };
319 
322 
324  struct VertexIndexMap : public boost::put_get_helper<VertexDescriptor, VertexIndexMap> {
325  using value_type = VertexDescriptor;
326  using key_type = VertexDescriptor;
327  using reference = VertexDescriptor;
328 
329  inline VertexDescriptor operator [] (const VertexDescriptor v) const { return v; }
330  inline VertexDescriptor operator () (const VertexDescriptor v) const { return v; }
331  };
332 
335  VertexDescriptor index = 0;
336 
337  public:
338  using iterator_category = std::random_access_iterator_tag;
339  using value_type = VertexDescriptor;
340  using difference_type = int;
341  using pointer = VertexDescriptor*;
342  using reference = const VertexDescriptor&;
343 
344  vertex_iterator();
345  vertex_iterator(VertexDescriptor i);
346  vertex_iterator(const vertex_iterator& other);
347  vertex_iterator(vertex_iterator&& other) noexcept;
348  vertex_iterator& operator = (const vertex_iterator& other);
349  vertex_iterator& operator = (vertex_iterator&& other) noexcept;
350 
351  bool operator == (const vertex_iterator& other) const;
352 
353  bool operator != (const vertex_iterator& other) const;
354 
355  vertex_iterator& operator ++ ();
356 
357  vertex_iterator operator ++ (int);
358 
359  vertex_iterator& operator -- ();
360 
361  vertex_iterator operator -- (int);
362 
363  vertex_iterator& operator + (unsigned i);
364 
365  vertex_iterator& operator - (unsigned i);
366 
367  VertexDescriptor operator * () const;
368 
369  int operator - (const vertex_iterator& other) const;
370  };
371 
373  vertex_iterator vbegin () const;
374 
376  vertex_iterator vend() const;
377 
380  const ImplicitBoundsGraph* basePtr_;
381 
382  VertexDescriptor i_, b_;
383  bool crossGroup_;
384 
385  void increment_();
386 
387  public:
388  using iterator_category = std::forward_iterator_tag;
389  using value_type = EdgeDescriptor;
390  using difference_type = int;
391  using pointer = EdgeDescriptor*;
392  using reference = const EdgeDescriptor&;
393 
394  edge_iterator();
396  const ImplicitBoundsGraph& base,
397  VertexDescriptor i
398  );
399  edge_iterator(const edge_iterator& other);
400  edge_iterator(edge_iterator&& other) noexcept;
401  edge_iterator& operator = (const edge_iterator& other);
402  edge_iterator& operator = (edge_iterator&& other) noexcept;
403 
404  edge_iterator& operator ++ ();
405 
406  edge_iterator operator ++ (int);
407 
408  bool operator == (const edge_iterator& other) const;
409 
410  bool operator != (const edge_iterator& other) const;
411 
412  std::string state() const;
413 
414  EdgeDescriptor operator * () const;
415 
416  double weight() const;
417  VertexDescriptor target() const;
418  };
419 
421  edge_iterator ebegin() const;
422 
424  edge_iterator eend() const;
425 
427  edge_iterator obegin(VertexDescriptor i) const;
428 
430  edge_iterator oend(VertexDescriptor i) const;
431 
434  const ImplicitBoundsGraph* basePtr_;
435  VertexDescriptor i_;
436  VertexDescriptor b_;
437  bool isLeft_;
438 
439  public:
440  using iterator_category = std::forward_iterator_tag;
441  using value_type = EdgeDescriptor;
442  using difference_type = int;
443  using pointer = EdgeDescriptor*;
444  using reference = const EdgeDescriptor&;
445 
446  // Default constructor
448  // Constructor for the begin iterator
449  in_group_edge_iterator(const ImplicitBoundsGraph& base, VertexDescriptor i);
450  // Constructor for the end iterator
452  const ImplicitBoundsGraph& base,
453  VertexDescriptor i,
454  bool /* tag */
455  );
458  in_group_edge_iterator& operator = (in_group_edge_iterator&& other) noexcept;
459  in_group_edge_iterator& operator = (const in_group_edge_iterator& other);
460 
461  inline in_group_edge_iterator& operator ++ () {
462  /* Find the next position in the matrix with information
463  * The fastest way to check if there is information is to just access
464  * either the lower or upper bound, and convert the double there to
465  * boolean. That boolean is true only if the double is != 0.
466  */
467  ++b_;
468  while(
469  b_ < static_cast<VertexDescriptor>(basePtr_->distances_.outerSize())
470  && (basePtr_->distances_(internal(i_), b_) == 0.0)
471  ) {
472  ++b_;
473  }
474  return *this;
475  }
476 
477  inline in_group_edge_iterator operator ++ (int) {
478  auto copy = *this;
479  ++(*this);
480  return copy;
481  }
482 
483  inline bool operator == (const in_group_edge_iterator& other) {
484  return (
485  isLeft_ == other.isLeft_
486  && i_ == other.i_
487  && b_ == other.b_
488  && basePtr_ == other.basePtr_
489  );
490  }
491  inline bool operator != (const in_group_edge_iterator& other) {
492  return !(*this == other);
493  }
494 
495  inline EdgeDescriptor operator *() const {
496  return {i_, target()};
497  }
498 
499  inline VertexDescriptor target() const {
500  if(isLeft_) {
501  return left(b_);
502  }
503 
504  return right(b_);
505  }
506 
507  inline double weight() const {
508  return basePtr_->upperBound(internal(i_), b_);
509  }
510  };
511 
512  inline in_group_edge_iterator in_group_edges_begin(const VertexDescriptor i) const {
513  return {*this, i};
514  }
515 
516  inline in_group_edge_iterator in_group_edges_end(const VertexDescriptor i) const {
517  return {*this, i, true};
518  }
519 };
520 
521 } // namespace DistanceGeometry
522 } // namespace Molassembler
523 } // namespace Scine
524 
525 #endif
VertexDescriptor num_edges() const
Returns the number of edges currently simulated by the graph.
Result< Eigen::MatrixXd > makeDistanceMatrix(Random::Engine &engine) noexcept
Generates a distance matrix by randomly fixing distances within triangle inequality bounds...
VertexDescriptor num_vertices() const
Returns the number of vertices simulated by the graph, which is 2N.
A helper struct to turn vertex descriptors into numeric indices.
Definition: ImplicitBoundsGraph.h:324
Result< Eigen::MatrixXd > makeDistanceBounds() const noexcept
Generates a bare distance bounds matrix by repeated shortest-paths calculations.
VertexDescriptor out_degree(VertexDescriptor i) const
Returns the number of out-edges for a particular vertex.
std::pair< EdgeDescriptor, bool > edge(VertexDescriptor i, VertexDescriptor j) const
Fetches an edge descriptor for a speculative edge from i to j.
const Eigen::MatrixXd & getMatrix() const
Allows const-ref access to the underlying matrix for debug purposes.
Definition: ImplicitBoundsGraph.h:284
Simulates a graph from which triangle inequality bounds can be calculated by shortest-paths.
Definition: ImplicitBoundsGraph.h:143
edge_iterator eend() const
Returns an end edge iterator.
vertex_iterator vbegin() const
Returns a begin-iterator for vertices.
VertexDescriptor target(const EdgeDescriptor &e) const
Returns the target vertex from an edge descriptor.
Definition: ImplicitBoundsGraph.h:276
A helper struct permitting read-access to an edge weight via an edge descriptor.
Definition: ImplicitBoundsGraph.h:308
Data struct for storing a numeric interval.
Library internal graph class wrapping BGL types.
Definition: PrivateGraph.h:26
VertexDescriptor source(const EdgeDescriptor &e) const
Returns the source vertex from an edge descriptor.
Definition: ImplicitBoundsGraph.h:268
An iterator to enumerate all edges in a graph.
Definition: ImplicitBoundsGraph.h:379
edge_iterator oend(VertexDescriptor i) const
Returns an end edge iterator for the out-edges of a specific vertex.
bool hasExplicit(const EdgeDescriptor &edge) const
Checks if there is explicit information present for a left-to-right edge.
edge_iterator obegin(VertexDescriptor i) const
Returns a begin edge iterator for the out-edges of a specific vertex.
std::array< Utils::ElementType, 2 > heaviestAtoms_
Stores the two heaviest element types.
Definition: ImplicitBoundsGraph.h:167
vertex_iterator vend() const
Returns an end-iterator for vertices.
Eigen::MatrixXd distances_
Dense adjacency matrix for O(1) access to fixed distances.
Definition: ImplicitBoundsGraph.h:170
static bool isLeft(const VertexDescriptor i) noexcept
Check if a vertex descriptor is part of the left subgraph.
Definition: ImplicitBoundsGraph.h:226
A random access iterator through all vertex descriptors of the graph.
Definition: ImplicitBoundsGraph.h:334
An iterator to enumerate only edges to the same part of the graph from specific vertices.
Definition: ImplicitBoundsGraph.h:433
EdgeWeightMap getEdgeWeightPropertyMap() const
Returns an instance of EdgeWeightMap.
const PrivateGraph * innerGraphPtr_
Pointer to molecule from which the bounds come from.
Definition: ImplicitBoundsGraph.h:164
edge_iterator ebegin() const
Returns a begin edge iterator.
Interface for the generation of new conformations of Molecules.
Partiality
Limit triangle inequality bounds smoothing to a subset of all atoms.
Definition: Conformers.h:42
double maximalImplicitLowerBound(VertexDescriptor i) const
Returns the length of the maximal implicit lower bound outgoing from a left vertex.