Commit a51869a3 by Nguyen, Thien Minh

### Got the one-qubit base case worked

```

Need to enhance the Pauli algebra handler to support multiple qubits
Signed-off-by: Thien Nguyen <nguyentm@ornl.gov>```
parent 9d653003
 # Simple 1-qubit demonstration of the Quatum Imaginary Time Evolution algorithm # Reference: https://www.nature.com/articles/s41567-019-0704-4 # Target H = 1/sqrt(2)(X + Z) # Expected minimum value: -1.0 import xacc,sys, numpy as np import matplotlib.pyplot as plt # Get access to the desired QPU and # allocate some qubits to run on qpu = xacc.getAccelerator('qpp') # Construct the Hamiltonian as an XACC PauliOperator ham = xacc.getObservable('pauli', '0.70710678118 X0 + 0.70710678118 Z0') # We just need 1 qubit buffer = xacc.qalloc(1) # See Fig. 2 (e) of https://www.nature.com/articles/s41567-019-0704-4 # Horizontal axis: 0 -> 2.5 # The number of Trotter steps nbSteps = 25 # The Trotter step size stepSize = 0.1 # Create the QITE algorithm qite = xacc.getAlgorithm('qite', { 'accelerator': qpu, 'observable': ham, 'step-size': stepSize, 'steps': nbSteps }) result = qite.execute(buffer) # Expected result: ~ -1 print('Min energy value = ', buffer.getInformation('opt-val')) E = buffer.getInformation('exp-vals') # Reproduce Fig. 2(e) of https://www.nature.com/articles/s41567-019-0704-4 plt.plot(np.arange(0, nbSteps + 1) * stepSize, E, 'ro', label = 'XACC QITE') plt.grid() plt.show() \ No newline at end of file
 ... @@ -64,6 +64,8 @@ bool QITE::initialize(const HeterogeneousMap ¶meters) ... @@ -64,6 +64,8 @@ bool QITE::initialize(const HeterogeneousMap ¶meters) m_observable = xacc::as_shared_ptr(parameters.getPointerLike("observable")); m_observable = xacc::as_shared_ptr(parameters.getPointerLike("observable")); } } m_approxOps.clear(); m_energyAtStep.clear(); return initializeOk; return initializeOk; } } ... @@ -118,10 +120,58 @@ std::shared_ptr QITE::constructPropagateCircuit() const ... @@ -118,10 +120,58 @@ std::shared_ptr QITE::constructPropagateCircuit() const } } } } std::cout << "Progagated kernel:\n" << propagateKernel->toString() << "\n"; // std::cout << "Progagated kernel:\n" << propagateKernel->toString() << "\n"; return propagateKernel; return propagateKernel; } } double QITE::calcCurrentEnergy(int in_nbQubits) const { // Trotter kernel up to this point auto propagateKernel = constructPropagateCircuit(); auto kernels = m_observable->observe(propagateKernel); std::vector coefficients; std::vector kernelNames; std::vector> fsToExec; double identityCoeff = 0.0; for (auto &f : kernels) { kernelNames.push_back(f->name()); std::complex coeff = f->getCoefficient(); int nFunctionInstructions = 0; if (f->getInstruction(0)->isComposite()) { nFunctionInstructions = propagateKernel->nInstructions() + f->nInstructions() - 1; } else { nFunctionInstructions = f->nInstructions(); } if (nFunctionInstructions > propagateKernel->nInstructions()) { fsToExec.push_back(f); coefficients.push_back(std::real(coeff)); } else { identityCoeff += std::real(coeff); } } auto tmpBuffer = xacc::qalloc(in_nbQubits); m_accelerator->execute(tmpBuffer, fsToExec); auto buffers = tmpBuffer->getChildren(); double energy = identityCoeff; for (int i = 0; i < buffers.size(); ++i) { auto expval = buffers[i]->getExpectationValueZ(); energy += expval * coefficients[i]; } std::cout << "Energy = " << energy << "\n"; return energy; } void QITE::execute(const std::shared_ptr buffer) const void QITE::execute(const std::shared_ptr buffer) const { { ... @@ -347,6 +397,8 @@ void QITE::execute(const std::shared_ptr buffer) const ... @@ -347,6 +397,8 @@ void QITE::execute(const std::shared_ptr buffer) const return updatedAham; return updatedAham; }; }; m_energyAtStep.emplace_back(calcCurrentEnergy(buffer->size())); // Time stepping: // Time stepping: for (int i = 0; i < m_nbSteps; ++i) for (int i = 0; i < m_nbSteps; ++i) { { ... @@ -358,12 +410,22 @@ void QITE::execute(const std::shared_ptr buffer) const ... @@ -358,12 +410,22 @@ void QITE::execute(const std::shared_ptr buffer) const auto nextAOps = calcAOps(kernel, hamTerm); auto nextAOps = calcAOps(kernel, hamTerm); m_approxOps.emplace_back(nextAOps); m_approxOps.emplace_back(nextAOps); } } m_energyAtStep.emplace_back(calcCurrentEnergy(buffer->size())); } } assert(m_energyAtStep.size() == m_nbSteps + 1); // Last energy value buffer->addExtraInfo("opt-val", ExtraInfo(m_energyAtStep.back())); // Also returns the full list of energy values // at each Trotter step. buffer->addExtraInfo("exp-vals", ExtraInfo(m_energyAtStep)); } } std::vector QITE::execute(const std::shared_ptr buffer, const std::vector& x) std::vector QITE::execute(const std::shared_ptr buffer, const std::vector& x) { { // TODO // We don't do any parameter optimization here, // hence don't support this! xacc::error("This method is unsupported!"); return {}; return {}; } } } // namespace algorithm } // namespace algorithm ... ...
 ... @@ -30,7 +30,9 @@ public: ... @@ -30,7 +30,9 @@ public: private: private: // Construct the Trotter propagate circuit up to current time step. // Construct the Trotter propagate circuit up to current time step. std::shared_ptr constructPropagateCircuit() const; std::shared_ptr constructPropagateCircuit() const; // Calculate the current energy, i.e. // the value of the observable at the current Trotter step. double calcCurrentEnergy(int in_nbQubits) const; private: private: // Number of Trotter steps // Number of Trotter steps int m_nbSteps; int m_nbSteps; ... @@ -47,6 +49,8 @@ private: ... @@ -47,6 +49,8 @@ private: // of the Hamiltonian observable // of the Hamiltonian observable // i.e. exp(-iAt) -> exp(-Ht) // i.e. exp(-iAt) -> exp(-Ht) mutable std::vector> m_approxOps; mutable std::vector> m_approxOps; // Energy value achieved at a Trotter step mutable std::vector m_energyAtStep; }; }; } // namespace algorithm } // namespace algorithm } // namespace xacc } // namespace xacc
 ... @@ -39,6 +39,13 @@ TEST(QITETester, checkSimple) ... @@ -39,6 +39,13 @@ TEST(QITETester, checkSimple) auto buffer = xacc::qalloc(1); auto buffer = xacc::qalloc(1); qite->execute(buffer); qite->execute(buffer); const double finalEnergy = (*buffer)["opt-val"].as(); std::cout << "Final Energy: " << finalEnergy << "\n"; // Fig (2.e) of https://www.nature.com/articles/s41567-019-0704-4 // Minimal Energy = -1 EXPECT_NEAR(finalEnergy, -1.0, 1e-3); const std::vector energyValues = (*buffer)["exp-vals"].as>(); EXPECT_EQ(energyValues.size(), nbSteps + 1); } } int main(int argc, char **argv) { int main(int argc, char **argv) { ... ...
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!