Skip to content

Commit 8447c90

Browse files
committed
added setDensityAmps
1 parent 5321ac8 commit 8447c90

File tree

5 files changed

+138
-7
lines changed

5 files changed

+138
-7
lines changed

QuEST/include/QuEST.h

+36-2
Original file line numberDiff line numberDiff line change
@@ -1494,7 +1494,8 @@ void initDebugState(Qureg qureg);
14941494
*/
14951495
void initStateFromAmps(Qureg qureg, qreal* reals, qreal* imags);
14961496

1497-
/** Overwrites a subset of the amplitudes in state-vector \p qureg, with those passed in \p reals and \p imags.
1497+
/** Overwrites a contiguous subset of the amplitudes in state-vector \p qureg,
1498+
* with those passed in \p reals and \p imags.
14981499
*
14991500
* Only amplitudes with indices in <b>[</b>\p startInd<b>,</b> \p startInd <b>+</b> \p numAmps<b>]</b>
15001501
* will be changed. The resulting \p qureg may not necessarily be in an L2 normalised state.
@@ -1522,6 +1523,7 @@ void initStateFromAmps(Qureg qureg, qreal* reals, qreal* imags);
15221523
*
15231524
*
15241525
* @see
1526+
* - setDensityAmps()
15251527
* - setWeightedQureg()
15261528
* - initStateFromAmps()
15271529
* - initBlankState()
@@ -1541,6 +1543,38 @@ void initStateFromAmps(Qureg qureg, qreal* reals, qreal* imags);
15411543
*/
15421544
void setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps);
15431545

