Skip to content

Commit

Permalink
ProbRdm() variants in shared library
Browse files Browse the repository at this point in the history
  • Loading branch information
WrathfulSpatula committed Jul 25, 2023
1 parent 1096544 commit 1abd64d
Show file tree
Hide file tree
Showing 7 changed files with 267 additions and 17 deletions.
4 changes: 4 additions & 0 deletions include/pinvoke_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ MICROSOFT_QUANTUM_DECL void qstabilizer_in_from_file(_In_ uintq sid, _In_ char*

// pseudo-quantum
MICROSOFT_QUANTUM_DECL double Prob(_In_ uintq sid, _In_ uintq q);
MICROSOFT_QUANTUM_DECL double ProbRdm(_In_ uintq sid, _In_ uintq q);
MICROSOFT_QUANTUM_DECL double PermutationProb(
_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* q, _In_reads_(n) bool* c);
MICROSOFT_QUANTUM_DECL double PermutationProbRdm(
_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* q, _In_reads_(n) bool* c);
MICROSOFT_QUANTUM_DECL double PermutationExpectation(_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* c);
MICROSOFT_QUANTUM_DECL double PermutationExpectationRdm(_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* c);

MICROSOFT_QUANTUM_DECL void DumpIds(_In_ uintq sid, _In_ IdCallback callback);
MICROSOFT_QUANTUM_DECL void Dump(_In_ uintq sid, _In_ ProbAmpCallback callback);
Expand Down
36 changes: 36 additions & 0 deletions include/qinterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2361,6 +2361,42 @@ class QInterface : public ParallelFor {
*/
virtual real1_f ExpectationBitsAll(const std::vector<bitLenInt>& bits, bitCapInt offset = 0);

/**
* Direct measure of bit probability to be in |1> state, treating all ancillary qubits as post-selected T gate
* gadgets
*
* \warning PSEUDO-QUANTUM
*/
virtual real1_f ProbRdm(bitLenInt qubitIndex) { return Prob(qubitIndex); }
/**
* Direct measure of full permutation probability, treating all ancillary qubits as post-selected T gate gadgets
*
* \warning PSEUDO-QUANTUM
*/
virtual real1_f ProbAllRdm(bitCapInt fullRegister) { return ProbAll(fullRegister); }
/**
* Direct measure of masked permutation probability, treating all ancillary qubits as post-selected T gate gadgets
*
* "mask" masks the bits to check the probability of. "permutation" sets the 0 or 1 value for each bit in the mask.
* Bits which are set in the mask can be set to 0 or 1 in the permutation, while reset bits in the mask should be 0
* in the permutation.
*
* \warning PSEUDO-QUANTUM
*/
virtual real1_f ProbMaskRdm(bitCapInt mask, bitCapInt permutation) { return ProbMask(mask, permutation); }
/**
* Get permutation expectation value of bits, treating all ancillary qubits as post-selected T gate gadgets
*
* The permutation expectation value of all included bits is returned, with bits valued from low to high as the
* order of the "bits" array parameter argument.
*
* \warning PSEUDO-QUANTUM
*/
virtual real1_f ExpectationBitsAllRdm(const std::vector<bitLenInt>& bits, bitCapInt offset = 0U)
{
return ExpectationBitsAll(bits, offset);
}

/**
* Statistical measure of masked permutation probability
*
Expand Down
13 changes: 13 additions & 0 deletions include/qstabilizerhybrid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,19 @@ class QStabilizerHybrid : public QParity, public QInterface {
return prob;
}

real1_f ACProbRdm(bitLenInt control, bitLenInt target)
{
CNOT(control, target);
const real1_f prob = ProbRdm(target);
CNOT(control, target);

return prob;
}

real1_f ProbAllRdm(bitCapInt fullRegister);
real1_f ProbMaskRdm(bitCapInt mask, bitCapInt permutation);
real1_f ExpectationBitsAllRdm(const std::vector<bitLenInt>& bits, bitCapInt offset = 0U);

/**
* Switches between CPU and GPU used modes. (This will not incur a performance penalty, if the chosen mode matches
* the current mode.) Mode switching happens automatically when qubit counts change, but Compose() and Decompose()
Expand Down
26 changes: 26 additions & 0 deletions include/qunit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,32 @@ class QUnit : public QParity, public QInterface {
virtual void SetDevice(int64_t dID);
virtual int64_t GetDevice() { return devID; }

real1_f ProbRdm(bitLenInt qubit)
{
const QEngineShard& shard = shards[qubit];
if (!shard.unit) {
return Prob(qubit);
}

return shard.unit->ProbRdm(qubit);
}
virtual real1_f CProbRdm(bitLenInt control, bitLenInt target)
{
AntiCNOT(control, target);
const real1_f prob = ProbRdm(target);
AntiCNOT(control, target);

return prob;
}
virtual real1_f ACProbRdm(bitLenInt control, bitLenInt target)
{
CNOT(control, target);
const real1_f prob = ProbRdm(target);
CNOT(control, target);

return prob;
}

virtual void SetQuantumState(const complex* inputState);
virtual void GetQuantumState(complex* outputState);
virtual void GetProbs(real1* outputProbs);
Expand Down
60 changes: 49 additions & 11 deletions src/pinvoke_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2302,15 +2302,13 @@ MICROSOFT_QUANTUM_DECL void CLXNOR(_In_ uintq sid, _In_ bool ci, _In_ uintq qi,
}
}

/**
* (External API) Get the probability that a qubit is in the |1> state.
*/
MICROSOFT_QUANTUM_DECL double Prob(_In_ uintq sid, _In_ uintq q)
double _Prob(_In_ uintq sid, _In_ uintq q, bool isRdm)
{
SIMULATOR_LOCK_GUARD_DOUBLE(sid)

try {
return (double)simulator->Prob(shards[simulator.get()][q]);
return isRdm ? (double)simulator->ProbRdm(shards[simulator.get()][q])
: (double)simulator->Prob(shards[simulator.get()][q]);
} catch (const std::exception& ex) {
simulatorErrors[sid] = 1;
std::cout << ex.what() << std::endl;
Expand All @@ -2319,10 +2317,17 @@ MICROSOFT_QUANTUM_DECL double Prob(_In_ uintq sid, _In_ uintq q)
}

/**
* (External API) Get the permutation expectation value, based upon the order of input qubits.
* (External API) Get the probability that a qubit is in the |1> state.
*/
MICROSOFT_QUANTUM_DECL double PermutationProb(
_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* q, _In_reads_(n) bool* c)
MICROSOFT_QUANTUM_DECL double Prob(_In_ uintq sid, _In_ uintq q) { return _Prob(sid, q, false); }

/**
* (External API) Get the probability that a qubit is in the |1> state, treating all ancillary qubits as post-selected T
* gate gadgets.
*/
MICROSOFT_QUANTUM_DECL double ProbRdm(_In_ uintq sid, _In_ uintq q) { return _Prob(sid, q, true); }

double _PermutationProb(_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* q, _In_reads_(n) bool* c, bool isRdm)
{
SIMULATOR_LOCK_GUARD_DOUBLE(sid)

Expand All @@ -2337,7 +2342,7 @@ MICROSOFT_QUANTUM_DECL double PermutationProb(
}

try {
return (double)simulator->ProbMask(mask, perm);
return isRdm ? (double)simulator->ProbMaskRdm(mask, perm) : (double)simulator->ProbMask(mask, perm);
} catch (const std::exception& ex) {
simulatorErrors[sid] = 1;
std::cout << ex.what() << std::endl;
Expand All @@ -2348,7 +2353,23 @@ MICROSOFT_QUANTUM_DECL double PermutationProb(
/**
* (External API) Get the permutation expectation value, based upon the order of input qubits.
*/
MICROSOFT_QUANTUM_DECL double PermutationExpectation(_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* c)
MICROSOFT_QUANTUM_DECL double PermutationProb(
_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* q, _In_reads_(n) bool* c)
{
return _PermutationProb(sid, n, q, c, false);
}

/**
* (External API) Get the permutation expectation value, based upon the order of input qubits, treating all ancillary
* qubits as post-selected T gate gadgets.
*/
MICROSOFT_QUANTUM_DECL double PermutationProbRdm(
_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* q, _In_reads_(n) bool* c)
{
return _PermutationProb(sid, n, q, c, true);
}

double _PermutationExpectation(_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* c, bool isRdm)
{
SIMULATOR_LOCK_GUARD_DOUBLE(sid)

Expand All @@ -2358,14 +2379,31 @@ MICROSOFT_QUANTUM_DECL double PermutationExpectation(_In_ uintq sid, _In_ uintq
}

try {
return (double)simulator->ExpectationBitsAll(q);
return isRdm ? (double)simulator->ExpectationBitsAllRdm(q) : (double)simulator->ExpectationBitsAll(q);
} catch (const std::exception& ex) {
simulatorErrors[sid] = 1;
std::cout << ex.what() << std::endl;
return (double)REAL1_DEFAULT_ARG;
}
}

/**
* (External API) Get the permutation expectation value, based upon the order of input qubits.
*/
MICROSOFT_QUANTUM_DECL double PermutationExpectation(_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* c)
{
return _PermutationExpectation(sid, n, c, false);
}

/**
* (External API) Get the permutation expectation value, based upon the order of input qubits, treating all ancillary
* qubits as post-selected T gate gadgets.
*/
MICROSOFT_QUANTUM_DECL double PermutationExpectationRdm(_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* c)
{
return _PermutationExpectation(sid, n, c, true);
}

MICROSOFT_QUANTUM_DECL void QFT(_In_ uintq sid, _In_ uintq n, _In_reads_(n) uintq* c)
{
SIMULATOR_LOCK_GUARD_VOID(sid)
Expand Down
16 changes: 10 additions & 6 deletions src/qinterface/qinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ real1_f QInterface::ProbReg(bitLenInt start, bitLenInt length, bitCapInt permuta
prob += ProbAll(i);
}

return (real1_f)prob;
return (real1_f)clampProb(prob);
}

/// Returns probability of permutation of the mask
Expand All @@ -279,7 +279,7 @@ real1_f QInterface::ProbMask(bitCapInt mask, bitCapInt permutation)
}
}

return (real1_f)prob;
return (real1_f)clampProb(prob);
}

/// "Circular shift right" - (Uses swap-based algorithm for speed)
Expand Down Expand Up @@ -387,7 +387,7 @@ void QInterface::ProbBitsAll(const std::vector<bitLenInt>& bits, real1* probsArr
real1_f QInterface::ExpectationBitsAll(const std::vector<bitLenInt>& bits, bitCapInt offset)
{
ThrowIfQbIdArrayIsBad(bits, qubitCount,
"QInterface::ExpectationBitsAll parameter controls array values must be within allocated qubit bounds!");
"QInterface::ExpectationBitsAll parameter qubits vector values must be within allocated qubit bounds!");

if (bits.size() == 1U) {
return Prob(bits[0]);
Expand All @@ -396,18 +396,22 @@ real1_f QInterface::ExpectationBitsAll(const std::vector<bitLenInt>& bits, bitCa
std::vector<bitCapInt> bitPowers(bits.size());
std::transform(bits.begin(), bits.end(), bitPowers.begin(), pow2);

real1_f expectation = 0;
real1 expectation = ZERO_R1;
for (bitCapInt lcv = 0U; lcv < maxQPower; ++lcv) {
bitCapInt retIndex = 0U;
for (size_t p = 0U; p < bits.size(); ++p) {
if (lcv & bitPowers[p]) {
retIndex |= pow2(p);
}
}
expectation += (bitCapIntOcl)(offset + retIndex) * ProbAll(lcv);
#if (QBCAPPOW > 6) && BOOST_AVAILABLE
expectation += (real1)((offset + retIndex).convert_to<real1_f>() * ProbAll(lcv));
#else
expectation += (real1)((offset + retIndex) * ProbAll(lcv));
#endif
}

return expectation;
return (real1_f)expectation;
}

std::map<bitCapInt, int> QInterface::MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots)
Expand Down
Loading

0 comments on commit 1abd64d

Please sign in to comment.