Commit 954a0238 authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Tidy up Qsim impl to use QCOR API



- use xacc::internal_compiler::execute rather than direct QPU execute().

- Use QCOR observable and weighted-sum API for the default cost function evaluator rather than via VQE.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 90bf593d
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -3,9 +3,14 @@
// Using noise-mitigation observable evaluation (Verified QPE)

// Compile and run with (e.g. using the 5-qubit Yorktown device)
/// $ qcor -qpu aer:ibmqx2 TrotterTdWorkflow.cpp
/// $ qcor -qpu -qpu aer[noise-model:<noise JSON>] -shots 8192 -opt-pass
/// two-qubit-block-merging VerifiedQuantumPhaseEstimation.cpp
/// $ ./a.out

// For this simple circuit, the Trotter circuit can be significantly simplified
// by the `two-qubit-block-merging` optimizer (combine Trotter steps and
// decompose the total circuit into a more efficient KAK circuit).

// Note: for simplicity, we use the time-dependent Ising model with only 2
// qubits, hence with QPE, we need a total of 3 qubits. These 3 qubits can be
// directly mapped to the triangular topology of the Yorktown device.
+2 −2
Original line number Diff line number Diff line
@@ -158,11 +158,10 @@ double PhaseEstimationObjFuncEval::evaluate(
    obsTermTracking.emplace_back(std::make_pair(termCoeff, termData));
  }

  auto qpu = xacc::internal_compiler::get_qpu();
  auto temp_buffer = xacc::qalloc(nbQubits + 1);
  // Execute all sub-kernels
  executePassManager(fsToExec);
  qpu->execute(temp_buffer, fsToExec);
  xacc::internal_compiler::execute(temp_buffer.get(), fsToExec);

  // Assemble execution data into a fast look-up map
  ExecutionData exeResult;
@@ -173,6 +172,7 @@ double PhaseEstimationObjFuncEval::evaluate(
  const auto mitigateMeasurementResult =
      [&](const std::map<std::string, int> &in_rawResult) {
        std::map<std::string, int> result{{"0", 0}, {"1", 0}};
        auto qpu = xacc::internal_compiler::get_qpu();
        const size_t bitIdx =
            (qpu->getBitOrder() == Accelerator::BitOrder::MSB) ? 0 : nbQubits;
        const std::string CORRECT_VERIFIED_BITSTRING(nbQubits, '0');
+8 −11
Original line number Diff line number Diff line
@@ -285,11 +285,9 @@ IterativeQpeWorkflow::execute(const QuantumSimulationModel &model) {
    auto iterQpe = constructQpeCircuit(stretchedObs, k, -2 * M_PI * omega_coef);
    kernel->addInstruction(iterQpe);
    // Executes the iterative QPE algorithm:
    auto qpu = xacc::internal_compiler::get_qpu();
    auto temp_buffer = xacc::qalloc(stretchedObs->nBits() + 1);
    // std::cout << "Kernel: \n" << kernel->toString() << "\n";

    qpu->execute(temp_buffer, kernel);
    xacc::internal_compiler::execute(temp_buffer.get(), kernel);
    // temp_buffer->print();

    // Estimate the phase value's bit at this iteration,
@@ -338,14 +336,13 @@ getWorkflow(const std::string &name, const HeterogeneousMap &init_params) {

double
DefaultObjFuncEval::evaluate(std::shared_ptr<CompositeInstruction> state_prep) {
  // Reuse existing VQE util to evaluate the expectation value:
  auto vqe = xacc::getAlgorithm("vqe");
  auto qpu = xacc::internal_compiler::get_qpu();
  vqe->initialize({{"ansatz", state_prep},
                   {"accelerator", qpu},
                   {"observable", target_operator}});
  auto tmp_child = qalloc(state_prep->nPhysicalBits());
  auto energy = vqe->execute(xacc::as_shared_ptr(tmp_child.results()), {})[0];
  auto subKernels = qcor::__internal__::observe(
      xacc::as_shared_ptr(target_operator), state_prep);
  // Run the pass manager (optimization + placement)
  executePassManager(subKernels);
  auto tmp_buffer = qalloc(state_prep->nPhysicalBits());
  xacc::internal_compiler::execute(tmp_buffer.results(), subKernels);
  const double energy = tmp_buffer.weighted_sum(target_operator);
  return energy;
}
} // namespace qsim
+1 −1
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ observe(std::shared_ptr<xacc::Observable> obs,
        std::shared_ptr<CompositeInstruction> program) {
  return obs->observe(program);
}
} // namespace __internal__

double observe(std::shared_ptr<CompositeInstruction> program,
               std::shared_ptr<xacc::Observable> obs,
@@ -86,5 +87,4 @@ double observe(std::shared_ptr<CompositeInstruction> program, Observable &obs,
    return q.weighted_sum(&obs);
  }();
}
} // namespace __internal__
} // namespace qcor
 No newline at end of file
+2 −1
Original line number Diff line number Diff line
@@ -89,11 +89,12 @@ double observe(std::shared_ptr<CompositeInstruction> program, Observable &obs,
double observe(std::shared_ptr<CompositeInstruction> program,
               std::shared_ptr<Observable> obs,
               xacc::internal_compiler::qreg &q);

namespace __internal__ {
// Observe the kernel and return the measured kernels
std::vector<std::shared_ptr<CompositeInstruction>>
observe(std::shared_ptr<Observable> obs,
        std::shared_ptr<CompositeInstruction> program);
} // namespace __internal__

// Create an observable from a string representation
std::shared_ptr<Observable> createObservable(const std::string &repr);