Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions quest/src/api/calculations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ extern "C" void _wrap_calcExpecNonHermitianPauliStrSum(qcomp* out, Qureg qureg,
qcomp calcExpecNonHermitianFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix) {
validate_quregFields(qureg, __func__);
validate_matrixFields(matrix, __func__);
validate_matrixIsSynced(matrix, __func__);
validate_matrixAndQuregAreCompatible(matrix, qureg, true, __func__);

return calcExpecNonHermitianFullStateDiagMatrPower(qureg, matrix, 1); // harmlessly re-validates
Expand All @@ -99,6 +100,7 @@ extern "C" void _wrap_calcExpecNonHermitianFullStateDiagMatr(qcomp* out, Qureg q
qcomp calcExpecNonHermitianFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent) {
validate_quregFields(qureg, __func__);
validate_matrixFields(matrix, __func__);
validate_matrixIsSynced(matrix, __func__);
validate_matrixAndQuregAreCompatible(matrix, qureg, true, __func__);

// this function never uses the qreal-pow overload (because we make
Expand Down
34 changes: 12 additions & 22 deletions quest/src/core/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,13 +470,13 @@ namespace report {


string COMP_MATR_NOT_SYNCED_TO_GPU =
"The CompMatr has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncCompMatr() after manually modifying elements, or overwrite all elements with setCompMatr() which automatically synchronises.";
"The CompMatr has yet not been synchronised, so potential changes to its elements may be ignored. Please call syncCompMatr() after manually modifying elements, or overwrite all elements with setCompMatr() which automatically synchronises.";

string DIAG_MATR_NOT_SYNCED_TO_GPU =
"The DiagMatr has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncDiagMatr() after manually modifying elements, or overwrite all elements with setDiagMatr() which automatically synchronises.";
"The DiagMatr has yet not been synchronised, so potential changes to its elements may be ignored. Please call syncDiagMatr() after manually modifying elements, or overwrite all elements with setDiagMatr() which automatically synchronises.";

string FULL_STATE_DIAG_MATR_NOT_SYNCED_TO_GPU =
"The FullStateDiagMatr has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncFullStateDiagMatr() after manually modifying elements, or overwrite elements in batch with setFullStateDiagMatr() which automatically synchronises.";
"The FullStateDiagMatr has yet not been synchronised, so potential changes to its elements may be ignored. Please call syncFullStateDiagMatr() after manually modifying elements, or overwrite elements in batch with setFullStateDiagMatr() which automatically synchronises.";


string MATRIX_SIZE_MISMATCHES_NUM_TARGETS =
Expand Down Expand Up @@ -580,7 +580,7 @@ namespace report {
"The given SuperOp's pointer to its GPU memory was NULL. This may imply the superoperator was already destroyed and had its memory pointers manually overwritten by the user.";

string SUPER_OP_NOT_SYNCED_TO_GPU =
"The SuperOp has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncSuperOp() after manually modifying the superoperator elements, or overwrite all elements with setSuperOp() which will automatically syncrhonise.";
"The SuperOp has yet not been synchronised, so potential changes to its elements may be ignored. Please call syncSuperOp() after manually modifying the superoperator elements, or overwrite all elements with setSuperOp() which will automatically synchronise.";


string SUPER_OP_SIZE_MISMATCHES_NUM_TARGETS =
Expand Down Expand Up @@ -688,7 +688,7 @@ namespace report {


string KRAUS_MAP_NOT_SYNCED_TO_GPU =
"The KrausMap has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncKrausMap() after manually modifying the superoperator elements, or overwrite all elements with setKrausMap() which will automatically syncrhonise.";
"The KrausMap has yet not been synchronised, so potential changes to its elements may be ignored. Please call syncKrausMap() after manually modifying the Kraus operator elements, or overwrite all elements with setKrausMap() which will automatically synchronise.";

string KRAUS_MAP_NOT_CPTP =
"The KrausMap was not (approximately) completely positive and trace preserving (CPTP).";
Expand Down Expand Up @@ -2758,13 +2758,9 @@ void validate_matrixFields(FullStateDiagMatr m, const char* caller) {
template <class T>
void assertMatrixIsSynced(T matr, string errMsg, const char* caller) {

// we don't need to perform any sync check in CPU-only mode
if (!mem_isAllocated(util_getGpuMemPtr(matr)))
return;

// check if GPU amps have EVER been overwritten; we sadly cannot check the LATEST changes were pushed though.
// note we check this whenever the matrix has GPU memory, even if it is being applied upon a Qureg which is
// NOT GPU-accelerated and ergo the GPU memory is not consulted. It's best to build the habit in the user!
// Check if sync was EVER performed; we sadly cannot check the LATEST changes were pushed though.
// We intentionally enforce this even in CPU-only mode because sync also marks the matrix as
// intentionally initialised after direct user modification.
assertThat(*(matr.wasGpuSynced) == 1, errMsg, caller);
}
void validate_matrixIsSynced(CompMatr matr, const char* caller) {
Expand Down Expand Up @@ -3393,11 +3389,9 @@ void validate_superOpIsSynced(SuperOp op, const char* caller) {
if (!global_isValidationEnabled)
return;

// we don't need to perform any sync check in CPU-only mode
if (!mem_isAllocated(util_getGpuMemPtr(op)))
return;

// check if GPU amps have EVER been overwritten; we sadly cannot check the LATEST changes were pushed though
// Check if sync was EVER performed; we sadly cannot check the LATEST changes were pushed though.
// We intentionally enforce this even in CPU-only mode because sync also marks the superoperator
// as intentionally initialised after direct user modification.
assertThat(*(op.wasGpuSynced), report::SUPER_OP_NOT_SYNCED_TO_GPU, caller);
}

Expand Down Expand Up @@ -3616,11 +3610,7 @@ void validate_krausMapIsSynced(KrausMap map, const char* caller) {
if (!global_isValidationEnabled)
return;

// we don't need to perform any sync check in CPU-only mode
if (!mem_isAllocated(util_getGpuMemPtr(map.superop)))
return;

// assert the map's superoperator has been synced
// Assert the derived superoperator has been computed by syncKrausMap(), even in CPU-only mode.
assertThat(*(map.superop.wasGpuSynced), report::KRAUS_MAP_NOT_SYNCED_TO_GPU, caller);
}

Expand Down
30 changes: 28 additions & 2 deletions tests/unit/calculations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,20 @@ TEST_CASE( "calcExpecNonHermitianFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_D
}
}

/// @todo input validation
SECTION( LABEL_VALIDATION ) {

Qureg qureg = getArbitraryCachedStatevec();
FullStateDiagMatr matr = createFullStateDiagMatr(qureg.numQubits);

SECTION( "matrix unsynced" ) {

REQUIRE_THROWS_WITH(
calcExpecNonHermitianFullStateDiagMatr(qureg, matr),
ContainsSubstring("not been synchronised") );
}

destroyFullStateDiagMatr(matr);
}
}


Expand Down Expand Up @@ -700,7 +713,20 @@ TEST_CASE( "calcExpecNonHermitianFullStateDiagMatrPower", TEST_CATEGORY LABEL_MI
}
}

/// @todo input validation
SECTION( LABEL_VALIDATION ) {

Qureg qureg = getArbitraryCachedStatevec();
FullStateDiagMatr matr = createFullStateDiagMatr(qureg.numQubits);

SECTION( "matrix unsynced" ) {

REQUIRE_THROWS_WITH(
calcExpecNonHermitianFullStateDiagMatrPower(qureg, matr, 1),
ContainsSubstring("not been synchronised") );
}

destroyFullStateDiagMatr(matr);
}
}


Expand Down
32 changes: 32 additions & 0 deletions tests/unit/channels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,38 @@ TEST_CASE( "createInlineSuperOp", TEST_CATEGORY ) {
}


TEST_CASE( "reportKrausMap", TEST_CATEGORY ) {

SECTION( LABEL_VALIDATION ) {

KrausMap map = createKrausMap(1, 1);

SECTION( "not synced" ) {

REQUIRE_THROWS_WITH( reportKrausMap(map), ContainsSubstring("not been synchronised") );
}

destroyKrausMap(map);
}
}


TEST_CASE( "reportSuperOp", TEST_CATEGORY ) {

SECTION( LABEL_VALIDATION ) {

SuperOp op = createSuperOp(1);

SECTION( "not synced" ) {

REQUIRE_THROWS_WITH( reportSuperOp(op), ContainsSubstring("not been synchronised") );
}

destroySuperOp(op);
}
}


/** @} (end defgroup) */


Expand Down
26 changes: 24 additions & 2 deletions tests/unit/decoherence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,18 @@ TEST_CASE( "mixKrausMap", TEST_CATEGORY ) {
destroyKrausMap(map);
}

/// @todo input validation
SECTION( LABEL_VALIDATION ) {

Qureg qureg = getArbitraryCachedDensmatr();
int targ = 0;

SECTION( "map unsynced" ) {

KrausMap map = createKrausMap(1, 1);
REQUIRE_THROWS_WITH( mixKrausMap(qureg, &targ, 1, map), ContainsSubstring("sync") );
destroyKrausMap(map);
}
}
}


Expand All @@ -325,7 +336,18 @@ TEST_CASE( "mixSuperOp", TEST_CATEGORY ) {
destroySuperOp(superOp);
}

/// @todo input validation
SECTION( LABEL_VALIDATION ) {

Qureg qureg = getArbitraryCachedDensmatr();
int targ = 0;

SECTION( "superoperator unsynced" ) {

SuperOp op = createSuperOp(1);
REQUIRE_THROWS_WITH( mixSuperOp(qureg, &targ, 1, op), ContainsSubstring("sync") );
destroySuperOp(op);
}
}
}


Expand Down
16 changes: 16 additions & 0 deletions tests/unit/matrices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1287,6 +1287,22 @@ TEST_CASE( "createInlineDiagMatr", TEST_CATEGORY ) {
}


TEST_CASE( "reportCompMatr", TEST_CATEGORY ) {

SECTION( LABEL_VALIDATION ) {

CompMatr matr = createCompMatr(1);

SECTION( "not synced" ) {

REQUIRE_THROWS_WITH( reportCompMatr(matr), ContainsSubstring("not been synchronised") );
}

destroyCompMatr(matr);
}
}


/** @} (end defgroup) */


Expand Down
3 changes: 0 additions & 3 deletions tests/unit/operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1029,9 +1029,6 @@ void testOperationValidation(auto operation) {

SECTION( "matrix unsynced" ) {

if (!getQuESTEnv().isGpuAccelerated)
return;

// only relevant to variable-size matrix functions
if constexpr (Targs == any && (Args == compmatr || Args == diagmatr || Args == diagpower))
*(std::get<0>(furtherArgs).wasGpuSynced) = 0;
Expand Down
Loading