Commit 988f3156 authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Add a method to evaluate all Trotter obs values in one shot



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 2dc99590
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -49,6 +49,18 @@ class CostFunctionEvaluator : public Identifiable {
public:
  // Evaluate the cost
  virtual double evaluate(std::shared_ptr<CompositeInstruction> state_prep) = 0;
  // Batching evaluation: observing multiple kernels in batches.
  // E.g. for non-vqe cases (Trotter), we have all kernels ready for observable evaluation
  virtual std::vector<double> evaluate(
      std::vector<std::shared_ptr<CompositeInstruction>> state_prep_circuits) {
    // Default is one-by-one, subclass to provide batching if supported.
    std::vector<double> result;
    for (auto &circuit : state_prep_circuits) {
      result.emplace_back(evaluate(circuit));
    }
    return result;
  }
  
  virtual bool initialize(Observable *observable,
                          const HeterogeneousMap &params = {});

+37 −0
Original line number Diff line number Diff line
#include "partial_tomography.hpp"
#include "qsim_utils.hpp"
#include "xacc.hpp"

namespace qcor {
namespace qsim {
@@ -14,5 +15,41 @@ double PartialTomoObjFuncEval::evaluate(
  const double energy = tmp_buffer.weighted_sum(target_operator);
  return energy;
}

std::vector<double> PartialTomoObjFuncEval::evaluate(
    std::vector<std::shared_ptr<CompositeInstruction>> state_prep_circuits) {
  xacc::info("Batching " + std::to_string(state_prep_circuits.size()) +
             " kernel observable evaluations.");
  std::vector<size_t> nbSubKernelsPerObs;
  std::vector<std::shared_ptr<CompositeInstruction>> fsToExec;
  for (auto &circ : state_prep_circuits) {
    auto subKernels =
        qcor::__internal__::observe(xacc::as_shared_ptr(target_operator), circ);
    // Run the pass manager (optimization + placement)
    executePassManager(subKernels);
    // Track number of obs. kernels
    nbSubKernelsPerObs.emplace_back(subKernels.size());
    fsToExec.insert(fsToExec.end(), subKernels.begin(), subKernels.end());
  }
  auto tmp_buffer = qalloc(target_operator->nBits());
  // Execute all kernels:
  xacc::internal_compiler::execute(tmp_buffer.results(), fsToExec);
  size_t bufferCounter = 0;
  std::vector<double> result;
  auto allChildBuffers = tmp_buffer.results()->getChildren();
  // Segregates the child buffers into groups (of each obs eval.)
  for (const auto &nbChildBuffers : nbSubKernelsPerObs) {
    auto temp_buf = qalloc(tmp_buffer.size());
    for (size_t idx = 0; idx < nbChildBuffers; ++idx) {
      auto bufferToAppend = allChildBuffers[bufferCounter + idx];
      temp_buf.results()->appendChild(bufferToAppend->name(), bufferToAppend);
    }
    bufferCounter += nbChildBuffers;
    result.emplace_back(temp_buf.weighted_sum(target_operator));
  }

  assert(result.size() == state_prep_circuits.size());
  return result;
}
} // namespace qsim
} // namespace qcor
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
@@ -8,6 +8,9 @@ public:
  // Evaluate the cost
  virtual double
  evaluate(std::shared_ptr<CompositeInstruction> state_prep) override;
  virtual std::vector<double> evaluate(
      std::vector<std::shared_ptr<CompositeInstruction>> state_prep_circuits)
      override;
  virtual const std::string name() const override { return "default"; }
  virtual const std::string description() const override { return ""; }
};
+7 −5
Original line number Diff line number Diff line
#include "time_dependent.hpp"
#include "qsim_utils.hpp"
#include "xacc_service.hpp"
#include "xacc.hpp"

namespace qcor {
namespace qsim {
@@ -29,11 +30,12 @@ TimeDependentWorkflow::execute(const QuantumSimulationModel &model) {
  // A TD workflow: stepping through Trotter steps,
  // compute expectations at each step.
  double currentTime = t_0;
  std::vector<double> resultExpectationValues;
  std::shared_ptr<CompositeInstruction> totalCirc;
  // Just support Trotter for now
  // TODO: support different methods:
  auto method = xacc::getService<AnsatzGenerator>("trotter");
  // List of all circuits to evaluate:
  std::vector<std::shared_ptr<CompositeInstruction>> allCircuits;
  for (;;) {
    // Evaluate the time-dependent Hamiltonian:
    auto ham_t = ham_func(currentTime);
@@ -54,16 +56,16 @@ TimeDependentWorkflow::execute(const QuantumSimulationModel &model) {
      totalCirc->addInstructions(stepAnsatz.circuit->getInstructions());
    }
    // std::cout << totalCirc->toString() << "\n";
    // Evaluate the expectation after these Trotter steps:
    const double ham_expect = evaluator->evaluate(totalCirc);
    resultExpectationValues.emplace_back(ham_expect);

    // Add the circuit for this time step to the list for later execution    
    allCircuits.emplace_back(xacc::ir::asComposite(totalCirc->clone()));
    currentTime += dt;
    if (currentTime > t_final) {
      break;
    }
  }

  // Evaluate exp-val at all timesteps
  auto resultExpectationValues = evaluator->evaluate(allCircuits);
  result.insert("exp-vals", resultExpectationValues);
  return result;
}