The Quantum Exact Simulation Toolkit v4.0.0
Loading...
Searching...
No Matches
initialisations.cpp
1/** @file
2 * API definitions for initialising Quregs into
3 * particular states. Note when a Qureg is GPU-
4 * accelerated, these functions only update the
5 * state in GPU memory; the CPU amps are unchanged.
6 *
7 * @author Tyson Jones
8 */
9
10#include "quest/include/qureg.h"
11#include "quest/include/calculations.h"
12#include "quest/include/initialisations.h"
13
14#include "quest/src/core/validation.hpp"
15#include "quest/src/core/localiser.hpp"
16#include "quest/src/core/utilities.hpp"
17#include "quest/src/core/bitwise.hpp"
18#include "quest/src/gpu/gpu_config.hpp"
19
20#include <algorithm>
21#include <cmath>
22#include <vector>
23
24using std::vector;
25
26
27
28/*
29 * C AND C++ AGNOSTIC FUNCTIONS
30 */
31
32// enable invocation by both C and C++ binaries
33extern "C" {
34
35
36
37/*
38 * INIT
39 */
40
41
42void initBlankState(Qureg qureg) {
43 validate_quregFields(qureg, __func__);
44
45 // |null> = {0, 0, 0, ...}
46 qcomp amp = 0;
47 localiser_statevec_initUniformState(qureg, amp);
48}
49
50
51void initZeroState(Qureg qureg) {
52 validate_quregFields(qureg, __func__);
53
54 // |0> = |0><0|
55 qindex ind = 0;
56 localiser_statevec_initClassicalState(qureg, ind);
57}
58
59
60void initPlusState(Qureg qureg) {
61 validate_quregFields(qureg, __func__);
62
63 // |+> = sum_i 1/sqrt(2^N) |i> where 2^N = numAmps
64 // |+><+| = sum_ij 1/2^N |i><j| where 2^N = sqrt(numAmps)
65 qcomp amp = 1.0 / std::sqrt(qureg.numAmps);
66 localiser_statevec_initUniformState(qureg, amp);
67}
68
69
70void initPureState(Qureg qureg, Qureg pure) {
71 validate_quregFields(qureg, __func__);
72 validate_quregFields(pure, __func__);
73 validate_quregCanBeInitialisedToPureState(qureg, pure, __func__);
74
75 // when qureg=statevec, we lazily invoke setQuregToSuperposition which
76 // invokes superfluous floating-point operations which will be happily
77 // occluded by the memory movement costs
78 (qureg.isDensityMatrix)?
79 localiser_densmatr_initPureState(qureg, pure):
80 localiser_statevec_setQuregToSuperposition(0, qureg, 1, pure, 0, pure);
81}
82
83
84void initClassicalState(Qureg qureg, qindex ind) {
85 validate_quregFields(qureg, __func__);
86 validate_basisStateIndex(qureg, ind, __func__);
87
88 // |ind><ind| = ||ind'>>
89 if (qureg.isDensityMatrix)
90 ind = util_getGlobalFlatIndex(qureg, ind, ind);
91
92 localiser_statevec_initClassicalState(qureg, ind);
93}
94
95
96void initDebugState(Qureg qureg) {
97 validate_quregFields(qureg, __func__);
98
99 localiser_statevec_initDebugState(qureg);
100}
101
102
103void initArbitraryPureState(Qureg qureg, qcomp* amps) {
104 validate_quregFields(qureg, __func__);
105
106 // set qureg = |amps> or |amps><amps|
107 (qureg.isDensityMatrix)?
108 localiser_densmatr_initArbitraryPureState(qureg, amps):
109 localiser_statevec_initArbitraryPureState(qureg, amps);
110}
111
112
113void initArbitraryMixedState(Qureg qureg, qcomp** amps) {
114 validate_quregFields(qureg, __func__);
115 validate_quregIsDensityMatrix(qureg, __func__);
116
117 localiser_densmatr_initArbitraryMixedState(qureg, amps);
118}
119
120
122 validate_quregFields(qureg, __func__);
123
124 // these invoked localiser functions may harmlessly
125 // re-call the API and re-perform input validation
126
127 if (qureg.isDensityMatrix)
128 localiser_densmatr_initUniformlyRandomPureStateAmps(qureg);
129 else {
130 localiser_statevec_initUnnormalisedUniformlyRandomPureStateAmps(qureg);
132 }
133}
134
135
136void initRandomMixedState(Qureg qureg, qindex numPureStates) {
137 validate_quregFields(qureg, __func__);
138 validate_quregIsDensityMatrix(qureg, __func__);
139 validate_numInitRandomPureStates(numPureStates, __func__);
140
141 localiser_densmatr_initMixtureOfUniformlyRandomPureStates(qureg, numPureStates);
142}
143
144
145
146/*
147 * SET
148 */
149
150
151void setQuregAmps(Qureg qureg, qindex startInd, qcomp* amps, qindex numAmps) {
152 validate_quregFields(qureg, __func__);
153 validate_quregIsStateVector(qureg, __func__);
154 validate_basisStateIndices(qureg, startInd, numAmps, __func__);
155
156 localiser_statevec_setAmps(amps, qureg, startInd, numAmps);
157}
158
159
160void setDensityQuregAmps(Qureg qureg, qindex startRow, qindex startCol, qcomp** amps, qindex numRows, qindex numCols) {
161 validate_quregFields(qureg, __func__);
162 validate_quregIsDensityMatrix(qureg, __func__);
163 validate_basisStateRowCols(qureg, startRow, startCol, numRows, numCols, __func__);
164
165 localiser_densmatr_setAmps(amps, qureg, startRow, startCol, numRows, numCols);
166}
167
168
169void setDensityQuregFlatAmps(Qureg qureg, qindex startInd, qcomp* amps, qindex numAmps) {
170 validate_quregFields(qureg, __func__);
171 validate_quregIsDensityMatrix(qureg, __func__);
172 validate_basisStateIndices(qureg, startInd, numAmps, __func__); // validation msg correct for density-matrix
173
174 localiser_statevec_setAmps(amps, qureg, startInd, numAmps);
175}
176
177
178void setQuregToClone(Qureg targetQureg, Qureg copyQureg) {
179 validate_quregFields(targetQureg, __func__);
180 validate_quregFields(copyQureg, __func__);
181 validate_quregsCanBeCloned(targetQureg, copyQureg, __func__);
182
183 // we invoke mixing/superposing, which involves superfluous
184 // floating-point operators but is not expected to cause an
185 // appreciable slowdown since simulation is memory-bound
186 (targetQureg.isDensityMatrix)?
187 localiser_densmatr_mixQureg(0, targetQureg, 1, copyQureg):
188 localiser_statevec_setQuregToSuperposition(0, targetQureg, 1, copyQureg, 0, copyQureg);
189}
190
191
192void setQuregToSuperposition(qcomp facOut, Qureg out, qcomp fac1, Qureg qureg1, qcomp fac2, Qureg qureg2) {
193 validate_quregFields(out, __func__);
194 validate_quregFields(qureg1, __func__);
195 validate_quregFields(qureg2, __func__);
196 validate_quregsCanBeSuperposed(out, qureg1, qureg2, __func__); // asserts statevectors
197
198 localiser_statevec_setQuregToSuperposition(facOut, out, fac1, qureg1, fac2, qureg2);
199}
200
201
203 validate_quregFields(qureg, __func__);
204
205 qreal prob = calcTotalProb(qureg); // harmlessly re-validates
206 validate_quregRenormProbIsNotZero(prob, __func__);
207
208 qreal norm = (qureg.isDensityMatrix)? prob : std::sqrt(prob);
209 qreal fac = 1 / norm;
210 localiser_statevec_setQuregToSuperposition(fac, qureg, 0, qureg, 0, qureg);
211
212 return fac;
213}
214
215
217 validate_quregFields(qureg, __func__);
218 validate_quregIsDensityMatrix(qureg, __func__);
219 validate_pauliStrSumFields(sum, __func__);
220 validate_pauliStrSumTargets(sum, qureg, __func__);
221
222 // sum is permitted to be non-Hermitian, since Hermiticity
223 // is insufficient to ensure qureg would be physical/valid
224
225 localiser_densmatr_setAmpsToPauliStrSum(qureg, sum);
226}
227
228
229void setQuregToPartialTrace(Qureg out, Qureg in, int* traceOutQubits, int numTraceQubits) {
230 validate_quregFields(in, __func__);
231 validate_quregFields(out, __func__);
232 validate_quregIsDensityMatrix(in, __func__);
233 validate_quregIsDensityMatrix(out, __func__);
234 validate_targets(in, traceOutQubits, numTraceQubits, __func__);
235 validate_quregCanBeSetToReducedDensMatr(out, in, numTraceQubits, __func__);
236
237 auto targets = util_getVector(traceOutQubits, numTraceQubits);
238 localiser_densmatr_partialTrace(in, out, targets);
239}
240
241
242void setQuregToReducedDensityMatrix(Qureg out, Qureg in, int* retainQubits, int numRetainQubits) {
243 validate_quregFields(in, __func__);
244 validate_quregFields(out, __func__);
245 validate_quregIsDensityMatrix(in, __func__);
246 validate_quregIsDensityMatrix(out, __func__);
247 validate_targets(in, retainQubits, numRetainQubits, __func__);
248 validate_quregCanBeSetToReducedDensMatr(out, in, in.numQubits - numRetainQubits, __func__);
249
250 auto traceQubits = util_getNonTargetedQubits(retainQubits, numRetainQubits, in.numQubits);
251 localiser_densmatr_partialTrace(in, out, traceQubits);
252}
253
254
255} // end de-mangler
256
257
258
259/*
260 * C++ OVERLOADS
261 */
262
263
264void setDensityQuregAmps(Qureg qureg, qindex startRow, qindex startCol, vector<vector<qcomp>> amps) {
265
266 // C++-specific validation
267 validate_matrixRowsAllSameSize(amps, __func__);
268
269 // we must pass nested pointers to the C function, so alloc a vector
270 // of pointers of amps. We defensively check the temp vector allocates fine
271 vector<qcomp*> ptrs;
272 size_t len = amps.size();
273 auto callback = [&]() { validate_tempAllocSucceeded(false, len, sizeof(qcomp*), __func__); };
274 util_tryAllocVector(ptrs, len, callback);
275
276 // then set the pointers
277 for (size_t i=0; i<len; i++)
278 ptrs[i] = amps[i].data();
279
280 // C function performs main validation
281 setDensityQuregAmps(qureg, startRow, startCol, ptrs.data(), len, (len>0)? len : 0); // avoid seg-fault
282}
283
284void setQuregAmps(Qureg qureg, qindex startInd, vector<qcomp> amps) {
285 setQuregAmps(qureg, startInd, amps.data(), amps.size());
286}
287
288void setDensityQuregFlatAmps(Qureg qureg, qindex startInd, vector<qcomp> amps) {
289 setDensityQuregFlatAmps(qureg, startInd, amps.data(), amps.size());
290}
291
292void setQuregToPartialTrace(Qureg out, Qureg in, vector<int> traceOutQubits) {
293 setQuregToPartialTrace(out, in, traceOutQubits.data(), traceOutQubits.size());
294}
295
296void setQuregToReducedDensityMatrix(Qureg out, Qureg in, vector<int> retainQubits) {
297 setQuregToReducedDensityMatrix(out, in, retainQubits.data(), retainQubits.size());
298}
qreal calcTotalProb(Qureg qureg)
void setDensityQuregFlatAmps(Qureg qureg, qindex startInd, qcomp *amps, qindex numAmps)
void setQuregToReducedDensityMatrix(Qureg out, Qureg in, int *retainQubits, int numRetainQubits)
void setQuregToPauliStrSum(Qureg qureg, PauliStrSum sum)
void setQuregAmps(Qureg qureg, qindex startInd, qcomp *amps, qindex numAmps)
void setQuregToPartialTrace(Qureg out, Qureg in, int *traceOutQubits, int numTraceQubits)
qreal setQuregToRenormalized(Qureg qureg)
void setQuregToClone(Qureg targetQureg, Qureg copyQureg)
void setDensityQuregAmps(Qureg qureg, qindex startRow, qindex startCol, qcomp **amps, qindex numRows, qindex numCols)
void setQuregToSuperposition(qcomp facOut, Qureg out, qcomp fac1, Qureg qureg1, qcomp fac2, Qureg qureg2)
void initArbitraryPureState(Qureg qureg, qcomp *amps)
void initRandomPureState(Qureg qureg)
void initPlusState(Qureg qureg)
void initZeroState(Qureg qureg)
void initPureState(Qureg qureg, Qureg pure)
void initDebugState(Qureg qureg)
void initRandomMixedState(Qureg qureg, qindex numPureStates)
void initClassicalState(Qureg qureg, qindex ind)
void initBlankState(Qureg qureg)
Definition qureg.h:49