OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
next_combination.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48/**
49 * @file next_combination.hpp
50 * @author tlin
51 * @date 10/27/2004
52 * @version 1.0
53 */
54
55#ifndef UTILS_NEXT_COMBINATION_HPP
56#define UTILS_NEXT_COMBINATION_HPP
57
58#include <iostream>
59#include <iterator>
60#include <vector>
61
62namespace OpenMD {
63
64 /**
65 * @brief STL next_permuation-like combination sequence generator.
66 * Given the first and last iterator of a sequence, next_combination
67 * iteratively generates all possible combinations.
68 * @return if more combination is availiable, otherwise return false
69 * @param iterContainer iterator container
70 * @param first the first iterator
71 * @param last the last iterator
72 * @note first and last must be random access iterators and iterContainer must
73 * be the container of random access iterators . And all of the iteratos in
74 * iterContainer must be within the range [first, last)
75 *
76 * @code
77 * std::vector<int> iv;
78 * iv.push_back(1);
79 * iv.push_back(8);
80 * std::vector<std::vector<int>::iterator> ic;
81 * while(next_combination(ic, iv.begin(), iv.end())) {
82 * for (i = ic.begin(); i < ic.end(); ++i) {
83 * std::cout << **i << "\t";
84 * }
85 * std::cout << std::endl;
86 * }
87 * //output
88 * //1
89 * //8
90 * //1 8
91 * @endcode
92 */
93 template<class RandomAccessIterator>
94 bool next_combination(std::vector<RandomAccessIterator>& iterContainer,
95 RandomAccessIterator first, RandomAccessIterator last) {
96 if (first == last) { return false; }
97
98 RandomAccessIterator endIter = --last;
99 typename std::vector<RandomAccessIterator>::iterator i =
100 iterContainer.end();
101
102 if (iterContainer.empty()) {
103 // if sequence is empty, we insert the first iterator
104 iterContainer.insert(iterContainer.end(), first);
105 return true;
106 } else if (*(--i) != endIter) {
107 // if the last iterator in iterContainer does not reaches the end, just
108 // increase its iterator by 1
109 ++(*i);
110 return true;
111 } else { // the last iterator in iterContainer does not reaches the end
112
113 // starts at the end of the sequence and works its way towards the front,
114 // looking for two consecutive members of the sequence where the
115 // difference between them is greater than one. For example , if the
116 // sequence contains 1, 5, 8, 9 (total number is 10, first is 0 and the
117 // last is 10 (due to STL's half open range)). At the end of while loop, j
118 // will point to 5, and i will point to 8, next combination should be 1,
119 // 6, 7, 8. If j is less than zero, it means it already reaches the last
120 // combination of current size. For instance, sequence may contain 6, 7,
121 // 8, 9 at this time, we need to increase the size of combination to 5
122 typename std::vector<RandomAccessIterator>::iterator j = i;
123 --j;
124 while (j >= iterContainer.begin() && *i == *j + 1) {
125 --i;
126 --j;
127 };
128
129 RandomAccessIterator raIter;
130 if (j - iterContainer.begin() <
131 0) { // reaches the last combination of current size
132 // half open range
133 if (last - first + 1 == int(iterContainer.size())) {
134 // if the current size equals to total number, done
135 return false;
136 } else {
137 // push the first currentSize+1 element into sequence
138
139 for (i = iterContainer.begin(), raIter = first;
140 i != iterContainer.end(); ++i, ++raIter) {
141 *i = raIter;
142 }
143 iterContainer.insert(iterContainer.end(), raIter);
144
145 return true;
146 }
147
148 } else {
149 ++(*j);
150 raIter = *j;
151 for (; i != iterContainer.end(); ++i) {
152 ++raIter;
153 *i = raIter;
154 }
155 return true;
156 }
157 }
158 } // end next_combination
159
160} // namespace OpenMD
161
162#endif // UTILS_NEXT_COMBINATION_HPP
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
bool next_combination(std::vector< RandomAccessIterator > &iterContainer, RandomAccessIterator first, RandomAccessIterator last)
STL next_permuation-like combination sequence generator.