Skip to content

Commit d4a5714

Browse files
committed
added setQuregToWeightedSum (and ToMixture)
1 parent 211d4e8 commit d4a5714

18 files changed

+796
-26
lines changed

quest/include/initialisations.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ void setDensityQuregFlatAmps(Qureg qureg, qindex startInd, qcomp* amps, qindex n
116116
void setQuregToClone(Qureg targetQureg, Qureg copyQureg);
117117

118118

119+
/// @notyetdoced
120+
/// @notyettested
121+
void setQuregToWeightedSum(Qureg out, qcomp* coeffs, Qureg* in, int numIn);
122+
123+
124+
/// @notyetdoced
125+
/// @notyettested
126+
void setQuregToMixture(Qureg out, qreal* probs, Qureg* in, int numIn);
127+
128+
119129
/** @notyetdoced
120130
* @notyettested
121131
*
@@ -227,6 +237,20 @@ void setQuregToPartialTrace(Qureg out, Qureg in, std::vector<int> traceOutQubits
227237
void setQuregToReducedDensityMatrix(Qureg out, Qureg in, std::vector<int> retainQubits);
228238

229239

240+
/// @ingroup init_amps
241+
/// @notyetdoced
242+
/// @cpponly
243+
/// @see setQuregToWeightedSum()
244+
void setQuregToWeightedSum(Qureg out, std::vector<qcomp> coeffs, std::vector<Qureg> in);
245+
246+
247+
/// @ingroup init_amps
248+
/// @notyetdoced
249+
/// @cpponly
250+
/// @see setQuregToMixture()
251+
void setQuregToMixture(Qureg out, std::vector<qreal> probs, std::vector<Qureg> in);
252+
253+
230254
#endif // __cplusplus
231255

232256

quest/src/api/decoherence.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ void mixQureg(Qureg outQureg, Qureg inQureg, qreal inProb) {
134134
validate_quregFields(outQureg, __func__);
135135
validate_quregFields(inQureg, __func__);
136136
validate_probability(inProb, __func__);
137-
validate_quregsCanBeMixed(outQureg, inQureg, __func__); // checks outQureg is densmatr
137+
validate_quregPairCanBeMixed(outQureg, inQureg, __func__); // checks outQureg is densmatr
138138

139139
qreal outProb = 1 - inProb;
140140
localiser_densmatr_mixQureg(outProb, outQureg, inProb, inQureg);

quest/src/api/initialisations.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,34 @@ void setQuregToReducedDensityMatrix(Qureg out, Qureg in, int* retainQubits, int
252252
}
253253

254254

255+
void setQuregToWeightedSum(Qureg out, qcomp* coeffs, Qureg* in, int numIn) {
256+
validate_quregFields(out, __func__);
257+
validate_numQuregsInSum(numIn, __func__);
258+
validate_quregsCanBeSummed(out, in, numIn, __func__); // also validates all init
259+
260+
auto coeffVec = util_getVector(coeffs, numIn);
261+
auto inVec = util_getVector(in, numIn);
262+
localiser_statevec_setQuregToWeightedSum(out, coeffVec, inVec);
263+
}
264+
265+
266+
void setQuregToMixture(Qureg out, qreal* probs, Qureg* in, int numIn) {
267+
validate_quregFields(out, __func__);
268+
validate_quregIsDensityMatrix(out, __func__);
269+
validate_numQuregsInSum(numIn, __func__);
270+
validate_quregsCanBeMixed(out, in, numIn, __func__); // also validates all init & densmatr
271+
validate_probabilities(probs, numIn, __func__);
272+
273+
// convert probs to complex (assume this alloc never fails)
274+
vector<qcomp> coeffVec(numIn);
275+
for (int i=0; i<numIn; i++)
276+
coeffVec[i] = getQcomp(probs[i], 0);
277+
278+
auto inVec = util_getVector(in, numIn);
279+
localiser_statevec_setQuregToWeightedSum(out, coeffVec, inVec);
280+
}
281+
282+
255283
} // end de-mangler
256284

257285

@@ -296,3 +324,15 @@ void setQuregToPartialTrace(Qureg out, Qureg in, vector<int> traceOutQubits) {
296324
void setQuregToReducedDensityMatrix(Qureg out, Qureg in, vector<int> retainQubits) {
297325
setQuregToReducedDensityMatrix(out, in, retainQubits.data(), retainQubits.size());
298326
}
327+
328+
void setQuregToWeightedSum(Qureg out, vector<qcomp> coeffs, vector<Qureg> in) {
329+
validate_numQuregsMatchesCoeffs(in.size(), coeffs.size(), __func__);
330+
331+
setQuregToWeightedSum(out, coeffs.data(), in.data(), in.size());
332+
}
333+
334+
void setQuregToMixture(Qureg out, vector<qreal> probs, vector<Qureg> in) {
335+
validate_numQuregsMatchesProbs(in.size(), probs.size(), __func__);
336+
337+
setQuregToMixture(out, probs.data(), in.data(), in.size());
338+
}

quest/src/core/accelerator.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ using std::min;
7474
#endif
7575

7676

77+
#define GET_FUNC_OPTIMISED_FOR_NUM_QUREGS(f, numquregs) \
78+
(vector <decltype(&f<0>)> {&f<0>, &f<1>, &f<2>, &f<3>, &f<4>, &f<5>, &f<-1>}) \
79+
[std::min((int) numquregs, MAX_OPTIMISED_NUM_QUREGS + 1)]
80+
7781
#define GET_FUNC_OPTIMISED_FOR_NUM_CTRLS(f, numctrls) \
7882
(vector <decltype(&f<0>)> {&f<0>, &f<1>, &f<2>, &f<3>, &f<4>, &f<5>, &f<-1>}) \
7983
[std::min((int) numctrls, MAX_OPTIMISED_NUM_CTRLS + 1)]
@@ -97,6 +101,11 @@ using std::min;
97101
#define ARR(f) vector<decltype(&f<0,0>)>
98102

99103

104+
#define GET_CPU_OR_GPU_FUNC_OPTIMISED_FOR_NUM_QUREGS(funcsuffix, qureg, numquregs) \
105+
((qureg.isGpuAccelerated)? \
106+
GET_FUNC_OPTIMISED_FOR_NUM_QUREGS( gpu_##funcsuffix, numquregs ) : \
107+
GET_FUNC_OPTIMISED_FOR_NUM_QUREGS( cpu_##funcsuffix, numquregs ))
108+
100109
#define GET_CPU_OR_GPU_FUNC_OPTIMISED_FOR_NUM_CTRLS(funcsuffix, qureg, numctrls) \
101110
((qureg.isGpuAccelerated)? \
102111
GET_FUNC_OPTIMISED_FOR_NUM_CTRLS( gpu_##funcsuffix, numctrls ) : \
@@ -539,6 +548,14 @@ void accel_statevector_anyCtrlAnyTargZOrPhaseGadget_sub(Qureg qureg, vector<int>
539548
*/
540549

541550

551+
void accel_statevec_setQuregToWeightedSum_sub(Qureg outQureg, vector<qcomp> coeffs, vector<Qureg> inQuregs) {
552+
553+
// consult outQureg's deployment since others are prior validated to match
554+
auto func = GET_CPU_OR_GPU_FUNC_OPTIMISED_FOR_NUM_QUREGS( statevec_setQuregToWeightedSum_sub, outQureg, inQuregs.size() );
555+
func(outQureg, coeffs, inQuregs);
556+
}
557+
558+
542559
void accel_statevec_setQuregToSuperposition_sub(qcomp facOut, Qureg outQureg, qcomp fac1, Qureg inQureg1, qcomp fac2, Qureg inQureg2) {
543560

544561
// consult outQureg's deployment (other quregs should match, though we dangerously do not assert this post-validation)

quest/src/core/accelerator.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ using std::vector;
3535
* used by cpu_subroutines.cpp and gpu_subroutines to force the compiler
3636
* to instantiate and compile their template definitions with the given
3737
* explicit parameters below. Notice the final parameter is always -1,
38-
* to handle when the number of controls or targets is not known at
38+
* to handle when the number of parameters (e.g. controls) is not known at
3939
* compile-time (it is larger than a bespoke, optimised instantiations),
4040
* causing the optimised function to fallback to a suboptimal but general
4141
* implementation.
@@ -44,6 +44,7 @@ using std::vector;
4444
// must match the macros below, and those in accelerator.cpp
4545
#define MAX_OPTIMISED_NUM_CTRLS 5
4646
#define MAX_OPTIMISED_NUM_TARGS 5
47+
#define MAX_OPTIMISED_NUM_QUREGS 5
4748

4849

4950
#define INSTANTIATE_FUNC_OPTIMISED_FOR_NUM_TARGS(returntype, funcname, args) \
@@ -58,6 +59,9 @@ using std::vector;
5859
#define INSTANTIATE_FUNC_OPTIMISED_FOR_NUM_CTRLS(returntype, funcname, args) \
5960
INSTANTIATE_FUNC_OPTIMISED_FOR_NUM_TARGS(returntype, funcname, args)
6061

62+
#define INSTANTIATE_FUNC_OPTIMISED_FOR_NUM_QUREGS(returntype, funcname, args) \
63+
INSTANTIATE_FUNC_OPTIMISED_FOR_NUM_TARGS(returntype, funcname, args)
64+
6165

6266
#define INSTANTIATE_FUNC_OPTIMISED_FOR_NUM_CTRLS_AND_TARGS(returntype, funcname, args) \
6367
private_INSTANTIATE(returntype, funcname, 0, args) \
@@ -228,6 +232,8 @@ void accel_statevector_anyCtrlPauliTensorOrGadget_subB(Qureg qureg, vector<int>
228232
* QUREG COMBINATION
229233
*/
230234

235+
void accel_statevec_setQuregToWeightedSum_sub(Qureg outQureg, vector<qcomp> coeffs, vector<Qureg> inQuregs);
236+
231237
void accel_statevec_setQuregToSuperposition_sub(qcomp facOut, Qureg outQureg, qcomp fac1, Qureg inQureg1, qcomp fac2, Qureg inQureg2);
232238

233239
void accel_densmatr_mixQureg_subA(qreal outProb, Qureg out, qreal inProb, Qureg in);

quest/src/core/localiser.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,19 @@ void localiser_statevec_anyCtrlPauliGadget(Qureg qureg, vector<int> ctrls, vecto
13711371
*/
13721372

13731373

1374+
void localiser_statevec_setQuregToWeightedSum(Qureg outQureg, vector<qcomp> coeffs, vector<Qureg> inQuregs) {
1375+
1376+
/// @todo
1377+
/// this function requires (as validated) distributions are identical.
1378+
/// It would be trivial to generalise this so that Qureg distributions
1379+
/// can differ (we merely spoof local Quregs, offsetting their memory).
1380+
/// They must still however be identically GPU-accelerated; this is a
1381+
/// low priority because this situation is non-sensical
1382+
1383+
accel_statevec_setQuregToWeightedSum_sub(outQureg, coeffs, inQuregs);
1384+
}
1385+
1386+
13741387
void localiser_statevec_setQuregToSuperposition(qcomp facOut, Qureg outQureg, qcomp fac1, Qureg inQureg1, qcomp fac2, Qureg inQureg2) {
13751388

13761389
/// @todo

quest/src/core/localiser.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ void localiser_statevec_anyCtrlPhaseGadget(Qureg qureg, vector<int> ctrls, vecto
127127
* QUREG COMBINATION
128128
*/
129129

130+
void localiser_statevec_setQuregToWeightedSum(Qureg outQureg, vector<qcomp> coeffs, vector<Qureg> inQuregs);
131+
130132
void localiser_statevec_setQuregToSuperposition(qcomp facOut, Qureg outQureg, qcomp fac1, Qureg inQureg1, qcomp fac2, Qureg inQureg2);
131133

132134
void localiser_densmatr_mixQureg(qreal outProb, Qureg out, qreal inProb, Qureg in);

quest/src/core/utilities.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,15 +218,6 @@ qindex util_getBitMask(vector<int> ctrls, vector<int> ctrlStates, vector<int> ta
218218
return util_getBitMask(qubits, states);
219219
}
220220

221-
vector<int> util_getVector(int* qubits, int numQubits) {
222-
223-
// permit qubits=nullptr, overriding numQubits (might be non-zero)
224-
if (qubits == nullptr)
225-
return {};
226-
227-
return vector<int> (qubits, qubits + numQubits);
228-
}
229-
230221

231222

232223
/*
@@ -384,7 +375,7 @@ qreal util_getSum(vector<qreal> list) {
384375
qreal sum = 0;
385376
qreal y, t, c=0;
386377

387-
// complex Kahan summation
378+
// Kahan summation
388379
for (auto& x : list) {
389380
y = x - c;
390381
t = sum + y;
@@ -1118,6 +1109,23 @@ qreal util_getMaxProbOfTwoQubitDepolarising() {
11181109
* TEMPORARY MEMORY ALLOCATION
11191110
*/
11201111

1112+
template <typename T>
1113+
vector<T> getVector(T* ptr, int length) {
1114+
1115+
// permit nullptr to indicate empty list, regardless of length
1116+
if (ptr == nullptr)
1117+
return {};
1118+
1119+
// assumes memory alloc failure is impossible
1120+
return vector<T> (ptr, ptr + length);
1121+
}
1122+
1123+
vector<int> util_getVector(int* ptr, int length) { return getVector(ptr, length); }
1124+
vector<qreal> util_getVector(qreal* ptr, int length) { return getVector(ptr, length); }
1125+
vector<qcomp> util_getVector(qcomp* ptr, int length) { return getVector(ptr, length); }
1126+
vector<Qureg> util_getVector(Qureg* ptr, int length) { return getVector(ptr, length); }
1127+
1128+
11211129
template <typename T>
11221130
void tryAllocVector(vector<T> &vec, qindex size, std::function<void()> errFunc) {
11231131

quest/src/core/utilities.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ vector<int> util_getBraQubits(vector<int> ketQubits, Qureg qureg);
5959

6060
vector<int> util_getNonTargetedQubits(int* targets, int numTargets, int numQubits);
6161

62-
vector<int> util_getVector(int* qubits, int numQubits);
63-
6462
vector<int> util_getConcatenated(vector<int> list1, vector<int> list2);
6563

6664
vector<int> util_getSorted(vector<int> list);
@@ -401,6 +399,13 @@ qreal util_getMaxProbOfTwoQubitDepolarising();
401399
* TEMPORARY MEMORY ALLOCATION
402400
*/
403401

402+
// alloc assumed to never fail
403+
vector<int> util_getVector(int* ptr, int length);
404+
vector<qreal> util_getVector(qreal* ptr, int length);
405+
vector<qcomp> util_getVector(qcomp* ptr, int length);
406+
vector<Qureg> util_getVector(Qureg* ptr, int length);
407+
408+
// calls errFunc when alloc fails
404409
void util_tryAllocVector(vector<qreal> &vec, qindex size, std::function<void()> errFunc);
405410
void util_tryAllocVector(vector<qcomp> &vec, qindex size, std::function<void()> errFunc);
406411
void util_tryAllocVector(vector<qcomp*> &vec, qindex size, std::function<void()> errFunc);

0 commit comments

Comments
 (0)