Primitive

Data Structures

struct  primitive::Vertex
 This is a collection of elements, for each point, required for graph traversal. More...
 
struct  primitive::Graph
 This is a per-frame object, containing all the vertices for the particular frame, along with the vector of rings generated. More...
 

Functions

std::vector< std::vector< int > > primitive::ringNetwork (std::vector< std::vector< int >> nList, int maxDepth)
 
Graph primitive::populateGraphFromNListID (molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> neighHbondList)
 
Graph primitive::populateGraphFromIndices (std::vector< std::vector< int >> nList)
 
Graph primitive::restoreEdgesFromIndices (Graph *fullGraph, std::vector< std::vector< int >> nList)
 
Graph primitive::countAllRingsFromIndex (std::vector< std::vector< int >> neighHbondList, int maxDepth)
 Creates a vector of vectors of all possible rings. More...
 
Graph primitive::removeNonSPrings (Graph *fullGraph)
 Removes the non-SP rings, using the Franzblau shortest path criterion. More...
 
int primitive::findRings (Graph *fullGraph, int v, std::vector< int > *visited, int maxDepth, int depth, int root=-1)
 Main function that searches for all rings. More...
 
int primitive::shortestPath (Graph *fullGraph, int v, int goal, std::vector< int > *path, std::vector< int > *visited, int maxDepth, int depth=1)
 Calculates the shortest path. More...
 
Graph primitive::clearGraph (Graph *currentGraph)
 Function for clearing vectors in Graph after multiple usage. More...
 

Variables

int primitive::Vertex::atomIndex
 
std::vector< int > primitive::Vertex::neighListIndex
 This is the index according to pointCloud. More...
 
bool primitive::Vertex::inGraph
 
std::vector< Vertexprimitive::Graph::pts
 
std::vector< std::vector< int > > primitive::Graph::rings
 

Detailed Description

Function Documentation

◆ clearGraph()

primitive::Graph primitive::clearGraph ( Graph currentGraph)

Function for clearing vectors in Graph after multiple usage.

Function for clearing Graph if it is already filled. This should be called before every frame is read in.

Parameters
[out]currentGraphThe cleared Graph

Definition at line 444 of file franzblau.cpp.

444  {
445  //
447  std::vector<std::vector<int>> tempRings;
448  tempPts.swap(currentGraph->pts);
449  tempRings.swap(currentGraph->rings);
450  return *currentGraph;
451 }
T swap(T... args)

◆ countAllRingsFromIndex()

primitive::Graph primitive::countAllRingsFromIndex ( std::vector< std::vector< int >>  neighHbondList,
int  maxDepth 
)

Creates a vector of vectors of all possible rings.

Get all possible rings (only atom indices, not IDs). The input neighbour list is in terms of indices. All possible rings (including non-SP) rings are generated using a recursive backtracking algorithm. This function calls the following functions internally:

  • primitive::populateGraphFromIndices (for initializing the Graph object)
  • primitive::findRings (for getting all rings, using backtracking)
  • primitive::restoreEdgesFromIndices (restores back-up of the edges since some may have been removed)
    Parameters
    [in]neighHbondListRow-ordered neighbour list by atom index (not ID).
    [in]maxDepthThe maximum depth upto which rings will be searched. This means that rings larger than maxDepth will not be generated.
    Returns
    The Graph object for the current frame.

Definition at line 64 of file franzblau.cpp.

