Commit f0b0b4ed by Mccaskey, Alex Committed by GitHub

### Merge pull request #193 from tnguyen-ornl/tnguyen/qpe

`Quantum Phase Estimation Algorithm`
parents e33afcda 1bf0fc2f
Pipeline #103311 passed with stage
in 70 minutes and 50 seconds
 ... ... @@ -1089,6 +1089,137 @@ In Python: print('Min QUBO value = ', buffer.getInformation('opt-val')) Quantum Phase Estimation ++++++++++++++++++++++++ The ``QPE`` algorithm (also known as quantum eigenvalue estimation algorithm) provides an implementation of Algorithm that estimates the phase (or eigenvalue) of an eigenvector of a unitary operator. Here the unitary operator is called an `oracle` which is a quantum subroutine that acts upon a set of qubits and returns the answer as a phase. The bits precision is automatically inferred from the size of the input buffer. +------------------------+------------------------------------------------------------------------+------------------------------------------+ | Algorithm Parameter | Parameter Description | type | +========================+========================================================================+==========================================+ | oracle | The circuit represents the unitary operator. | pointer-like CompositeInstruction | +------------------------+------------------------------------------------------------------------+------------------------------------------+ | accelerator | The backend quantum computer to use. | pointer-like Accelerator | +------------------------+------------------------------------------------------------------------+------------------------------------------+ | state-preparation | The circuit to prepare the eigen state. | pointer-like CompositeInstruction | +------------------------+------------------------------------------------------------------------+------------------------------------------+ .. code:: cpp #include "xacc.hpp" #include "xacc_service.hpp" int main(int argc, char **argv) { xacc::Initialize(argc, argv); // Accelerator: auto acc = xacc::getAccelerator("qpp", {std::make_pair("shots", 4096)}); // In this example: we want to estimate the *phase* of an arbitrary 'oracle' // i.e. Oracle(|State>) = exp(i*Phase)*|State> // and we need to estimate that Phase. // Oracle: CPhase(theta) or CU1(theta) which is defined as // 1 0 0 0 // 0 1 0 0 // 0 0 1 0 // 0 0 0 e^(i*theta) // The eigenstate is |11>; i.e. CPhase(theta)|11> = e^(i*theta)|11> // Since this oracle operates on 2 qubits, we need to add more qubits to the buffer. // The more qubits we have, the more accurate the estimate. // Resolution := 2^(number qubits in the calculation register). // 5-bit precision => 7 qubits in total auto buffer = xacc::qalloc(7); auto qpe = xacc::getService("QPE"); auto compiler = xacc::getCompiler("xasm"); // Create oracle: CPhase gate with theta = 2pi/3 // i.e. the phase value to estimate is 1/3 ~ 0.33333. auto gateRegistry = xacc::getService("quantum"); auto oracle = gateRegistry->createComposite("oracle"); oracle->addInstruction(gateRegistry->createInstruction("CPhase", { 0, 1 }, { 2.0 * M_PI/ 3.0 })); // Eigenstate preparation = |11> state auto statePrep = compiler->compile(R"(__qpu__ void prep1(qbit q) { X(q[0]); X(q[1]); })", nullptr)->getComposite("prep1"); // Initialize the Quantum Phase Estimation: qpe->initialize({ std::make_pair("accelerator", acc), std::make_pair("oracle", oracle), std::make_pair("state-preparation", statePrep) }); // Run the algorithm qpe->execute(buffer); // Expected result: // The factor here is 2^5 (precision) = 32 // we expect the two most-likely bitstring is 10 and 11 // i.e. the true result is between 10/32 = 0.3125 and 11/32 = 0.34375 std::cout << "Probability of the two most-likely bitstrings 10 (theta = 0.3125) and 11 (theta = 0.34375 ): \n"; std::cout << "Probability of |11010> (11) = " << buffer->computeMeasurementProbability("11010") << "\n"; std::cout << "Probability of |01010> (10) = " << buffer->computeMeasurementProbability("01010") << "\n"; xacc::Finalize(); } or in Python .. code:: python import xacc,sys, numpy as np # Get access to the desired QPU and # allocate some qubits to run on qpu = xacc.getAccelerator('qpp', { 'shots': 4096 }) # In this example: we want to estimate the *phase* of an arbitrary 'oracle' # i.e. Oracle(|State>) = exp(i*Phase)*|State> # and we need to estimate that Phase. # The oracle is a simple T gate, and the eigenstate is |1> # T|1> = e^(i*pi/4)|1> # The phase value of pi/4 = 2pi * (1/8) # i.e. if we use a 3-bit register for estimation, # we will get the correct answer of 1 deterministically. xacc.qasm('''.compiler xasm .circuit oracle .qbit q T(q[0]); ''') oracle = xacc.getCompiled('oracle') # We need to prepare the eigenstate |1> xacc.qasm('''.compiler xasm .circuit prep .qbit q X(q[0]); ''') statePrep = xacc.getCompiled('prep') # We need 4 qubits (3-bit precision) buffer = xacc.qalloc(4) # Create the QPE algorithm qpe = xacc.getAlgorithm('QPE', { 'accelerator': qpu, 'oracle': oracle, 'state-preparation': statePrep }) qpe.execute(buffer) # We should only get the bit string of |100> = 1 # i.e. phase value of 1/2^3 = 1/8. print(buffer) Accelerator Decorators ---------------------- ROErrorDecorator ... ...
 import xacc,sys, numpy as np # Get access to the desired QPU and # allocate some qubits to run on qpu = xacc.getAccelerator('qpp', { 'shots': 4096 }) # In this example: we want to estimate the *phase* of an arbitrary 'oracle' # i.e. Oracle(|State>) = exp(i*Phase)*|State> # and we need to estimate that Phase. # The oracle is a simple T gate, and the eigenstate is |1> # T|1> = e^(i*pi/4)|1> # The phase value of pi/4 = 2pi * (1/8) # i.e. if we use a 3-bit register for estimation, # we will get the correct answer of 1 deterministically. xacc.qasm('''.compiler xasm .circuit oracle .qbit q T(q[0]); ''') oracle = xacc.getCompiled('oracle') # We need to prepare the eigenstate |1> xacc.qasm('''.compiler xasm .circuit prep .qbit q X(q[0]); ''') statePrep = xacc.getCompiled('prep') # We need 4 qubits (3-bit precision) buffer = xacc.qalloc(4) # Create the QPE algorithm qpe = xacc.getAlgorithm('QPE', { 'accelerator': qpu, 'oracle': oracle, 'state-preparation': statePrep }) qpe.execute(buffer) # We should only get the bit string of |100> = 1 # i.e. phase value of 1/2^3 = 1/8. print(buffer) \ No newline at end of file
 ... ... @@ -35,3 +35,6 @@ target_link_libraries(nah_ucc3 PRIVATE xacc xacc-quantum-gate) add_executable(qaoa_qubo solve_qubo_with_qaoa.cpp) target_link_libraries(qaoa_qubo PRIVATE xacc xacc-quantum-gate) add_executable(quantum_phase_estimation quantum_phase_estimation.cpp) target_link_libraries(quantum_phase_estimation PRIVATE xacc xacc-quantum-gate)