1546+
/** Overwrites a contiguous subset of the amplitudes in density-matrix \p qureg,
1547+
* with those passed in \p reals and \p imags, intrepreted column-wise.
1548+
*
1549+
* Only the first \p numAmp amplitudes starting from row-column index (\p startRow, \p startCol), and
1550+
* proceeding down the column (wrapping around between rows) will be modified.
1551+
* The resulting \p qureg may not necessarily be a valid density matrix normalisation.
1552+
*
1553+
* In distributed mode, this function assumes the subset \p reals and \p imags exist
1554+
* (at least) on the node(s) containing the ultimately updated elements.\n
1555+
*
1556+
*
1557+
* @see
1558+
* - setAmps()
1559+
* - initStateFromAmps()
1560+
*
1561+
* @ingroup init
1562+
* @param[in,out] qureg the density-matrix to modify
1563+
* @param[in] startRow the row-index of the first amplitude in \p qureg to modify
1564+
* @param[in] startCol the column-index of the first amplitude in \p qureg to modify
1565+
* @param[in] reals array of the real components of the new amplitudes
1566+
* @param[in] imags array of the imaginary components of the new amplitudes
1567+
* @param[in] numAmps the length of each of the reals and imags arrays
1568+
* @throws invalidQuESTInputError()
1569+
* - if \p qureg is not a density matrix (i.e. is a state-vector)
1570+
* - if \p startRow is outside [0, `1 << qureg.numQubitsRepresented`]
1571+
* - if \p startCol is outside [0, `1 << qureg.numQubitsRepresented`]
1572+
* - if \p numAmps is outside [0, `qureg.numAmpsTotal`]
1573+
* - if \p numAmps is larger than the remaining number of amplitudes from (`startRow`, `startCol`), column-wise
1574+
* @author Tyson Jones
1575+
*/
1576+
void setDensityAmps(Qureg qureg, long long int startRow, long long int startCol, qreal* reals, qreal* imags, long long int numAmps);
1577+
15441578
/** Overwrite the amplitudes of \p targetQureg with those from \p copyQureg.
15451579
*
15461580
* Registers must either both be state-vectors, or both be density matrices, and
@@ -6621,7 +6655,7 @@ void applyQFT(Qureg qureg, int* qubits, int numQubits);
66216655
* @ingroup operator
66226656
* @param[in,out] qureg a state-vector or density matrix to modify
66236657
* @param[in] qubit the qubit to which to apply the projector
6624-
* @param[in] the single-qubit outcome (`0` or `1`) to project \p qubit into
6658+
* @param[in] outcome the single-qubit outcome (`0` or `1`) to project \p qubit into
66256659
* @throws invalidQuESTInputError()
66266660
* - if \p qubit is outside [0, `qureg.numQubitsRepresented`)
66276661
* - if \p outcome is not in {0,1}

QuEST/src/QuEST.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -1027,9 +1027,12 @@ void setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, lo
10271027
qasm_recordComment(qureg, "Here, some amplitudes in the statevector were manually edited.");
10281028
}
10291029

1030-
void setDensityAmps(Qureg qureg, qreal* reals, qreal* imags) {
1031-
long long int numAmps = qureg.numAmpsTotal;
1032-
statevec_setAmps(qureg, 0, reals, imags, numAmps);
1030+
void setDensityAmps(Qureg qureg, long long int startRow, long long int startCol, qreal* reals, qreal* imags, long long int numAmps) {
1031+
validateDensityMatrQureg(qureg, __func__);
1032+
validateNumDensityAmps(qureg, startRow, startCol, numAmps, __func__);
1033+
1034+
long long int startInd = startRow + startCol*(1 << qureg.numQubitsRepresented);
1035+
statevec_setAmps(qureg, startInd, reals, imags, numAmps);
10331036

10341037
qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
10351038
}

QuEST/src/QuEST_validation.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,9 @@ static const char* errorMessages[] = {
122122
[E_INVALID_STATE_INDEX] = "Invalid state index. Must be >=0 and <2^numQubits.",
123123
[E_INVALID_AMP_INDEX] = "Invalid amplitude index. Must be >=0 and <2^numQubits.",
124124
[E_INVALID_ELEM_INDEX] = "Invalid element index. Must be >=0 and <2^numQubits.",
125-
[E_INVALID_NUM_AMPS] = "Invalid number of amplitudes. Must be >=0 and <=2^numQubits.",
125+
[E_INVALID_NUM_AMPS] = "Invalid number of amplitudes. Must be >=0 and <=2^numQubits (or for density matrices, <=2^(2 numQubits)).",
126126
[E_INVALID_NUM_ELEMS] = "Invalid number of elements. Must be >=0 and <=2^numQubits.",
127-
[E_INVALID_OFFSET_NUM_AMPS_QUREG] = "More amplitudes given than exist in the statevector from the given starting index.",
127+
[E_INVALID_OFFSET_NUM_AMPS_QUREG] = "More amplitudes given than exist in the state from the given starting index.",
128128
[E_INVALID_OFFSET_NUM_ELEMS_DIAG] = "More elements given than exist in the diagonal operator from the given starting index.",
129129
[E_TARGET_IS_CONTROL] = "Control qubit cannot equal target qubit.",
130130
[E_TARGET_IN_CONTROLS] = "Control qubits cannot include target qubit.",
@@ -390,6 +390,15 @@ void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps,
390390
QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
391391
}
392392

393+
void validateNumDensityAmps(Qureg qureg, long long int startRow, long long int startCol, long long int numAmps, const char* caller) {
394+
validateAmpIndex(qureg, startRow, caller);
395+
validateAmpIndex(qureg, startCol, caller);
396+
QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
397+
398+
long long int startInd = startRow + startCol*(1 << qureg.numQubitsRepresented);
399+
QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
400+
}
401+
393402
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char* caller) {
394403
long long int indMax = 1LL << op.numQubits;
395404
QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);

QuEST/src/QuEST_validation.h

+2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ void validateSecondQuregStateVec(Qureg qureg2, const char *caller);
7878

7979
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char* caller);
8080

81+
void validateNumDensityAmps(Qureg qureg, long long int startRow, long long int startCol, long long int numAmps, const char* caller);
82+
8183
void validateFileOpened(int opened, char* fn, const char* caller);
8284

8385
void validateProb(qreal prob, const char* caller);

tests/test_state_initialisations.cpp

+83
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,89 @@ TEST_CASE( "setAmps", "[state_initialisations]" ) {
444444

445445

446446

447+
/** @sa setDensityAmps
448+
* @ingroup unittest
449+
* @author Tyson Jones
450+
*/
451+
TEST_CASE( "setDensityAmps", "[state_initialisations]" ) {
452+
453+
Qureg matr = createDensityQureg(NUM_QUBITS, QUEST_ENV);
454+
qreal reals[matr.numAmpsTotal];
455+
qreal imags[matr.numAmpsTotal];
456+
int maxInd = (1 << NUM_QUBITS);
457+
458+
SECTION( "correctness" ) {
459+
460+
SECTION( "density-matrix" ) {
461+
462+
// all valid number of amplitudes and offsets
463+
int startRow = GENERATE_COPY( range(0,maxInd) );
464+
int startCol = GENERATE_COPY( range(0,maxInd) );
465+
466+
int numPriorAmps = startRow + startCol*(1 << matr.numQubitsRepresented);
467+
int maxNumAmps = matr.numAmpsTotal - numPriorAmps;
468+
int numAmps = GENERATE_COPY( range(0,maxNumAmps) ); // upper-bound allows all amps specified
469+
470+
// generate random amplitudes
471+
for (int i=0; i<numAmps; i++) {
472+
reals[i] = getRandomReal(-5,5);
473+
imags[i] = getRandomReal(-5,5);
474+
}
475+
476+
// check both specified and un-specified amplitudes are correctly handled
477+
initDebugState(matr);
478+
QMatrix matrRef = toQMatrix(matr);
479+
480+
setDensityAmps(matr, startRow, startCol, reals, imags, numAmps);
481+
482+
int r=startRow;
483+
int c=startCol;
484+
for (int i=0; i<numAmps; i++) {
485+
qcomp amp = reals[i] + imags[i] * (qcomp) 1i;
486+
matrRef[r][c] = amp;
487+
488+
r++;
489+
if (r >= maxInd ) {
490+
r=0;
491+
c++;
492+
}
493+
}
494+
495+
REQUIRE( areEqual(matr, matrRef) );
496+
}
497+
}
498+
SECTION( "input validation" ) {
499+
500+
SECTION( "start index" ) {
501+
502+
int badInd = GENERATE_COPY( -1, maxInd );
503+
int numAmps = 0;
504+
REQUIRE_THROWS_WITH( setDensityAmps(matr, badInd, 0, reals, imags, numAmps), Contains("Invalid amplitude index") );
505+
REQUIRE_THROWS_WITH( setDensityAmps(matr, 0, badInd, reals, imags, numAmps), Contains("Invalid amplitude index") );
506+
}
507+
508+
SECTION( "number of amplitudes" ) {
509+
510+
// independent
511+
int numAmps = GENERATE_COPY( -1, matr.numAmpsTotal+1 );
512+
REQUIRE_THROWS_WITH( setDensityAmps(matr, 0, 0, reals, imags, numAmps), Contains("Invalid number of amplitudes") );
513+
514+
// invalid considering start-index
515+
REQUIRE_THROWS_WITH( setDensityAmps(matr, maxInd-1, maxInd-1, reals, imags, 2), Contains("More amplitudes given than exist") );
516+
REQUIRE_THROWS_WITH( setDensityAmps(matr, maxInd-1, maxInd-2, reals, imags, maxInd+2), Contains("More amplitudes given than exist") );
517+
}
518+
SECTION( "state-vector" ) {
519+
520+
Qureg vec = createQureg(NUM_QUBITS, QUEST_ENV);
521+
REQUIRE_THROWS_WITH( setDensityAmps(vec, 0, 0, reals, imags, 0), Contains("valid only for density matrices") );
522+
destroyQureg(vec, QUEST_ENV);
523+
}
524+
}
525+
destroyQureg(matr, QUEST_ENV);
526+
}
527+
528+
529+
447530
/** @sa setWeightedQureg
448531
* @ingroup unittest
449532
* @author Tyson Jones

0 commit comments

Comments
 (0)