65  {
66  //
67  primitive::Graph fullGraph; // Graph object
69  visited; // Contains the indices (NOT IDs) visited for a particular node
70  int depth; // Current depth
71 
72  // ------------------------------
73  // Init
74  // Initialize the graph object with all the information from the neighbour
75  // list (of indices only)
76  fullGraph = primitive::populateGraphFromIndices(neighHbondList);
77  // ------------------------------
78  // Loop through every vertex
79  for (int iatom = 0; iatom < neighHbondList.size(); iatom++) {
80  visited.clear();
81  depth = 0;
82  // Call the function for getting rings
83  primitive::findRings(&fullGraph, iatom, &visited, maxDepth, depth);
84  } // loop through every vertex
85  // ------------------------------
86  // Restore back-up of the edges (some may have been removed)
87  fullGraph = primitive::restoreEdgesFromIndices(&fullGraph, neighHbondList);
88  // ------------------------------
89 
90  return fullGraph;
91 }
T clear(T... args)
Graph restoreEdgesFromIndices(Graph *fullGraph, std::vector< std::vector< int >> nList)
Definition: franzblau.cpp:283
Graph populateGraphFromIndices(std::vector< std::vector< int >> nList)
Definition: franzblau.cpp:248
int findRings(Graph *fullGraph, int v, std::vector< int > *visited, int maxDepth, int depth, int root=-1)
Main function that searches for all rings.
Definition: franzblau.cpp:116
T size(T... args)
This is a per-frame object, containing all the vertices for the particular frame, along with the vect...
Definition: franzblau.hpp:108

◆ findRings()

int primitive::findRings ( Graph fullGraph,
int  v,
std::vector< int > *  visited,
int  maxDepth,
int  depth,
int  root = -1 
)

Main function that searches for all rings.

All possible rings are searched for in this function, which recursively calls itself. The rings are 'grown' from the root node (which is the first vertex) using the backtracking algorithm. When it is first called (before the root node has been assigned), root is a dummy value (which is equal to -1, a value that can never be legitimate).

Parameters
[in,out]fullGraphGraph object containing the vertices (and the neighbour lists). Vertices may be 'removed' from the Graph.
[in]vThe current vertex being visited or checked. It is added to the list of all vertices visited.
[in]visitedA vector containing a list of the vertices visited for book-keeping. If the current visited vector fulfills the condition for being a ring, it is added to the rings vector of vector in the Graph.
[in]maxDepthThe maximum depth upto which rings will be searched. This means that rings larger than maxDepth will not be generated.
[in]depthThe current depth. When this function is called for the first time from primitive::countAllRingsFromIndex, the depth is initialized to 0. When the depth is greater than or equal to maxDepth, the function exits.
[in]rootThe first vertex, from which the current visited vector (candidate ring) is being grown. This is initialized to a dummy value of -1, when it is called from primitive::countAllRingsFromIndex.

Definition at line 116 of file franzblau.cpp.

117  {
118  //
119  int nnumNeighbours; // Number of nearest neighbours for iNode
120  int n; // Node of a neighbour (index)
121  // -------------
122  // For the first call:
123  if (root == -1) {
124  root = v; // Init the root as the current node
125  fullGraph->pts[v].inGraph = false; // Remove the root from the graph
126  } // first call
127  //
128  // Checks
129  if (depth >= maxDepth) {
130  return 1; // false?
131  } // searched until the maximum length specified
132  //
133  // Add the current node to the visited vector
134  visited->push_back(v);
135  // -------------
136  // Depth-first search
137  // 1. Pick a root node (above)
138  // 2. Search all the neighbouring nodes
139  // 3. Start a recursion call, from the second nearest neighbours
140  // 3(i) If the neighbour equals the root (selected in 1), ring has been found!
141  // 3(ii) Or else search for all the unvisited neighbours
142  // 4. Remove the root node from the graph
143  // 5. Update the vector of vectors containing all rings
144  // -------------
145  // Start the search
146  depth += 1; // Go to the next layer
147  nnumNeighbours = fullGraph->pts[v].neighListIndex.size();
148  // Loop through the neighbours of iNode
149  for (int j = 0; j < nnumNeighbours; j++) {
150  n = fullGraph->pts[v].neighListIndex[j]; // Neighbour index
151  // Has a ring been found?!
152  if (depth > 2 && n == root) {
153  // Add the visited vector to the rings vector of vector
154  fullGraph->rings.push_back(*visited);
155  } // A ring has been found!
156  // Otherwise search all the neighbours which have not been searched already
157  else if (fullGraph->pts[n].inGraph) {
158  fullGraph->pts[n].inGraph = false; // Set to false now
159  // Recursive call
160  primitive::findRings(fullGraph, n, visited, maxDepth, depth, root);
161  fullGraph->pts[n].inGraph = true; // Put n back in the graph
162  } // Search the other unsearched neighbours
163  } // end of search through all neighbours
164  // -------------
165  // When the depth is 2, remove just the root from the neighbours of iNode
166  if (depth == 2) {
167  // Search for root in the neighbour list of v
168  for (int j = 0; j < fullGraph->pts[v].neighListIndex.size(); j++) {
169  if (root == fullGraph->pts[v].neighListIndex[j]) {
170  fullGraph->pts[v].neighListIndex.erase(
171  fullGraph->pts[v].neighListIndex.begin() + j);
172  } // end of erase
173  } // end of search
174  } // remove root not edges
175 
176  //
177  (*visited).pop_back();
178  //
179  return 0;
180 }
T push_back(T... args)

