All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
Primitive

Namespaces

namespace  primitive
 Functions for generating primitive rings. This namespace contains struct definitions and functions that are used for generating primitive (shortest-path) rings (directed cyclic graphs).
 

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.
 
Graph primitive::removeNonSPrings (Graph *fullGraph)
 Removes the non-SP rings, using the Franzblau shortest path criterion.
 
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.
 
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.
 
Graph primitive::clearGraph (Graph *currentGraph)
 Function for clearing vectors in Graph after multiple usage.
 

Variables

int primitive::Vertex::atomIndex
 
std::vector< int > primitive::Vertex::neighListIndex
 This is the index according to pointCloud.
 
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.

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

◆ 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.

Code
65 {
66 //
67 primitive::Graph fullGraph; // Graph object
68 std::vector<int>
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}
Graph populateGraphFromIndices(std::vector< std::vector< int > > nList)
Graph restoreEdgesFromIndices(Graph *fullGraph, std::vector< std::vector< int > > nList)
int findRings(Graph *fullGraph, int v, std::vector< int > *visited, int maxDepth, int depth, int root=-1)
Main function that searches for all rings.
This is a per-frame object, containing all the vertices for the particular frame, along with the vect...

◆ 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.

Code
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}

◆ 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.

Code
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
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.

Code
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}
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.

Code
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
316 std::vector<std::vector<int>>
317 emptyTempRings; // Empty vector of vectors to swap
318 std::vector<std::vector<int>>
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}
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.

◆ 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.

Code
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.

Code
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.

◆ 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.

Code
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:
Code
=
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.