The Quantum Exact Simulation Toolkit v4.0.0
Loading...
Searching...
No Matches
lists.cpp
1/** @file
2 * Testing utilities which generate lists of integers.
3 *
4 * @author Tyson Jones
5 */
6
7#include <catch2/generators/catch_generators.hpp>
8#include <catch2/generators/catch_generators_range.hpp>
9#include <catch2/generators/catch_generators_adapters.hpp>
10
11#include "quest/include/quest.h"
12
13#include "lists.hpp"
14#include "macros.hpp"
15#include "random.hpp"
16#include "linalg.hpp"
17
18#include <tuple>
19#include <vector>
20#include <limits>
21#include <algorithm>
22
23using std::tuple;
24using std::vector;
25
26using Catch::Generators::IGenerator;
27using Catch::Generators::GeneratorWrapper;
28
29
30
31/*
32 * PRIVATE
33 */
34
35
36vector<int> getGeneratorElems(GeneratorWrapper<int>& gen) {
37
38 vector<int> list;
39 do { list.push_back(gen.get()); } while (gen.next());
40
41 return list;
42}
43
44
45
46/*
47 * SUBLISTS
48 */
49
50
51vector<int> getSublist(vector<int> list, int start, int len) {
52
53 return vector<int>(list.begin() + start, list.begin() + start + len);
54}
55
56
57vector<qcomp> getSublist(vector<qcomp> list, int start, int len) {
58
59 return vector<qcomp>(list.begin() + start, list.begin() + start + len);
60}
61
62
63
64/*
65 * RANGE
66 */
67
68
69vector<int> getRange(int start, int endExcl) {
70 DEMAND( endExcl >= start );
71
72 vector<int> out(endExcl - start);
73
74 for (size_t i=0; i<out.size(); i++)
75 out[i] = start + i;
76
77 return out;
78}
79
80
81vector<int> getRange(int endExcl) {
82 return getRange(0, endExcl);
83}
84
85
86
87/*
88 * COMPLEMENTS
89 */
90
91
92vector<int> getComplement(vector<int> listA, vector<int> listB) {
93
94 std::sort(listA.begin(), listA.end());
95 std::sort(listB.begin(), listB.end());
96
97 vector<int> out;
98 std::set_difference(
99 listA.begin(), listA.end(),
100 listB.begin(), listB.end(),
101 std::back_inserter(out));
102
103 return out;
104}
105
106
107
108/*
109 * SUBLIST GENERATORs
110 */
111
112
113/// @private
114class SublistGenerator final : public IGenerator<vector<int>> {
115
116 // list of all possible (unique) elements
117 vector<int> list;
118
119 // output sublist of user-specified length
120 int sublen;
121 vector<int> sublist;
122
123 // indicates which elements of list are in sublist
124 vector<bool> featured;
125
126private:
127
128 void prepareSublist() {
129
130 // choose the next combination
131 int j=0;
132 for (size_t i=0; i<list.size(); i++)
133 if (featured[i])
134 sublist[j++] = list[i];
135
136 // prepare for permuting
137 std::sort(sublist.begin(), sublist.end());
138 }
139
140public:
141
142 SublistGenerator(vector<int> list, int sublen):
143 list(list),
144 sublen(sublen)
145 {
146 // ensure sublist would not be longer than list
147 DEMAND( sublen <= list.size() );
148
149 // populate sublist with first elements
150 sublist.resize(sublen);
151 featured.resize(list.size());
152 fill(featured.end() - sublen, featured.end(), true);
153
154 prepareSublist();
155 }
156
157 vector<int> const& get() const override {
158
159 // return a copy of sublist
160 return sublist;
161 }
162
163 bool next() override {
164
165 // offer next permutation of the current combination
166 if (std::next_permutation(sublist.begin(), sublist.end()))
167 return true;
168
169 // else generate the next combination
170 if (std::next_permutation(featured.begin(), featured.end())) {
171
172 prepareSublist();
173 return true;
174 }
175
176 // else indicate generator is exhausted
177 return false;
178 }
179};
180
181
182GeneratorWrapper<vector<int>> sublists(GeneratorWrapper<int>&& gen, int sublen) {
183
184 vector<int> list;
185 do { list.push_back(gen.get()); } while (gen.next());
186
187 return GeneratorWrapper<vector<int>>(
188 Catch::Detail::make_unique<SublistGenerator>(
189 list, sublen));
190}
191
192
193
194/*
195 * DISJOINT SUBLISTS GENERATOR
196 */
197
198
199/// @private
200class DisjointSublistsGenerator : public IGenerator<listpair> {
201
202 // list of all possible (unique) elements
203 vector<int> list;
204
205 // lengths of each sublist
206 int sublen1;
207 int sublen2;
208 listpair sublists;
209
210 // underlying generator
211 SublistGenerator subGen;
212
213public:
214
215 DisjointSublistsGenerator(vector<int> list, int sublen1, int sublen2):
216 list(list),
217 sublen1(sublen1),
218 sublen2(sublen2),
219 subGen(list, sublen1 + sublen2)
220 {
221 static_cast<void>(next()); // ignore bool return
222 }
223
224 listpair const& get() const override {
225 return sublists;
226 }
227
228 bool next() override {
229
230 // stop when sublist generator is exhausted
231 if (!subGen.next())
232 return false;
233
234 // else, obtain the next (sublist) sequence
235 vector<int> combined = subGen.get();
236 vector<int> sublist1 = getSublist(combined, 0, sublen1);
237 vector<int> sublist2 = getSublist(combined, sublen1, sublen2);
238
239 sublists = {sublist1, sublist2};
240 return true;
241 }
242};
243
244
245GeneratorWrapper<listpair> disjointsublists(GeneratorWrapper<int>&& gen, int sublen1, int sublen2) {
246
247 vector<int> list;
248 do { list.push_back(gen.get()); } while (gen.next());
249
250 return GeneratorWrapper<listpair>(
251 Catch::Detail::make_unique<DisjointSublistsGenerator>(
252 list, sublen1, sublen2));
253}
254
255
256
257/*
258 * GENERATOR WRAPPERS
259 */
260
261
262listpair GENERATE_CTRLS_AND_TARGS(int numQubits, int numCtrls, int numTargs) {
263 DEMAND( numQubits >= numCtrls + numTargs );
264
265 // impose a limit on the number of {ctrls,targs} to generate (max-int if none set)
266 int numPerms = getNumPermutations(numQubits, numCtrls + numTargs);
267 int maxPerms = TEST_MAX_NUM_QUBIT_PERMUTATIONS;
268 if (maxPerms == 0)
269 maxPerms = std::numeric_limits<int>::max();
270
271 // if all permutations are permitted, determinstically generate each in turn.
272 // note this wastefully generates all orderings of ctrl qubits, despite that
273 // this has no effect on all API operations, but we carefully check anyway!
274 if (numPerms < maxPerms)
275 return GENERATE_COPY( disjointsublists(range(0,numQubits), numCtrls, numTargs) );
276
277 // otherwise generate as many random {ctrls,targs} as permitted
278 GENERATE_COPY( range(0,maxPerms) );
279 return getRandomFixedNumCtrlsTargs(numQubits, numCtrls, numTargs);
280}
281
282
283vector<int> GENERATE_TARGS(int numQubits, int numTargs) {
284 DEMAND( numQubits >= numTargs );
285
286 auto [ctrls, targs] = GENERATE_CTRLS_AND_TARGS(numQubits, 0, numTargs);
287 return targs;
288}
const int TEST_MAX_NUM_QUBIT_PERMUTATIONS
Definition macros.hpp:54