◆ populateGraphFromIndices()

primitive::Graph primitive::populateGraphFromIndices ( std::vector< std::vector< int >>  nList)

Creates a graph object and fills it with the information from a neighbour list of INDICES NOT ATOM IDs created before. NOTE: the neighbourListIndex contains the indices and NOT the atom IDs as in the neighbour list

Fills a Graph object with information from the PointCloud and the neighbour list. The indices in the neighbour list in the Vertex object are NOT the atom IDs (they are the atom indices according to the input PointCloud). The input neighbour list is by index NOT atom IDs. Otherwise, this function does the same thing as primitive::populateGraphFromNListID. The only difference is that this function takes the neighbour list BY INDEX.

Parameters
[in]nListThe row-ordered neighbour list, containing atom indices (according to the input PointCloud).
Returns
The Graph object for the current frame.

Definition at line 248 of file franzblau.cpp.

248  {
249  //
250  primitive::Graph fullGraph; // Contains all the information of the pointCloud
251  primitive::Vertex iVertex; // The vertex corresponding to a particular point
252  int nnumNeighbours; // Number of nearest neighbours for iatom
253  int iatom, jatom; // Atom index being saved
254  // ------------------------------
255  // Loop through every point in nList
256  for (int i = 0; i < nList.size(); i++) {
257  iatom = nList[i][0]; // Atom index of i
258  // neighListIndex is simply the i^th row of nList
259  //
260  // Update iVertex
261  iVertex.atomIndex = iatom;
262  iVertex.neighListIndex = nList[i];
263  // Add to the Graph object
264  fullGraph.pts.push_back(iVertex);
265  } // end of loop through iatom
266 
267  return fullGraph;
268 }
std::vector< int > neighListIndex
This is the index according to pointCloud.
Definition: franzblau.hpp:92
std::vector< Vertex > pts
Definition: franzblau.hpp:109
This is a collection of elements, for each point, required for graph traversal.
Definition: franzblau.hpp:90

◆ populateGraphFromNListID()

primitive::Graph primitive::populateGraphFromNListID ( molSys::PointCloud< molSys::Point< double >, double > *  yCloud,
std::vector< std::vector< int >>  neighHbondList 
)

Creates a graph object and fills it with the information from a neighbour list and pointCloud created before. NOTE: the neighbourListIndex contains the indices and NOT the atom IDs as in the neighbour list

Fills a Graph object with information from the PointCloud and the neighbour list. The indices in the neighbour list in the Vertex object are NOT the atom IDs (they are the atom indices according to the input PointCloud). The input neighbour list is by atom ID.

Parameters
[in]yCloudThe input PointCloud.
[in]neighHbondListThe row-ordered neighbour list, containing atom IDs, and not the atom indices.
Returns
The Graph object for the current frame.

Definition at line 192 of file franzblau.cpp.

194  {
195  //
196  primitive::Graph fullGraph; // Contains all the information of the pointCloud
197  primitive::Vertex iVertex; // The vertex corresponding to a particular point
198  int nnumNeighbours; // Number of nearest neighbours for iatom
199  std::vector<int> iNeigh; // Neighbours of the current iatom
200  int jatomID; // Atom ID of the nearest neighbour
201  int jatomIndex; // Atom index of the nearest neighbour
202  // ------------------------------
203  // Loop through every point in yCloud
204  for (int iatom = 0; iatom < yCloud->nop; iatom++) {
205  // -----
206  // Update the neighbours of iatom (only the indices!)
207  iNeigh.clear(); // init
208  nnumNeighbours = neighHbondList[iatom].size() -
209  1; // The first element is atomID of iatom
210  for (int j = 1; j <= nnumNeighbours; j++) {
211  jatomID = neighHbondList[iatom][j]; // Atom ID
212  // Get the atom index for the vector nearest neighbour list
213  auto it = yCloud->idIndexMap.find(jatomID);
214  if (it != yCloud->idIndexMap.end()) {
215  jatomIndex = it->second;
216  } // found jatomIndex
217  else {
218  std::cerr << "Panic induced!\n";
219  return fullGraph;
220  } // jatomIndex not found
221  // Update iNeigh
222  iNeigh.push_back(jatomIndex);
223  } // end of loop through nearest neighbours
224  // -----
225  // Update iVertex
226  iVertex.atomIndex = iatom;
227  iVertex.neighListIndex = iNeigh;
228  // Add to the Graph object
229  fullGraph.pts.push_back(iVertex);
230  } // end of loop through every iatom
231  // ------------------------------
232 
233  return fullGraph;
234 }
T end(T... args)
T find(T... args)
int nop
Current frame number.
Definition: mol_sys.hpp:173
std::unordered_map< int, int > idIndexMap
xlo, ylo, zlo
Definition: mol_sys.hpp:176

◆ removeNonSPrings()

primitive::Graph primitive::removeNonSPrings ( primitive::Graph fullGraph)

Removes the non-SP rings, using the Franzblau shortest path criterion.

Removes non-SP rings (according to the Franzblau shortest path criterion) from the rings vector of vectors member n the Graph object. The rings vector of vectors contains indices and NOT atom IDs. This function calls primitive::shortestPath internally to calculate the shortest path.

Parameters
[in]fullGraphThe Graph object for the current frame. This also contains the rings vector of vectors, which has all possible rings (possibly inclding non-SP rings).
Returns
The Graph object for the current frame.

Definition at line 307 of file franzblau.cpp.

307  {
308  //
309  int nVertices = fullGraph->pts.size(); // Number of vertices in the graph
310  int nRings = fullGraph->rings.size(); // Number of rings
311  std::vector<bool> ringsToRemove; // Vector containing the logical values for
312  // removal of the current ring index
313  std::vector<int> currentRing; // Current ring being evaluated
314  int ringSize; // Length of the current ring
315  bool removeRing; // Logical for removing the current ring (true) or not
317  emptyTempRings; // Empty vector of vectors to swap
319  primitiveRings; // Vector of vectors of rings after removing non SP rings
320  int currentV; // Current vertex
321  int currentN; // Current neighbour
322  int dist_r; // Distance over ring
323  int dist_g; // Distance over the entire graph
324  int d_jk; // Absolute difference between j and k
325  std::vector<int> path; // Vector containing a path
326  std::vector<int> visited; // Vector containing the visited points
327  // -------------------
328  // Make sure all the vertices are in the graph before removing non-SP rings
329  for (int iVer = 0; iVer < nVertices; iVer++) {
330  fullGraph->pts[iVer].inGraph = true;
331  } // end of loop through every vertex
332  // -------------------
333  // Loop through every ring
334  for (int iRing = 0; iRing < nRings; iRing++) {
335  currentRing = fullGraph->rings[iRing]; // Current ring
336  ringSize = currentRing.size(); // Length of the current ring
337  removeRing = false; // init
338  // Loop through every j^th vertex
339  for (int jVer = 0; jVer < ringSize; jVer++) {
340  // connect with all other, skip j-j (distance=0) and j-(j+1) (nearest
341  // neighbors)
342  for (int kVer = jVer + 2; kVer < ringSize; kVer++) {
343  // If not remove
344  if (!removeRing) {
345  currentV = currentRing[jVer]; // current 'vertex'
346  currentN = currentRing[kVer]; // Current 'neighbour'
347  d_jk = std::abs(jVer - kVer);
348  dist_r = std::min(d_jk, std::abs(d_jk - ringSize)) +
349  1; // Distance over the ring
350  path.clear(); // init
351  visited.clear();
352  // Call shortest path function
353  primitive::shortestPath(fullGraph, currentV, currentN, &path,
354  &visited, dist_r, 0);
355  dist_g = path.size(); // Length of the path over the graph
356  if (dist_g < dist_r) {
357  removeRing = true;
358  } // Decide whether to keep or remove the ring
359  } // If ring is not to be removed
360  } // end of loop through k^th vertex
361  } // end of loop through j^th vertex
362  // Update bool value for removal of currentRing
363  ringsToRemove.push_back(removeRing);
364  } // end of loop through rings
365  // -------------------
366  // Remove all the rings whose indices are given in the ringsToRemove vector
367  for (int i = 0; i < ringsToRemove.size(); i++) {
368  if (!ringsToRemove[i]) {
369  primitiveRings.push_back(fullGraph->rings[i]);
370  } // updates new copy
371  } // end of loop through ringsToRemove
372  // -------------------
373  // Update the graph rings with the primitiveRings
374  emptyTempRings.swap(fullGraph->rings);
375  fullGraph->rings = primitiveRings;
376  // -------------------
377  return *fullGraph;
378 }
std::vector< std::vector< int > > rings
Definition: franzblau.hpp:112
int shortestPath(Graph *fullGraph, int v, int goal, std::vector< int > *path, std::vector< int > *visited, int maxDepth, int depth=1)
Calculates the shortest path.
Definition: franzblau.cpp:397
T min(T... args)

◆ restoreEdgesFromIndices()

primitive::Graph primitive::restoreEdgesFromIndices ( Graph fullGraph,
std::vector< std::vector< int >>  nList 
)

Re-fills the neighbour lists of a graph object from a neighbour list of INDICES NOT ATOM IDs created before. NOTE: the neighbourListIndex contains the indices and NOT the atom IDs as in the neighbour list

Re-fills the neighbour lists of a Graph object from a row-ordered neighbour list (which is BY INDEX not IDs). Some vertices may have been removed while rings were generated using the backtracking algorithm (primitive::findRings). Also, the indices in the neighbour list in the Vertex object are not the atom IDs.

Parameters
[in]fullGraphThe Graph object for the current frame. The neighbour lists of component Vertex objects may have been depleted.
[in]nListThe row-ordered neighbour list, containing atom indices (according to the input PointCloud).
Returns
The Graph object for the current frame.

Definition at line 283 of file franzblau.cpp.

284  {
285  //
286  // ------------------------------
287  // Loop through every point in nList
288  for (int i = 0; i < nList.size(); i++) {
289  // neighListIndex is simply the i^th row of nList
290  // Update the neighListIndex list in the graph object
291  fullGraph->pts[i].neighListIndex = nList[i];
292  } // end of loop through iatom
293 
294  return *fullGraph;
295 }

◆ ringNetwork()

std::vector< std::vector< int > > primitive::ringNetwork ( std::vector< std::vector< int >>  nList,
int  maxDepth 
)

Returns a vector of vectors containing the rings (of all sizes), by atom index, given the neighbour list also by index (preferably the hydrogen-bonded neighbour list). Internally uses the Graph and Vertex objects.

The vector of vector of rings, by index, is returned, given a neighbour list (also by index) and the maximum depth upto which rings will be searched, using the Franzblau algorithm for shortest paths. This function is registered in Lua and exposed to the user. This internally calls the functions:

  • primitive::countAllRingsFromIndex (to generate all rings)
  • primitive::removeNonSPrings (to only get the primitive rings)
    Parameters
    [in]nListRow-ordered neighbour list by index (and NOT the atom ID)
    [in]maxDepthThe maximum depth upto which rings will be searched. This means that rings larger than maxDepth in length will not be generated.
    Returns
    A vector of vectors of the rings; each ring contains the atom indices of the ring members.

Definition at line 32 of file franzblau.cpp.

32  {
33  //
34  primitive::Graph fullGraph; // Graph object, contains the connectivity
35  // information from the neighbourlist
36 
37  // Find all possible rings, using backtracking. This may contain non-primitive
38  // rings as well.
39  fullGraph = primitive::countAllRingsFromIndex(nList, maxDepth);
40 
41  // Remove all non-SP rings using the Franzblau algorithm.
42  fullGraph = primitive::removeNonSPrings(&fullGraph);
43 
44  // The rings vector of vectors inside the fullGraph graph object is the ring
45  // network information we want
46  return fullGraph.rings;
47 }
Graph countAllRingsFromIndex(std::vector< std::vector< int >> neighHbondList, int maxDepth)
Creates a vector of vectors of all possible rings.
Definition: franzblau.cpp:64
Graph removeNonSPrings(Graph *fullGraph)
Removes the non-SP rings, using the Franzblau shortest path criterion.
Definition: franzblau.cpp:307

◆ shortestPath()

int primitive::shortestPath ( Graph fullGraph,
int  v,
int  goal,
std::vector< int > *  path,
std::vector< int > *  visited,
int  maxDepth,
int  depth = 1 
)

Calculates the shortest path.

Calculates the shortest path for a particular ring. This function uses recursion.

Parameters
[in]fullGraphThe Graph object for the current frame.
[in]vThe current vertex being checked.
[in]goalThe first element of the candidate ring being checked (the root node).
[in]pathThe path or length of the visited points (This basically contains all the indices in the visited vector, excluding the current vertex).
[in]visitedThis vector contains the indices of the vertices visited or checked (for book-keeping).
[in]maxDepthThe maximum depth or maximum length of the rings.
[in]depthThe current depth. When this function is called from primitive::removeNonSPrings, the depth is initialized as 0.
Returns
The Graph object for the current frame.

Definition at line 397 of file franzblau.cpp.

399  {
400  int len_path = 0; // Length of the path
401  int nnumNeighbours; // Number of neighbours for a particular v
402  int n; // Index of the nearest neighbour of v
403  // Start the search for the shortest path
404  if (depth < maxDepth) {
405  depth += 1; // One layer below
406  (*visited).push_back(
407  v); // Add the current vertex to the path (visited points)
408  //
409  if (v == goal) {
410  len_path = (*path).size(); // Path of the length of visited points
411  // If the current path is shorter OR this is the first path found
412  if (depth < len_path || len_path == 0) {
413  (*path) = (*visited);
414  maxDepth = depth;
415  } // Current path is the shortest
416  } // Goal reached
417  // Recursive calls to function
418  else {
419  nnumNeighbours = fullGraph->pts[v].neighListIndex.size();
420  // Search all the neighbours
421  for (int j = 0; j < nnumNeighbours; j++) {
422  n = fullGraph->pts[v].neighListIndex[j]; // Index of nearest neighbour
423  // If n has not already been searched:
424  if (fullGraph->pts[n].inGraph == true) {
425  fullGraph->pts[n].inGraph = false; // Set to false
426  primitive::shortestPath(fullGraph, n, goal, path, visited, maxDepth,
427  depth); // Recursive call
428  fullGraph->pts[n].inGraph = true; // Put back in the graph
429  } // If n is in the graph, call recursively
430  } // End of loop over all neighbours
431  } // Goal not reached
432  //
433  // Pop the vector
434  (*visited).pop_back();
435  } // for depth less than maxDepth
436  return 0;
437 }

Variable Documentation

◆ atomIndex

int primitive::Vertex::atomIndex

Definition at line 91 of file franzblau.hpp.

◆ inGraph

bool primitive::Vertex::inGraph
Initial value:
=
true

Contains the INDICES (not the atomIDs) of the neighbouring vertices

Definition at line 94 of file franzblau.hpp.

◆ neighListIndex

std::vector<int> primitive::Vertex::neighListIndex

This is the index according to pointCloud.

Definition at line 92 of file franzblau.hpp.

◆ pts

std::vector<Vertex> primitive::Graph::pts

Definition at line 109 of file franzblau.hpp.

◆ rings

std::vector<std::vector<int> > primitive::Graph::rings

Collection of vertices. The index of each should be the same as that in pointCloud

Definition at line 112 of file franzblau.hpp.